opensm-3.3.20/0000755000205000001450000000000012726324754010104 500000000000000opensm-3.3.20/config/0000755000205000001450000000000012726324753011350 500000000000000opensm-3.3.20/config/libtool.m40000644000205000001450000077341112726323063013204 00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 56 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl _LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\[$]0 --fallback-echo"')dnl " lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` ;; esac _LT_OUTPUT_LIBTOOL_INIT ]) # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) cat >"$CONFIG_LT" <<_LTEOF #! $SHELL # Generated by $as_me. # Run this file to recreate a libtool stub with the current configuration. lt_cl_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2008 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. if test "$no_create" != yes; then lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) fi ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_XSI_SHELLFNS sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(whole_archive_flag_spec, $1)='' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX # ----------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl AC_LINK_IFELSE(AC_LANG_PROGRAM,[ lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. m4_defun([_LT_PROG_ECHO_BACKSLASH], [_LT_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac ECHO=${lt_ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF [$]* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(lt_ECHO) ]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that does not interpret backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [AC_CHECK_TOOL(AR, ar, false) test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1]) AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line __oline__ "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method == "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC*) # IBM XL 8.0 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE(int foo(void) {}, _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' ) LDFLAGS="$save_LDFLAGS" else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then _LT_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [fix_srcfile_path], [1], [Fix the shell variable $srcfile for the compiler]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_PROG_CXX # ------------ # Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ # compiler, we have our own version here. m4_defun([_LT_PROG_CXX], [ pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) AC_PROG_CXX if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_CXX dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_CXX], []) # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [AC_REQUIRE([_LT_PROG_CXX])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 will use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; xl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=echo else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_PROG_F77 # ------------ # Since AC_PROG_F77 is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_F77], [ pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) AC_PROG_F77 if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_F77 dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_F77], []) # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_REQUIRE([_LT_PROG_F77])dnl AC_LANG_PUSH(Fortran 77) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${F77-"f77"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_PROG_FC # ----------- # Since AC_PROG_FC is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_FC], [ pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) AC_PROG_FC if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_FC dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_FC], []) # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_REQUIRE([_LT_PROG_FC])dnl AC_LANG_PUSH(Fortran) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${FC-"f95"} compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC="$lt_save_CC" ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC= CC=${RC-"windres"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC="$lt_save_CC" ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_XSI_SHELLFNS # --------------------- # Bourne and XSI compatible variants of some useful shell functions. m4_defun([_LT_PROG_XSI_SHELLFNS], [case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $[*] )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } dnl func_dirname_and_basename dnl A portable version of this function is already defined in general.m4sh dnl so there is no need for it here. # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[[^=]]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$[@]"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]+=\$[2]" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]=\$$[1]\$[2]" } _LT_EOF ;; esac ]) opensm-3.3.20/config/ltoptions.m40000644000205000001450000002724212726323063013565 00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [0], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) opensm-3.3.20/config/ltsugar.m40000644000205000001450000001042412726323063013205 00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) opensm-3.3.20/config/ltversion.m40000644000205000001450000000127712726323063013557 00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # Generated from ltversion.in. # serial 3017 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.2.6b]) m4_define([LT_PACKAGE_REVISION], [1.3017]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.2.6b' macro_revision='1.3017' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) opensm-3.3.20/config/lt~obsolete.m40000644000205000001450000001311312726323063014074 00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 4 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) opensm-3.3.20/config/osmvsel.m40000644000205000001450000002431312407077041013214 00000000000000 dnl osmvsel.m4: an autoconf for OpenSM Vendor Selection option dnl dnl To use this macro, just do OPENIB_APP_OSMV_SEL. dnl the new configure option --with-osmv will be defined. dnl current supported values are: openib(default),sim,gen1 dnl The following variables are defined: dnl OSMV_LDADD - LDADD additional libs for linking the vendor lib AC_DEFUN([OPENIB_APP_OSMV_SEL], [ # --- BEGIN OPENIB_APP_OSMV_SEL --- dnl Define a way for the user to provide the osm vendor type AC_ARG_WITH(osmv, AC_HELP_STRING([--with-osmv=], [define the osm vendor type to build]), AC_MSG_NOTICE(Using OSM Vendor Type:$with_osmv), with_osmv="openib") dnl Define a way for the user to provide the path to the ibumad installation AC_ARG_WITH(umad-prefix, AC_HELP_STRING([--with-umad-prefix=], [define the dir used as prefix for ibumad installation]), AC_MSG_NOTICE(Using ibumad installation prefix:$with_umad_prefix), with_umad_prefix="") dnl Define a way for the user to provide the path to the ibumad includes AC_ARG_WITH(umad-includes, AC_HELP_STRING([--with-umad-includes=], [define the dir where ibumad includes are installed]), AC_MSG_NOTICE(Using ibumad includes from:$with_umad_includes), with_umad_includes="") if test x$with_umad_includes = x; then if test x$with_umad_prefix != x; then with_umad_includes=$with_umad_prefix/include fi fi dnl Define a way for the user to provide the path to the ibumad libs AC_ARG_WITH(umad-libs, AC_HELP_STRING([--with-umad-libs=], [define the dir where ibumad libs are installed]), AC_MSG_NOTICE(Using ibumad libs from:$with_umad_libs), with_umad_libs="") if test x$with_umad_libs = x; then if test x$with_umad_prefix != x; then dnl Should we use lib64 or lib if test "$(uname -m)" = "x86_64" -o "$(uname -m)" = "ppc64"; then with_umad_libs=$with_umad_prefix/lib64 else with_umad_libs=$with_umad_prefix/lib fi fi fi dnl Define a way for the user to provide the path to the simulator installation AC_ARG_WITH(sim, AC_HELP_STRING([--with-sim=], [define the simulator prefix for building sim vendor (default /usr)]), AC_MSG_NOTICE(Using Simulator from:$with_sim), with_sim="/usr") dnl based on the with_osmv we can try the vendor flag if test $with_osmv = "openib"; then AC_DEFINE(OSM_VENDOR_INTF_OPENIB, 1, [Define as 1 for OpenIB vendor]) OSMV_INCLUDES="-I\$(srcdir)/../include -I\$(srcdir)/../../libibumad/include -I\$(includedir)" OSMV_LDADD="-L\$(abs_srcdir)/../../libibumad/.libs -L\$(libdir) -libumad" if test "x$with_umad_libs" != "x"; then OSMV_LDADD="-L$with_umad_libs $OSMV_LDADD" fi if test "x$with_umad_includes" != "x"; then OSMV_INCLUDES="-I$with_umad_includes $OSMV_INCLUDES" fi AC_DEFINE(DUAL_SIDED_RMPP, 1, [Define as 1 if you want Dual Sided RMPP Support]) elif test $with_osmv = "sim" ; then AC_DEFINE(OSM_VENDOR_INTF_SIM, 1, [Define as 1 for sim vendor]) OSMV_INCLUDES="-I$with_sim/include -I\$(srcdir)/../include" OSMV_LDADD="-L$with_sim/lib -libmscli" elif test $with_osmv = "gen1"; then AC_DEFINE(OSM_VENDOR_INTF_TS, 1, [Define as 1 for ts vendor]) if test -z $MTHOME; then MTHOME=/usr/local/ibgd/driver/infinihost fi OSMV_INCLUDES="-I$MTHOME/include -I\$(srcdir)/../include" dnl we need to find the TS includes somewhere... osmv_found=0 if test -z $TSHOME; then osmv_dir=`uname -r|sed 's/-smp//'` osmv_dir_smp=`uname -r` for d in /usr/src/linux-$osmv_dir /usr/src/linux-$osmv_dir_smp /lib/modules/$osmv_dir/build /lib/modules/$osmv_dir_smp/build/; do if test -f $d/drivers/infiniband/include/ts_ib_useraccess.h; then OSMV_INCLUDES="$OSMV_INCLUDES -I$d/drivers/infiniband/include" osmv_found=1 fi done else if test -f $TSHOME/ts_ib_useraccess.h; then OSMV_INCLUDES="$OSMV_INCLUDES -I$TSHOME" osmv_found=1 fi fi if test $osmv_found = 0; then AC_MSG_ERROR([Fail to find gen1 include files dir]) fi OSMV_LDADD="-L/usr/local/ibgd/driver/infinihost/lib -lvapi -lmosal -lmtl_common -lmpga" elif test $with_osmv = "vapi"; then AC_DEFINE(OSM_VENDOR_INTF_MTL, 1, [Define as 1 for vapi vendor]) OSMV_INCLUDES="-I/usr/mellanox/include -I/usr/include -I\$(srcdir)/../include" OSMV_LDADD="-L/usr/lib -L/usr/mellanox/lib -lib_mgt -lvapi -lmosal -lmtl_common -lmpga" else AC_MSG_ERROR([Invalid Vendor Type provided:$with_osmv should be either openib,sim,gen1]) fi AM_CONDITIONAL(OSMV_VAPI, test $with_osmv = "vapi") AM_CONDITIONAL(OSMV_GEN1, test $with_osmv = "gen1") AM_CONDITIONAL(OSMV_SIM, test $with_osmv = "sim") AM_CONDITIONAL(OSMV_OPENIB, test $with_osmv = "openib") AC_DEFINE(VENDOR_RMPP_SUPPORT, 1, [Define as 1 if you want Vendor RMPP Support]) AC_SUBST(OSMV_LDADD) AC_SUBST(OSMV_INCLUDES) # --- END OPENIB_APP_OSMV_SEL --- ]) dnl OPENIB_APP_OSMV_SEL dnl Check for the vendor lib dependency AC_DEFUN([OPENIB_APP_OSMV_CHECK_LIB], [ # --- BEGIN OPENIB_APP_OSMV_CHECK_LIB --- if test "$disable_libcheck" != "yes"; then dnl based on the with_osmv we can try the vendor flag if test $with_osmv = "openib"; then LDADD="$LDADD $OSMV_LDADD" AC_CHECK_LIB(ibumad, umad_init, [], AC_MSG_ERROR([umad_init() not found. libosmvendor of type openib requires libibumad.])) elif test $with_osmv = "sim" ; then LDFLAGS="$LDFLAGS -L$with_sim/lib" AC_CHECK_FILE([$with_sim/lib/libibmscli.a], [], AC_MSG_ERROR([ibms_bind() not found. libosmvendor of type sim requires libibmscli.])) elif test $with_osmv = "gen1"; then LDFLAGS="$LDFLAGS -L$MTHOME/lib -L$MTHOME/lib64 -lmosal -lmtl_common -lmpga" AC_CHECK_LIB(vapi, vipul_init, [], AC_MSG_ERROR([vipul_init() not found. libosmvendor of type gen1 requires libvapi.])) elif test $with_osmv != "vapi"; then AC_MSG_ERROR([OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_LIB]) fi fi # --- END OPENIB_APP_OSMV_CHECK_LIB --- ]) dnl OPENIB_APP_OSMV_CHECK_LIB dnl Check for the vendor lib dependency AC_DEFUN([OPENIB_APP_OSMV_CHECK_HEADER], [ # --- BEGIN OPENIB_APP_OSMV_CHECK_HEADER --- dnl we might be required to ignore this check if test "$disable_libcheck" != "yes"; then if test $with_osmv = "openib"; then osmv_headers=infiniband/umad.h elif test $with_osmv = "sim" ; then osmv_headers=ibmgtsim/ibms_client_api.h elif test $with_osmv = "gen1"; then osmv_headers= elif test $with_osmv = "vapi"; then osmv_headers=vapi.h else AC_MSG_ERROR([OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_HEADER]) fi if test "x$osmv_headers" != "x"; then AC_CHECK_HEADERS($osmv_headers) fi fi # --- END OPENIB_APP_OSMV_CHECK_HEADER --- ]) dnl OPENIB_APP_OSMV_CHECK_HEADER dnl Check for socket console support AC_DEFUN([OPENIB_OSM_CONSOLE_SOCKET_SEL], [ # --- BEGIN OPENIB_OSM_CONSOLE_SOCKET_SEL --- dnl Console over a loopback socket is default if libwrap is available AC_MSG_CHECKING([to enable console loopback]) AC_ARG_ENABLE(console-loopback, [ --enable-console-loopback Enable a console socket on the loopback interface, requires tcp_wrappers (default yes)], [case $enableval in yes) console_loopback=yes ;; no) console_loopback=no ;; esac], console_loopback=yes) AC_MSG_RESULT([$console_loopback]) if test $console_loopback = yes; then AC_CHECK_LIB(wrap, request_init, [], [console_loopback=no AC_MSG_WARN(libwrap is missing. setting console_loopback=no)]) fi if test $console_loopback = yes; then AC_DEFINE(ENABLE_OSM_CONSOLE_LOOPBACK, 1, [Define as 1 if you want to enable a loopback console]) fi dnl Console over a socket connection AC_MSG_CHECKING([to enable console socket]) AC_ARG_ENABLE(console-socket, [ --enable-console-socket Enable a console socket, requires --enable-console-loopback (default no)], [case $enableval in yes) console_socket=yes ;; no) console_socket=no ;; esac], console_socket=no) AC_MSG_RESULT([$console_socket]) if test $console_socket = yes; then if test $console_loopback = no; then AC_MSG_ERROR([--enable-console-socket requires --enable-console-loopback]) fi AC_DEFINE(ENABLE_OSM_CONSOLE_SOCKET, 1, [Define as 1 if you want to enable a console on a socket connection]) fi # --- END OPENIB_OSM_CONSOLE_SOCKET_SEL --- ]) dnl OPENIB_OSM_CONSOLE_SOCKET_SEL dnl Check if they want the PerfMgr AC_DEFUN([OPENIB_OSM_PERF_MGR_SEL], [ # --- BEGIN OPENIB_OSM_PERF_MGR_SEL --- dnl enable the perf-mgr AC_MSG_CHECKING([to enable perf mgr]) AC_ARG_ENABLE(perf-mgr, [ --enable-perf-mgr Enable the performance manager (default yes)], [case $enableval in yes) perf_mgr=yes ;; no) perf_mgr=no ;; esac], perf_mgr=yes) AC_MSG_RESULT([$perf_mgr]) AC_MSG_CHECKING([to enable perf mgr profiling]) AC_ARG_ENABLE(perf-mgr-profile, [ --enable-perf-mgr-profile Enable the performance manager profiling (default no)], [case $enableval in yes) perf_mgr_profile=yes ;; no) perf_mgr_profile=no ;; esac], perf_mgr_profile=no) AC_MSG_RESULT([$perf_mgr_profile]) if test $perf_mgr = yes; then AC_DEFINE(ENABLE_OSM_PERF_MGR, 1, [Define as 1 if you want to enable the performance manager]) if test $perf_mgr_profile = yes; then AC_DEFINE(ENABLE_OSM_PERF_MGR_PROFILE, 1, [Define as 1 if you want to enable the performance manager profiling code]) fi fi # --- END OPENIB_OSM_PERF_MGR_SEL --- ]) dnl OPENIB_OSM_PERF_MGR_SEL dnl Check if they want the event plugin AC_DEFUN([OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL], [ # --- BEGIN OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL --- dnl enable the default-event-plugin AC_MSG_CHECKING([to enable default event plugin]) AC_ARG_ENABLE(default-event-plugin, [ --enable-default-event-plugin Enable a default event plugin "osmeventplugin" (default no)], [case $enableval in yes) default_event_plugin=yes ;; no) default_event_plugin=no ;; esac], default_event_plugin=no) AC_MSG_RESULT([$default_event_plugin]) if test $default_event_plugin = yes; then AC_DEFINE(ENABLE_OSM_DEFAULT_EVENT_PLUGIN, 1, [Define as 1 if you want to enable the event plugin]) DEFAULT_EVENT_PLUGIN=osmeventplugin else DEFAULT_EVENT_PLUGIN= fi AC_SUBST([DEFAULT_EVENT_PLUGIN]) # --- END OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL --- ]) dnl OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL opensm-3.3.20/config/compile0000755000205000001450000000717312361552573012654 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2005-05-14.22 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` # Create the lock directory. # Note: use `[/.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: opensm-3.3.20/config/config.guess0000755000205000001450000012206511312032604013573 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-06-17' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown ## for Red Hat Linux if test -f /etc/redhat-release ; then VENDOR=redhat ; else VENDOR= ; fi # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha*:OpenVMS:*:*) echo alpha-hp-vms exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit 0 ;; DRS?6000:UNIX_SV:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7 && exit 0 ;; esac ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c \ && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && exit 0 echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then # avoid double evaluation of $set_cc_for_build test -n "$CC_FOR_BUILD" || eval $set_cc_for_build if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; *:UNICOS/mp:*:*) echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*|*:GNU/FreeBSD:*:*) # Determine whether the default compiler uses glibc. eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #if __GLIBC__ >= 2 LIBC=gnu #else LIBC= #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:[34]*) echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' exit 0 ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips64 #undef mips64el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mips64el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips64 #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-${VENDOR:-unknown}-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-${VENDOR:-unknown}-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu exit 0 ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-${VENDOR:-unknown}-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit 0 ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) case `uname -p` in *86) UNAME_PROCESSOR=i686 ;; powerpc) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: opensm-3.3.20/config/config.sub0000755000205000001450000007305511312032604013242 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003 Free Software Foundation, Inc. timestamp='2003-06-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64vr | mips64vrel \ | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | msp430 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | s390 | s390x \ | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic4x | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64vr-* | mips64vrel-* \ | mips64orion-* | mips64orionel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | msp430-* \ | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | s390-* | s390x-* \ | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nv1) basic_machine=nv1-cray os=-unicosmp ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tic55x | c55x*) basic_machine=tic55x-unknown os=-coff ;; tic6x | c6x*) basic_machine=tic6x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: opensm-3.3.20/config/depcomp0000755000205000001450000004426712110765443012652 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free # Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: opensm-3.3.20/config/install-sh0000755000205000001450000003253712110765443013276 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2009-04-28.21; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # 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 # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false no_target_directory= usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call `install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then trap '(exit $?); exit' 1 2 13 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names starting with `-'. case $src in -*) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writeable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; -*) prefix='./';; *) prefix='';; esac eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: opensm-3.3.20/config/ltmain.sh0000755000205000001450000073306012726323063013115 00000000000000# Generated from ltmain.m4sh. # ltmain.sh (GNU libtool) 2.2.6b # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print informational messages (default) # --version print version information # -h, --help print short or long help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.2.6b # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=ltmain.sh PACKAGE=libtool VERSION=2.2.6b TIMESTAMP="" package_revision=1.3017 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # NLS nuisances: We save the old values to restore during execute mode. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done $lt_unset CDPATH : ${CP="cp -f"} : ${ECHO="echo"} : ${EGREP="/bin/grep -E"} : ${FGREP="/bin/grep -F"} : ${GREP="/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/bin/sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # Generated shell functions inserted here. # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: # In the unlikely event $progname began with a '-', it would play havoc with # func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result case $progname in -*) progname=./$progname ;; esac # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname${mode+: }$mode: $*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` done my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "X$my_tmpdir" | $Xsed } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "X$1" | $Xsed \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_version # Echo version message to standard output and exit. func_version () { $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $SED -n '/^# Usage:/,/# -h/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" $ECHO $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help # Echo long help message to standard output and exit. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" exit $? } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { func_error "missing argument for $1" exit_cmd=exit } exit_cmd=: # Check that we have a working $ECHO. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then # Yippee, $ECHO works! : else # Restart under the correct shell, and then maybe $ECHO will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # Parse options once, thoroughly. This comes as soon as possible in # the script to make things like `libtool --version' happen quickly. { # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Parse non-mode specific arguments: while test "$#" -gt 0; do opt="$1" shift case $opt in --config) func_config ;; --debug) preserve_args="$preserve_args $opt" func_echo "enabling shell trace mode" opt_debug='set -x' $opt_debug ;; -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break execute_dlfiles="$execute_dlfiles $1" shift ;; --dry-run | -n) opt_dry_run=: ;; --features) func_features ;; --finish) mode="finish" ;; --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break case $1 in # Valid mode arguments: clean) ;; compile) ;; execute) ;; finish) ;; install) ;; link) ;; relink) ;; uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac mode="$1" shift ;; --preserve-dup-deps) opt_duplicate_deps=: ;; --quiet|--silent) preserve_args="$preserve_args $opt" opt_silent=: ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false ;; --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break preserve_args="$preserve_args $opt $1" func_enable_tag "$1" # tagname is set here shift ;; # Separate optargs to long options: -dlopen=*|--mode=*|--tag=*) func_opt_split "$opt" set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} shift ;; -\?|-h) func_usage ;; --help) opt_help=: ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_duplicate_deps ;; esac # Having warned about all mis-specified options, bail out if # anything was wrong. $exit_cmd $EXIT_FAILURE } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } ## ----------- ## ## Main. ## ## ----------- ## $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi test -z "$mode" && func_fatal_error "error: you must specify a MODE." # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$mode' for more information." } # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_ltwrapper_scriptname_result="" if func_ltwrapper_executable_p "$1"; then func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" fi } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case "$@ " in " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi removelist="$removelist $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist removelist="$removelist $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir command="$command -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$mode'" ;; esac $ECHO $ECHO "Try \`$progname --help' for more information about other modes." exit $? } # Now that we've collected a possible --mode arg, show help if necessary $opt_help && func_mode_help # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $execute_dlfiles; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_quote_for_eval "$file" args="$args $func_quote_for_eval_result" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" $ECHO "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS $ECHO "X----------------------------------------------------------------------" | $Xsed $ECHO "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done $ECHO $ECHO "If you ever happen to want to link against installed libraries" $ECHO "in a given directory, LIBDIR, you must either use libtool, and" $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" $ECHO "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" $ECHO " during execution" fi if test -n "$runpath_var"; then $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" $ECHO " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $ECHO $ECHO "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" $ECHO "pages." ;; *) $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac $ECHO "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS } test "$mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $ECHO "X$nonopt" | $GREP shtool >/dev/null; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" } done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" fi $ECHO >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; " case $host in *cygwin* | *mingw* | *cegcc* ) $ECHO >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" lt_dlsym_const= ;; *osf5*) echo >> "$output_objdir/$my_dlsyms" "\ /* This system does not cope well with relocations in const data */" lt_dlsym_const= ;; *) lt_dlsym_const=const ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) symtab_cflags="$symtab_cflags $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper_part1 [arg=no] # # Emit the first part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part1 () { func_emit_wrapper_part1_arg1=no if test -n "$1" ; then func_emit_wrapper_part1_arg1=$1 fi $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then ECHO=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then # Yippee, \$ECHO works! : else # Restart under the correct shell, and then maybe \$ECHO will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $ECHO "\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done " } # end: func_emit_wrapper_part1 # func_emit_wrapper_part2 [arg=no] # # Emit the second part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part2 () { func_emit_wrapper_part2_arg1=no if test -n "$1" ; then func_emit_wrapper_part2_arg1=$1 fi $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # end: func_emit_wrapper_part2 # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=no if test -n "$1" ; then func_emit_wrapper_arg1=$1 fi # split this up so that func_emit_cwrapperexe_src # can call each part independently. func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_path_tmp1=`( cmd //c echo "$1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_tmp1=`cygpath -w "$1"` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result="" fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_to_host_pathlist_tmp2="$1" # Once set for this call, this variable should not be # reassigned. It is used in tha fallback case. func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e 's|^:*||' -e 's|:*$||'` case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" fi fi fi IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result" ; then func_error "Could not determine the host path(s) corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" ;; esac ;; esac fi } # end: func_to_host_pathlist # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include # define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include # define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif # endif #endif #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif #ifdef _MSC_VER # define S_IXUSR _S_IEXEC # define stat _stat # ifndef _INTPTR_T_DEFINED # define intptr_t int # endif #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifdef __CYGWIN__ # define FOPEN_WB "wb" #endif #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #undef LTWRAPPER_DEBUGPRINTF #if defined DEBUGWRAPPER # define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args static void ltwrapper_debugprintf (const char *fmt, ...) { va_list args; va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } #else # define LTWRAPPER_DEBUGPRINTF(args) #endif const char *program_name = NULL; void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_fatal (const char *message, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_opt_process_env_set (const char *arg); void lt_opt_process_env_prepend (const char *arg); void lt_opt_process_env_append (const char *arg); int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); static const char *script_text_part1 = EOF func_emit_wrapper_part1 yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ "/' -e 's/$/\\n"/' echo ";" cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", tmp_pathspec)); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { char *errstr = strerror (errno); lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal ("Could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } int lt_split_name_value (const char *arg, char** name, char** value) { const char *p; int len; if (!arg || !*arg) return 1; p = strchr (arg, (int)'='); if (!p) return 1; *value = xstrdup (++p); len = strlen (arg) - strlen (*value); *name = XMALLOC (char, len); strncpy (*name, arg, len-1); (*name)[len - 1] = '\0'; return 0; } void lt_opt_process_env_set (const char *arg) { char *name = NULL; char *value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); } lt_setenv (name, value); XFREE (name); XFREE (value); } void lt_opt_process_env_prepend (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); } new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_opt_process_env_append (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); } new_value = lt_extend_str (getenv (name), value, 1); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF } # end: func_emit_cwrapperexe_src # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) deplibs="$deplibs $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) weak_libs="$weak_libs $arg" prev= continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname '-L' '' "$arg" dir=$func_stripname_result if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" linker_flags="$linker_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" compiler_flags="$compiler_flags $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_duplicate_deps ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= case $lib in *.la) func_source "$lib" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" dir=$func_stripname_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $ECHO $ECHO "*** Warning: Trying to link with static lib archive $deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because the file extensions .$libext of this argument makes me believe" $ECHO "*** that it is just a static archive that I should not use here." else $ECHO $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) temp_rpath="$temp_rpath$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded notinst_deplibs="$notinst_deplibs $lib" need_relink=no ;; *) if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $ECHO if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $ECHO $ECHO "*** And there doesn't seem to be a static archive available" $ECHO "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $ECHO $ECHO "*** Warning: This system can not link to static lib archive $lib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $ECHO "*** But as you try to build a module library, libtool will still create " $ECHO "*** a static module, that should work as long as the dlopening application" $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) func_dirname "$deplib" "" "." dir="$func_dirname_result" # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else $ECHO $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" libobjs="$libobjs $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` done fi if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | $GREP . >/dev/null; then $ECHO if test "X$deplibs_check_method" = "Xnone"; then $ECHO "*** Warning: inter-library dependencies are not supported in this platform." else $ECHO "*** Warning: inter-library dependencies are not known to be supported." fi $ECHO "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $ECHO $ECHO "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" $ECHO "*** a static module, that should work as long as the dlopening" $ECHO "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $ECHO "*** The inter-library dependencies that have been dropped here will be" $ECHO "*** automatically added whenever a program is linked with this library" $ECHO "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $ECHO $ECHO "*** Since this library must not contain undefined symbols," $ECHO "*** because either the platform does not support them or" $ECHO "*** it was explicitly requested with -no-undefined," $ECHO "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" delfiles="$delfiles $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" func_len " $cmd" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then func_show_eval "$cmd" 'exit $?' skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" $ECHO 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done $ECHO ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do $ECHO "$obj" >> $output done delfiles="$delfiles $output" output=$firstobj\"$file_list_spec$output\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=$obj func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi delfiles="$delfiles $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *cegcc) # Disable wrappers for cegcc, we are cross compiling anyway. wrappers_required=no ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $ECHO for shipping. if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then oldobjs="$oldobjs $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles oldobjs="$oldobjs $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else $ECHO "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlfiles="$newdlfiles $libdir/$name" ;; *) newdlfiles="$newdlfiles $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlprefiles="$newdlprefiles $libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$mode" = link || test "$mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) RM="$RM $arg"; rmforce=yes ;; -*) RM="$RM $arg" ;; *) files="$files $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then objdir="$origobjdir" else objdir="$dir/$origobjdir" fi func_basename "$file" name="$func_basename_result" test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result rmfiles="$rmfiles $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$mode" = uninstall || test "$mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 opensm-3.3.20/config/missing0000755000205000001450000002623312110765443012665 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and \`g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; esac # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; tar*) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar*) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: opensm-3.3.20/config/ylwrap0000755000205000001450000001404312110765446012531 00000000000000#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, # 2007, 2009 Free Software Foundation, Inc. # # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case "$1" in '') echo "$0: No files given. Try \`$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input="$1" shift case "$input" in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input="`pwd`/$input" ;; esac pairlist= while test "$#" -ne 0; do if test "$1" = "--"; then shift break fi pairlist="$pairlist $1" shift done # The program to run. prog="$1" shift # Make any relative path in $prog absolute. case "$prog" in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog="`pwd`/$prog" ;; esac # FIXME: add hostname here for parallel makes that run commands on # other machines. But that might take us over the 14-char limit. dirname=ylwrap$$ trap "cd '`pwd`'; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 mkdir $dirname || exit 1 cd $dirname case $# in 0) "$prog" "$input" ;; *) "$prog" "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then set X $pairlist shift first=yes # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot="no" if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot="yes" fi # The directory holding the input. input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` # Quote $INPUT_DIR so we can use it in a regexp. # FIXME: really we should care about more than `.' and `\'. input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'` while test "$#" -ne 0; do from="$1" # Handle y_tab.c and y_tab.h output by DOS if test $y_tab_nodot = "yes"; then if test $from = "y.tab.c"; then from="y_tab.c" else if test $from = "y.tab.h"; then from="y_tab.h" fi fi fi if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend `../'. case "$2" in [\\/]* | ?:[\\/]*) target="$2";; *) target="../$2";; esac # We do not want to overwrite a header file if it hasn't # changed. This avoid useless recompilations. However the # parser itself (the first file) should always be updated, # because it is the destination of the .y.c rule in the # Makefile. Divert the output of all other files to a temporary # file so we can compare them to existing versions. if test $first = no; then realtarget="$target" target="tmp-`echo $target | sed s/.*[\\/]//g`" fi # Edit out `#line' or `#' directives. # # We don't want the resulting debug information to point at # an absolute srcdir; it is better for it to just mention the # .y file with no path. # # We want to use the real output file name, not yy.lex.c for # instance. # # We want the include guards to be adjusted too. FROM=`echo "$from" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` TARGET=`echo "$2" | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'` sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \ -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$? # Check whether header files must be updated. if test $first = no; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$2" is unchanged rm -f "$target" else echo updating "$2" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the first file. This # is a blatant hack to let us support using "yacc -d". If -d # is not specified, we don't want an error when the header # file is "missing". if test $first = yes; then ret=1 fi fi shift shift first=no done else ret=$? fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: opensm-3.3.20/doc/0000755000205000001450000000000012726324754010651 500000000000000opensm-3.3.20/doc/performance-manager-HOWTO.txt0000644000205000001450000001174612363333702016140 00000000000000OpenSM Performance manager HOWTO ================================ Introduction ============ OpenSM now includes a performance manager which collects port counters from the subnet and stores them internally in OpenSM. Some of the features of the performance manager are: 1) Collect port data and error counters per v1.2.1 spec and store in 64 bit internal counts. 2) Automatic reset of counters when they reach approximately 3/4 full. (While not guaranteeing that counts will not be missed, this does keep counts incrementing as best as possible given the current spec limitations.) 3) Basic warnings in the OpenSM log on "critical" errors like symbol errors. 4) Automatically detects "outside" resets of counters and adjusts to continue collecting data. 5) Can be run when OpenSM is in standby or inactive states in addition to master state. Known issues are: 1) Data counters will be lost on high data rate links. Sweeping the fabric fast enough for even a DDR link is not practical. 2) Default partition support only. Setup and Usage =============== Using the Performance Manager consists of 3 steps: 1) compiling in support for the perfmgr (Optionally: the console socket as well) 2) enabling the perfmgr and console in opensm.conf 3) retrieving data which has been collected. 3a) using console to "dump data" 3b) using a plugin module to store the data to your own "database" Step 1: Compile in support for the Performance Manager ------------------------------------------------------ At this time, it is really best to enable the console socket option as well. OpenSM can be run in an "interactive" mode. But with the console socket option turned on one can also make a connection to a running OpenSM. By default, only "loopback" is enabled with the console with socket being a compile time option. Regardless, please be aware of your network security configuration for as the commands presented in the console can affect the operation of your subnet. Step 2: Enable the perfmgr and console in opensm.conf ----------------------------------------------------- Turning the Performance Manager on is pretty easy, set the following options in the opensm.conf config file. (Default location is /usr/local/etc/opensm/opensm.conf) # Turn it all on perfmgr TRUE # redirection enable perfmgr_redir TRUE # sweep time in seconds perfmgr_sweep_time_s 180 # Max outstanding queries perfmgr_max_outstanding_queries 500 # Ignore CAs on sweep perfmgr_ignore_cas FALSE # Remove missing nodes from DB perfmgr_rm_nodes TRUE # Log error counters to opensm.log perfmgr_log_errors TRUE # Query PerfMgt Get(ClassPortInfo) for extended capabilities # Extended capabilities include 64 bit extended counters # and transmit wait support perfmgr_query_cpi TRUE # Log xmit_wait errors perfmgr_xmit_wait_log FALSE # If logging xmit_wait's; set threshold perfmgr_xmit_wait_threshold 65535 # Dump file to dump the events to event_db_dump_file /var/log/opensm_port_counters.log Also, enable the console socket and configure the port for it to listen to if desired. # console [off|local|loopback|socket] console socket # Telnet port for console (default 10000) console_port 10000 "local" is only useful if you run OpenSM in the foreground. Step 3: Retrieve data which has been collected ---------------------------------------------- Step 3a: Using console dump function ------------------------------------ The console command "perfmgr dump_counters" will dump counters to the file specified in the opensm.conf file. In the example above "/var/log/opensm_port_counters.log" Example output is below: "SW1 wopr ISR9024D (MLX4 FW)" 0x8f10400411f56 port 1 (Since Mon May 12 13:27:14 2008) symbol_err_cnt : 0 link_err_recover : 0 link_downed : 0 rcv_err : 0 rcv_rem_phys_err : 0 rcv_switch_relay_err : 2 xmit_discards : 0 xmit_constraint_err : 0 rcv_constraint_err : 0 link_integrity_err : 0 buf_overrun_err : 0 vl15_dropped : 0 xmit_data : 470435 rcv_data : 405956 xmit_pkts : 8954 rcv_pkts : 6900 unicast_xmit_pkts : 0 unicast_rcv_pkts : 0 multicast_xmit_pkts : 0 multicast_rcv_pkts : 0 Step 3b: Using a plugin module ------------------------------ If you want a more automated method of retrieving the data OpenSM provides a plugin interface to extend OpenSM. The header file is osm_event_plugin.h. The functions you register with this interface will be called when data is collected. You can then use that data as appropriate. An example plugin can be configured at compile time using the "--enable-default-event-plugin" option on the configure line. This plugin is very simple. It logs "events" received from the performance manager to a log file. I don't recommend using this directly but rather use it as a template to create your own plugin. opensm-3.3.20/doc/QoS_management_in_OpenSM.txt0000644000205000001450000005210512512763044016132 00000000000000 QoS Management in OpenSM ============================================================================== Table of contents ============================================================================== 1. Overview 2. Full QoS Policy File 3. Simplified QoS Policy Definition 4. Policy File Syntax Guidelines 5. Examples of Full Policy File 6. Simplified QoS Policy - Details and Examples 7. SL2VL Mapping and VL Arbitration ============================================================================== 1. Overview ============================================================================== When QoS in OpenSM is enabled (-Q or --qos), OpenSM looks for QoS Policy file. The default name of OpenSM QoS policy file is /usr/local/etc/opensm/qos-policy.conf. The default may be changed by using -Y or --qos_policy_file option with OpenSM. During fabric initialization and at every heavy sweep OpenSM parses the QoS policy file, applies its settings to the discovered fabric elements, and enforces the provided policy on client requests. The overall flow for such requests is: - The request is matched against the defined matching rules such that the QoS Level definition is found. - Given the QoS Level, path(s) search is performed with the given restrictions imposed by that level. There are two ways to define QoS policy: - Full policy, where the policy file syntax provides an administrator various ways to match PathRecord/MultiPathRecord (PR/MPR) request and enforce various QoS constraints on the requested PR/MPR - Simplified QoS policy definition, where an administrator would be able to match PR/MPR requests by various ULPs and applications running on top of these ULPs. While the full policy syntax is very flexible, in many cases the simplified policy definition would be sufficient. ============================================================================== 2. Full QoS Policy File ============================================================================== QoS policy file has the following sections: I) Port Groups (denoted by port-groups). This section defines zero or more port groups that can be referred later by matching rules (see below). Port group lists ports by: - Port GUID - Port name, which is a combination of NodeDescription and IB port number - PKey, which means that all the ports in the subnet that belong to partition with a given PKey belong to this port group - Partition name, which means that all the ports in the subnet that belong to partition with a given name belong to this port group - Node type, where possible node types are: CA, SWITCH, ROUTER, ALL, and SELF (SM's port). II) QoS Setup (denoted by qos-setup). This section describes how to set up SL2VL and VL Arbitration tables on various nodes in the fabric. However, this is not supported in OpenSM currently. SL2VL and VLArb tables should be configured in the OpenSM options file (default location - /usr/local/etc/opensm/opensm.conf). III) QoS Levels (denoted by qos-levels). Each QoS Level defines Service Level (SL) and a few optional fields: - MTU limit - Rate limit - PKey - Packet lifetime When path(s) search is performed, it is done with regards to restriction that these QoS Level parameters impose. One QoS level that is mandatory to define is a DEFAULT QoS level. It is applied to a PR/MPR query that does not match any existing match rule. Similar to any other QoS Level, it can also be explicitly referred by any match rule. IV) QoS Matching Rules (denoted by qos-match-rules). Each PathRecord/MultiPathRecord query that OpenSM receives is matched against the set of matching rules. Rules are scanned in order of appearance in the QoS policy file such as the first match takes precedence. Each rule has a name of QoS level that will be applied to the matching query. A default QoS level is applied to a query that did not match any rule. Queries can be matched by: - Source port group (whether a source port is a member of a specified group) - Destination port group (same as above, only for destination port) - PKey - QoS class - Service ID To match a certain matching rule, PR/MPR query has to match ALL the rule's criteria. However, not all the fields of the PR/MPR query have to appear in the matching rule. For instance, if the rule has a single criterion - Service ID, it will match any query that has this Service ID, disregarding rest of the query fields. However, if a certain query has only Service ID (which means that this is the only bit in the PR/MPR component mask that is on), it will not match any rule that has other matching criteria besides Service ID. ============================================================================== 3. Simplified QoS Policy Definition ============================================================================== Simplified QoS policy definition comprises of a single section denoted by qos-ulps. Similar to the full QoS policy, it has a list of match rules and their QoS Level, but in this case a match rule has only one criterion - its goal is to match a certain ULP (or a certain application on top of this ULP) PR/MPR request, and QoS Level has only one constraint - Service Level (SL). The simplified policy section may appear in the policy file in combine with the full policy, or as a stand-alone policy definition. See more details and list of match rule criteria below. ============================================================================== 4. Policy File Syntax Guidelines ============================================================================== - Empty lines are ignored. - Leading and trailing blanks, as well as empty lines, are ignored, so the indentation in the example is just for better readability. - Comments are started with the pound sign (#) and terminated by EOL. - Any keyword should be the first non-blank in the line, unless it's a comment. - Keywords that denote section/subsection start have matching closing keywords. - Having a QoS Level named "DEFAULT" is a must - it is applied to PR/MPR requests that didn't match any of the matching rules. - Any section/subsection of the policy file is optional. ============================================================================== 5. Examples of Full Policy File ============================================================================== As mentioned earlier, any section of the policy file is optional, and the only mandatory part of the policy file is a default QoS Level. Here's an example of the shortest policy file: qos-levels qos-level name: DEFAULT sl: 0 end-qos-level end-qos-levels Port groups section is missing because there are no match rules, which means that port groups are not referred anywhere, and there is no need defining them. And since this policy file doesn't have any matching rules, PR/MPR query won't match any rule, and OpenSM will enforce default QoS level. Essentially, the above example is equivalent to not having QoS policy file at all. The following example shows all the possible options and keywords in the policy file and their syntax: # # See the comments in the following example. # They explain different keywords and their meaning. # port-groups port-group # using port GUIDs name: Storage # "use" is just a description that is used for logging # Other than that, it is just a comment use: SRP Targets port-guid: 0x10000000000001, 0x10000000000005-0x1000000000FFFA port-guid: 0x1000000000FFFF end-port-group port-group name: Virtual Servers # The syntax of the port name is as follows: # "node_description/Pnum". # node_description is compared to the NodeDescription of the node, # and "Pnum" is a port number on that node. port-name: vs1 HCA-1/P1, vs2 HCA-1/P1 end-port-group # using partitions defined in the partition policy port-group name: Partitions partition: Part1 pkey: 0x1234 end-port-group # using node types: CA, ROUTER, SWITCH, SELF (for node that runs SM) # or ALL (for all the nodes in the subnet) port-group name: CAs and SM node-type: CA, SELF end-port-group end-port-groups qos-setup # This section of the policy file describes how to set up SL2VL and VL # Arbitration tables on various nodes in the fabric. # However, this is not supported in OpenSM currently - the section is # parsed and ignored. SL2VL and VLArb tables should be configured in the # OpenSM options file (by default - /usr/local/etc/opensm/opensm.conf). end-qos-setup qos-levels # Having a QoS Level named "DEFAULT" is a must - it is applied to # PR/MPR requests that didn't match any of the matching rules. qos-level name: DEFAULT use: default QoS Level sl: 0 end-qos-level # the whole set: SL, MTU-Limit, Rate-Limit, PKey, Packet Lifetime qos-level name: WholeSet sl: 1 mtu-limit: 4 rate-limit: 5 pkey: 0x1234 packet-life: 8 end-qos-level end-qos-levels # Match rules are scanned in order of their apperance in the policy file. # First matched rule takes precedence. qos-match-rules # matching by single criteria: QoS class qos-match-rule use: by QoS class qos-class: 7-9,11 # Name of qos-level to apply to the matching PR/MPR qos-level-name: WholeSet end-qos-match-rule # show matching by destination group and service id qos-match-rule use: Storage targets destination: Storage service-id: 0x10000000000001, 0x10000000000008-0x10000000000FFF qos-level-name: WholeSet end-qos-match-rule qos-match-rule source: Storage use: match by source group only qos-level-name: DEFAULT end-qos-match-rule qos-match-rule use: match by all parameters qos-class: 7-9,11 source: Virtual Servers destination: Storage service-id: 0x0000000000010000-0x000000000001FFFF pkey: 0x0F00-0x0FFF qos-level-name: WholeSet end-qos-match-rule end-qos-match-rules ============================================================================== 6. Simplified QoS Policy - Details and Examples ============================================================================== Simplified QoS policy match rules are tailored for matching ULPs (or some application on top of a ULP) PR/MPR requests. This section has a list of per-ULP (or per-application) match rules and the SL that should be enforced on the matched PR/MPR query. Match rules include: - Default match rule that is applied to PR/MPR query that didn't match any of the other match rules - SDP - SDP application with a specific target TCP/IP port range - SRP with a specific target IB port GUID - RDS - iSER - iSER application with a specific target TCP/IP port range - IPoIB with a default PKey - IPoIB with a specific PKey - any ULP/application with a specific Service ID in the PR/MPR query - any ULP/application with a specific PKey in the PR/MPR query - any ULP/application with a specific target IB port GUID in the PR/MPR query - any ULP/application with a specific source IB port GUID in the PR/MPR query - any ULP/application with a specific source or target IB port GUID in the PR/MPR query Since any section of the policy file is optional, as long as basic rules of the file are kept (such as no referring to nonexisting port group, having default QoS Level, etc), the simplified policy section (qos-ulps) can serve as a complete QoS policy file. The shortest policy file in this case would be as follows: qos-ulps default : 0 #default SL end-qos-ulps It is equivalent to the previous example of the shortest policy file, and it is also equivalent to not having policy file at all. Below is an example of simplified QoS policy with all the possible keywords: qos-ulps default : 0 # default SL sdp, port-num 30000 : 0 # SL for application running on top # of SDP when a destination # TCP/IPport is 30000 sdp, port-num 10000-20000 : 0 sdp : 1 # default SL for any other # application running on top of SDP rds : 2 # SL for RDS traffic iser, port-num 900 : 0 # SL for iSER with a specific target # port iser : 3 # default SL for iSER ipoib, pkey 0x0001 : 0 # SL for IPoIB on partition with # pkey 0x0001 ipoib : 4 # default IPoIB partition, # pkey=0x7FFF any, service-id 0x6234 : 6 # match any PR/MPR query with a # specific Service ID any, pkey 0x0ABC : 6 # match any PR/MPR query with a # specific PKey srp, target-port-guid 0x1234 : 5 # SRP when SRP Target is located on # a specified IB port GUID any, target-port-guid 0x0ABC-0xFFFFF : 6 # match any PR/MPR query with # a specific target port GUID any, source-port-guid 0x5678 : 7 # match any PR/MPR query with # a specific source port # GUID any, source-target-port-guid 0x9abcd : 8 # match any PR/MPR query with # a specific source or target port # GUID end-qos-ulps Similar to the full policy definition, matching of PR/MPR queries is done in order of appearance in the QoS policy file such as the first match takes precedence, except for the "default" rule, which is applied only if the query didn't match any other rule. All other sections of the QoS policy file take precedence over the qos-ulps section. That is, if a policy file has both qos-match-rules and qos-ulps sections, then any query is matched first against the rules in the qos-match-rules section, and only if there was no match, the query is matched against the rules in qos-ulps section. Note that some of these match rules may overlap, so in order to use the simplified QoS definition effectively, it is important to understand how each of the ULPs is matched: 6.1 IPoIB IPoIB query is matched by PKey. Default PKey for IPoIB partition is 0x7fff, so the following three match rules are equivalent: ipoib : ipoib, pkey 0x7fff : any, pkey 0x7fff : 6.2 SDP SDP PR query is matched by Service ID. The Service-ID for SDP is 0x000000000001PPPP, where PPPP are 4 hex digits holding the remote TCP/IP Port Number to connect to. The following two match rules are equivalent: sdp : any, service-id 0x0000000000010000-0x000000000001ffff : 6.3 RDS Similar to SDP, RDS PR query is matched by Service ID. The Service ID for RDS is 0x000000000106PPPP, where PPPP are 4 hex digits holding the remote TCP/IP Port Number to connect to. Default port number for RDS is 0x48CA, which makes a default Service-ID 0x00000000010648CA. The following two match rules are equivalent: rds : any, service-id 0x00000000010648CA : 6.4 iSER Similar to RDS, iSER query is matched by Service ID, where the the Service ID is also 0x000000000106PPPP. Default port number for iSER is 0x0CBC, which makes a default Service-ID 0x0000000001060CBC. The following two match rules are equivalent: iser : any, service-id 0x0000000001060CBC : 6.5 SRP Service ID for SRP varies from storage vendor to vendor, thus SRP query is matched by the target IB port GUID. The following two match rules are equivalent: srp, target-port-guid 0x1234 : any, target-port-guid 0x1234 : Note that any of the above ULPs might contain target port GUID in the PR query, so in order for these queries not to be recognized by the QoS manager as SRP, the SRP match rule (or any match rule that refers to the target port guid only) should be placed at the end of the qos-ulps match rules. 6.6 MPI SL for MPI is manually configured by MPI admin. OpenSM is not forcing any SL on the MPI traffic, and that's why it is the only ULP that did not appear in the qos-ulps section. ============================================================================== 7. SL2VL Mapping and VL Arbitration ============================================================================== OpenSM cached options file has a set of QoS related configuration parameters, that are used to configure SL2VL mapping and VL arbitration on IB ports. These parameters are: - Max VLs: the maximum number of VLs that will be on the subnet. - High limit: the limit of High Priority component of VL Arbitration table (IBA 7.6.9). - VLArb low table: Low priority VL Arbitration table (IBA 7.6.9) template. - VLArb high table: High priority VL Arbitration table (IBA 7.6.9) template. - SL2VL: SL2VL Mapping table (IBA 7.6.6) template. It is a list of VLs corresponding to SLs 0-15 (Note that VL15 used here means drop this SL). There are separate QoS configuration parameters sets for various target types: CAs, routers, switch external ports, and switch's enhanced port 0. The names of such parameters are prefixed by "qos__" string. Here is a full list of the currently supported sets: qos_ca_ - QoS configuration parameters set for CAs. qos_rtr_ - parameters set for routers. qos_sw0_ - parameters set for switches' port 0. qos_swe_ - parameters set for switches' external ports. Here's the example of typical default values for CAs and switches' external ports (hard-coded in OpenSM initialization): qos_ca_max_vls 15 qos_ca_high_limit 0 qos_ca_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0 qos_ca_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4 qos_ca_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 qos_swe_max_vls 15 qos_swe_high_limit 0 qos_swe_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0 qos_swe_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4 qos_swe_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 VL arbitration tables (both high and low) are lists of VL/Weight pairs. Each list entry contains a VL number (values from 0-14), and a weighting value (values 0-255), indicating the number of 64 byte units (credits) which may be transmitted from that VL when its turn in the arbitration occurs. A weight of 0 indicates that this entry should be skipped. If a list entry is programmed for VL15 or for a VL that is not supported or is not currently configured by the port, the port may either skip that entry or send from any supported VL for that entry. Note, that the same VLs may be listed multiple times in the High or Low priority arbitration tables, and, further, it can be listed in both tables. The limit of high-priority VLArb table (qos__high_limit) indicates the number of high-priority packets that can be transmitted without an opportunity to send a low-priority packet. Specifically, the number of bytes that can be sent is high_limit times 4K bytes. A high_limit value of 255 indicates that the byte limit is unbounded. Note: if the 255 value is used, the low priority VLs may be starved. A value of 0 indicates that only a single packet from the high-priority table may be sent before an opportunity is given to the low-priority table. Keep in mind that ports usually transmit packets of size equal to MTU. For instance, for 4KB MTU a single packet will require 64 credits, so in order to achieve effective VL arbitration for packets of 4KB MTU, the weighting values for each VL should be multiples of 64. Below is an example of SL2VL and VL Arbitration configuration on subnet: qos_ca_max_vls 15 qos_ca_high_limit 6 qos_ca_vlarb_high 0:4 qos_ca_vlarb_low 0:0,1:64,2:128,3:192,4:0,5:64,6:64,7:64 qos_ca_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 qos_swe_max_vls 15 qos_swe_high_limit 6 qos_swe_vlarb_high 0:4 qos_swe_vlarb_low 0:0,1:64,2:128,3:192,4:0,5:64,6:64,7:64 qos_swe_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 In this example, there are 8 VLs configured on subnet: VL0 to VL7. VL0 is defined as a high priority VL, and it is limited to 6 x 4KB = 24KB in a single transmission burst. Such configuration would suit a VL that needs low latency and uses a small MTU when transmitting packets. Rest of the VLs are defined as low priority VLs with different weights, while VL4 is effectively turned off. opensm-3.3.20/doc/partition-config.txt0000644000205000001450000001572612654644603014617 00000000000000OpenSM Partition configuration =============================== The default name of OpenSM partitions configuration file is '$(OPENSM_CONFIG_DIR)/partitions.conf' (where $(OPENSM_CONFIG_DIR) is set at configure time and defaults to ${sysconfdir}/opensm). The default may be changed at run time by using the --Pconfig (-P) option with OpenSM. The default partition will be created by OpenSM unconditionally even when partition configuration file does not exist or cannot be accessed. The default partition has P_Key value 0x7fff. OpenSM's port will always have full membership in default partition. All other end ports will have full membership if the partition configuration file is not found or cannot be accessed, or limited membership if the file exists and can be accessed but there is no rule for the Default partition. Effectively, this amounts to the same as if one of the following rules below appear in the partition configuration file: In the case of no rule for the Default partition: Default=0x7fff : ALL=limited, SELF=full ; In the case of no partition configuration file or file cannot be accessed: Default=0x7fff : ALL=full ; File Format =========== Comments: Line content followed after \'#\' character is comment and ignored by parser. General file format: :[]; Partition Definition: [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited|both] PartitionName - string, will be used with logging. When omitted, empty string will be used. PKey - P_Key value for this partition. Only low 15 bits will be used. When omitted will be autogenerated. indx0 - indicates that this pkey should be inserted in block 0 index 0. ipoib_bc_flags - used to indicate/specify IPoIB capability of this partition. defmember=full|limited|both - specifies default membership for port guid list. Default is limited. ipoib_bc_flags: ipoib_flag|[mgroup_flag]* ipoib_flag: ipoib - indicates that this partition may be used for IPoIB, as a result the IPoIB broadcast group will be created with the mgroup_flag flags given, if any. Partition Properties: [|]* | Port list: [,] Port Specifier: [=[full|limited|both]] PortGUID - GUID of partition member EndPort. Hexadecimal numbers should start from 0x, decimal numbers are accepted too. full or - indicates full and/or limited membership for limited or this port. When omitted (or unrecognized) both limited membership is assumed. Both indicates both full and limited membership for this port. MCast Group: mgid=gid[,mgroup_flag]* - gid specified is verified to be a Multicast address. IP groups are verified to match the rate and mtu of the broadcast group. The P_Key bits of the mgid for IP groups are verified to either match the P_Key specified in by "Partition Definition" or if they are 0x0000 the P_Key will be copied into those bits. mgroup_flag: rate= - specifies rate for this MC group (default is 3 (10GBps)) mtu= - specifies MTU for this MC group (default is 4 (2048)) sl= - specifies SL for this MC group (default is 0) scope= - specifies scope for this MC group (default is 2 (link local)). Multiple scope settings are permitted for a partition. NOTE: This overwrites the scope nibble of the specified mgid. Furthermore specifying multiple scope settings will result in multiple MC groups being created. Q_Key= - specifies the Q_Key for this MC group (default: 0x0b1b for IP groups, 0 for other groups) WARNING: changing this for the broadcast group may break IPoIB on client nodes!!! TClass= - specifies tclass for this MC group (default is 0) FlowLabel= - specifies FlowLabel for this MC group (default is 0) Note that values for rate, mtu, and scope, for both partitions and multicast groups, should be specified as defined in the IBTA specification (for example, mtu=4 for 2048). There are several useful keywords for PortGUID definition: - 'ALL' means all end ports in this subnet. - 'ALL_CAS' means all Channel Adapter end ports in this subnet. - 'ALL_SWITCHES' means all Switch end ports in this subnet. - 'ALL_ROUTERS' means all Router end ports in this subnet. - 'SELF' means subnet manager's port. Empty list means no ports in this partition. Notes: ----- White space is permitted between delimiters ('=', ',',':',';'). PartitionName does not need to be unique, PKey does need to be unique. If PKey is repeated then those partition configurations will be merged and first PartitionName will be used (see also next note). It is possible to split partition configuration in more than one definition, but then PKey should be explicitly specified (otherwise different PKey values will be generated for those definitions). Examples: -------- Default=0x7fff : ALL, SELF=full ; Default=0x7fff : ALL, ALL_SWITCHES=full, SELF=full ; NewPartition , ipoib : 0x123456=full, 0x3456789034=limi, 0x2134af2306 ; YetAnotherOne = 0x300 : SELF=full ; YetAnotherOne = 0x300 : ALL=limited ; ShareIO = 0x80 , defmember=full : 0x123451, 0x123452; # 0x123453, 0x123454 will be limited ShareIO = 0x80 : 0x123453, 0x123454, 0x123455=full; # 0x123456, 0x123457 will be limited ShareIO = 0x80 , defmember=limited : 0x123456, 0x123457, 0x123458=full; ShareIO = 0x80 , defmember=full : 0x123459, 0x12345a; ShareIO = 0x80 , defmember=full : 0x12345b, 0x12345c=limited, 0x12345d; # multicast groups added to default Default=0x7fff,ipoib: mgid=ff12:401b::0707,sl=1 # random IPv4 group mgid=ff12:601b::16 # MLDv2-capable routers mgid=ff12:401b::16 # IGMP mgid=ff12:601b::2 # All routers mgid=ff12::1,sl=1,Q_Key=0xDEADBEEF,rate=3,mtu=2 # random group ALL=full; Note: ---- The following rule is equivalent to how OpenSM used to run prior to the partition manager: Default=0x7fff,ipoib:ALL=full; opensm-3.3.20/doc/opensm-sriov.txt0000644000205000001450000001407412104655724013773 00000000000000OpenSM SRIOV (Alias GUID) Support 12/9/11 Overview In order to support virtualized environments, alias GUID support is added to OpenSM. This support allows an SA client to add and remove additional port GUIDs based on SubAdmSet/SubAdmDelete of GUIDInfoRecord. A set with a GUID of 0 in a valid GUIDInfoRecord index as indicated by the component mask indicates that the additional GUID is to be SM assigned. The OpenIB OUI (0x001405), along with a configured byte and a pseudorandom number is currently used for this algorithm (which may be changed in the future). Most SA queries are updated to handle alias GUIDs as part of any GID specified inside the query. These include SA path record, multipath record, multicast record, and service record. There are only a few SA queries (InformInfoRecord, InformInfo) that are not currently updated for alias GUID support. In terms of the IBA spec, alias GUIDs are termed additional port GUIDs. IBA 1.2.1 Volume 1 Changes for Alias GUID Support The following are MgtWG WG APPROVED spec changes to IBA 1.2.1 volume 1 relative to this support: RefID 4704 15.2.5.18 GUIDInfoRecord p. 932 line 14 Table 213 GUIDInfoRecord An entity that wishes to add or remove additional port GUIDs can do so using the SubnAdmSet() and SubnAdmDelete() methods with the GUIDInfoRecord attribute. This causes the SM to set the updated GUIDs in the specified port via the SM GUIDInfo attribute. SubnAdmSet() method is used to add additional port GUIDs. SubnAdmDelete() method is used to remove previously added additional port GUIDs. o15-0.x.y: If SA supports additional port GUIDs, then both SubAdmSet(GUIDInfoRecord) and SubnAdmDelete(GUIDInfoRecord) are supported. o15-0.x.y: If SA supports additional port GUIDs, the component mask for SubAdmSet(GUIDInfoRecord) and SubnAdmDelete(GUIDInfoRecord) is required to include both LID and block number. If the component mask does not include both of these, SA shall return an error status of ERR_REQ_INSUFFICIENT_COMPONENTS in its response to the corresponding method. o15-0.x.y: If SA supports additional port GUIDs, for a SubAdmSet(GUIDInfoRecord), the component mask indicates which GUID indices are to be set. A GUID can either be added or replaced. A GUID of 0 indicates that the GUID for this index is to be assigned by the SM. o15-0.x.y: If SA supports additional port GUIDs, for a SubAdmDelete(GUIDInfoRecord), the component mask indicates which GUID indices are to be removed. o15-0.x.y: If SA supports additional port GUIDs, the SA shall return an error status of ERR_REQ_INVALID to any attempt to set or delete block number 0 index 0. RefID 4705 p.899 line 26 15.2.4 Table 188 SA-Specific Optional Capabilities IsAdditionalGUIDsSupported | CM2 | 5 | If this value is 1, SA shall support the ability to add and remove additional port GUIDs via SubAdmSet/SubnAdmDelete(GUIDInfoRecord) as described in RefID 4706 p.904 line 21 15.2.5.1 Table 192 Subnet Administration Attribute / Method Map b: SubAdmSet and SubAdmDelete of GUIDInfoRecord are supported if SA:ClassPortInfo.CapabilityMask2 indicates IsAdditionalGUIDsSupported. RefID 4714 Clarify GUID 0 in SA Set GUIDInfoRecord response p.932 line 14 15.2.18 o15-0.x.y: If SA supports additional port GUIDs, for a SubAdmSet(GUIDInfoRecord), the component mask indicates which GUID indices are to be set. A GUID can either be added or replaced. A GUID of 0 indicates that the GUID for this index is to be assigned by the SM. o15-0.x.y: If SA supports additional port GUIDs, for a SubAdmSet(GUIDInfoRecord), the component mask indicates which GUID indices are to be set. A GUID can either be added or replaced. In the request, a GUID of 0 indicates that the GUID for this index is to be assigned by the SM. In the response, a GUID of 0 indicates that the GUID requested for this index was not accepted by the SA. RefID 4776 SM GUIDInfo initialization GUIDInfo Description The requirements for setting additional GUIDs are beyond the scope of the specification. OpenSM SRIOV Configuration Some new options were added for SRIOV configuration of OpenSM. 1. Allow both pkeys -W or --allow_both_pkeys on the command line or allow_both_pkeys TRUE in the options file. Default is false. allow_both_pkeys indicates whether both full and limited membership on the same partition is allowed or not. In order to support allow_both_pkeys, the partition file syntax is extended with "both" flag (in addition to "full" and "limited"). defmember=full|limited|both or [PortGUID[=full|=limited|=both]] 2. SM assigned GUID byte sm_assigned_guid in the options file. Default is 0. An SM assigned GUID byte is added as a configuration option where an alias GUID is formed from OpenFabrics OUI followed by 40 bits xy 00 ab cd ef where xy is the SM assigned guid byte and ab cd ef is an SM autogenerated 24 bits. The SM assigned GUID byte should be configured as subnet unique. Also, the algorithm to obtain a "unique" SM assigned GUID is changing from being based on a static monatomically incrementing counter for the SM autogenerated part (like SA MCMemberRecord SM assigned MGIDs). The number of retries to find an unused GUID is currently hardcoded at 1000. Note that it is not a current requirement to maintain SM assigned GUIDs across OpenSM failover. Note also that on reregistration, a host may reregister the previously SM assigned GUID. Operational Notes Duplicated alias GUIDs are detected against alias and physical GUIDs and result in rejection of such registrations. When a port is dropped, any alias GUID registrations are removed. These are reregistered by client reregistration mechanism. The exception to this is service registrations as these are not currently reregistered by the ULPs/applications that use them. Futures 1. An alias GUID enforcement feature to which physical ports are allowed to request which alias GUIDs. opensm-3.3.20/doc/current-routing.txt0000644000205000001450000012312512664020703014471 00000000000000Current OpenSM Routing 11/14/12 OpenSM offers nine routing engines: 1. Min Hop Algorithm - based on the minimum hops to each node where the path length is optimized. 2. UPDN Unicast routing algorithm - also based on the minimum hops to each node, but it is constrained to ranking rules. This algorithm should be chosen if the subnet is not a pure Fat Tree, and deadlock may occur due to a loop in the subnet. 3. DNUP Unicast routing algorithm - similar to UPDN but allows routing in fabrics which have some CA nodes attached closer to the roots than some switch nodes. 4. Fat-tree Unicast routing algorithm - this algorithm optimizes routing of fat-trees for congestion-free "shift" communication pattern. It should be chosen if a subnet is a symmetrical fat-tree. Similar to UPDN routing, Fat-tree routing is credit-loop-free. 5. LASH unicast routing algorithm - uses Infiniband virtual layers (SL) to provide deadlock-free shortest-path routing while also distributing the paths between layers. LASH is an alternative deadlock-free topology-agnostic routing algorithm to the non-minimal UPDN algorithm avoiding the use of a potentially congested root node. 6. DOR Unicast routing algorithm - based on the Min Hop algorithm, but avoids port equalization except for redundant links between the same two switches. This provides deadlock free routes for hypercubes when the fabric is cabled as a hypercube and for meshes when cabled as a mesh (see details below). 7. Torus-2QoS unicast routing algorithm - a DOR-based routing algorithm specialized for 2D/3D torus topologies. Torus-2QoS provides deadlock-free routing while supporting two quality of service (QoS) levels. In addition it is able to route around multiple failed fabric links or a single failed fabric switch without introducing deadlocks, and without changing path SL values granted before the failure. 8. DFSSSP unicast routing algorithm - a deadlock-free single-source- shortest-path routing, which uses the SSSP algorithm (see algorithm 9.) as the base to optimize link utilization and uses Infiniband virtual lanes (SL) to provide deadlock-freedom. 9. SSSP unicast routing algorithm - a single-source-shortest-path routing algorithm, which globally balances the number of routes per link to optimize link utilization. This routing algorithm has no restrictions in terms of the underlying topology. OpenSM provides an optional unicast routing cache (enabled by -A or --ucast_cache options). When enabled, unicast routing cache prevents routing recalculation (which is a heavy task in a large cluster) when there was no topology change detected during the heavy sweep, or when the topology change does not require new routing calculation, e.g. when one or more CAs/RTRs/leaf switches going down, or one or more of these nodes coming back after being down. A very common case that is handled by the unicast routing cache is host reboot, which otherwise would cause two full routing recalculations: one when the host goes down, and the other when the host comes back online. OpenSM also supports a file method which can load routes from a table. See modular-routing.txt for more information on this. The basic routing algorithm is comprised of two stages: 1. MinHop matrix calculation How many hops are required to get from each port to each LID ? The algorithm to fill these tables is different if you run standard (min hop) or Up/Down. For standard routing, a "relaxation" algorithm is used to propagate min hop from every destination LID through neighbor switches For Up/Down routing, a BFS from every target is used. The BFS tracks link direction (up or down) and avoid steps that will perform up after a down step was used. 2. Once MinHop matrices exist, each switch is visited and for each target LID, a decision is made as to what port should be used to get to that LID. This step is common to standard and Up/Down routing. Each port has a counter counting the number of target LIDs going through it. When there are multiple alternative ports with same MinHop to a LID, the one with less previously assigned LIDs is selected. If LMC > 0, more checks are added: Within each group of LIDs assigned to same target port, a. use only ports which have same MinHop b. first prefer the ones that go to different systemImageGuid (then the previous LID of the same LMC group) c. if none - prefer those which go through another NodeGuid d. fall back to the number of paths method (if all go to same node). Effect of Topology Changes OpenSM will preserve existing routing in any case where there is no change in the fabric switches unless the -r (--reassign_lids) option is specified. -r --reassign_lids This option causes OpenSM to reassign LIDs to all end nodes. Specifying -r on a running subnet may disrupt subnet traffic. Without -r, OpenSM attempts to preserve existing LID assignments resolving multiple use of same LID. If a link is added or removed, OpenSM does not recalculate the routes that do not have to change. A route has to change if the port is no longer UP or no longer the MinHop. When routing changes are performed, the same algorithm for balancing the routes is invoked. In the case of using the file based routing, any topology changes are currently ignored The 'file' routing engine just loads the LFTs from the file specified, with no reaction to real topology. Obviously, this will not be able to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent switches will be skipped. Multicast is not affected by 'file' routing engine (this uses min hop tables). Min Hop Algorithm ----------------- The Min Hop algorithm is invoked by default if no routing algorithm is specified. It can also be invoked by specifying '-R minhop'. The Min Hop algorithm is divided into two stages: computation of min-hop tables on every switch and LFT output port assignment. Link subscription is also equalized with the ability to override based on port GUID. The latter is supplied by: -i --ignore_guids This option provides the means to define a set of ports (by guids) that will be ignored by the link load equalization algorithm. LMC awareness routes based on (remote) system or switch basis. UPDN Routing Algorithm ---------------------- Purpose of UPDN Algorithm The UPDN algorithm is designed to prevent deadlocks from occurring in loops of the subnet. A loop-deadlock is a situation in which it is no longer possible to send data between any two hosts connected through the loop. As such, the UPDN routing algorithm should be used if the subnet is not a pure Fat Tree, and one of its loops may experience a deadlock (due, for example, to high pressure). The UPDN algorithm is based on the following main stages: 1. Auto-detect root nodes - based on the CA hop length from any switch in the subnet, a statistical histogram is built for each switch (hop num vs number of occurrences). If the histogram reflects a specific column (higher than others) for a certain node, then it is marked as a root node. Since the algorithm is statistical, it may not find any root nodes. The list of the root nodes found by this auto-detect stage is used by the ranking process stage. Note 1: The user can override the node list manually. Note 2: If this stage cannot find any root nodes, and the user did not specify a guid list file, OpenSM defaults back to the Min Hop routing algorithm. 2. Ranking process - All root switch nodes (found in stage 1) are assigned a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the subnet are ranked incrementally. This ranking aids in the process of enforcing rules that ensure loop-free paths. 3. Min Hop Table setting - after ranking is done, a BFS algorithm is run from each (CA or switch) node in the subnet. During the BFS process, the FDB table of each switch node traversed by BFS is updated, in reference to the starting node, based on the ranking rules and guid values. At the end of the process, the updated FDB tables ensure loop-free paths through the subnet. Note: Up/Down routing does not allow LID routing communication between switches that are located inside spine "switch systems". The reason is that there is no way to allow a LID route between them that does not break the Up/Down rule. One ramification of this is that you cannot run SM on switches other than the leaf switches of the fabric. UPDN Algorithm Usage Activation through OpenSM Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm. Use `-a ' for adding an UPDN guid file that contains the root nodes for ranking. If the `-a' option is not used, OpenSM uses its auto-detect root nodes algorithm. Notes on the guid list file: 1. A valid guid file specifies one guid in each line. Lines with an invalid format will be discarded. 2. The user should specify the root switch guids. However, it is also possible to specify CA guids; OpenSM will use the guid of the switch (if it exists) that connects the CA to the subnet as a root node. To learn more about deadlock-free routing, see the article "Deadlock Free Message Routing in Multiprocessor Interconnection Networks" by William J Dally and Charles L Seitz (1985). DNUP Routing Algorithm ---------------------- Purpose: The DNUP algorithm is designed to serve a similar purpose to UPDN. However it is intended to work in network topologies which are unsuited to UPDN due to nodes being connected closer to the roots than some of the switches. An example would be a fabric which contains nodes and uplinks connected to the same switch. The operation of DNUP is the same as UPDN with the exception of the ranking process. In DNUP all switch nodes are ranked based solely on their distance from CA Nodes, all switch nodes directly connected to at least one CA are assigned a value of 1 all other switch nodes are assigned a value of one more than the minimum rank of all neighbor switch nodes. Fat-tree Routing Algorithm -------------------------- Purpose: The fat-tree algorithm optimizes routing for "shift" communication pattern. It should be chosen if a subnet is a symmetrical or almost symmetrical fat-tree of various types. It supports not just K-ary-N-Trees, by handling for non-constant K, cases where not all leafs (CAs) are present, any Constant Bisectional Ratio (CBB) ratio. As in UPDN, fat-tree also prevents credit-loop-deadlocks. If the root guid file is not provided ('-a' or '--root_guid_file' options), the topology has to be pure fat-tree that complies with the following rules: - Tree rank should be between two and eight (inclusively) - Switches of the same rank should have the same number of UP-going port groups*, unless they are root switches, in which case the shouldn't have UP-going ports at all. - Switches of the same rank should have the same number of DOWN-going port groups, unless they are leaf switches. - Switches of the same rank should have the same number of ports in each UP-going port group. - Switches of the same rank should have the same number of ports in each DOWN-going port group. - All the CAs have to be at the same tree level (rank). If the root guid file is provided, the topology doesn't have to be pure fat-tree, and it should only comply with the following rules: - Tree rank should be between two and eight (inclusively) - All the Compute Nodes** have to be at the same tree level (rank). Note that non-compute node CAs are allowed here to be at different tree ranks. * ports that are connected to the same remote switch are referenced as 'port group'. ** list of compute nodes (CNs) can be specified by '-u' or '--cn_guid_file' OpenSM options. Note that although fat-tree algorithm supports trees with non-integer CBB ratio, the routing will not be as balanced as in case of integer CBB ratio. In addition to this, although the algorithm allows leaf switches to have any number of CAs, the closer the tree is to be fully populated, the more effective the "shift" communication pattern will be. In general, even if the root list is provided, the closer the topology to a pure and symmetrical fat-tree, the more optimal the routing will be. The algorithm also dumps compute node ordering file (opensm-ftree-ca-order.dump) in the same directory where the OpenSM log resides. This ordering file provides the CN order that may be used to create efficient communication pattern, that will match the routing tables. Routing between non-CN nodes The use of the cn_guid_file option allows non-CN nodes to be located on different levels in the fat tree. In such case, it is not guaranteed that the Fat Tree algorithm will route between two non-CN nodes. In the scheme below, N1, N2 and N3 are non-CN nodes. Although all the CN have routes to and from them, there will not necessarily be a route between N1,N2 and N3. Such routes would require to use at least one of the Switch the wrong way around (In fact, go out of one of the top Switch through a downgoing port while we are supposed to go up). Spine1 Spine2 Spine 3 / \ / | \ / \ / \ / | \ / \ N1 Switch N2 Switch N3 /|\ /|\ / | \ / | \ Going down to compute nodes To solve this problem, a list of non-CN nodes can be specified by \'-G\' or \'--io_guid_file\' option. Theses nodes will be allowed to use switches the wrong way around a specific number of times (specified by \'-H\' or \'--max_reverse_hops\'. With the proper max_reverse_hops and io_guid_file values, you can ensure full connectivity in the Fat Tree. In the scheme above, with a max_reverse_hop of 1, routes will be instanciated between N1<->N2 and N2<->N3. With a max_reverse_hops value of 2, N1,N2 and N3 will all have routes between them. Please note that using max_reverse_hops creates routes that use the switch in a counter-stream way. This option should never be used to connect nodes with high bandwidth traffic between them ! It should only be used to allow connectivity for HA purposes or similar. Also having routes the other way around can in theory cause credit loops. Use these options with extreme care ! Usage: Activation through OpenSM Use '-R ftree' option to activate the fat-tree algorithm. Note: LMC > 0 is not supported by fat-tree routing. If this is specified, the default routing algorithm is invoked instead. LASH Routing Algorithm ---------------------- LASH is an acronym for LAyered SHortest Path Routing. It is a deterministic shortest path routing algorithm that enables topology agnostic deadlock-free routing within communication networks. When computing the routing function, LASH analyzes the network topology for the shortest-path routes between all pairs of sources / destinations and groups these paths into virtual layers in such a way as to avoid deadlock. Note LASH analyzes routes and ensures deadlock freedom between switch pairs. The link from HCA between and switch does not need virtual layers as deadlock will not arise between switch and HCA. In more detail, the algorithm works as follows: 1) LASH determines the shortest-path between all pairs of source / destination switches. Note, LASH ensures the same SL is used for all SRC/DST - DST/SRC pairs and there is no guarantee that the return path for a given DST/SRC will be the reverse of the route SRC/DST. 2) LASH then begins an SL assignment process where a route is assigned to a layer (SL) if the addition of that route does not cause deadlock within that layer. This is achieved by maintaining and analysing a channel dependency graph for each layer. Once the potential addition of a path could lead to deadlock, LASH opens a new layer and continues the process. 3) Once this stage has been completed, it is highly likely that the first layers processed will contain more paths than the latter ones. To better balance the use of layers, LASH moves paths from one layer to another so that the number of paths in each layer averages out. Note, the implementation of LASH in opensm attempts to use as few layers as possible. This number can be less than the number of actual layers available. In general LASH is a very flexible algorithm. It can, for example, reduce to Dimension Order Routing in certain topologies, it is topology agnostic and fares well in the face of faults. It has been shown that for both regular and irregular topologies, LASH outperforms Up/Down. The reason for this is that LASH distributes the traffic more evenly through a network, avoiding the bottleneck issues related to a root node and always routes shortest-path. The algorithm was developed by Simula Research Laboratory. To learn more about LASH and the flexibility behind it, the requirement for layers, performance comparisons to other algorithms, see the following articles: "Layered Routing in Irregular Networks", Lysne et al, IEEE Transactions on Parallel and Distributed Systems, VOL.16, No12, December 2005. "Routing for the ASI Fabric Manager", Solheim et al. IEEE Communications Magazine, Vol.44, No.7, July 2006. "Layered Shortest Path (LASH) Routing in Irregular System Area Networks", Skeie et al. IEEE Computer Society Communication Architecture for Clusters 2002. Use '-R lash -Q ' option to activate the LASH algorithm. Note: QoS support has to be turned on in order that SL/VL mappings are used. Note: LMC > 0 is not supported by the LASH routing. If this is specified, the default routing algorithm is invoked instead. For open regular cartesian meshes the DOR algorithm is the ideal routing algorithm. For toroidal meshes on the other hand there are routing loops that can cause deadlocks. LASH can be used to route these cases. The performance of LASH can be improved by preconditioning the mesh in cases where there are multiple links connecting switches and also in cases where the switches are not cabled consistently. An option exists for LASH to do this. To invoke this use '-R lash -Q --do_mesh_analysis'. This will add an additional phase that analyses the mesh to try to determine the dimension and size of a mesh. If it determines that the mesh looks like an open or closed cartesian mesh it reorders the ports in dimension order before the rest of the LASH algorithm runs. DOR Routing Algorithm --------------------- The Dimension Order Routing algorithm is based on the Min Hop algorithm and so uses shortest paths. Instead of spreading traffic out across different paths with the same shortest distance, it chooses among the available shortest paths based on an ordering of dimensions. Each port must be consistently cabled to represent a hypercube dimension or a mesh dimension. Paths are grown from a destination back to a source using the lowest dimension (port) of available paths at each step. This provides the ordering necessary to avoid deadlock. When there are multiple links between any two switches, they still represent only one dimension and traffic is balanced across them unless port equalization is turned off. In the case of hypercubes, the same port must be used throughout the fabric to represent the hypercube dimension and match on both ends of the cable. In the case of meshes, the dimension should consistently use the same pair of ports, one port on one end of the cable, and the other port on the other end, continuing along the mesh dimension. Use '-R dor' option to activate the DOR algorithm. Torus-2QoS Routing Algorithm ---------------------------- Torus-2QoS is a routing algorithm designed for large-scale 2D/3D torus fabrics. The torus-2QoS routing engine can provide the following functionality on a 2D/3D torus: - routing that is free of credit loops - two levels of QoS, assuming switches support 8 data VLs - ability to route around a single failed switch, and/or multiple failed links, without - introducing credit loops - changing path SL values - very short run times, with good scaling properties as fabric size increases Unicast Routing: Torus-2QoS is a DOR-based algorithm that avoids deadlocks that would otherwise occur in a torus using the concept of a dateline for each torus dimension. It encodes into a path SL which datelines the path crosses as follows: sl = 0; for (d = 0; d < torus_dimensions; d++) /* path_crosses_dateline(d) returns 0 or 1 */ sl |= path_crosses_dateline(d) << d; For a 3D torus, that leaves one SL bit free, which torus-2QoS uses to implement two QoS levels. Torus-2QoS also makes use of the output port dependence of switch SL2VL maps to encode into one VL bit the information encoded in three SL bits. It computes in which torus coordinate direction each inter-switch link "points", and writes SL2VL maps for such ports as follows: for (sl = 0; sl < 16; sl ++) /* cdir(port) reports which torus coordinate direction a switch port * "points" in, and returns 0, 1, or 2 */ sl2vl(iport,oport,sl) = 0x1 & (sl >> cdir(oport)); Thus, on a pristine 3D torus, i.e., in the absence of failed fabric switches, torus-2QoS consumes 8 SL values (SL bits 0-2) and 2 VL values (VL bit 0) per QoS level to provide deadlock-free routing on a 3D torus. Torus-2QoS routes around link failure by "taking the long way around" any 1D ring interrupted by a link failure. For example, consider the 2D 6x5 torus below, where switches are denoted by [+a-zA-Z]: | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----D----+----+-- | | | | | | 2 --+----+----I----r----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 For a pristine fabric the path from S to D would be S-n-T-r-D. In the event that either link S-n or n-T has failed, torus-2QoS would use the path S-m-p-o-T-r-D. Note that it can do this without changing the path SL value; once the 1D ring m-S-n-T-o-p-m has been broken by failure, path segments using it cannot contribute to deadlock, and the x-direction dateline (between, say, x=5 and x=0) can be ignored for path segments on that ring. One result of this is that torus-2QoS can route around many simultaneous link failures, as long as no 1D ring is broken into disjoint segments. For example, if links n-T and T-o have both failed, that ring has been broken into two disjoint segments, T and o-p-m-S-n. Torus-2QoS checks for such issues, reports if they are found, and refuses to route such fabrics. Note that in the case where there are multiple parallel links between a pair of switches, torus-2QoS will allocate routes across such links in a round- robin fashion, based on ports at the path destination switch that are active and not used for inter-switch links. Should a link that is one of several such parallel links fail, routes are redistributed across the remaining links. When the last of such a set of parallel links fails, traffic is rerouted as described above. Handling a failed switch under DOR requires introducing into a path at least one turn that would be otherwise "illegal", i.e. not allowed by DOR rules. Torus-2QoS will introduce such a turn as close as possible to the failed switch in order to route around it. In the above example, suppose switch T has failed, and consider the path from S to D. Torus-2QoS will produce the path S-n-I-r-D, rather than the S-n-T-r-D path for a pristine torus, by introducing an early turn at n. Normal DOR rules will cause traffic arriving at switch I to be forwarded to switch r; for traffic arriving from I due to the "early" turn at n, this will generate an "illegal" turn at I. Torus-2QoS will also use the input port dependence of SL2VL maps to set VL bit 1 (which would be otherwise unused) for y-x, z-x, and z-y turns, i.e., those turns that are illegal under DOR. This causes the first hop after any such turn to use a separate set of VL values, and prevents deadlock in the presence of a single failed switch. For any given path, only the hops after a turn that is illegal under DOR can contribute to a credit loop that leads to deadlock. So in the example above with failed switch T, the location of the illegal turn at I in the path from S to D requires that any credit loop caused by that turn must encircle the failed switch at T. Thus the second and later hops after the illegal turn at I (i.e., hop r-D) cannot contribute to a credit loop because they cannot be used to construct a loop encircling T. The hop I-r uses a separate VL, so it cannot contribute to a credit loop encircling T. Extending this argument shows that in addition to being capable of routing around a single switch failure without introducing deadlock, torus-2QoS can also route around multiple failed switches on the condition they are adjacent in the last dimension routed by DOR. For example, consider the following case on a 6x6 2D torus: | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----D----+----+-- | | | | | | 3 --+----+----I----u----+----+-- | | | | | | 2 --+----+----q----R----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 Suppose switches T and R have failed, and consider the path from S to D. Torus-2QoS will generate the path S-n-q-I-u-D, with an illegal turn at switch I, and with hop I-u using a VL with bit 1 set. As a further example, consider a case that torus-2QoS cannot route without deadlock: two failed switches adjacent in a dimension that is not the last dimension routed by DOR; here the failed switches are O and T: | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----+----D----+-- | | | | | | 2 --+----+----I----q----r----+-- | | | | | | 1 --m----S----n----O----T----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 In a pristine fabric, torus-2QoS would generate the path from S to D as S-n-O-T-r-D. With failed switches O and T, torus-2QoS will generate the path S-n-I-q-r-D, with illegal turn at switch I, and with hop I-q using a VL with bit 1 set. In contrast to the earlier examples, the second hop after the illegal turn, q-r, can be used to construct a credit loop encircling the failed switches. Multicast Routing: Since torus-2QoS uses all four available SL bits, and the three data VL bits that are typically available in current switches, there is no way to use SL/VL values to separate multicast traffic from unicast traffic. Thus, torus-2QoS must generate multicast routing such that credit loops cannot arise from a combination of multicast and unicast path segments. It turns out that it is possible to construct spanning trees for multicast routing that have that property. For the 2D 6x5 torus example above, here is the full-fabric spanning tree that torus-2QoS will construct, where "x" is the root switch and each "+" is a non-root switch: 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 +----+----+----x----+----+ | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 For multicast traffic routed from root to tip, every turn in the above spanning tree is a legal DOR turn. For traffic routed from tip to root, and some traffic routed through the root, turns are not legal DOR turns. However, to construct a credit loop, the union of multicast routing on this spanning tree with DOR unicast routing can only provide 3 of the 4 turns needed for the loop. In addition, if none of the above spanning tree branches crosses a dateline used for unicast credit loop avoidance on a torus, and if multicast traffic is confined to SL 0 or SL 8 (recall that torus-2QoS uses SL bit 3 to differentiate QoS level), then multicast traffic also cannot contribute to the "ring" credit loops that are otherwise possible in a torus. Torus-2QoS uses these ideas to create a master spanning tree. Every multicast group spanning tree will be constructed as a subset of the master tree, with the same root as the master tree. Such multicast group spanning trees will in general not be optimal for groups which are a subset of the full fabric. However, this compromise must be made to enable support for two QoS levels on a torus while preventing credit loops. In the presence of link or switch failures that result in a fabric for which torus-2QoS can generate credit-loop-free unicast routes, it is also possible to generate a master spanning tree for multicast that retains the required properties. For example, consider that same 2D 6x5 torus, with the link from (2,2) to (3,2) failed. Torus-2QoS will generate the following master spanning tree: 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 --+----+----+ x----+----+-- | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 Two things are notable about this master spanning tree. First, assuming the x dateline was between x=5 and x=0, this spanning tree has a branch that crosses the dateline. However, just as for unicast, crossing a dateline on a 1D ring (here, the ring for y=2) that is broken by a failure cannot contribute to a torus credit loop. Second, this spanning tree is no longer optimal even for multicast groups that encompass the entire fabric. That, unfortunately, is a compromise that must be made to retain the other desirable properties of torus-2QoS routing. In the event that a single switch fails, torus-2QoS will generate a master spanning tree that has no "extra" turns by appropriately selecting a root switch. In the 2D 6x5 torus example, assume now that the switch at (3,2), i.e. the root for a pristine fabric, fails. Torus-2QoS will generate the following master spanning tree for that case: | 4 + + + + + + | | | | | | 3 + + + + + + | | | | | 2 + + + + + | | | | | 1 +----+----x----+----+----+ | | | | | | y=0 + + + + + + | x=0 1 2 3 4 5 Assuming the y dateline was between y=4 and y=0, this spanning tree has a branch that crosses a dateline. However, again this cannot contribute to credit loops as it occurs on a 1D ring (the ring for x=3) that is broken by a failure, as in the above example. Torus Topology Discovery: The algorithm used by torus-2QoS to construct the torus topology from the undirected graph representing the fabric requires that the radix of each dimension be configured via torus-2QoS.conf. It also requires that the torus topology be "seeded"; for a 3D torus this requires configuring four switches that define the three coordinate directions of the torus. Given this starting information, the algorithm is to examine the cube formed by the eight switch locations bounded by the corners (x,y,z) and (x+1,y+1,z+1). Based on switches already placed into the torus topology at some of these locations, the algorithm examines 4-loops of interswitch links to find the one that is consistent with a face of the cube of switch locations, and adds its swiches to the discovered topology in the correct locations. Because the algorithm is based on examining the topology of 4-loops of links, a torus with one or more radix-4 dimensions requires extra initial seed configuration. See torus-2QoS.conf(5) for details. Torus-2QoS will detect and report when it has insufficient configuration for a torus with radix-4 dimensions. In the event the torus is significantly degraded, i.e., there are many missing switches or links, it may happen that torus-2QoS is unable to place into the torus some switches and/or links that were discovered in the fabric, and will generate a warning in that case. A similar condition occurs if torus-2QoS is misconfigured, i.e., the radix of a torus dimension as configured does not match the radix of that torus dimension as wired, and many switches/links in the fabric will not be placed into the torus. Quality Of Service Configuration: OpenSM will not program switchs and channel adapters with SL2VL maps or VL arbitration configuration unless it is invoked with -Q. Since torus-2QoS depends on such functionality for correct operation, always invoke OpenSM with -Q when torus-2QoS is in the list of routing engines. Any quality of service configuration method supported by OpenSM will work with torus-2QoS, subject to the following limitations and considerations. For all routing engines supported by OpenSM except torus-2QoS, there is a one-to-one correspondence between QoS level and SL. Torus-2QoS can only support two quality of service levels, so only the high-order bit of any SL value used for unicast QoS configuration will be honored by torus-2QoS. For multicast QoS configuration, only SL values 0 and 8 should be used with torus-2QoS. Since SL to VL map configuration must be under the complete control of torus-2QoS, any configuration via qos_sl2vl, qos_swe_sl2vl, etc., must and will be ignored, and a warning will be generated. For inter-switch links, Torus-2QoS uses VL values 0-3 to implement one of its supported QoS levels, and VL values 4-7 to implement the other. For endport links (CA, router, switch management port), Torus-2QoS uses VL value 0 for one of its supported QoS levels and VL value 1 to implement the other. Hard-to-diagnose application issues may arise if traffic is not delivered fairly across each of these two VL ranges. For inter-switch links, Torus-2QoS will detect and warn if VL arbitration is configured unfairly across VLs in the range 0-3, and also in the range 4-7. Note that the default OpenSM VL arbitration configuration does not meet this constraint, so all torus-2QoS users should configure VL arbitration via qos_ca_vlarb_high, qos_swe_vlarb_high, qos_ca_vlarb_low, qos_swe_vlarb_low, etc. Note that torus-2QoS maps SL values to VL values differently for inter-switch and endport links. This is why qos_vlarb_high and qos_vlarb_low should not be used, as using them may result in VL arbitration for a QoS level being different across inter-switch links vs. across endport links. Operational Considerations: Any routing algorithm for a torus IB fabric must employ path SL values to avoid credit loops. As a result, all applications run over such fabrics must perform a path record query to obtain the correct path SL for connection setup. Applications that use rdma_cm for connection setup will automatically meet this requirement. If a change in fabric topology causes changes in path SL values required to route without credit loops, in general all applications would need to repath to avoid message deadlock. Since torus-2QoS has the ability to reroute after a single switch failure without changing path SL values, repathing by running applications is not required when the fabric is routed with torus-2QoS. Torus-2QoS can provide unchanging path SL values in the presence of subnet manager failover provided that all OpenSM instances have the same idea of dateline location. See torus-2QoS.conf(5) for details. Torus-2QoS will detect configurations of failed switches and links that prevent routing that is free of credit loops, and will log warnings and refuse to route. If "no_fallback" was configured in the list of OpenSM routing engines, then no other routing engine will attempt to route the fabric. In that case all paths that do not transit the failed components will continue to work, and the subset of paths that are still operational will continue to remain free of credit loops. OpenSM will continue to attempt to route the fabric after every sweep interval, and after any change (such as a link up) in the fabric topology. When the fabric components are repaired, full functionality will be restored. In the event OpenSM was configured to allow some other engine to route the fabric if torus-2QoS fails, then credit loops and message deadlock are likely if torus-2QoS had previously routed the fabric successfully. Even if the other engine is capable of routing a torus without credit loops, applications that built connections with path SL values granted under torus-2QoS will likely experience message deadlock under routing generated by a different engine, unless they repath. To verify that a torus fabric is routed free of credit loops, use ibdmchk to analyze data collected via ibdiagnet -vlr. DFSSSP and SSSP Routing Algorithm --------------------------------- The (Deadlock-Free) Single-Source-Shortest-Path routing algorithm is designed to optimize link utilization thru global balancing of routes, while supporting arbitrary topologies. The DFSSSP routing algorithm uses Infiniband virtual lanes (SL) to provide deadlock-freedom. The DFSSSP algorithm consists of five major steps: 1) It discovers the subnet and models the subnet as a directed multigraph in which each node represents a node of the physical network and each edge represents one direction of the full-duplex links used to connect the nodes. 2) A loop, which iterates over all CA and switches of the subnet, will perform three steps to generate the linear forwarding tables for each switch: 2.1) use Dijkstra's algorithm to find the shortest path from all nodes to the current selected destination; 2.2) update the egde weights in the graph, i.e. add the number of routes, which use a link to reach the destination, to the link/edge; 2.3) update the LFT of each switch with the outgoing port which was used in the current step to route the traffic to the destination node. 3) After the number of available virtual lanes or layers in the subnet is detected and a channel dependency graph is initialized for each layer, the algorithm will put each possible route of the subnet into the first layer. 4) A loop iterates over all channel dependency graphs (CDG) and performs the following substeps: 4.1) search for a cycle in the current CDG; 4.2) when a cycle is found, i.e. a possible deadlock is present, one edge is selected and all routes, which induced this egde, are moved to the "next higher" virtual layer (CDG[i+1]); 4.3) the cycle search is continued until all cycles are broken and routes are moved "up". 5) When the number of needed layers does not exceeds the number of available SL/VL to remove all cycles in all CDGs, the rounting is deadlock-free and an relation table is generated, which contains the assignment of routes from source to destination to a SL Note on SSSP: This algorithm does not perform the steps 3)-5) and can not be considered to be deadlock-free for all topologies. But on the one hand, you can choose this algorithm for really large networks (5,000+ CAs and deadlock-free by design) to reduce the runtime of the algorithm. On the other hand, you might use the SSSP routing algorithm as an alternative, when all deadlock-free routing algorithms fail to route the network for whatever reason. In the last case, SSSP was designed to deliver an equal or higher bandwidth due to better congestion avoidance than the Min Hop routing algorithm. Notes for usage: a) running DFSSSP: '-R dfsssp -Q' a.1) QoS has to be configured to equally spread the load on the available SL or virtual lanes a.2) applications must perform a path record query to get path SL for each route, which the application will use to transmite packages b) running SSSP: '-R sssp' c) both algorithms support LMC > 0 Hints for separate optimization of compute and I/O traffic: Having more nodes (I/O and compute) connected to a switch than incoming links can result in a 'bad' routing of the I/O traffic as long as (DF)SSSP routing is not aware of the dedicated I/O nodes, i.e., in the following network configuration CN1-CN3 might send all I/O traffic via Link2 to IO1,IO2: CN1 Link1 IO1 \ /----\ / CN2 -- Switch1 Switch2 -- CN4 / \----/ \ CN3 Link2 IO2 To prevent this from happening (DF)SSSP can use both the compute node guid file and the I/O guid file specified by the '-u' or '--cn_guid_file' and '-G' or '--io_guid_file' options (similar to the Fat-Tree routing). This ensures that traffic towards compute nodes and I/O nodes is balanced separately and therefore distributed as much as possible across the available links. Port GUIDs, as listed by ibstat, must be specified (not Node GUIDs). The priority for the optimization is as follows: compute nodes -> I/O nodes -> other nodes Possible use case szenarios: a) neither '-u' nor '-G' are specified: all nodes a treated as 'other nodes' and therefore balanced equally; b) '-G' is specified: traffic towards I/O nodes will be balanced optimally; c) the system has three node types, such as login/admin, compute and I/O, but the balancing focus should be I/O, then one has to use '-u' and '-G' with I/O guids listed in cn_guid_file and compute node guids listed in io_guid_file; d) ... For more information about the algorithms, i.e. balancing the routes and moving the routes to different virtual layers, and about comparison with other routing algorithms, please refer to the following articles: 1. J. Domke, T. Hoefler and W. Nagel: Deadlock-Free Oblivious Routing for Arbitrary Topologies, In Proceedings of the 25th IEEE International Parallel & Distributed Processing Symposium (IPDPS 2011) 2. T. Hoefler, T. Schneider and A. Lumsdaine: Optimized Routing for Large-Scale InfiniBand Networks, In 17th Annual IEEE Symposium on High Performance Interconnects (HOTI 2009) opensm-3.3.20/doc/opensm_release_notes-3.3.txt0000644000205000001450000030711412726312262016041 00000000000000 OpenSM Release Notes 3.3 ============================= Version: OpenSM 3.3.x Repo: git://git.openfabrics.org/~halr/opensm.git Date: June 2016 1 Overview ---------- This document describes the contents of the OpenSM 3.3 release. OpenSM is an InfiniBand compliant Subnet Manager and Administration, and runs on top of OpenIB. The OpenSM version for this release is opensm-3.3.20. This document includes the following sections: 1 This Overview section (describing new features and software dependencies) 2 Known Issues And Limitations 3 Unsupported IB compliance statements 4 Bug Fixes 5 Main Verification Flows 6 Qualified Software Stacks and Devices 1.1 Major New Features * Mesh Analysis for LASH routing algorithm. The performance of LASH can be improved by preconditioning the mesh in cases where there are multiple links connecting switches and also in cases where the switches are not cabled consistently. Activated with --do_mesh_analysis command line and config file option. * Reloadable OpenSM configuration (preliminary implemented) This is possible now to reload OpenSM configuration parameters on the fly without restarting. * Routing paths sorted balancing (for UpDown and MinHops) This sorts the port order in which routing paths balancing is performed by OpenSM. Helps to improve performance dramatically (40-50%) for most popular application communication patterns. To overwrite this behavior use --guid_routing_order_file command line option. * Weighted Lid Matrices calculation (for UpDown, MinHop and DOR). This low level routing fine-tuning feature provides the means to define a weighting factor per port for customizing the least weight hops for the routing. Custom weights are provided using file specified with '--hop_weights_file' command line option. * I/O nodes connectivity (for FatTree). This provides possibility to define the set of I/O nodes for the Fat-Tree routing algorithm. I/O nodes are non-CN nodes allowed to use up to N (specified using --max_reverse_hops) switches the wrong way around to improve connectivity. I/O nodes list is provided using file and --io_guid_file command line option. * MGID to MLID compression - infrastructure for many MGIDs to single MLID compression. This becomes helpful when number of multicast groups exceeds subnet's MLID routing capability (normally 1024 groups). In such cases many multicast groups (MGID) can be routed using same MLID value. * Torus-2QoS unicast routing algorithm - a DOR-based routing algorithm specialized for 2D/3D torus topologies. Torus-2QoS provides deadlock-free routing while supporting two quality of service (QoS) levels. In addition it is able to route around multiple failed fabric links or a single failed fabric switch without introducing deadlocks, and without changing path SL values granted before the failure. * DNUP Unicast routing algorithm - similar to UPDN but allows routing in fabrics which have some CA nodes attached closer to the roots than some switch nodes. * SSSP Unicast routing algorithm - SSSP unicast routing algorithm - a single-source-shortest-path routing algorithm, which globally balances the number of routes per link to optimize link utilization. This routing algorithm has no restrictions in terms of the underlying topology. * DFSSSP unicast routing algorithm - a deadlock-free single-source- shortest-path routing, which uses the SSSP algorithm as the base to optimize link utilization and uses Infiniband virtual lanes (SL) to provide deadlock- freedom. * SRIOV (Alias GUID) Support - In order to support virtualized environments, alias GUID support is added to OpenSM. This support allows an SA client to add and remove additional port GUIDs based on SubAdmSet/SubAdmDelete of GUIDInfoRecord. * Extended speed support This provides support for FDR and EDR speeds. * Congestion control support (experimental) * Many code improvements, optimizations and cleanups. * Windows support (early stage). 1.2 Minor New Features: fbe5107 osm_subnet.c: Add support for Switch-IB2 in is_mlnx_ext_port_info_supported 6eb8b96 ftree: Additional ftree indexing algorithm c1f7ffd Support configuration for index 0 in pkey table 1b73efd osm_sa_mcmember_record.c: Conditionalize multicast join parameter validation on new mcgroup_join_validation option 4cd7ec3 osm_sa_mcmember_record.c: Validate IPoIB non broadcast group parameters on group creation fd754d2 Support another new MLNX OUI 66301d8 osm_subnet.c: Add more supported device IDs 948e2b1 Add separate dispatcher for SA set and delete requests 672de65 perfmgr: Add xmit_wait to event plugin error counters data structure d86e7e3 perfmgr: Add xmit_wait support 7e6bdef opensm/man/opensm.8.in: Add section for MKey support aebe678 opensm: Add support for multicast service records 5509234 opensm/scripts/sldd.sh: Update to support guid2mkey/neighbors 2ae1477 opensm: Ensure sweep interval/mkey lease are sensibly set cefe79b opensm: Check for valid mkey protection level in config file 8fa0d2c opensm: Add neighboring link cache file 5088d08 opensm: Log errors on SubnGet timeouts 9eed9c6 opensm: Add support for setting mkey protection levels 5c4157d opensm: Add locking where necessary around osm_req_* 2f74f34 opensm: Allow recovery of subnets with misset mkeys e5dc557 opensm: Add guid2mkey cache file support 3659b37 opensm/osm_sa_class_port_info.c: Indicate support for PortInfo CapMask2 matching in SA ClassPortInfo:CapabilityMask2 8016d3b opensm/osm_base.h: Add some SA ClassPortInfo CapabilityMask2 bits 1a31c44 opensm/osm_perfmgr.c: Use non conflicting error codes in log messages 03a75d0 opensm/osm_sa_path_record.c: Restore osm_get_path_params functionality a9340cf opensm: Support (null) being specified for per_module_logging_file option 00375aa opensm/osm_perfmgr.c: Eliminate compile warning 7868c98 opensm: Remove unused per_module_logging option 49c460b Call drop manager before checking for other Master SM in the fabric c0604f3 Increase p_port->discovery_count only when received PortInfo for port 0 of the switch 24b30d2 opensm/osm_node_info_rcv.c: Handle non-compliant SMA gracefully a4f2689 opensm/osm_vendor_ibumad: Add management class into match criteria 4be6375 opensm/osm_sa*.c: Log requester port GUID at DEBUG level 4cca51d opensm/osm_sa_mcmember_record.c: Log requester port GUID at DEBUG level 15b3eae opensm/osm_sa_path_record.c: Log requester port GUID at DEBUG level 0b580ca opensm/osm_sa_path_record.c: Add debug logging to pr_match_mgrp_attributes ed4b7fb opensm/osm_sa_mcmember_record.c: In mcmr_rcv_join_mgrp, add MGID to log message 872dae4 opensm/osm_sa_mcmember_record.c: Dump MCMemberRecord in mcmr_query_mgrp 71f2ce7 Sending SL2VL and VLARB SET MADs in distributed manner f07bcc1 opensm/osm_subnet.c: Cosmetic formatting change c823a5b opensm/osm_link_mgr.c: Set PortInfo:PortState to LinkDown when remote port isn't accessible ab88df6 Add support to reread configuration file when stacked in rediscovery loop. 67c9bae opensm: Move per_mod_log_tbl array from subn to log structure 2cbd9f5 opensm/cl_atomic_osd.h: Cosmetic formatting change cd63dec opensm/osm_helper.c: Add CapabilityMask2 to notice dump for trap 144 9205812 opensm/ib_types.h: Add CapabilityMask2 to notice for trap 144 25de706 opensm/osm_sa_path_record.c: Add missing end-of-line in the log message 3551530 opensm/osm_trap_rcv.c: Remove vestigial comment 067d217 opensm/osm_inform.c: Make log message format consistent for error messages 759b82a opensm/osm_trap_rcv.c: Add better logging for traps 257 and 258 b806657 opensm/osm_sa_mad_ctrl.c: Eliminate commented out code line a851693 opensm/perfmgr: add logging of error counters 52fa659 opensm/console: add perfmgr "print_errors" (pe) console command. a832ce2 opensm/console: Add human readable output for perfmgr data counters 77a1756 opensm/console: add abreviations for perfmgr commands aca9a07 opensm/console; add port option to perfmgr print_counters 00628cc opensm/console: add "print all" to print_counters console command f5de9b5 opensm: perfmgr mark inactive nodes in perfmgr db ff06340 opensm: perfmgr delete "inactive" nodes from the DB 059d8f4 opensm/console: protect against 0 entered for the perfmgr sweep_time cc86607 opensm/perfmgr: Add config option to ignore Channel Adapters. 91f0c00 opensm/osm_node_info_rcv.c: In ni_rcv_process_existing_ca_or_router, handle error c930a23 opensm/osm_subnet.c: Indicate lmc and lmc_esp0 are not changeable "on the fly" 7825e67 opensm/libopensm.map: Removed unimplemented routine 7de7b04 opensm/main.c: Handle daemon mode with guid specified as 0 more gracefully 9478fbf opensm/osm_subnet.c: Support MLNX ExtendedPortInfo for ConnectIB device f8fc334 opensm/osm_node_info_rec.c: Also handle non compliant SMA in ni_rcv_process_existing b4a481d opensm: Eliminate unneeded field in DR path structure 01bc8c9 opensm/osm_state_mgr.c: Force subn->need_update when coming out of STANDBY 276be8b opensm: Dump info functions update for per module logging 64b512a opensm/osm_vendor_ibumad.c: Make binding log message clearer e70c8c1 opensm: Add enum for FILE_ID for per module logging 2a2db8c opensm: Add per module logging support e21b106 opensm: Cosmetic changes 3ddb2e3 opensm: Add partition manager configuration doc to docs 9586649 opensm/opensm_release_notes-3.3.txt: Update Unsupported IB Compliance Statements 826b5c4 opensm/osm_ucast_dfsssp.c: Use osm_log_is_active b2cad9d opensm/complib/cl_fleximap.h: Cosmetic changes 322a310 opensm/osm_ucast_ftree.c: Add a couple of asserts e3a946d opensm: Add FDR10 support 6cea3df opensm/osm_sa_portinfo_record.c: Add SA PortInfoRecord support for CapabilityMask2 matching 9ac7eeb opensm: Add infrastructure support for CapabilityMask2 field in PortInfo 8bc7c30 opensm: make loopback console compile on by default. 566b462 opensm/ib_types.h: Update SA PortInfoRecord component masks 480de4a opensm: Use forward extensible and safer way to compare mkey_lmc field in PortInfo attribute 22ca966 opensm: enable perfmgr build by default 4250c59 opensm: perfmgr only run sweep timer when enabled 1810672 Support scatter ports dd21107 Support port shifting 1c2a298 OpenSM torus routing order list b92d21f opensm: Create all directories in database path on Windows 83b6752 opensm/osm_subnet.c: In osm_subn_destroy, delete service records 0fc8124 opensm: Add OSM_VENDOR_ID_OPENIB support c0d8b56 opensm/osm_sa_node_record.c: In nr_rcv_create_nr, only set some variables when needed 9acaba0 opensm/osm_helper.c: Add some missing fields to osm_dump_portinfo_record 8a43aea Allow comma in plugin names parsing cdf227c opensm: Proper mfttop initialization when starting/restarting cde0c0d opensm: Convert remaining helper routines for GID printing format bc5743c opensm: Add support for MaxCreditHint and LinkRoundTripLatency to osm_dump_port_info 6cd34ab opensm: Add Dell to known vendor list 003d6bd opensm: Add more info for traps 144 and 256-259 in osm_dump_notice 5b0c5de opensm/osm_ucat_ftree.c Enhance min hops counters usage 0715b92 ib_types.h: Add ib_switch_info_get_state_opt_sl2vlmapping routine 2ddba79 opensm: Remove some __ and __osm_ prefixes ea0691f opensm/iba/ib_types.h: Add PortXmit/RcvDataSL PerfMgt attributes 9c79be5 ib_types.h: Adding BKEY violation trap (259) c608ea6 opensm: Add and utilize ib_gid_is_notzero routine b639e64 opensm: Handle trap repress on trap 144 generation b034205 Add pkey table support to osm_get_all_port_attr 876605b opensm/ib_types.h: Add attribute ID for PortCountersExtended aae3bbc opensm: PortInfo requests for discovered switches 0147b09 opensm/osm_lid_mgr: use single array for used_lids a9225b0 opensm/Makefile.am: remove osm_build_id.h junk file generation 8e3a57d opensm/osm_console.c: Add list of SMs to status command 3d664b9 opensm/osm_console.c : Added dump_portguid function to console to generate a list of port guids matching one or more regexps 85b35bc opensm/osm_helper.c: print port number as decimal 8674cb7 opensm: sort port order for routing by switch loads 80c0d48 opensm: rescan config file even in standby 8b7aa5e opensm/osm_subnet.c enable log_max_size opt update 8558ee5 opensm/include/iba/ib_types.h: Add xmit_wait for PortCounters ecde2f7 opensm/osm_subnet.c support subnet configuration rescan and update 58c45e4 opensm/osm_log.c save log_max_size in subnet opt in MB cf88e93 opensm: Add new partition keyword for all hca, switches and routers 4bfd4e0 opensm: remove libibcommon build dependencies 3718fc4 opensm/event_plugin: link opensm with -rdynamic flag 587ce14 opensm/osm_inform.c report IB traps to plugin ced5a6e opensm/opensm/osm_console.c: move reporting of plugins to "status" command. 696aca2 opensm: Add configurable retries for transactions 0d932ff opensm/osm_sa_mcmember_record.c: optimization in zero mgid comparison 254c2ef opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, set init failure on PKeyTable and QoS initialization failure 83bd10a opensm: Reduce heap consumption by multicast routing tables (MFTs) cd33bc5 opensm: Add some additional HP vendor IDs/OUIs f78ec3a opensm/osm_mcast_tbl.(h c): Make max_mlid_ho be maximum MLID configured 2d13530 opensm: Add infrastructure support for PortInfo IsMulticastPkeyTrapSuppressionSupported 3ace760 opensm: Reduce heap consumption by unicast routing tables (LFTs) eec568e osmtest: Add SA get PathRecord stress test aabc476 opensm: Add infrastructure support for more newly allocated PortInfo CapabilityMask bits c83c331 opensm: improve multicast re-routing requests processing 46db92f opensm: Parallelize (Stripe) MFT sets across switches 00c6a6e opensm: Parallelize (Stripe) LFT sets across switches e21c651 opensm/osm_base.h: Add new SA ClassPortInfo:CapabilityMask2 bit allocations 09056b1 opensm/ib_types.h: Add CounterSelect2 field to PortCounters attribute 6a63003 opensm: Add ability to configure SMSL 25f071f opensm/lash: Set minimum VL for LASH to use 622d853 opensm/osm_ucast_ftree.cd: Added support for same level links 8146ba7 opensm: Add new Sun vendor ID 1d7dd18 opensm/osm_ucast_ftree.c: Enhanced Fat-Tree algorithm e07a2f1 Add LMC support to DOR routing 1acfe8a opensm: Add SuperMicro to list of recognized vendors f02f40e opensm: implement 'connect_roots' option in fat-tree routing 748d41e opensm SA DB dump/restore: added option to dump SA DB on every sweep b03a95e complib/cl_fleximap: add cl_fmap_match() function b7a8a87 opensm/include/iba/ib_types.h: adding Congestion Control definitions fa356f8 opensm: Add support for optimized SLtoVLMappingTable programming 8aaae91 Dimension port order file support 7662eec opensm: Add option to specify prefix to syslog messages 2382cf3 opensm: Add update_desc command to opensm console 7cbe193 opensm: toggle sweeping V3 6f61d8f opensm/osmeventplugin: added new events to monitor SM 84cf603 opensm/main.c: force stdout to be line-buffered b3bb0ab opensm/osm_dump.c: Dump SL2VL tables if routing engine might have modified them 8a08719 opensm/osm_dump.c: dump SL2VL tables in debug verbosity level when QoS is on fc908c9 opensm/osm_sa_multipath_record.c: Add mtu validation if supplied 687e1f8 opensm/osm_sa_mcmember_record.c: Add mtu validation if supplied 76f5b09 opensm/osm_sa_path_record.c: Add mtu validation if supplied 9f38fae opensm/osm_helper: Add ib_mtu_is_valid 655230b opensm/osm_sa_multipath_record.c: Add rate validation if supplied cb1484d opensm/osm_sa_mcmember_record.c: Add rate validation if supplied 485d068 opensm/osm_sa_path_record.c: Add rate validation if supplied 300f4d9 opensm/osm_helper: Add ib_rate_is_valid 9b50961 opensm: Change osm_routing_engine struct to not use C++ reserved word c9c0aa6 opensm/man/torus-2QoS.conf.5.in: Update portgroup_max_ports section 3c97f06 opensm: Add the precreation of multicast groups a9b9f09 opensm/osm_sminfo_rcv.c: Handle SMP status 1190c15 opensm/osm_switch.c: In osm_switch_set_hops, return, error when port_num is invalid 3d149db Changed sl_path API to include slid and dlid only 6cfb0eb Optimized and deadlock-free routing algorithm for InfiniBand 45f93ec opensm: Add additional IBM vendor ID/OUI c386eb2 opensm/osm_state_mgr.c: Cosmetic change to log message 703e596 opensm: Add support for partition enforcement types to accomodate IBA extended link speeds a2a03a8 Check block_num validity in set_guidinfo() and del_guidinfo() requests e6ec61f end error resoponse to invalid LID in GUIDInfo request 7fce500 opensm/Makefile.am: Add doc/opensm-sriov.txt to docs 264aeb1 opensm: Add documentation for SRIOV support c639832 opensm: Enhance osm_physp_share_this_pkey for allow_both_pkeys policy b17b63c opensm: When allowing both pkeys, on a switch external, (peer) port eliminate limited pkey when full pkey with same base is present a758da2 opensm: Add command line option for allow_both_pkeys f412de3 opensm: Update partition documentation and man page for (allowing) both (limited and full) memberships in the same partition 726ce6a Support allowing both full and limited members of same partition 4ccf32f opensm/PKeyMgr: Support pkey index reuse when there are no longer any previously unused indices available eb375a6 opensm/osm_pkey_mgr.c: Detect pkey table overflow in pkey_mgr_update_port 411e742 opensm/PkeyMgr: Don't change end port pkey index when simultaneously adding and removing partitions 15e7223 opensm/osm_sa_guidinfo_record.c: In set_guidinfo, better SM reassigned guid handing e79b725 opensm: Handle SubnSet GUIDInfo asynchronously from GUIDInfoRecord handling 96c741d opensm: Some cosmetic formatting changes 1d5e370 opensm/osm_sa_guidinfo_record.c: Better status for SA response efd3ba2 opensm/osm_sa.c: Change log level of message db8b7da opensm/osm_sa_service_record.c: Alias GUID support 5330986 opensm/osm_sa_multipath_record.c: Add support for alias GUIDs 44168c9 opensm/osm_sa_guidinfo_record.c: In del_guidinfo, validate guid not in use 63eb65b opensm: Add multicast support for alias GUIDs 700d15f opensm/osm_sa_path_record.c: Add support for alias GUIDs f818387 opensm/osm_sa_guidinfo_record.c: Use OSM_VENDOR_ID_OPENIB define rather than IB_OPENIB_OUI 97e360e opensm: Dump/load SA GUIDInfoRecords fe74f1d opensm: Make SA assigned guids persistent across port down/up events eb8f1d9 opensm: Add support for alias GUIDs b3b1861 opensm: osm_subnet.c: Updated patch to add error-reporting to the parsing of opensm.conf cd8a708 opensm/man/opensm.8.in: Add description for OSM_LOG_SYS logging flag 1308e5c opensm/osm_console.c: Add display of FDR10 ports to portstatus_parse f4722b0 opensm: Reset client reregistration when receiving handover 5fdb0b9 opensm/configure.in: Remove Default-Start from opensmd init script b966100 opensm/osm_sm_state_mgr.c: Start sweep immedeately when recieving HANDOVER in DISCOVERING state 4349c07 opensm: Add physp_p discovery count support d706cbf opensm/osm_sm_mad_ctrl.c: Upon receiving trap repress we should decrease qp0_mads_outstanding_on_wire e1e4706 opensm: Revert "opensm/osm_ucast_ftree: When roots are not connected, update hop count but not lft" 7a49366 opensm: Changed #if to #ifdef when using ENABLE_OSM_PERF_MGR_PROFILE 34af1a5 opensm/osm_torus.c: torus routing should fail with VLCap 1 on switch external ports 2b8940b opensm/osm_torus.c: In dump_torus, make sure switch is present before dumping 2364e8e opensm: Add better error output when parsing node name maps 7204287 opensm/osm_sa_mcmember_record.c: Only use scope from MC group in copy_from_create_mc_rec 4eb0f69 opensm/osm_dump.c: Remove incorrect assert 1ddb44b OpenSM: dfsssp - moved paths from one to another VL might be counted multiple times a0a9eea OpenSM: DFSSSP does not find LIDs due to wrong byte order (v2) 13fd952 OpenSM: dfsssp - avoid unnecessary nested loop in vltable_print for OSM_LOG_INFO 1cbed64 OpenSM: dfsssp - change the port traversal for sssp c2f0bb9 OpenSM: dfsssp - add support for base/enhanced switch port 64873ff OpenSM: dfsssp ignores differences in the lmc value 162493e opensm/osm_req.c: In req_determine_mkey, use osm_physp APIs fc53bdc opensm/osm_torus.c: Dump torus when OSM_LOG_ROUTING specified 434afa6 opensm/torus: Add configuration for max_changes to report 35bcddf opensm/osm_torus.c: Consolidate some parsing with parse_unsigned 3f3d26f opensm/osm_prtn_config.c: Insert autogenerated pkey into MGID for IPoIB d80ca1e opensm/osm_port_info_rcv.c: Don't modify subnet minimal values when PortState DOWN f97a2e9 opensm/osm_ucast_ftree.c: Eliminate unneeded NULL pointer checks prior to calls to free 8a77f23 opensm/osm_ucast_ftree.c: Remove duplicate free in fabric_create_leaf_switch_array 338a67b opensm/osm_subnet.c: Improve error messages in subn_validate_neighbor 0a1c9bf opensm/osm_req.c: In req_determine_mkey, add more info when ERR 1107 occurs b974ca3 opensm/osm_torus.c: Improve some misconfiguration error messages e986d57 opensm/osm_torus.c: Minor simplification to check_qos_config 95b6f83 opensm: Update doc for changes to torus routing for, endport support 998fb43 opensm/osm_torus.c: Add copyright 268d327 opensm/osm_torus.c: Improve QoS configuration d1d2de5 opensm: Update doc for changes to torus routing for CA, support a362b5b opensm/osm_torus.c: Require only 2 data VLs supported (PortInfo.VLCap) and use VLs 0-1 on CA links 3f536ae opensm: Add routing specific update_vlarb hook routine a2415f3 Add Per Module Logging support for Congestion Manager a6d3694 opensm: clean up error message, function name is printed by logging code 2cf8078 opensm/osm_sa_mcmember_record.c: Return proper scope for query with valid SA key c1a206e opensm: update performance manager documentation f204e9c opensm: Protect against spurious wakeups when calling cl_event_wait_on 7db5c75 opensm/osm_subnet.c: Only parameters that marked with can_update flag should be updated during conf file rescan 282714a /etc/init.d/opensmd: Improve systemd integration 8b116d7 opensm/osm_trap_rcv.c: Eliminate unneeded trap_rcv_process_response routine 4008c2f opensm.spec.in: Improve portability 01ab744 Make it possible to enable opensm with chkconfig c68ae63 Add command-line option --pidfile ffb9a82 opensm/osm_torus.c: Check fabric minimum data VLs on switch external ports d0258f3 opensm: Track minimum value in the fabric for data VLs supported on switch external ports 36159c2 opensm/osm_torus.c: Cosmetic formatting change dba3f92 opensm/osm_helper.c: Add some missing new lines to log message output 94468b5 opensm/osm_ucast_updn.c: Add error codes to a couple of log messages 86a203b Correct option names in opensm man page 3482438 opensm/osm_sa.h: Cosmetic commentary change 824e1f0 opensm/ib_types.h: Commentary and cosmetic formatting change 3711e8a opensm/complib/cl_spinlock.h: Remove some unimplemented routines 0c3f57f opensm/osm_torus.c: Add error code to error log message 8e6dfbd opensm: Add .gitignore 6248495 opensm/osm_port_info_rcv.c: use PF() hint on fatal conditions dff5927 opensm/osm_port_info_rcv.c: check received local_port_num b7b1505 opensm/libvendor/osm_vendor_ibumad.c: validate response MAD properties c215eea opensm/libvendor/osm_vendor_ibumad.c:rename "mad" to "p_mad" to indicate pointer e00f67b opensm/libvendor/osm_vendor_ibumad_sa.c: use wrapper function instead of direct access ebc772c opensm/osm_node_info_rcv.c: using "PF" hint for all the fatal conditions e2f06cd opensm/complib: define macros for for "if" statements with branch prediction hints 0e33c11 opensm/configure.in: check that compiler supports __builtin_expect() 2cb1854 OpenSM: Add new Mellanox OUI 8e5fc57 opensm: osm_pkey: Remove unused variables e96a933 opensm: Manage ports that do not support congestion control fbb74ca opensm: improve search common pkeys. db34e30 opensm/osm_vendor_ibumad.c: Add management class to error log message ba36f81 opensm/perfmgr/console: add 'pm sweep' f118668 opensm/osm_sa: Improve SA record response handling (osm_sa_respond) b09ac65 opensm/osm_sa_informinfo.c: Add trusted support for InformInfo/InformInfoRecord 5b2390e dfsssp: optimization for dedicated compute and IO nodes 33f4f17 Add new option for guid_routing_order_no_scatter a5f54f1 osm_ucast_mgr.c: After applying guid_order options, add nodes sorted by neighbor switch load 5a97c78 Try default partition config if parsing partitions.conf fails cc5fa17 Add support for synchronizing in memory files with storage 9853841 Implement atomic update operation for sa_db_file 3e146fa Add option to disable M_Key lookup 51b187b Add flags to OSM_EVENT_ID_UCAST_ROUTING_DONE c97bd7b Permit toggling log flush from console 8395084 OpenSM: dfsssp - add support for multicast 96eafa0 ftree: Allow defining only io_guids file and consider rest of nodes as CN nodes 6cd6114 opensm: Add support for LFT changed event b73c378 opensm/perfmgr; add support for PortCountersExtended NOIETF 70f5820 opensm/perfmgr: Issue PortCountersExtended query when supported 1.3 Library API Changes 44a6358 libvendor/osm_vendor_ibumad.c: Support GRH (for GS classes) de02954 osm_trap_rcv.c: Log DR path to node when trap 128 1.4 Software Dependencies OpenSM depends on the installation of libibumad package (distributed as part of OFA IB management together with OpenSM) and IB stack presence, in particular libibumad uses user_mad kernel interface ('ib_umad' kernel module). The qualified driver versions are provided in Table 2, "Qualified IB Stacks". Also, building of QoS manager policy file parser requires flex, and either bison or byacc installed. 1.5 Supported Devices Firmware The main task of OpenSM is to initialize InfiniBand devices. The qualified devices and their corresponding firmware versions are listed in Table 3. 2 Known Issues And Limitations ------------------------------ * No Service / Key associations: There is no way to manage Service access by Keys. * No SM to SM SMDB synchronization: Puts the burden of re-registering services, multicast groups, and inform-info on the client application (or IB access layer core). 3 Unsupported IB Compliance Statements -------------------------------------- The following section lists all the IB compliance statements which OpenSM does not support. Please refer to the IB specification for detailed information regarding each compliance statement. * C14-22 (Authentication): M_Key M_KeyProtectBits and M_KeyLeasePeriod shall be set in one SubnSet method. As a work-around, an OpenSM option is provided for defining the protect bits. * C14-67 (Authentication): On SubnGet(SMInfo) and SubnSet(SMInfo) - if M_Key is not zero then the SM shall generate a SubnGetResp if the M_Key matches, or silently drop the packet if M_Key does not match. * C15-0.1.23.4 (Authentication): InformInfoRecords shall always be provided with the QPN set to 0, except for the case of a trusted request, in which case the actual subscriber QPN shall be returned. * o13-17.1.2 (Event-FWD): If no permission to forward, the subscription should be removed and no further forwarding should occur. * C14-44 (Initialization): If the SM discovers that it is missing an M_Key to update CA/RT/SW, it should notify the higher level. * C14-62.1.1.12 (Initialization): PortInfo:M_Key - Set the M_Key to a node based random value. * C14-62.1.1.13 (Initialization): PortInfo:M_KeyProtectBits - set according to an optional policy. * C14-62.1.1.24 (Initialization): SwitchInfo:DefaultPort - should be configured for random FDB. * C14-62.1.1.32 (Initialization): RandomForwardingTable should be configured. * o15-0.1.12 (Multicast): If the JoinState is SendOnlyNonMember = 1 (only), then the endport should join as sender only. * o15-0.1.8 (Multicast): If a request for creating an MCG with fields that cannot be met, return ERR_REQ_INVALID (currently ignores SL and FlowLabelTClass). * C15-0.1.8.6 (SA-Query): Respond to SubnAdmGetTraceTable - this is an optional attribute. * C15-0.1.13 Services: Reject ServiceRecord create, modify or delete if the given ServiceP_Key does not match the one included in the ServiceGID port and the port that sent the request. * C15-0.1.14 (Services): Provide means to associate service name and ServiceKeys. 4 Bug Fixes ----------- 4.1 Major Bug Fixes 62ea61a osm_state_mgr.c: Fix bug in handling of PortInfo Set timeout 34e81df Change precedence in pkey manager with indx0 feature aa905e2 osm_pkey.[h c], osm_prtn.c: Create method to set pkey at indx0 8a696eb osm_base.h: Fix OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED definition 70a364f opensm/osm_pkey_mgr.c: Fix pkey index wraparound/reuse 6e27bba osm_multicast.c: Dump sa after deleting well known mc group df212a6 osm_multicast.c: Fix not dumping empty predefined mc groups 1007810 osm_sa_guidinfo_record.c: Fix memory leak in set_guidinfo 6272a56 osm_ucast_dfsssp.c: In dfsssp_do_mcast_routing, update adj_list first 44b4edc osm_ucast_mgr.c: LFT update breaks if IB_SMP_DATA_SIZE changes 19dbb67 osm_ucast_dfsssp.c: Fix dangling pointer when dfsssp used with ucast cache 76bd8cd osm_sa_mcmember_record.c: Add error logging for mismatches to validate_other_comp_fields 122cad3 osm_sa_mcmember_record.c: When joining MC group and MC group already exists, validate other components if supplied 909976d Add more checks for physp validity b37560b osm_mcast_mgr.c: Add check for physp validity to create_mgrp_switch_map e4e449e osm_ucast_ftree.c: Fix wrong is_io assignment to the second HCA port e9bbf44 osm_ucast_ftree.c: Fix wrong handling of dual port HCA ccab3b8 osm_ucast_ftree.c: ftree calculates wrong number of compute nodes per leaf 06ae3ad osm_sa.c: Fix osm_db_file_dump f1ab545 osm_drop_mgr.c: Do not set SM port discovery count to 0 when switch remote port is nonresponsive cd12dcd osm_port_info_rcv.c: Fix calculation of minimum data VLs cb20b11 osm_ucast_ftree.c: Fail routing if max rank is 0 and more than one root c633e05 osm_ucast_ftree.c: Mark HCA ports connected to unranked switches f004819 osm_sa.c: Fix race condition when writing SA DB file a64de2e osm_prtn_config.c: Fix wrong pkey table calculation in allow_both_pkeys mode 0b6d8ea osm_sa_mcmember_record.c: Validate port's neighbor_mtu when joining MC group 80ca401 osm_sa_path_record.c: When both [D S] GID and LID are supplied, validate that underlying ports are the same 1fa8089 osm_sa_path_record.c: Handle path query by DGID and SLID 141293d osmtest/osmt_multicast.c: Fix MC join with unrealistic rate test f471571 osm_subnet.c: Remove support for changing allow_both_pkeys on the fly cd31ff6 osm_port_info_rcv.c: Sending MEPI(Get) to local switch ports on hop 0 4c3d782 osm_state_mgr.c: Mark port as undiscovered when removed by drop_mgr a1c4bc2 osm_console.c: Fix display of negative counters in console a6c2bf8 Add cleanup of SA cache after handover 075ff44 osm_mcast_tbl.c: Wrong assert placement in osm_mcast_tbl_get_block 953b70d osm_opensm.c: Fix race condition between traps handling and SA shutdown 5e50a3c osm_sa_mcmember_record.c: Extend P_Pkey validation on MCMemberRecord(Join) 3fcb121 osm_subnet.c: Improved m_key_lookup description in generated conf file b4d20d7 osm_port_info_rcv.c: In pi_rcv_process_switch_port0, store port 0's PortInfo before querying switch external ports 062d35d osm_port_info_rcv.c: In pi_rcv_process_switch_port0, determine mkey 899664d osm_ucast_mgr.c: Support diverse paths for LMC > 0 when scatter_ports is enabled 6dc0b80 osm_opensm.c: Call cl_disp_shutdown for SA SET dispatcher 3199d34 osmeventplugin.c: Modify osm_event_plugin_t initialization 94c2d74 Revert "osm_ucast_mgr.c: Force unicast routing to fail when lft allocations fail" patch 1d205bc osm_ucast_mgr.c: Select exit ports for lid offset > 0 using new_lft 2a32095 osm_ucast_cache.c: Rewrite p_sw->lft allocation in osm_ucast_cache_process e2ee83e Use routing engine calculated LFT for SA queries 1413d64 osm_state_mgr.c: Remove new_lft buffers cleanup f2b96de osm_ucast_mgr.c: Force unicast routing to fail when lft allocations fail 8ea4e06 osm_congestion_control.c: Reset cc_timeout_count when count threshold passed 0b7c80c osm_congestion_control.c: Consistently set cc_unavailable_flag e590ebc osm_congestion_control.c: Add additional header status check in cc_rcv_mad f130d5a osm_subnet.c: Correct output error with congestion control table entries 0a695ae osm_switch.c: Fix wrong assertion failed in osm_switch_get_lft_block() 5077198 osm_perfmgr.c: Reset physp_discovered before discovery 8d51ae5 osm_state_mgr.c: Avoid continuing discovery when SM port is unresponsive f017063 Better way to handle polling other MASTER SM 25e5ee5 complib/cl_dispatcher.c: Check registrations vector size when searching for handlers 6b0fb4d osm_lid_mgr.c: Send client reregistration in case of SM LID change 5d231f8 osm_pkey_mgr.c: Use calloc instead of malloc in pkey_mgr_process_physical_port 985859e Fix turning on first_time_master_sweep flag 4629e80 osm_mcast_mgr.c: Invalidate cache due to multicast routing errors b6a1dd4 osm_state_mgr.c: Avoid ucast cache invalidation due to errors during initialization db69cd8 osm_perfmgr.c: Fix perfmgr sweep_state race b42f11f osm_vendor_ibumad.c: Better match table eviction strategy cc0d61b libvendor/osm_vendor_ibumad.c: Check the next CA if an error is returned for the current one a16349d osm_trap_rcv.c: Lock released without locking in some cases of trap processing 6c6e4cc osm_sa_guidinfo_record.c: Fix crash when receiving AGUID SET/DELETE with block_num equal to max_block a8b23b7 osm_vl15intf.c: Fix potential NULL dereference in vl15_send_mad e94d471 osm_torus.c: Fix torus crash when actual topology is not torus a20cd5f osm_sa_service_record.c: Fix locking issue in osm_sr_rcv_process 127acf1 osm_sa_mcmember_record.c: Fix double locking in mcmr_rcv_join_mgrp c86c30a All SA queries should validate the requester port under lock 80e1e59 osm_sminfo_rcv.c: Send trap 144 to a newly found MASTER SM when in MASTER state 0189dea osm_sm_state_mgr.c: Fix opensm crash after handover 52c4a30 osm_sm_state_mgr.c: Reconfigure the fabric when receiving HANDOVER/POLLING_TIMEOUT in MASTER state 26af3a9 Fix crash during handover f775a1a osm_sa_path_record.c: Search for requester port should be under lock 24d6219 osm_sw_info_rcv.c: Fix sending PortInfo during lightsweep 12d2c8e osm_node_info_rcv.c: Fix multiple switch discovery during a sweep ef22eb9 osm_qos.c: Fix possible seg fault 9dd8f45 dfsssp: avoid crash due to port initialisation errors f6418cf osm_ucast_dfsssp.c: prevent double free error 1633550 Resend LFTs/VLArb/SL2VL MADs in case of error 90d19c2 osm_port_info_rcv.c: Reread pkeys from SP0 if switch rebooted during a sweep 6e90421 Better handling of topology changes in the fabric b33c3ba Change discovery order of switch data 395b5f0 Handle bad SMP status a322f51 Skip TID 0 on 32 bit wraparound for SMP, SA and PerfMgt queries cded9af Fix transaction id casting 3585f8b opensm: Fix crash found with ucast cache 74e12d9 opensm: fix part_enforce parameter parsing crash 647a98e Fixed crash in sm_state_mgr_send_master_sm_info_req() during fabric merge 63ebd0d Fix crash in ucast cache when chain of switches connected back at once to the fabric 3b21d6f Fix crash in ucast cache when ucast cache invalidates after updating one of the switches 5654e22 Fix invalid error check, which lead to segfault 7bf7482 fix segfault corner case w/ updn routing and LMC > 0 18990fa opensm: set IS_SM bit during opensm init 3551389 fix local port smlid in osm_send_trap144() a6de48d opensm/osm_link_mgr.c initialize SMSL 82df467 opensm/osm_req.c: Shouldn't reveal port's MKey on Trap method 45ebff9 opensm/osm_console_io.h: Modify osm_console_exit so only the connection is killed, not the socket d10660a opensm/osm_req.c: In osm_send_trap144, set producer type according to node type 8a2d2dd opensm/osm_node_info_rcv.c: create physp for the newly discovered port of the known node 39b241f opensm/lid_mgr: fix duplicated lid assignment b44c398 opensm: invalidate routing cache when entering master state 595f2e3 opensm: update LFTs when entering master 8406c65 opensm: fix port chooser fa90512 opensm/osm_vendor_*_sa: fix incompatibility with QLogic SM 7ec9f7c opensm: discard multicast SA PR with wildcard DGID 5cdb53f opensm/osm_sa_node_record.c use comp mask to match by LID or GUID 55f9772 opensm: Return single PathRecord for SubnAdmGet with DGID/SGID wild carded 5ec0b5f opensm: compress IPV6 SNM groups to use a single MLID 26e7e83 opensm/osm_lid_mgr: fix couple of duplicate LIDs bugs fedc419 opensm: Multicast root switch calculation 6772fdb opensm: Fix sl2vl configuration dd3470f complib/cl_timer.c: fixing cl_timer calculation ae1bcdd opensm/osm_lid_mgr.c: Allow switch lids to be non LMC aligned 593547e Wrong handling of MC create and delete traps 4c822b0 opensm/osm_prtn.c: removing TopSpin hack 8214e2a opensm: Add support for SwitchInfo:MulticastFDBTop 1e544ba opensm: fixed memory leak in multicast spanning tree calculation 0456b3f Fixed multicast groups reconfiguration during heawy sweep 9ad844f Fix ucast cache crash, when switch doesn't have valid phys ports 07aa9fa opensm: fix crash in osm_ucast_mgr 076bd38 opensm/osm_ucast_cache.c: fix crash in ucast cache when switch with lid 0 dropped 9cbb8af opensm/osm_ucast_ftree.c: fix opensm segfault in osm_ucast_ftree.c edd0552 opensm/osm_qos_policy.c: fix segmentation fault on osm_qos_policy_match_rule_destroy (osm_qos_policy.c) dec1109 DFSSSP: fix a memory leak in dfsssp_build_graph d5fe528 opensm/osm_req.c: In req_determine_mkey, fix DR algorithm a46b33e opensm: fix crash in DFSSSP routing engine on reroute d2312af opensm/osm_link_mgr.c: Fix sending PortInfo(Set) with AM SMSupportExtendedSpeeds bit set for switch base port 0 06ae82c opensm/osm_link_mgr.c: Set AM SMSupportExtendedSpeeds bit if port supports ExtPortInfo b2cd2d7 opensm/osm_ucast_ftree.c: Fix unranked nodes bug in FTree 8384156 opensm/osm_torus.c: Fix crash in torus_update_osm_vlarb 0ff054a osm_trap_rcv.c: Removed unneeded lock when disabling port e7c4ec3 osm_trap_rcv.c: Minimize time holding RW lock for SystemImageGUID changed trap 145 1418f8a osm_trap_rcv.c: In trap_rcv_process_request, change locking strategy 280a2ac osm_trap_rcv.c: fix locking in trap_rcv_process_request() a45e311 osm_db_files.c: Minor improvement to fix in previous commit 86cf679666f49f6073c1ddf2b9ff644a41537a57 86cf679 osm_db_files.c: Fix issue introduced in commit aaa7b1e67ec6e5fc2a10accf46d538f9d47c6323 ed7be1a Add client_rereg flag to Port Info context 413e4fa osm_trap_rcv.c: fix race condition during sweep 90a7960 osm_ucast_file.c: Fix crash when port is invalid in LFT file a1ccf88 osm_sa_path_record.c: path_sl may return SL different from requested SL 8f3f7d0 osm_sm_state_mgr.c: Fix race condition during sm_state_mgr_send_master_sm_info_req b1b1b37 Fix minhop population in fabric with duplicate lids ed9de4c osm_mcast_mgr.c: Fix wrong comparison in mcast_mgr_subdivide() c5d5faa Only rewrite db files during heavy sweep when there is a real change 9aa6dcd osm_drop_mgr.c: fix timeouts on Get Pkey from ext switch ports 361c014 Fix dropping node after setPkey mad 2585f58 Improve memory consumption of pkey manager by using cl_map for accum_pkeys 754bd75 osm_opensm.c: When exiting, update SADB only in MASTER state 3cc0a3e Fix timeout handling for pkeyGet for sw port 0 189a39d Fix possible use of lid 0 when sending set PortInfo after failure of the first PortInfo set 6d1d1a4 Fix handling of get P_KeyTable on timeout df385e8 osm_ucast_cache.c: Fix memory leak in ucast_cache 79ba877 osm_link_mgr.c: active_transition parameter in PortInfo(Set) context may not be initialized b442062 Resend trap 144 when detecting remote MASTER SM with lower priority 49ea151 osm_pkey.c: Fix find common pkey bug fix e3aa9e8 dfsssp: send multicast forwarding tables to switches 4a39fb1 dfsssp: send multicast forwarding tables to switches d5f6e25 osm_sa_mcmember_record.c: Fix incorrect comparison of IPv6 MGID when searching for SNM MLID 908c524 osm_guid_mgr.c: Fix GUIDInfo SET function e8bf592 Clean up event subscriptions if a port goes away 7c9afa0 Improve m_key lookup 807d9ed osm_trap_rcv.c: Fix locking in aging callback eb294d5 osm_lid_mgr.c: Don't configure MTU and LMC for base SP0 a47e5d0 complib/cl_event_wheel.c: Roundup timeout to nearest msec 2a8c474 complib: Fix memory leak in cl_thread_pool_destroy function 1960fbc osm_trap_rcv.c: Fix crash in babbling port feature 1872d11 osm_sa_sminfo_record.c: fix sminfo sa query returns all sminfo records when filtering by LID in osm_smir_rcv_process b92f25a osm_ucast_cache.c : Fix dereference null return value 21765ad When SM fails to load/parse root_guids file use MinHop heuristics 7c21c14 Fix shift pattern support in FTREE routing for native ftree topologies 35f4419 osm_ucast_ftree.c: fix dereferencing null variable 4d36d6d osm_ucast_ftree.c : fix dereferencing null variable 49f1a71 opensm: fix possible double free in osm_ucast_ftree.c 2695128 Fix fat-tree routing for CAs with more than 1 connected port 42558d6 osm_sm_state_mgr.c Don't clear IS_SM bit when changing state to NOT_ACTIVE 21a5b5f DFSSSP - workaround for better VL balancing b42ae68 osm_console_io.c Memory leak when closing console bcf00cb osm_ucast_dfsssp.c: Fix memory leak in dfsssp_do_dijkstra_routing f42a232 Fix segfault in osm_mgrp_delete_port() 1a94326 osm_sa_multipath_record.c Use aliasGUIDs when building responses 943a40a opensm: Fix Q_Key, TClass and limited keys parsing warnings in partitions.conf 0fc6e8b osm_lid_mgr.c: Fix duplicate LID assignment after SM port down becc27e osm_sa_mad_ctrl.c: Drop incoming SA queries when shutting down dbeb7a7 Change LFT event to be per block/per switch rather than just per switch 25c088a Setup SM port GUID in subnet object as soon as it is known 92c502a osm_sa_mcmember_record.c: On join and leave, validate subnet prefix in port GID c0602ed opensm/osm_port_info_rcv.c: Fix min_sw_data_vls calculation 2d8df36 opensm/osm_sw_info_rcv.c: Fix double release of lock in osm_si_rcv_process e7435ef opensm/osm_torus.c: avoid the possibility of following stale ->priv pointers 904a555 opensm/perfmgr: fix access to shared sweep_state variable 1458263 opensm/perfmgr: don't clear data counters in PortCounters when ExtendedPortCounters is supported b6d0001 opensm/perfmgr: issue ClassPortInfo as first query to each port. e1af1ce opensm/osm_console.c: Use ib_port_info_get_link_speed_ext_enabled 2ba9919 opensm/osm_console.c: Do not perform portstatus checks on down ports 5c45f60 opensm/osm_console.c: Support portstatus output for unenabled width/speed 1947644 opensm/osm_qos_policy.c: fix memory leak when parsing policy file 9358164 opensm/osm_sa_multipath_record.c: Validate required components are indicated fbe0d02 opensm/osm_sa_multipath_record.c: Make sure either none or both ServiceID parameters are supplied f929ac1 opensm/osm_sa_path_record.c: Make sure either none or both ServiceID parameters are supplied 43efbc2 opensm/osm_sa_multipath_record.c: Fix seg fault in mpr_rcv_get_apm_paths 250802d opensm/osm_qos_policy.c: Fix source & destination GUID policy check 9f231a8 libvendor/osm_vendor_ibumad.c: fix mad validation in case of multipath record response 2be4e20 opensm/perfmgr: update node name when Node Description is received from node f37bf3c opensm/perfmgr: skip data counters when only printing errors 8412591 opensm/perfmgr: mark/report time of last counter update 4.2 Other Bug Fixes bb15d2f osm_service.c: Fix missing endian conversion in log message c0e8141 Fix various coverity issues a0d9157 osm_subnet.c: Add guid_routing_order_no_scatter option to opensm.conf 5d521c1 osm_state_mgr.c: Update comment in state_mgr_check_tbl_consistency ccefa3d osm_sm_mad_ctrl.c: Add ':' to "ERR 3120" error message dc45fca ib_types.h: Comment change to indicate 1.3.1 rather than 1.2 IBA spec 37e1246 ib_types.h: Cosmetic formatting changes 73fd8ee man/opensm.8.in: Fix typo (missing close parenthesis) c32b813 doc/current-routing.txt: Fix typo c4691e7 ib_types.h: Cosmetic commentary fix 85e2214 osm_sa_mcmember_record.c: Prevent log errors swamp in MC query scenario 88626f4 osm_sa_mcmember_record.c: Updated Mellanox copyright years 432727b osm_sa_mcmember_record.c: Cosmetic formatting change to mcmr_rcv_create_new_mgrp b85c31e osm_prtn_config.c: Cosmetic formatting changes in manage_membership_change 1a2a6d7 osm_prtn_config.c: Updated Mellanox copyright years 8b288b8 osm_mcast_mgr.c: Cosmetic formatting change in create_mgrp_switch_map 4772806 osm_state_mgr.c: Fix uninitialized area of SMInfo SET mad 175de41 osm_prtn.c: Cosmetic formatting change 870b21a osm_ucast_dfsssp.c: Fix some commentary typos d5c51e9 osm_ucast_mgr.c: Cosmetic formatting change f234d83 osm_inform.c: Cosmetic code refactoring in match_inf_rec fdd1a68 Updated some Mellanox copyrights ecf07eb Set Type field in Notice attribute using IB_NOTICE_TYPE_SUBN_MGMT define 022e6af Use SM trap defines from ib_types.h rather than hard coded values d111a2c ib_types.h: Cosmetic formatting change 1cbea4b osmtest/osmt_multicast.c: Cosmetic changes c52a1b2 osm_drop_mgr.c: Eliminated redundant check for switch node type 2c4771f osm_ucast_dfsssp.c: Minor change to setting dropped when switch exists e94fc29 osm_subnet.[h c]: Fix wrong function documentation and parameter list 098259e Updated Mellanox copyrights in some recently changed files 1f3dcb4 osm_ucast_ftree.c: Cosmetic formatting changes in fabric_construct_hca_ports e92cfe5 iba/ib_types.h: Fix commentary typo 5109f44 osm_ucast_ftree.c: Cosmetic formatting change 0bc858e osm_ucast_ftree.c: Cosmetic variable name changes in ftree_port_group_t struct 08e8a9a osm_sa_path_record.c: Refactored PR [D/S] GID and LID validation 7777987 osm_sa_path_record.c: Cosmetic formatting change a7ac5fc osm_prtn_config.c: Handle valgrind warning in osm_prtn_config_parse_file 609b777 osm_ucast_ftree.c: Cosmetic formatting change d9a601b osm_ucast_ftree.c: Remove no longer needed code in remove_depended_hca 1f6cd87 osm_state_mgr.c: Cosmetic formatting changes 7f2f902 libvendor/osm_vendor_ibumad_sa.c: Cosmetic formatting change to ERR 5501 log message e527ec6 libvendor/osm_vendor_ibumad_sa.c: Cosmetic formatting changes to osmv_query_sa ec2e2bf osm_pkey.h: Fix osm_physp_has_pkey method description bf3818b partition_config.txt: Small correction in doc file 9fa761c osm_ucast_ftree.c: Removed *p_ftree parameter from sw_destroy function 652b063 osm_ucast_ftree.c: Removed *p_ftree parameter from sw_create function d504e76 doc/QoS_management_in_OpenSM.txt: Cosmetic changes a28d63e Fix documentation on ignore-guids command line option df32644 osm_subnet.c: Minor clarification to SwitchCongestionSetting Control Map description in generated option file 483ff00 man/osmtest.8: Minor tweaks to inventory option description 8d3c6f8 osm_sa_mcmember_record.c: Change to log messages for PKey consistency 504e43f osm_req.c: Cosmetic formatting change a5e484b osm_node.h: Fix commentary typo 6ceb0ce osm_sa_mcmember_record.c: Removed redundancy in comment 9e0cba3 osm_prtn_config.c: Cosmetic formatting change 0eb5117 osm_sa_mcmember_record.c: Cosmetic formatting change 2541ed9 osm_ucast_mgr.c: Cosmetic formatting change 28fd4ee osm_[subnet congestion_control].c: Cosmetic commentary change 391c244 osm_congestion_control.c: Added Mellanox copyright 7e08621 osm_congestion_control.c: In cc_rcv_mad, add attribute ID and modifier to log message 62075d6 osm_perfmgr.c: Fix endian of MAD status in pc_recv_process cd94c9c osm_congestion_control.c: Fix endian of MAD status in cc_rcv_mad cb5df8b osm_congestion_control.c: Fix endian of node and port GUIDs in some log messages 68887fb osm_congestion_control.c: Cosmetic changes 1331a46 osm_subnet.[h c]: Fix possibility for open file descriptor issue ce15bb7 osm_perfmgr.c: Output remote port on perfmgr error counter log messages 030ac82 osm_sa.c: Improve ERR 4C05 log message fbb63d6 osm_subnet.c: Update MEPI supported devices white list 0774229 osm_subnet.c: Cosmetic formatting change 5871ef7 osm_sa.c: Check return value from chmod in opensm_dump_to_file 61cd0cf osm_switch.c: Fix potential memory leak due to misuse of realloc c78adde osm_req.c: Initialize dest_port_guid in req_determine_mkey dd5e5df osm_mcast_mgr.c: Add MLID to error 0A06 log message 63900bc osm_vendor_ibumad.h: Use UMAD_MAX_DEVICES for OSM_UMAD_MAX_CAS a5c0200 iba/ib_types.h: Add support for new MAD SM:PortInfoExtended and for modifying PM:PortExtendedSpeedsCounters 3f99535 osm_port_info_rcv.c: In osm_pi_rcv_process, move assert before first log message a0b9444 Change osm_subn_t.log_max_size type to uint32_t b5abaa2 osmeventplugin.c: Add include of osm_config.h as first OpenSM include ecce4e3 osm_console.c: Handle LinkSpeed[Ext]Active 0 for portstatus command f622810 osm_console.c: Fix unknown speed/width port reporting for portstatus command ffdd042 osm_console_io.c: In is_authorized, STRING_UNKNOWN is define a6ba888 Add missing keyword in partition definition in man page and partition.txt doc 7444e5e Fix the difference in osm_opensm struct size between OpenSM and plugin(s) caf764f osm_subnet.h: Fixed commentary typo 117bc82 osm_prtn.c: Change message verbosity for log message in osm_prtn_add_port 3b172ab osm_config.h.in: Fixed the difference in osm_opensm_t struct size between opensm and plugins d13d4bd osm_console.c: Track and report unknown/speed width ports d63e7f6 osm_sa_path_record.c: Cosmetic formatting changes 48d159b libvendor/osm_vendor_ibumad.c: Remove GID index 0 check in umad_receiver d7f1d02 libvendor/osm_vendor_ibumad.c: memset osm_mad_addr_t before setting fields 96f89d6 osm_console.c: Included unknown speed/width ports in "possible issues" 44df235 osm_dump.c: In dump_topology_node, handle link_width_active of 4 for 8X a1e58e0 osm_link_mgr.c: Fix bug in mlnx extended port info setting fcb6967 osm_subnet.c: Improve sweep_on_trap documentation in generated conf file 47a6b00 osm_sa_multipath_record.c: Better logging for 4514, 4515, and 4505 error messages 115529b osm_sa_path_record.c: Better logging for 1F02 error message fe079df osm_sa_path_record.c: Better logging for 1F05 and 1F03 error messages 43c378f osm_ucast_mgr.c: A couple of cosmetic log message changes in ucast_mgr_route 9a5e514 osmtest/osmtest.c: Cosmetic formatting change 90db6c3 osm_state_mgr.c: Cosmetic formatting changes e7139af osmtest/osmtest.c: Fix osmtest_get_sm_gid when running osmtest on node other than SM node 83ea812 doc/performance-manager-HOWTO.txt: Update perfmgr config options documentation d4d5af3 libvendor/osm_vendor_ibumad_sa.c: Fixed endian in debug log message c1080b9 osmtest/main.c: Cosmetic change to output for consistency 179fbac Add support for additional Mellanox OUI be3e4f1 osm_subnet.c: Remove duplicate strcmp check in osm_subn_rescan_conf_files method e6fc2f8 Add some missing documentation files to installation ed1571a osm_subnet.c: Change default for perfmgr_query_cpi option 3a1b458 osm_mcast_mgr.c: Cosmetic change to error log mesage 56bd964 opensm.init.in: Fix return value checking in opensm.init script 787c16e Eliminate redundant calls to ib_port_info_compute_rate 6a2d081 Shorten long lines while calculating SA rate 6ec10d6 man/opensm.8.in: Update date on man page 1dcf322 Improve scatter ports documentation b1a8fb0 osm_subnet.c: Cosmetic formatting change in subn_validate_neighbor d1b70fc osm_perfmgr.c: Add log message when perfmgr sweep is skipped 8098a4d osm_perfmgr.c: Remove unnecessary log message 38bc2e4 Skip state_mgr_check_tbl_consistency when no LID is changed by lid or link managers ce73c60 osm_drop_mgr.c: Add missing CR at end of log message in drop_mgr_check_node 8255f8f osm_state_mgr.c: Improve error flow with wrong LIDs 86f1720 osm_sa_path_record.c: Fix some commentary typos 2bc6074 osmtest/main.c: Output formatting change for case 'x' 60727f7 osmtest: Add GRH tests for SA queries d29dcd7 osm_sa_path_record.c: Fix misleading error messages during sweep e91908b Add osm_congestion_control.c to per module logging support 3de1091 osm_congestion_control.c: Fix error code 3ee0a22 osm_sm.c: In sm_sweeper, no need to check for timeout after cl_event_wait_on EVENT_NO_TIMEOUT f3e1924 osm_trap_rcv.c: In shutup_noisy_port, improve ERR 3811 log message f73ff43 osm_mcast_mgr.c: In mcast_mgr_process_mlid, cosmetic change to log message ab9fec9 osm_congestion_control.c: In cc_poller_send, handle cl_event_wait_on return status af04af7 osm_[sm sa]_mad_ctrl.c: Improve unsupported attribute error messages 16fee25 osm_helper.c: In osm_get_lsa_str, fix printing of wrong FDR10 data if link is down 6c70bf1 PerfMgr: Eliminate no longer used sig_sweep variable 41d0a42 osm_perfmgr.c: In perfmgr_send_mad, handle cl_event_wait_on return status d764777 osm_perfmgr.c: Minor code factoring in perfmgr_send_mad fa31298 doc/opensm_release_notes-3.3.txt: Updated repo location 8394ef8 libvendor/osm_vendor_ibumad.c: Commentary change 0ab7492 osm_subnet.c: More cosmetic changes to opensm conf file PerfMgr documentation cc977be osm_subnet.c: Enhance opensm conf file documentation for PerfMgr options 38273db osm_port_info_rcv.c: Fixed calculation of min_data_vls dc3259e Add support for additional Mellanox OUI 99a8e74 osmtest.c: Fixed missing assignment of return value from function osmtest_get_port_rec_by_num 9ffa520 Fix the creation of empty multicast groups from SADB 1d3aacf osm_perfmgr_db.c: Add missing clear of new xmit_wait counter in clear_counters 0f9b15c SM should resweep the fabric if vl15_send_mad fails ee5f6d5 osm_perfmgr.c: Added Mellanox copyright 05be6c4 osm_perfmgr.c: Eliminate unneeded initialization in pc_recv_process 9ac71fd osm_perfmgr.c: Cosmetic formatting changes 54c6c86 osm_log.c: Fix wrong hour and date display in log when CL_ASSERT fail 5c81051 osm_console_io.c: Handle return value of function setsockopt 2e1294a osm_sa_[mcmember path]_record.c: Optimize clearing of SA record items db9c450 osm_guid_info_rcv.c: Fix assert placement in osm_gi_rcv_process bb723ae libvendor/osm_vendor_ibumad.c: Cosmetic change to umad_set_grh calls 5ca6bdc osm_perfmgr.c: Add current PerfMgr sweep state to 54FF error log message 753af81 osm_mcast_mgr.c: Add missing new line at end of ERR 0A21 log message d437d58 osm_mcast_mgr.c: Fix endian of port GUID in ERR 0A06 log message 51fb51d osm_ucast_mgr.c: Fix duplicated error codes 21c2ab7 osm_sa_mad_ctrl.c: In sa_mad_ctrl_rcv_callback, improve 1A04 error log message c83bde4 doc/performance-manager-HOWTO.txt: Fix typo abaf91b osm_sa_service_record.c: Improved locking 1f4de58 osm_subnet.c: Fix bug in parsing configuration file 0fa5fc1 osm_sa_mcmember_record.c: Fix removing members from existing mc group due to invalid requests e156626 osm_qos_parser_y.y: Added range check for mtu limit parsing cb439b3 osm_qos_parser_y.y: Added range check for rate limit parsing a556f82 man/opensm.8.in: Minor fixes to per module logging configuration 7991745 osm_node_info_rcv.c: Update local copy of node info for known nodes 1c637df osm_node_info_rcv.c: Update NodeInfo.SysImageGUID on heavy sweep 275a56a osm_state_mgr.c: Clear first time sweep even after subnet error 09b5ffe osm_sa_path_record.c: In osm_pr_rcv_process, release lock before log message ef7a651 osm_state_mgr.c: Revert commit to "remove redundant unset to first_time_master_sweep" 23dfbf8 osm_state_mgr.c: Remove redundant unset to first_time_master_sweep e5a87dd Revert "Reset client reregistration when receiving handover" 28e5fa7 osm_sw_info_rcv.c: Add check of switch mcast_cap 78b6e8f osm_subnet.c: Fix resource leak neighbor parser ("subn_validate_neighbor" function) 46749c0 osm_subnet.c: Fix resource leak guid2mkey parser (guid validation function) 6212e4b osm_ucast_ftree.c: Fix memory leak in ftree fabric_rank afb6cb8 osm_ucast_mgr.c: Use LFT block of all port 0s to indicate resend 319e065 ib_types.h: Rename ib_switch_info_set_state_change function b1c17a8 ib_types.h: Fix shadow declaration warnings e3f0440 osm_ucast_updn.c: Fix the AA0B error number 30d9020 osm_ucast_updn.c: Add missing ERR number to log message e8a9275 osm_port.c: Improve ERR 4108 log message 740c22b opensm/include/opensm/osm_log.h: Fix commentary cut 'n paste error 13ebee4 opensm/osm_subnet.c: Fixed ftree/updn configuration failure when root_guid_file points to non-existing file 8a9d267 opensm: fix locking in osm_guid_mgr_process 4d682bb opensm: Fix pthread_create() return value checks 63c6609 opensm/osm_port.h: Fix commentary typo 3e4e00b opensm/osmtest: fix osmtest ignores timeout parameter 68b1d92 opensm: perfmgr fix dump_counters 9d16039 opensm/perfmgr: fix endian conversion of PortCounters 324f269 opensm/osm_sa_inform_info.c: Fix some error log messages 1d5213a opensm/osm_madw.h: Fix a couple of cut 'n paste commentary errors 3fc662d opensm/torus-2QoS: Fix some typos in documentation 048c66e Fixed Multicast precreation parsing 086d611 Fixes in SL2VL table distribution algorithm 7d9f0c9 Fix deadlock between sminfo_set_req() and osm_sm_state_mgr() 69741e6 Fix base port0 sl2vl mapping optimization bcda38e Fix SL2VL configuration 7e39542 Fix pre-creation of MC group with MGID containing P_Key 20e1a46 opensm/osm_congestion_control.c: Fix initialization hex string a59072d opensm/osm_congestion_control.c: Skip TID 0 on 32 bit wraparound 7d18662 osmtest/osmtest.c: Fix permission e7d4574 opensm/perfmgr: update new error codes to '54' prefix e17dae6 opensm/osm_sa_portinfo_record.c: In pir_rcv_new_pir, fix switch port 0 physp 93b2f56 libvendor/osm_vendor_ibumad.c: fix unused-but-set warning cda58af fixed unsused-but-set warning for DEBUG variables e881d0e opensm/osmtest/osmt_multicast.: Fix typo in log message 203f3c6 opensm/osm_switch.c: Fix compile warnings 67c2538 opensm/man/opensm.8.in: Fix some typos 7338efc opensm/osmtest/osmtest.c: Fix endian in some log messages 67063ca opensm/libvendor: Fix compile warnings on 64 bit machines when building --with-osmv=sim a8c209c opensm: fixed port order configuration in torus routing engine 7359cfc opensm/osm_ucast_mgr.c: Fix some issues found by Coverity 0150ab9 opensm/osm_ucast_ftree.c: Fix some issues found by Coverity 267a08f opensm/osm_pkey_mgr.c: Fix cast 12f772d opensm: Fix some OSM_SIGNAL and OSM_SM_SIGNAL numbering c29c4f1 opensm/osm_sa_service_record.c: Fix minor memory leak f936f8b opensm: fix strtoull error handling 0292ae2 opensm: fixed segfault when enable qos on fabric with no switches 619fa64 osmtest/osmt_multicast.c: Fixed another insufficient component case 1618803 opensm/osm_sa.c: Fix commentary typo c98fec9 opensm/osm_subnet.c: Fix description of max_msg_fifo_timeout 0a3839f osmtest/osmtest.c: Fix trap flow not implemented log message f08479a opensm/osm_base.h: Fix a commentary typo ae966f6 osmtest/osmt_multicast.c: Fix some typos 8a3b5b9 osmtest/osmt_multicast.c: Fixed some error codes in OSM_LOG messages c90953d osmtest/osmt_multicast.c: Fixed a couple of typos in OSM_LOG messages f7f1ead opensm/osm_sa_mcmember_record.c: Fix handling of invalid PKey 65d3e4f opensm/osm_pkey_mgr.c: Fix commentary typo 34d61cc opensm/perfmgr: fix overflow processing 77d79b4 opensm: fixed potential null variable dereferencing in libvendor 350c6e4 opensm: fixed potential memory leak in osm_ucast_ftree() e206872 opensm: Fixed debug message in osm_vendor_send() 1b3e93e opensm: fixed sizeof of pointer allocation in osm_ucast_lash() f0b915a Fix SANodeRecord.nodeInfo.localPortNum 3332658 opensm: fixed memory leak in multicast spanning tree calculation e4525b1 opensm: fixed indentation and decreased verbosity of RMPP length message 10ac4c1 Fix compile warning introduced by patch "fixed getline pointer allocation free in osm_console_io" bf23d7c opensm: fixed getline pointer allocation free in osm_console_io 54b1583 Makefile: ChangeLog and version generation script path fix 4911e0b performance-manager-HOWTO.txt: Indicate master state 86ccaa4 opensm/osm_pkey_mgr.c: Fix pkey endian in log message b79b079 opensm.8.in: Add mention of backing documentation for QoS policy file and performance manager b4d92af opensm/osm_perfmgr.c: Eliminate duplicated error number a10b57a opensm/osm_ucast_ftree.c: lids are always handled in host order 44273a2 opensm/osm_ucast_ftree.c: fixing bug in indexing 5cd98f7 Fix further bugs around console closure and clean up code. 6b34339 opensm/osm_opensm.c: add newline to log message 68c241c send trap144 when local priority is higher than master priority 6462999 opensm/osm_inform.c: In __osm_send_report, make sure p_report_madw valid before using 9b8561a opensm/console: Fixed osm_console poll to handle POLLHUP 91d0700 osm_vendor_ibumad.c: In clear_madw, fix tid endian in message 5a5136b osm_switch.h : Fixed wrong comment about return value of osm_switch_set_hops c1ec8c0 osm_ucast_ftree.c: Removed useless initialization on switch indexes 418d01f opensm/osm_helper.c: use single buffer in osm_dump_dr_smp() 2c9153c opensm/osm_helper.c: consolidate dr path printing code 048c447 opensm/osm_helper.c: return then log is inactive dd3ef0c opensm: Return error status when cl_disp_register fails 0143bf7 opensm/osm_perfmgr.c: Improve assert in osm_pc_rcv_process 6622504 osm_perfmgr.c: In osm_perfmgr_shutdown, add missing cl_disp_unregister 7b66dee opensm: remove unneeded anymore physp initializations f11274a opensm/partition-config.txt: Update for defmember feature d240e7d opensm/osm_sm_state_mgr.c: Remove unneeded return statement 898fb8c opensm: Improve some snprintf uses 6820e63 opensm/osm_sa_link_record.c: improve get_base_lid() 64c8d31 opensm: initialize all switch ports 555fae8 opensm/sweep: add log message before lid assignment 8e22307 opensm/console: Enhance perfmgr print_counters for better nodenames b9721a1 opensm/osm_console.c: Improve perfmgr print_counters error message 4d8dc72 opensm/osm_inform.c: Fix sense of zero GID compare in __match_inf_rec a98dd82 opensm/main.c: remove enable_stack_dump() call db6d51e opensm/osm_subnet: fix crash in qos string config parameters reloading e5111c8 opensm: proper config file rescan e5295b2 opensm: pre-scan command line for config file option e2f549e opensm/osm_console.c: Eliminate some extraneous parentheses 0a265dc opensm/console: dump_portguid - don't duplicate matched guids 540fefb opensm/console: dump_portguid command fixes d96202c opensm/osm_console.c: Add missing command in help_perfmgr ae1bd3c opensm/osm_helper.c: Add port counters to __osm_disp_msg_str 1d38b31 opensm/osm_ucast_mgr.c: Add error numbers for some OSM_LOG prin 156c749 opensm: fix structure definition for trap 257-258 5c09f4a opensm/osm_state_mgr.c: small bug in scanning lid table 72a2fa2 opensm/osm_sa.c: fixing SA MAD dump 539a4d3 opensm/osm_ucast_ftree.c Fixed bad init value for down port index 6690833 opensm/ftree: simplify root guids setup. 90e3291 opensm/ftree: cleanup ftree_sw_tbl_element_t use c07d245 opensm/qos_config: no invalid option message on default values b382ad8 opensm: avoid memory leaks on config parameters reloading 45f57ce opensm/osm_ucast_ftree.c: Fixed bug on index port incrementation 3d618aa opensm/osm_subnet.c: break matching when config parameter already found 44d98e3 opensm/osm_subnet.c: clean_val() remove trailing quotation 173010a opensm/doc/perf-manager-arch.txt: Fix some commentary typos 83bf6c5 opensm/osm_subnet.c fix parse functions for big endian machines 6b9a1e9 opensm/PerfMgr: Primarily fix enhanced switch port 0 perf manager operation 4f79a17 opensm/osm_perfmgr.c: In osm_perfmgr_init, eliminate memory leak on error 22da81f opensm/osm_ucast_ftree.c: fix full topology dump aa25fcb opensm/osm_port_info_rcv.c: don't clear sw->need_update if port 0 is active 003bd4b opensm/osm_subnet.c Fix memory leak for QOS string parameters. 9cbbab2 opensm/opensm.spec: fix event plugin config options 996e8f6 OpenSM: update osmeventplugin example for the new TRAP event. 67f4c07 opensm/lash: simplify some memory allocations 3e6bcdb opensm/lash: fix memory leaks 3ff97b9 opensm/vendor: save some stack memory ccc7621 opensm/osm_ucast_ftree.c: fixing errors in comments 1a802b3 Corrected incoherency in __osm_ftree_fabric_route_to_non_cns comments 85a7e54 opensm/osm_sm.c: fix MC group creation in race condition aad1af2 opensm/osm_trap_rcv.c: Improvements in log_trap_info() f619d67 opensm/osm_trap_rcv.c: Minor reorganization of trap_rcv_process_request 084335b opensm/link_mgr: verify port's lid d525931 opensm/osm_vendor_ibumad: Use OSM_UMAD_MAX_AGENTS rather than UMAD_CA_MAX_AGENTS f342c62 opensm/osm_sa.c: don't ignore failure in osm_mgrp_add_port() 587fda4 osmtest/osmt_multicast.c: fix strict aliasing breakage warning 6931f3e opensm: make subnet's max mlid update implementation independent 30f1acd osm_ucast_ftree.c missing reset of ca_ports ac04779 opensm: fix LFT allocation size a7838d0 opensm/osm_ucast_cache: reduce OSM_LOG_INFO debug printouts c027335 opensm/osm_ucast_updn.c: Further reduction in cas_per_sw allocation e8ee292 opensm/opensm/osm_subnet.c: adjust buffer to ensure a '\n' is printed 84d9830 opensm/osm_ucast_updn.c: Reduce temporary allocation of cas_per_sw 347ad64 opensm/ib_types.h: Mask off client rereg bit in set_client_rereg c2ab189 opensm/osm_state_mgr.c: in cleanup_switch() check only relevant LFT part 40c93d3 use transportable constant attributes c8fa71a osmtest -code cleanup - use strncasecmp() 770704a opensm/osm_mcast_mgr.c: In mcast_mgr_set_mft_block, fix node GUID in log message 3d20f82 opensm/osm_sa_path_record.c: separate router guid resolution code 27ea3c8 opensm: fix gcc-4.4.1 warnings c88bfd3 opensm/osm_lid_mgr.c: Fix typo in OSM_LOG message a9ea08c opensm/osm_mesh.c: Add dump_mesh routine at OSM_LOG_DEBUG level bc2a61e C++ style coding does not compile 6647600 opensm: remove meanless 'const' keywords in APIs 323a74f opensm/osm_qos_parser_y.y: fix endless loop 0121a81 opensm: fix endless looping in mcast_mgr 696c022 opensm: fix some obvious -Wsign-compare warnings b91e3c3 opensm/osm_get_port_by_lid(): don't bother with lmc ca582df opensm/osm_get_port_by_lid(): speedup a port lookup fd846ee opensm/osm_mesh.c: simplify compare_switches() function fe20080 osm_sa.c - void * arithmetic causes problems 220130f osm_helper.c use explicit value for struct init 0168ece use standard varargs syntax in macro OSM_LOG() 180b335 update functions to match .h prototypes 9240ef4 opensm/osm_ucast_lash: fix use after free bug 6f1a21a opensm: osm_get_port_by_lid() helper c9e2818 opensm/osm_sa_path_record.c: validate multicast membership 225dcf5 opensm/osm_mesh.c: Remove edges in lash matrix 4dd928b opensm/osm_sa_mcmember_record.c: clean uninitialized variable use c48f0bc opensm/osm_perfmgr_db.c: Fix memory leak of db nodes 82d3585 opensm/osm_notice.c: move logging code to separate function 9557f60 opensm/osm_inform.c: For traps 64-67, use GID from DataDetails in log message e2e78d9 opensm/opensm.8.in: Indicate default rule for Default partition 08c5beb opensm/osm_sa_node_record.c: dump NodeInfo with debug verbosity 1fe88f0 opensm/multicast: merge mcm_port and mcm_info ba75747 opensm/multicast: consolidate port addition/removing code 5e61ab8 opensm: port object reference in mcm ports list 5c5dacf opensm: fix uninitialized return value in osm_sm_mcgrp_leave() 7cfe18d osm_ucast_ftree.c: Removed reverse_hop parameters from fabric_route_upgoing_by_going_down aa7fb47 opensm/multicast: kill mc group to_be_deleted flag a4910fe opensm/osm_mcast_mgr.c: multicast routing by mlid - renaming 1d14060 opensm/multicast: remove change id tracking 5a84951 opensm: use mgrp pointer as osm_sm_mcgrp_join/leave() parameter d8e3ff5 opensm: use mgrp pointer in port mcm_info 0631cd3 opensm doc: Indicated limited (rather than partial) partition membership 1010535 opensm/osm_ucast_lash.c: In lash_core, return status -1 for all errors 942e20f opensm/osm_helper.c: Add SM priority changed into trap 144 description 2372999 opensm/osm_ucast_mgr: better lft setup e268b32 opensm/osm_helper.c: Only change method when > rather than >= 9309e8c complib/cl_event.c: change nanosec var type long d93b126 opensm/complib: account for nsec overflow in timeout values ef4c8ac opensm/osm_qos_policy.c: matching PR query to QoS level with pkey c93b58b opensm: fixing some data types in osm_req_get/set 2b89177 opensm/libvendor/osm_vendor_ibumad.c: Handle umad_alloc failure in osm_vendor_get 2cba163 opensm/osm_helper.c: In osm_dump_dr_smp, fix endian of status 47397e3 opensm/osm_sm_mad_ctrl.c: Fix endian of status in error message e83b7ca opensm/osm_mesh.c: Reorder switches for lash 9256239 opensm/osm_trap_rcv.c: Validate trap is 144 before checking for NodeDescription changed 011d9ca opensm/osm_ucast_lash.c: Handle calloc failure in generate_cdg_for_sp 59964d7 opensm: fixing handling of opt.max_wire_smps f4e3cd0 opensm/osm_ucast_lash.c: Directly call calloc/free rather than create/delete_cdg 5a208bd opensm/osm_ucast_lash.c: Added error numbers to some error log messages 3b80d10 opensm/osm_helper.c: fix printing trap 258 details f682fe0 opensm: do not configure MFTs when mcast support is disabled cc42095 opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, indicate failed attribute aebf215 opensm/osm_ucast_lash.c: Remove osm_mesh_node_delete call from switch_delete 1ef4694 opensm/osm_path.h: In osm_dr_path_init, only copy needed part of path c594a2d opensm: osm_dr_path_extend can fail due to invalid hop count 46e5668 opensm/osm_lash: Fix use after free problem in osm_mesh_node_delete 81841dc opensm/osm_ucast_lash.c: Handle malloc failures better 2801203 opensm: remove extra "0x" from debug message. 88821d2 opensm/main.c: Display SMSL when specified f814dcd opensm/osm_subnet.c: Format lash_start_vl consistent with other uint8 items 66669c9 opensm/main.c: Display LASH start VL when specified 31bb0a7 opensm/osm_mcst_mgr.c: check number of switches only once 75e672c opensm: find MC group by MGID using fleximap 2b7260d Clarify the syntax of the hop_weights_file e6f0070 opensm/osm_mesh.c: Improve VL utilization 27497a0 opensm/osm_ucast_ftree.c Fix assert comparing number of CAs to CN ports 3b98131 opensm/osm_qos_policy.c: Use proper size in malloc in osm_qos_policy_vlarb_scope_create e6f367d opensm/osm_ucast_ftree.c: Made error numbers unique in some log messages 83261a8 osm_ucast_ftree.c Count number of hops instead of calculating it 7bdf4ff opensm/osm_sa_(path multipath)_record.c: Fix typo in a couple of log messages 0f8ed87 opensm/osm_ucast_mgr.c: Add error numbers to some error log messages 0b5ccb4 complib/Makefile.am: prevent file duplications e0b8ec9 opensm/osm_sminfo_rcv.c: clean type of smi_rcv_process_get_sm() 4d01005 opensm: sweep component processors return status value 6ad8d78 opensm/libvendor/osm_vendor_(ibumad mlx)_sa.c: Handle malloc failure in __osmv_send_sa_req cf97ebf opensm/osm_ucast_lash.(h c): Replace memory allocation by array 957461c opensm/osm_sa.c add attribute and component mask to error message 5d339a1 osm_dump.c dump port if lft is set up 518083d osm_port.c: check if op_vls = 0 before max_op_vls comparison b6964cb opensm/osm_port.c: Change log level of Invalid OP_VLS 0 message to VERBOSE b27568c opensm/PerfMgr: Reduce host name length bc495c0 opensm/osm_lid_mgr.c bug in opensm LID assignment 5a466fd opensm/osm_perfmgr_db.c: Remove unneeded initialization in perfmgr_db_print_by_name 57cf328 opensm/osm_ucast_ftree.c Increase the size of the hop table 8323cf1 opensm/PerfMgr: Remove some underbars from internal names 65b1c15 opensm: Changes to spec and make files for updated release notes cd226c7 OpenSM: include/vendor/osm_vendor.h - Replaced #elif with no condition by #else 9f8bd4a management: Fixed custom_release in SPEC files c0b8207 opensm/PerfMgr: Change redir_tbl_size to num_ports for better clarity 596bb08 opensm/osm_sa.c: check for SA DB file only if requested 2f2bd4e opensm SA DB dump/restore: load SA DB only once 4abcbf2 opensm: Added print_desc to various log messages 5e3d235 opensm/osm_vendor_ibumad.c: Move error info into single message 8e5ca10 opensm/libvendor//osm_vendor_ibumad_sa.c: uninitialized fields d13c2b6 opensm/osm_sm_mad_ctrl.c Changes to some error messages f79d315 opensm/osm_sm_mad_ctrl.c: Add missing call to return mad to mad pool 150a9b1 opensm/osm_sa_mcmember_record.c: print mcast join/create failures in VERBOSE instead of DEBUG level 9b7882a opensm/osm_vendor_ibumad.c: Change LID format to decimal in log message 5256c43 opensm/osm_vendor_mlx: fix compilation error 93db10d opensm/osm_vendor_mlx_txn.c: eliminate bunch of compilation warnings 156fdc1 opensm/osm_helper.c Log format changes 7a55434 opensm/osm_ucast_ftree.c Changed log level a1694de opensm/osm_state_mgr.c Added more info to some error messages fdec20a opensm/osm_trap_rcv.c: Eliminate heavy sweep on receipt of trap 145 13a32a7 opensm - standardize on a single Windows #define - take #2 b236a10 opensm/osm_db_files.c: kill useless malloc() castings 4ba0c26 opensm/osm_db_files.c: add '/' path delimited e3b98a5 opensm/osm_sm_mad_ctrl.c: Fix qp0_mads_accounting dbbe5b3 opensm/osm_subnet.c: fixing bug in dumping options file f22856a opensm/osm_ucast_mgr.c: fix memory leak 0d5f0b6 opensm: osm_get_mgrp_by_mgid() helper e3c044a osm_sa_mcmember_record.c: pass MCM Record data to mlid allocator 3dda2dc opensm/osm_sa_member_record.c: mlid independent MGID generator 1f95a3c opensm/osm_sa_mcmember_record.c: move mgid allocation code b78add1 complib: replace intn_t types by C99 intptr_t a864fd3 osmtest/osmt_mtl_regular_qp.c: cleaning uintn_t use 9e01318 opensm/osm_console.c: make const functions f8c4c3e opensm/osm_mgrp_new(): add subnet db insertion 80da047 complib/fleximap: make compar callback to return int bf7fe2d opensm: cleanup intn_t uses 0862bba opensm/main.c: opensm cannot be killed while asking for port guid 2b70193 opensm/complib: bug in cl_list_insert_array_head/tail functions 4764199 opensm - use C99 transportable data type for pointer storage a9c326c opensm/osm_state_mgr.c: do not probe remote side of port 0 4945706 opensm/osm_mcast_mgr.c: fix return value on alloc_mfts() failures 8312a24 OpenSM: Fix unused variable compiler warning. ab8f0a3 opensm/partition: keep multicast group pointer a817430 opensm: Only clear SMP beyond end of PortInfo attribute 52fb6f2 opensm/osm_switch.h: Remove dead osm_switch_get_physp_ptr routine aa6d932 opensm/osm_mcast_tbl.c: In osm_mcast_tbl_clear_mlid, use memset to clear port mask entry 2ad846b opensm/osm_trap_rcv.c: use source_lid and port_num for logging b9d7756 opensm/osm_mcast_tbl: Fix size of port mask table array 11c0a9b opensm/main.c: Use strtoul rather than strtol for parsing transaction timeout 0608af9 opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, revert setting of init failure on QoS initialization failures c6b4d4a opensm/osm_vendor_ibumad.c: Add transaction ID to osm_vendor_send log message 520af84 opensm/osm_sa_path_record.c: don't set dgid pointer for local subnet 4a878fb opensm/osm_mcast_mgr.c: fix osm_mcast_mgr_compute_max_hops for managed switch 7c48590 opensm/osm_log.c: add OSM_LOG_SYS to default flags 89f7cb6 opensm/osm_lid_mgr: use 'first_time_master_sweep' flag 0cb7fab opensm: conversion to osm_get_port_by_lid() 9d14fc0 opensm/osm_lid_mgr.c: fix memory leak c364aa1 opensm/opensm.init.in: fix install warning on SLES11 1010c9c opensm/osm_sa_path_record.c: livelock in pr_rcv_get_path_parms 4b2cd5e opensm/vendor: fix portguids array size 52bf5b2 opensm/osm_subnet.c: fixing some options to not "hot-swappable" 8900da0 opensm/osm_subnet.{c,h}: passing options to the event plugins 051c57f Delete port only after GID OUT trap was sent d4ebf7e opensm/complib/cl_passivelock.h: remove unneeded casting 8fdb17c opensm/complib/cl_types.h: convert cl_status_t to int fd7fb1e opensm/osm_mcast_mgr.c: preserve root switch calculation functionality fcb0f3a opensm/osm_mcast_mgr.c: code simplifications 444f559 opensm/osm_mcast_mgr.c: fix bug in MC root switch calculation 041ebcb opensm/osm_mcast_mgr.c: remove redundant casting 3717f53 opensm/osm_sa_pkey_record.c: optimize port selection logic 48352be opensm/osm_mcast_mgr.c: fix memory leak f3cf83f opensm/complib/cl_ptr_vector.c: fix bug/compiler warning 27c8ebd opensm/osm_subnet.h: remove redundant function definition f296938 opensm/osm_vl_arb_rcv.c: fix double mutex release bug 00bc48e opensm/osm_port_info_rcv.c: fix compilation warning 8823800 opensm/osm_sa.{c,h}: osm_sa_db_file_dump() return values f4581f3 opensm/osm_qos.c: Fix typo in OSM_LOG message e3c790a opensm/osm_update_node_desc(): minor prototype improvement 3cc68cb opensm/osm_vl_arb_rcv.c: Dump table after validating block number 7dbb96e opensm SA DB: dump only if modified fa2106d opensm/osm_sa_infrominfo.c: fixes and simplifications in lid range check 051a1dd opensm/osm_qos.c: split switch external and end ports setup a6c0189 opensm/osm_qos.c: merge SL2VL mapping capability check 3fe8efe opensm/osm_slvl_map_rcv.c: verify port number values received from network 88c372c opensm/osm_slvl_map_rcv.c: fix mutex double release bug d282093 opensm/osm_slvl_map_rcv.c: fix port parsing on BE machine 8e9dbd3 osm_sa_path_record.c: use PR DGID by reference 7c9d375 osm_sa_path_record.c: separate mutlicast processing code cb2d18e opensm/osm_sa_path_record.c: MGID must be specified explicitly bd3932b opensm/osm_mcast_mgr.c: strip log-only variable 9d93de3 opensm/osm_pkey_mgr.c: Eliminate unneeded parameter from pkey_mgr_get_physp_max_blocks API 5f49472 opensm/include/osm_helper.h: Eliminate some duplicate declarations e8ddcd4 opensm/osm_opensm.c: no report when SM is exiting 77ce7c8 complib/cl_timer: remove not needed timeval initializations 490aae2 opensm/osm_helper.c: Add some missing message names to disp_msg_str d678a21 opensm: Modify OSM_LOG_SYS messages 4cfb481 opensm: Fix wrong messages in MC delete flow 5b82f92 opensm/osm_req.c: In osm_send_trap144, eliminate redundant clear of m_key in smp 9bf64dc opensm/osm_qos.c: Eliminate unneeded endport SL to VL setup 34b536c opensm/osm_sa_path_record.c: adding wrapper for pr_rcv_get_path_parms() 237b5d1 opensm/osm_mcast_mgr.c: Only route MLIDs with more than 1 member a72db14 opensm/osm_trap_rcv.c: No need for heavy sweep when just NodeDescription changes ea9a768 opensm/osmtest.c: fix bug in getting attr offset a3dec3a iba/ib_types.h: remove assertion in ib_get_attr_offset() 6bc032a return no path when path does not exist 1592ae9 opensm: Better handling of non responsive SMAs a69f01b opensm/osm_perfmgr.c: Remove unnecessary lock reference from Performance Manager object 167ade2 opensm: fixing compilation issues in some header files e1c253e opensm/qos.c: Revert port ranges for calls to sl2vl_update_table(). 0689f49 opensm/libvendor Reduce stack consumption 59056c7 opensm - address windows env issues ff14200 opensm/osm_sa_multipath_record.c: livelock in mpr_rcv_get_path_parms 3f23d83 opensm/osm_sa_path_record.c: Add error code to newly added log message 7fc6cd3 ib_types.h add debug assert 4fd4ca3 osmtest - use helper function 6fdc20a opensm/complib use portable macro syntax bf23d7c opensm: fixed getline pointer allocation free in osm_console_io 74867c7 Add node/port/qos information to some error messages 31a617d replace (long*)(long) casting with transportable data type (uintptr_t) 8da7521 opensm/st.c: fix potential core dumps 6a30911 opensm/osm_console.c: fix memory and file descriptor leaks 696f12c opensm/osm_qos_parser_y.y: fixing bunch of memory leaks on invalid values 3a7b97c opensm/osm_ucast_file.c: closing file descriptor in error path b4575c5 opensm/osm_pkey_mgr.c: fixing small memory leak dc0695f opensm/osm_ucast_lash.c: small bug in calculating allocated size 3c9604b opensm/osm_ucast_ftree.c: fixing another memory leak at error path 4460990 opensm/osm_ucast_ftree.c: fix small memory leak in error path 857cd6c opensm/osm_trap_rcv.c: fix possible core dump b74bef5 opensm/osm_trap_rcv.c: No need to check for sweep for trap 145 81dade3 opensm/osm_ucast_ftree: When roots are not connected, update hop count but not lft acf2337 osmtest/osmt_service.c: In osmt_run_service_records_flow, add missing status 6db7f4a opensm/osm_state_mgr.c: Don't signal DISCOVER to SM state machine when already DISCOVERING 28693c5 Fix autotools to include the necessary M4 files c1c8730 osm_vl15intf.c: fixing use-after-free coredump 3353f9b opensm/osm_helper.c: use ARR_SIZE macro instead of hardcoded values 2da9849 osmtest/osmt_slvl_vl_arb.c: handling fopen() failure f48d5ea opensm/osm_db_files.c: malloc() return value run-time check ea3ef82 opensm/osm_db_files.c: fix small memory leak f4a5174 opensm/osm_subnet.c: fixing small bug in error path c18ef23 opensm/osm_mesh.c: fixing a bug in compare_switches() 83b74cd opensm/osm_helper.c: fix potential overrun of the array 85c0ac9 osmtest/osmtest.c: handle timeouts in PR stress test ebb2c84 opensm/osm_node_info_rcv.c: move p_physp declaration under code block 5c88113 opensm/osm_node_info_rcv.c: remove useless code line 866d939 opensm/osm_sa_vlarb_record.c: removed unused variable 15a8770 opensm/osm_sa_pkey_record.c: removing unused variable 8f002b7 opensm/osm_pkey.c: removing unused function 9c0fa2f opensm/osm_sminfo_rcv.c: removing unused variable d3f060a opensm/osm_mtree.c: removing useless 'if' statement bbef64a libvendor/osm_vendor_mlx_sa.c: remove useless "if" statement 2da02b5 libvendor/osm_vendor_ibumad_sa.c: remove useless "if" statement 435dde0 opensm/sa: simplify osm_mcmr_rcv_find_or_create_new_mgrp() function call e7a872d opensm/osm_qos_policy.c: change a log message ffbe7d0 opensm: Cause status of unicast routing attempt to propogate to callers of osm_ucast_mgr_process(). 673877a opensm: Make mcast_mgr_purge_tree() available outside osm_mcast_mgr.c. b135687 opensm: Track the minimum value in the fabric of data VLs supported. 7c1ee64 opensm: Fix typo in routing section in man page and doc d206011 opensm/osmtest/osmtest.c: inventory file parsing bugfix e01121a fixed deprecated conversion from string constant to char* warning a7ba101 opensm/main.c: Change size parameter in setvbuf call from 0 to BUFSIZ 2a92554 opensm/osmtest/osmt_multicast.c: Fix multicast flow failures on pkey validation 364e65b opensm/osm_dump.c: Fix FDR10 speed dumping 80e11b9 osmtest/osmt_multicast.c: Fix check of partial JoinState delete request - removing NonMember (o15.0.1.14) 78e1e4e osmtest/osmt_multicast.c: Fix check of BAD RATE when connecting to existing MGID (o15.0.1.13) e94e972 osmtest/osmt_multicast.c: Fix first MGID=0 MC group creation case daedad7 opensm/osmtest/osmt_multicast.c: Fix an unrealistic rate case 110ae10 opensm: fixed segfault in osm_destroy d666205 opensm/osm_prtn.c: Fix typo in log message f3ccb45 opensm: Remove duplicate definition of IB_MAD_STATUS_CLASS_MASK 917070c Move no_fallback_routing_engine from osm_subn_opt_t to osm_opensm_t. d71a924 Free memory from osm_subn_opt_t when osm_subn_t destroyed 1b75fa4 Remove duplicate initialization of scatter_ports b5f4570 Do not load configs from the default config file and specified config file f24a089 Fix memleak and segfault 247d0d8 Fix IPoIB broadcast group creation on non-default Pkey 78d86bd opensm/osm_subnet.c: Trivial optimization to code flow in subn_verify_sl2vl 6bb41e3 opensm/complib/cl_atomic.h: Commentary changes 28ee7b9 opensm/osm_sa_class_port_info.c: Conditionalize setting of OSM_CAP2_IS_MCAST_TOP_SUPPORTED 29e59a2 Removed unused parameter "ib_mad_addr" from umad_reciever() 63ad0bb opensm/osmeventplugin/src/osmeventplugin.c: Output LIDs in decimal 17967c2 opensm/osm_switch.h: Fix commentary typo 6d3e223 opensm/osm_perfmgr.c: Enhance send error log message 08abcd4 opensm/osm_sa_mad_ctrl.c: Enhance send error log message 13f3e0f opensm/libvendor/osm_vendor_ibumad.c: Fix DR path printing on send timeouts 0dfd760 Fix suggest parentheses around operand warning ad2dbf8 Support source-target-port-guid QoS policy configuration with ULP 'any' 080e3ad Support source-port-guid QoS policy configuration with ULP 'any' 49777a9 Fix typo in qos-ulps parsing comment bcfe1b9 opensm/osm_torus.c: Use "OpenSM standard" error codes 683397d Fix use of GNU old-style field designator extension 719fcd4 Fix use of logical && with constant operand; switch to bitwise & 6bc87bd opensm: fix search common pkeys a6ac5e3 opensm/osm_drop_mgr.c: GID out trap fix 7717505 opensm/osm_pkey_mgr.c: fix segfault when trying to access not allocated block eb90efd include/opensm/osm_subnet.h: fix comment typos 0a315e3 opensm/include/iba/ib_types.h: fix comment typos and errors 125baa0 opensm/opensm.8.in: Fix cut 'n paste error f0d14d2 opensm/osm_ucast_ftree.c: Fix some typos 841096f opensm: Fix opensm handover/relinquish corner case bf420ac opensm/osm_helper.c: Fix commentary typo 2be999c opensm: fixed description in osm_routing_engine cf3d185 gen_chlog.sh: fixed version ordering 8d49c5d opensm/osm_sa_guidinfo_record.c: Fix locking 8d764b8 Fix continous looping when clearing accum_pkeys table 32500a6 opensm/osm_link_mgr.c: Fix sending PortInfo Set for ports supporting extended speed e24ff39 Fix Pkey enforcement configuration 041e47a Fix PathRecord reply to be the same for allow_both_pkeys ON and OFF 3c9b81d OpenSM/osm_prtn_config.c: Fix non-initialized pointer usage 28a40a2 Fix logging messages about op_vls and mtu mismatch 5e672a6 Fix memory leak on dfsssp_context_destroy() 3a87fa2 opensm/osm_req.c: fix first sweep m_key search algorithm 2108431 opensm: fix default cc_max_outstanding_mads assignment dae214f opensm/osm_log.h: fix function documentation 1cf0bb9 opensm/osm_congestion_control.c: fix use-after-free found by coverity ab5af49 opensm/osm_ucast_dfsssp.c : fix dereference before null check b6a2f6a opensm/osm_ucast_dfsssp.c : fix dereference null return value df66c1f opensm: Fix incorrect use of sizeof c58a416 opensm/osm_dump.c: Fix output port on SL2VL table for non switch nodes 8af5bce opensm/osm_sa_slvl_record.c: Fix out port for CAs and routers 18a77f9 opensm/osm_torus.c: Fix memory leak 4ccbdc1 Fix -Wformat-security warnings with clang c762389 Fix -Wtautological-compare warnings with clang 9e6dd8f Fix linker error with clang with -O < 2 27da5eb opensm/include/osm_opensm.h: Fix commentary typo b9067ba opensm/include/complib/cl_packon.h: Fix some commentary typos e522f74 opensm/osm_perfmgr_db.c: Fix output error due to possible 32bit int overflow 6f94c4c opensm: Fix signed vs unsigned int comparison 2ea2cf3 opensm/osm_vl15intf.c: Fix commentary typo f396936 opensm/complib/cl_atomic_osd.h: Fix long standing bug in cl_atomic_sub 606157c osmtest/osmt_multicast.c: Fix 02BF error 03d55f6 opensm/osm_sw_info_rcv.c: Fixed locking issue on osm_get_node_by_guid error d7e4da1 opensm: Use IB_PATH_SELECTOR_EXACTLY rather than harded coded constant 735c86d opensm/osm_sa_informinfo.c: Fix infr_rcv_respond to only copy InformInfo 074ec5a osm_perfmgr.h: Cosmetic formatting changes 05af776 osm_drop_mgr.c: Add missing assert de254f9 osm_opensm.c: Add missing ERR number b1e58bb osmeventplugin: Fix compile warning 48c9f43 osm_prtn_config.c: Some changes to osm_prtn_config_parse_file 6321afa osm_subnet.c: Cosmetic change to config file output aaa7b1e osm_db_files.c: Some minor fixes/improvements to osm_db_store 3cae07c osm_perfmgr.c: Cosmetic formatting changes 07b24a3 osm_port_info_rcv.c: Reset client reregister bit only on a response to SET 84c9832 osm_ucast_ftree.c: replace assert with error return value 1c0f0 osm_sa_path_record.c: Improve ERR 1F1D to show the pkey specified in PathQuery 94e99a8 osm_mcast_mgr.c: Removed mcast_mgr_purge_tree_node due to code duplication 929934e osm_pkey.[h c]: Remove dead function osm_pkey_tbl_clear_accum_pkeys bf42ec8 osm_mtree.c: Cosmetic change in osm_mtree_destroy function 7e96f32 osm_sm_state_mgr.c: Fix handling of polling retry number 78d87b9 osm_mcast_mgr.c: fixed missing error message number a1df1d7 osm_state_mgr.c: Fix error print in state_mgr_check_tbl_consistency() 1441937 osm_mcast_mgr.c Add block number to error message edd5e74 Redundant remove() function call during db file generation dcb2df0 osm_link_mgr.c: Fix uninitialized value (physp0) 7160cce osm_link_mgr.c: Fix uninitialized value (physp0) 5aa4ea3 osm_link_mgr.c: fix uninitialized variable usage cf014ec reduce log level for missing partition configuration file. d3aeae8 osmtest: Handle other than default subnet prefix 181c863 osm_vendor_ibumad.c: Improve ERR 5430 log message 7321689 osm_state_mgr.c Add info to some error messages 0fc753d osm_sa_path_record.c: Eliminate extraneous space in 1F1A log message 18b3be9 Use trap number defines rather than actual trap numbers 270a700 osm_db_files.c: Add osm_db_domain_init failure handling into test program 2b82c1c Handle memory allocation failure in osm_db_domain_init() 8284132 Use after free in osm_prtn_delete e186b4a osm_sa_guidinfo_record.c: False duplicate GUID error messages d95d461 osm_sa_informinfo.c Add attribute info to log messages 94789a8 osm_port_info_rcv.c Issue a log message if we cannot read the MKey of a port b67db2b osm_helper.c: Fix out-of-bounds read ef86015 osm_db_files.c : Fix resource leak guid2lid parser 4a2d2d8 osm_subnet.c: Fix memory leak caused by commit dc0760cb8088fbe079e19682570a884ba01e94ff 168eaeb osm_db_files.c: Fix memory leak when deleting entries from osm db edfaddc osm_ucast_dfsssp.c: Fix some typos e1804f4 dfsssp - add missing and change existing return values d5ef9af update man page and usage explanation for --lfts_file 6fdd844 osm_sa_path_record.c: Fix rate setting issue in SA PR handling 4d6925c osm_vendor_ibumad.c: Fix explicit null derefenced issue found by coverity 2d67f3e opensm/osm_db_pack.c: Removed uneeded asserts 09e1e7e libvendor/osm_pkt_randomizer.c: Fix broken compilation with vendor sim 6ff99aa complib/cl_event_wheel.c: Add print of num_regs in cl_event_wheel_dump a3957f2 complib/cl_event_wheel.c: Fix duplicate error codes ceb4041 Fix test scenario in cl_event_wheel 5824714 osmeventplugin/osmeventplugin.c: Add Mellanox copyright 7186965 osm_event_plugin.h: Add Mellanox copyright cd3b715 osmtest: Make the "-guid" option's argument mandatory 0154977 complib/cl_event_wheel.h: Some cosmetic fixes b78b1d5 osm_sa_mcmember_record.c validate_requested_mgid returning boolean 58ee065 osm_ucast_mgr.c: Fix extra copy in set_lft_block routine 5bf6e72 osm_ucast_mgr.c: Fix duplicated code for fallback routing engine 2e5966e osm_sm_state_mgr.c Trivial log changes aed1675 Log changes related to event subscription and forwarding 75bba51 Minor log formatting changes 16b4dfc Some log changes 51f87ee Add attribute information to SA request error messages abd47cc osm_sa_mcmember_record.c Reduce number of error messages the for same event ae9d7e7 Add trap details to notice log message 886de5d ib_types.h: Fix commentary typo 234401b cl_threadpool.h: Remove vestigial mention of cl_thread_pool_construct e20f37a osm_subnet.c Remove empty syslog message 898e9a3 osm_ucast_lash.c: Cosmetic formatting change 6d0413d opensm/osm_ucast_dfsssp.c: Fix unused variable in update_mcft() 583d4cf osm_console_io.c: Handle another write-strings issue cbbe385 osm_sa_mcmember_record.c: Improve debug log message in validate_modify 4f835ae osm_congestion_control.c: Simplify some code 23ebbe9 osm_log.c: Remove unneeded initialization in osm_log 550fdeb osm_lid_mgr.c: Some commentary fixes/updates 1d50845 opensm: Add configure output messages for several configure options 91384ed osm_lid_mgr.c: Fix a couple of commentary typos a238800 ib_types.h: Trap 144 PortInfo:CapabilityMask2 changed bit definition 564b6eb opensm: fix dfsssp uninitialized value 395157e opensm/osm_node.h: Fix some commentary typos 664494a opensm: Fix issues causing const warnings for strings 8840f82 opensm/osm_switch.h: Cosmetic change 1a06167 opensm/man/osmtest.8: Add option for using full world path queries eb43f7e opensm/osm_torus.c: clarify log messages on stale priv pointers 1f7ceb8 opensm/osmtest: fix debug build dc0760c opensm/osm_subnet.c: Miscellaneous minor fixes 4924ea7 osmtest: Add support for full world path records back as option 6f1a67e osmtest/osmtest.c: Minor reordering of code in osmtest_write_all_path_recs e9556df opensm/osmtest.c: half_world_query when creating inventory file 81d3ea3 opensm/osm_subnet.c: Change default for perfmgr_query_cpi to FALSE 309317d opensm/osm_ucast_ftree.c: Fix invalid debug output message d0a8532 opensm/perfmgr: clean up: break out redirect processing from pc_recv_process ef32e12 opensm: make osm_pr_rcv_get_end_points, osm_pr_rcv_process_pair, osm_pr_rcv_process_half public 7723c07 opensm: make osm_get_path_params public 7ac18bb opensm/osm_perfmgr.c: Cosmetic changes fe52571 opensm/perfmgr: add failed port guid to error message 8b67a1c opensm/osm_req.c: Better implementation of req_determine_mkey 37eecc8 opensm/libibvendor: osm_vendor_get_all_port_attr include sm_sl value in port attribute struct 8ac930e osmtest/osmt_multicast.c: Fix IPoIB MC group recognition 5a33cc6 osmtest/osmt_multicast.c: Fix commentary typo 186a598 opensm/osm_sa_multipath_record.c: Fix commentary typo 4cb3751 osm_dump.c: Fix typo in dump_lid_matrix a0deac6 opensm/osm_dump.c: Fix enhanced switch port 0 handling in print_node_report abbbe8a opensm/ib_types.h: Add missing IB_MPR_COMPMASK_SERVICEID define 505d48b opensm/osm_torus.c: Cosmetic formatting changes dc44d48 opensm/ib_types.h: Add missing IB_PR_COMPMASK_SERVICEID define * Other less critical or visible bugs were also fixed. 5 Main Verification Flows ------------------------- OpenSM verification is run using the following activities: * osmtest - a stand-alone program * ibmgtsim (IB management simulator) based - a set of flows that simulate clusters, inject errors and verify OpenSM capability to respond and bring up the network correctly. * small cluster regression testing - where the SM is used on back to back or single switch configurations. The regression includes multiple OpenSM dedicated tests. * cluster testing - when we run OpenSM to setup a large cluster, perform hand-off, reboots and reconnects, verify routing correctness and SA responsiveness at the ULP level (IPoIB and SDP). 5.1 osmtest osmtest is an automated verification tool used for OpenSM testing. Its verification flows are described by list below. * Inventory File: Obtain and verify all port info, node info, link and path records parameters. * Service Record: - Register new service - Register another service (with a lease period) - Register another service (with service p_key set to zero) - Get all services by name - Delete the first service - Delete the third service - Added bad flows of get/delete non valid service - Add / Get same service with different data - Add / Get / Delete by different component mask values (services by Name & Key / Name & Data / Name & Id / Id only ) * Multicast Member Record: - Query of existing Groups (IPoIB) - BAD Join with insufficient comp mask (o15.0.1.3) - Create given MGID=0 (o15.0.1.4) - Create given MGID=0xFF12A01C,FE800000,00000000,12345678 (o15.0.1.4) - Create BAD MGID=0xFA. (o15.0.1.6) - Create BAD MGID=0xFF12A01B w/ link-local not set (o15.0.1.6) - New MGID with invalid join state (o15.0.1.9) - Retry of existing MGID - See JoinState update (o15.0.1.11) - BAD RATE when connecting to existing MGID (o15.0.1.13) - Partial JoinState delete request - removing FullMember (o15.0.1.14) - Full Delete of a group (o15.0.1.14) - Verify Delete by trying to Join deleted group (o15.0.1.14) - BAD Delete of IPoIB membership (no prev join) (o15.0.1.15) * GUIDInfo Record: - All GUIDInfoRecords in subnet are obtained * MultiPathRecord: - Perform some compliant and noncompliant MultiPathRecord requests - Validation is via status in responses and IB analyzer * PKeyTableRecord: - Perform some compliant and noncompliant PKeyTableRecord queries - Validation is via status in responses and IB analyzer * LinearForwardingTableRecord: - Perform some compliant and noncompliant LinearForwardingTableRecord queries - Validation is via status in responses and IB analyzer * Event Forwarding: Register for trap forwarding using reports - Send a trap and wait for report - Unregister non-existing * Trap 64/65 Flow: Register to Trap 64-65, create traps (by disconnecting/connecting ports) and wait for report, then unregister. * Stress Test: send PortInfoRecord queries, both single and RMPP and check for the rate of responses as well as their validity. 5.2 IB Management Simulator OpenSM Test Flows: The simulator provides ability to simulate the SM handling of virtual topologies that are not limited to actual lab equipment availability. OpenSM was simulated to bring up clusters of up to 10,000 nodes. Daily regressions use smaller (16 and 128 nodes clusters). The following test flows are run on the IB management simulator: * Stability: Up to 12 links from the fabric are randomly selected to drop packets at drop rates up to 90%. The SM is required to succeed in bringing the fabric up. The resulting routing is verified to be correct as well. * LID Manager: Using LMC = 2 the fabric is initialized with LIDs. Faults such as zero LID, Duplicated LID, non-aligned (to LMC) LIDs are randomly assigned to various nodes and other errors are randomly output to the guid2lid cache file. The SM sweep is run 5 times and after each iteration a complete verification is made to ensure that all LIDs that could possibly be maintained are kept, as well as that all nodes were assigned a legal LID range. * Multicast Routing: Nodes randomly join the 0xc000 group and eventually the resulting routing is verified for completeness and adherence to Up/Down routing rules. * osmtest: The complete osmtest flow as described in the previous table is run on the simulated fabrics. * Stress Test: This flow merges fabric, LID and stability issues with continuous PathRecord, ServiceRecord and Multicast Join/Leave activity to stress the SM/SA during continuous sweeps. InformInfo Set/Delete/Get were added to the test such both existing and non existing nodes perform them in random order. 5.3 OpenSM Regression Using a back-to-back or single switch connection, the following set of tests is run nightly on the stacks described in table 2. The included tests are: * Stress Testing: Flood the SA with queries from multiple channel adapters to check the robustness of the entire stack up to the SA. * Dynamic Changes: Dynamic Topology changes, through randomly dropping SMP packets, used to test OpenSM adaptation to an unstable network & verify DB correctness. * Trap Injection: This flow injects traps to the SM and verifies that it handles them gracefully. * SA Query Test: This test exhaustively checks the SA responses to all possible single component mask. To do that the test examines the entire set of records the SA can provide, classifies them by their field values and then selects every field (using component mask and a value) and verifies that the response matches the expected set of records. A random selection using multiple component mask bits is also performed. 5.4 Cluster testing: Cluster testing is usually run before a distribution release. It involves real hardware setups of 16 to 32 nodes (or more if a beta site is available). Each test is validated by running all-to-all ping through the IB interface. The test procedure includes: * Cluster bringup * Hand-off between 2 or 3 SM's while performing: - Node reboots - Switch power cycles (disconnecting the SM's) * Unresponsive port detection and recovery * osmtest from multiple nodes * Trap injection and recovery 6 Qualified Software Stacks and Devices --------------------------------------- OpenSM Compatibility -------------------- Note that OpenSM version 3.2.1 and earlier used a value of 1 in host byte order for the default SM_Key, so there is a compatibility issue with these earlier versions of OpenSM when the 3.2.2 or later version is running on a little endian machine. This affects SM handover as well as SA queries (saquery tool in infiniband-diags). Table 2 - Qualified IB Stacks ============================= Stack | Version -----------------------------------------|-------------------------- The main stream Linux kernel | 2.6.x OFED | 1.5,1.5.x OFED | 1.4 OFED | 1.3 OFED | 1.2 OFED | 1.1 OFED | 1.0 Table 3 - Qualified Devices and Corresponding Firmware ====================================================== Mellanox Device | FW versions ------------------------------------|------------------------------- InfiniScale | fw-43132 5.2.000 (and later) InfiniScale III | fw-47396 0.5.000 (and later) InfiniScale IV | fw-48436 7.1.000 (and later) InfiniHost | fw-23108 3.5.000 (and later) InfiniHost III Lx | fw-25204 1.2.000 (and later) InfiniHost III Ex (InfiniHost Mode) | fw-25208 4.8.200 (and later) InfiniHost III Ex (MemFree Mode) | fw-25218 5.3.000 (and later) ConnectX IB | fw-25408 2.3.000 (and later) QLogic/PathScale Device | Note --------|----------------------------------------------------------- iPath | QHT6040 (PathScale InfiniPath HT-460) iPath | QHT6140 (PathScale InfiniPath HT-465) iPath | QLE6140 (PathScale InfiniPath PE-880) iPath | QLE7240 iPath | QLE7280 Note 1: OpenSM does not run on an IBM Galaxy (eHCA) as it does not expose QP0 and QP1. However, it does support it as a device on the subnet. Note 2: QoS firmware and Mellanox devices HCAs: QoS supported by ConnectX. QoS-enabled FW release is 2_5_000 and later. Switches: QoS supported by InfiniScale III Any InfiniScale III FW that is supported by OpenSM supports QoS. opensm-3.3.20/include/0000755000205000001450000000000012726324777011534 500000000000000opensm-3.3.20/include/opensm/0000755000205000001450000000000012726324767013034 500000000000000opensm-3.3.20/include/opensm/osm_config.h.in0000644000205000001450000000334012726324751015646 00000000000000/* include/osm_config.h.in * * Defines various OpenSM configuration parameters to be used by various * plugins and third party tools. * * NOTE: Defines used in header files MUST be included here to ensure plugin * compatibility. */ #ifndef _OSM_CONFIG_H_ #define _OSM_CONFIG_H_ /* define 1 if OpenSM build is in a debug mode */ #undef OSM_DEBUG #undef _DEBUG_ /* Define as 1 if you want Dual Sided RMPP Support */ #undef DUAL_SIDED_RMPP /* Define as 1 if you want to enable a console on a socket connection */ #undef ENABLE_OSM_CONSOLE_SOCKET /* Define as 1 if you want to enable the event plugin */ #undef ENABLE_OSM_DEFAULT_EVENT_PLUGIN /* Define as 1 if you want to enable the performance manager */ #undef ENABLE_OSM_PERF_MGR /* Define as 1 if you want to enable the performance manager profiling code */ #undef ENABLE_OSM_PERF_MGR_PROFILE /* Define a default node name map file */ #undef HAVE_DEFAULT_NODENAME_MAP /* Define a default OpenSM config file */ #undef HAVE_DEFAULT_OPENSM_CONFIG_FILE /* Define a Partition config file */ #undef HAVE_DEFAULT_PARTITION_CONFIG_FILE /* Define a Prefix Routes config file */ #undef HAVE_DEFAULT_PREFIX_ROUTES_FILE /* Define a QOS policy config file */ #undef HAVE_DEFAULT_QOS_POLICY_FILE /* Define OpenSM config directory */ #undef OPENSM_CONFIG_DIR /* Define as 1 for vapi vendor */ #undef OSM_VENDOR_INTF_MTL /* Define as 1 for OpenIB vendor */ #undef OSM_VENDOR_INTF_OPENIB /* Define as 1 for sim vendor */ #undef OSM_VENDOR_INTF_SIM /* Define as 1 for ts vendor */ #undef OSM_VENDOR_INTF_TS /* Define as 1 if you want Vendor RMPP Support */ #undef VENDOR_RMPP_SUPPORT /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD #endif /* _OSM_CONFIG_H_ */ opensm-3.3.20/include/opensm/osm_version.h.in0000644000205000001450000000344212104655724016066 00000000000000/* * Copyright (c) 2004-2008 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. * */ #ifndef _OSM_VERSION_H_ #define _OSM_VERSION_H_ /****s* OpenSM: Base/OSM_VERSION * NAME * OSM_VERSION * * DESCRIPTION * The version string for OpenSM * * SYNOPSIS */ #define OSM_VERSION "OpenSM @VERSION@" /********/ #endif /* _OSM_VERSION_H_ */ opensm-3.3.20/include/opensm/osm_attrib_req.h0000644000205000001450000000606312104655724016132 00000000000000/* * Copyright (c) 2004-2008 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. * */ #ifndef _OSM_ATTRIB_REQ_H_ #define _OSM_ATTRIB_REQ_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * Abstract: * Declaration of the attribute request object. This object * encapsulates information needed by the generic request controller * to request an attribute from a node. * These objects are part of the OpenSM family of objects. */ /****h* OpenSM/Attribute Request * NAME * Attribute Request * * DESCRIPTION * The Attribute Request structure encapsulates * encapsulates information needed by the generic request controller * to request an attribute from a node. * * This structure allows direct access to member variables. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Attribute Request/osm_attrib_req_t * NAME * osm_attrib_req_t * * DESCRIPTION * Attribute request structure. * * This structure allows direct access to member variables. * * SYNOPSIS */ typedef struct osm_attrib_req { uint16_t attrib_id; uint32_t attrib_mod; osm_madw_context_t context; osm_dr_path_t path; cl_disp_msgid_t err_msg; } osm_attrib_req_t; /* * FIELDS * attrib_id * Attribute ID for this request. * * attrib_mod * Attribute modifier for this request. * * context * Context to insert in outbound mad wrapper context. * * path * The directed route path to the node. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_ATTRIB_REQ_H_ */ opensm-3.3.20/include/opensm/osm_base.h0000644000205000001450000006012412654627044014712 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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: * Basic OpenSM definitions and structures. * This object represents an OpenSM "base class". * This object is part of the OpenSM family of objects. */ #ifndef _OSM_BASE_H_ #define _OSM_BASE_H_ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef __WIN__ #include #endif #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Constants * NAME * Constants * * DESCRIPTION * The following constants are used throughout the OpenSM. * * AUTHOR * Steve King, Intel * *********/ /****h* OpenSM/Base * NAME * Base * * DESCRIPTION * The Base object encapsulates basic information needed by the * OpenSM to manage objects. Each OpenSM object includes the * Base object as the first member. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Base/OSM_DEFAULT_M_KEY * NAME * OSM_DEFAULT_M_KEY * * DESCRIPTION * Managment key value used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_M_KEY 0 /********/ /****s* OpenSM: Base/OSM_DEFAULT_SM_KEY * NAME * OSM_DEFAULT_SM_KEY * * DESCRIPTION * Subnet Manager key value used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_SM_KEY CL_HTON64(1) /********/ /****s* OpenSM: Base/OSM_DEFAULT_SA_KEY * NAME * OSM_DEFAULT_SA_KEY * * DESCRIPTION * Subnet Adminstration key value. * * SYNOPSIS */ #define OSM_DEFAULT_SA_KEY OSM_DEFAULT_SM_KEY /********/ /****s* OpenSM: Base/OSM_DEFAULT_LMC * NAME * OSM_DEFAULT_LMC * * DESCRIPTION * Default LMC value used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_LMC 0 /********/ /****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS * NAME * OSM_DEFAULT_MAX_OP_VLS * * DESCRIPTION * Default Maximal Operational VLs to be initialized on * the link ports PortInfo by the OpenSM. * Default value provides backward compatibility. * * SYNOPSIS */ #define OSM_DEFAULT_MAX_OP_VLS 5 /********/ /****s* OpenSM: Base/OSM_DEFAULT_SL * NAME * OSM_DEFAULT_SL * * DESCRIPTION * Default SL value used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_SL 0 /********/ /****s* OpenSM: Base/OSM_DEFAULT_SCATTER_PORTS * NAME * OSM_DEFAULT_SCATTER_PORTS * * DESCRIPTION * Default Scatter Ports value used by OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_SCATTER_PORTS 0 /********/ /****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY * NAME * OSM_DEFAULT_SM_PRIORITY * * DESCRIPTION * Default SM priority value used by the OpenSM, * as defined in the SMInfo attribute. 0 is the lowest priority. * * SYNOPSIS */ #define OSM_DEFAULT_SM_PRIORITY 0 /********/ /****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR * NAME * OSM_DEFAULT_TMP_DIR * * DESCRIPTION * Specifies the default temporary directory for the log file, * osm-subnet.lst, and other log files. * * SYNOPSIS */ #ifdef __WIN__ #define OSM_DEFAULT_TMP_DIR "%TEMP%\\" #else #define OSM_DEFAULT_TMP_DIR "/var/log/" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR * NAME * OSM_DEFAULT_CACHE_DIR * * DESCRIPTION * Specifies the default cache directory for the db files. * * SYNOPSIS */ #ifdef __WIN__ #define OSM_DEFAULT_CACHE_DIR "%TEMP%" #else #define OSM_DEFAULT_CACHE_DIR "/var/cache/opensm" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE * NAME * OSM_DEFAULT_LOG_FILE * * DESCRIPTION * Specifies the default log file name * * SYNOPSIS */ #ifdef __WIN__ #define OSM_DEFAULT_LOG_FILE OSM_DEFAULT_TMP_DIR "osm.log" #else #define OSM_DEFAULT_LOG_FILE "/var/log/opensm.log" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_CONFIG_FILE * NAME * OSM_DEFAULT_CONFIG_FILE * * DESCRIPTION * Specifies the default OpenSM config file name * * SYNOPSIS */ #if defined(HAVE_DEFAULT_OPENSM_CONFIG_FILE) #define OSM_DEFAULT_CONFIG_FILE HAVE_DEFAULT_OPENSM_CONFIG_FILE #elif defined (OPENSM_CONFIG_DIR) #define OSM_DEFAULT_CONFIG_FILE OPENSM_CONFIG_DIR "/opensm.conf" #else #define OSM_DEFAULT_CONFIG_FILE "/etc/opensm/opensm.conf" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE * NAME * OSM_DEFAULT_PARTITION_CONFIG_FILE * * DESCRIPTION * Specifies the default partition config file name * * SYNOPSIS */ #if defined(HAVE_DEFAULT_PARTITION_CONFIG_FILE) #define OSM_DEFAULT_PARTITION_CONFIG_FILE HAVE_DEFAULT_PARTITION_CONFIG_FILE #elif defined(OPENSM_CONFIG_DIR) #define OSM_DEFAULT_PARTITION_CONFIG_FILE OPENSM_CONFIG_DIR "/partitions.conf" #else #define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/opensm/partitions.conf" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_POLICY_FILE * NAME * OSM_DEFAULT_QOS_POLICY_FILE * * DESCRIPTION * Specifies the default QoS policy file name * * SYNOPSIS */ #if defined(HAVE_DEFAULT_QOS_POLICY_FILE) #define OSM_DEFAULT_QOS_POLICY_FILE HAVE_DEFAULT_QOS_POLICY_FILE #elif defined(OPENSM_CONFIG_DIR) #define OSM_DEFAULT_QOS_POLICY_FILE OPENSM_CONFIG_DIR "/qos-policy.conf" #else #define OSM_DEFAULT_QOS_POLICY_FILE "/etc/opensm/qos-policy.conf" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_TORUS_CONF_FILE * NAME * OSM_DEFAULT_TORUS_CONF_FILE * * DESCRIPTION * Specifies the default file name for extra torus-2QoS configuration * * SYNOPSIS */ #ifdef __WIN__ #define OSM_DEFAULT_TORUS_CONF_FILE strcat(GetOsmCachePath(), "osm-torus-2QoS.conf") #elif defined(OPENSM_CONFIG_DIR) #define OSM_DEFAULT_TORUS_CONF_FILE OPENSM_CONFIG_DIR "/torus-2QoS.conf" #else #define OSM_DEFAULT_TORUS_CONF_FILE "/etc/opensm/torus-2QoS.conf" #endif /* __WIN__ */ /***********/ /****d* OpenSM: Base/OSM_DEFAULT_PREFIX_ROUTES_FILE * NAME * OSM_DEFAULT_PREFIX_ROUTES_FILE * * DESCRIPTION * Specifies the default prefix routes file name * * SYNOPSIS */ #if defined(HAVE_DEFAULT_PREFIX_ROUTES_FILE) #define OSM_DEFAULT_PREFIX_ROUTES_FILE HAVE_DEFAULT_PREFIX_ROUTES_FILE #elif defined(OPENSM_CONFIG_DIR) #define OSM_DEFAULT_PREFIX_ROUTES_FILE OPENSM_CONFIG_DIR "/prefix-routes.conf" #else #define OSM_DEFAULT_PREFIX_ROUTES_FILE "/etc/opensm/prefix-routes.conf" #endif /***********/ /****d* OpenSM: Base/OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE * NAME * OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE * * DESCRIPTION * Specifies the default file name for per module logging configuration * * SYNOPSIS */ #ifdef __WIN__ #define OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE strcat(GetOsmCachePath(), "per-module-logging.conf") #elif defined(OPENSM_CONFIG_DIR) #define OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE OPENSM_CONFIG_DIR "/per-module-logging.conf" #else #define OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE "/etc/opensm/per-module-logging.conf" #endif /* __WIN__ */ /***********/ /****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS * NAME * OSM_DEFAULT_SWEEP_INTERVAL_SECS * * DESCRIPTION * Specifies the default number of seconds between subnet sweeps. * * SYNOPSIS */ #define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC * NAME * OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC * * DESCRIPTION * Specifies the default transaction timeout in milliseconds. * * SYNOPSIS */ #define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 200 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT * NAME * OSM_DEFAULT_SUBNET_TIMEOUT * * DESCRIPTION * Specifies the default subnet timeout. * timeout time = 4us * 2^timeout. * We use here ~1sec. * * SYNOPSIS */ #define OSM_DEFAULT_SUBNET_TIMEOUT 0x12 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE * NAME * OSM_DEFAULT_SWITCH_PACKET_LIFE * * DESCRIPTION * Specifies the default max life time for a pcket on the switch. * timeout time = 4us * 2^timeout. * We use here the value of ~1sec * A Value > 19dec disables this mechanism. * * SYNOPSIS */ #define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE * NAME * OSM_DEFAULT_HEAD_OF_QUEUE_LIFE * * DESCRIPTION * Sets the time a packet can live in the head of the VL Queue * We use here the value of ~1sec * A Value > 19dec disables this mechanism. * * SYNOPSIS */ #define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE * NAME * OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE * * DESCRIPTION * Sets the time a packet can live in the head of the VL Queue * of a port that drives a CA port. * We use here the value of ~256msec * * SYNOPSIS */ #define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0x10 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_VL_STALL_COUNT * NAME * OSM_DEFAULT_LEAF_VL_COUNT * * DESCRIPTION * Sets the number of consecutive head of queue life time drops that * puts the VL into stalled state. In stalled state, the port is supposed * to drop everything for 8*(head of queue lifetime) * * SYNOPSIS */ #define OSM_DEFAULT_VL_STALL_COUNT 0x7 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT * NAME * OSM_DEFAULT_LEAF_VL_STALL_COUNT * * DESCRIPTION * Sets the number of consecutive head of queue life time drops that * puts the VL into stalled state. In stalled state, the port is supposed * to drop everything for 8*(head of queue lifetime). This value is for * switch ports driving a CA port. * * SYNOPSIS */ #define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x7 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT * NAME * OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT * * DESCRIPTION * Specifies the default timeout for ignoring same trap. * timeout time = 5000000us * We use here ~5sec. * * SYNOPSIS */ #define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT * NAME * OSM_DEFAULT_UNHEALTHY_TIMEOUT * * DESCRIPTION * Specifies the default timeout for setting port as unhealthy. * timeout time = 60000000us * We use here ~60sec. * * SYNOPSIS */ #define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD * NAME * OSM_DEFAULT_ERROR_THRESHOLD * * DESCRIPTION * Specifies default link error threshold to be set by SubnSet(PortInfo). * * SYNOPSIS */ #define OSM_DEFAULT_ERROR_THRESHOLD 0x08 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE * NAME * OSM_DEFAULT_SMP_MAX_ON_WIRE * * DESCRIPTION * Specifies the default number of VL15 SMP MADs allowed on * the wire at any one time. * * SYNOPSIS */ #define OSM_DEFAULT_SMP_MAX_ON_WIRE 4 /***********/ /****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE * NAME * OSM_SM_DEFAULT_QP0_RCV_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP0 receive queue * * SYNOPSIS */ #define OSM_SM_DEFAULT_QP0_RCV_SIZE 256 /***********/ /****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE * NAME * OSM_SM_DEFAULT_QP0_SEND_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP0 send queue * * SYNOPSIS */ #define OSM_SM_DEFAULT_QP0_SEND_SIZE 256 /***********/ /****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE * NAME * OSM_SM_DEFAULT_QP1_RCV_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP1 receive queue * * SYNOPSIS */ #define OSM_SM_DEFAULT_QP1_RCV_SIZE 256 /***********/ /****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE * NAME * OSM_SM_DEFAULT_QP1_SEND_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP1 send queue * * SYNOPSIS */ #define OSM_SM_DEFAULT_QP1_SEND_SIZE 256 /****d* OpenSM: Base/OSM_PM_DEFAULT_QP1_RCV_SIZE * NAME * OSM_PM_DEFAULT_QP1_RCV_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP1 receive queue * * SYNOPSIS */ #define OSM_PM_DEFAULT_QP1_RCV_SIZE 256 /***********/ /****d* OpenSM: Base/OSM_PM_DEFAULT_QP1_SEND_SIZE * NAME * OSM_PM_DEFAULT_QP1_SEND_SIZE * * DESCRIPTION * Specifies the default size (in MADs) of the QP1 send queue * * SYNOPSIS */ #define OSM_PM_DEFAULT_QP1_SEND_SIZE 256 /****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS * NAME * OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS * * DESCRIPTION * Specifies the polling timeout (in miliseconds) - the timeout * between one poll to another. * * SYNOPSIS */ #define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000 /**********/ /****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER * NAME * OSM_SM_DEFAULT_POLLING_RETRY_NUMBER * * DESCRIPTION * Specifies the number of polling retries before the SM goes back * to DISCOVERY stage. So the default total time for handoff is 40 sec. * * SYNOPSIS */ #define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 4 /**********/ /****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_MTU * Name * OSM_DEFAULT_MGRP_MTU * * DESCRIPTION * Default MTU used for new MGRP creation (2048 bytes) * Note it includes the MTUSelector which is set to "Greater Than" * * SYNOPSIS */ #define OSM_DEFAULT_MGRP_MTU 0x04 /***********/ /****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_RATE * Name * OSM_DEFAULT_MGRP_RATE * * DESCRIPTION * Default RATE used for new MGRP creation (10Gb/sec) * Note it includes the RateSelector which is set to "Greater Than" * * SYNOPSIS */ #define OSM_DEFAULT_MGRP_RATE 0x03 /***********/ /****d* OpenSM: MC Member Record Receiver/OSM_DEFAULT_MGRP_SCOPE * Name * OSM_DEFAULT_MGRP_SCOPE * * DESCRIPTION * Default SCOPE used for new MGRP creation (link local) * * SYNOPSIS */ #define OSM_DEFAULT_MGRP_SCOPE IB_MC_SCOPE_LINK_LOCAL /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_MAX_VLS * Name * OSM_DEFAULT_QOS_MAX_VLS * * DESCRIPTION * Default Maximum VLs used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_QOS_MAX_VLS 15 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_HIGH_LIMIT * Name * OSM_DEFAULT_QOS_HIGH_LIMIT * * DESCRIPTION * Default Limit of High Priority in VL Arbitration used by OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_QOS_HIGH_LIMIT 0 /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_VLARB_HIGH * Name * OSM_DEFAULT_QOS_VLARB_HIGH * * DESCRIPTION * Default High Priority VL Arbitration table used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_QOS_VLARB_HIGH "0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0" /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_VLARB_LOW * Name * OSM_DEFAULT_QOS_VLARB_LOW * * DESCRIPTION * Default Low Priority VL Arbitration table used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_QOS_VLARB_LOW "0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4" /***********/ /****d* OpenSM: Base/OSM_DEFAULT_QOS_SL2VL * Name * OSM_DEFAULT_QOS_SL2VL * * DESCRIPTION * Default QoS SL2VL Mapping Table used by the OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_QOS_SL2VL "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7" /***********/ /****d* OpenSM: Base/OSM_NO_PATH * NAME * OSM_NO_PATH * * DESCRIPTION * Value indicating there is no path to the given LID. * * SYNOPSIS */ #define OSM_NO_PATH 0xFF /**********/ /****d* OpenSM: Base/OSM_NODE_DESC_UNKNOWN * NAME * OSM_NODE_DESC_UNKNOWN * * DESCRIPTION * Value indicating the Node Description is not set and is "unknown" * * SYNOPSIS */ #define OSM_NODE_DESC_UNKNOWN "" /**********/ /****d* OpenSM: Base/osm_thread_state_t * NAME * osm_thread_state_t * * DESCRIPTION * Enumerates the possible states of worker threads, such * as the subnet sweeper. * * SYNOPSIS */ typedef enum _osm_thread_state { OSM_THREAD_STATE_NONE = 0, OSM_THREAD_STATE_INIT, OSM_THREAD_STATE_RUN, OSM_THREAD_STATE_EXIT } osm_thread_state_t; /***********/ /* * OSM_CAP are from IBA 1.2.1 Table 117 and Table 188 */ /****d* OpenSM: Base/OSM_CAP_IS_TRAP_SUP * Name * OSM_CAP_IS_SUBN_TRAP_SUP * * DESCRIPTION * Management class generates Trap() MADs * * SYNOPSIS */ #define OSM_CAP_IS_SUBN_TRAP_SUP (1 << 0) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_GET_SET_NOTICE_SUP * Name * OSM_CAP_IS_GET_SET_NOTICE_SUP * * DESCRIPTION * Management class supports Get/Set(Notice) * * SYNOPSIS */ #define OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP (1 << 1) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP * Name * OSM_CAP_IS_SUBN_OPT_RECS_SUP * * DESCRIPTION * Support all optional attributes except: * MCMemberRecord, TraceRecord, MultiPathRecord * * SYNOPSIS */ #define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP * Name * OSM_CAP_IS_UD_MCAST_SUP * * DESCRIPTION * Multicast is supported * * SYNOPSIS */ #define OSM_CAP_IS_UD_MCAST_SUP (1 << 9) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_MULTIPATH_SUP * Name * OSM_CAP_IS_MULTIPATH_SUP * * DESCRIPTION * MultiPathRecord and TraceRecord are supported * * SYNOPSIS */ #define OSM_CAP_IS_MULTIPATH_SUP (1 << 10) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP * Name * OSM_CAP_IS_REINIT_SUP * * DESCRIPTION * SM/SA supports re-initialization supported * * SYNOPSIS */ #define OSM_CAP_IS_REINIT_SUP (1 << 11) /***********/ /****d* OpenSM: Base/OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED * Name * OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED * * DESCRIPTION * SM/SA supports enhanced SA PortInfoRecord searches per 1.2 Errata: * ClassPortInfo:CapabilityMask.IsPortInfoCapMaskMatchSupported is 1, * then the AttributeModifier of the SubnAdmGet() and SubnAdmGetTable() * methods affects the matching behavior on the PortInfo:CapabilityMask * component. If the high-order bit (bit 31) of the AttributeModifier * is set to 1, matching on the CapabilityMask component will not be an * exact bitwise match as described in . Instead, * matching will only be performed on those bits which are set to 1 in * the PortInfo:CapabilityMask embedded in the query. * * SYNOPSIS */ #define OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED (1 << 13) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_QOS_SUPPORTED * Name * OSM_CAP2_IS_QOS_SUPPORTED * * DESCRIPTION * QoS is supported * * SYNOPSIS */ #define OSM_CAP2_IS_QOS_SUPPORTED (1 << 1) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_REVERSE_PATH_PKEY_SUPPPORTED * Name * OSM_CAP2_IS_REVERSE_PATH_PKEY_SUPPPORTED * * DESCRIPTION * Reverse path PKeys indicate in PathRecord responses * * SYNOPSIS */ #define OSM_CAP2_IS_REVERSE_PATH_PKEY_SUPPPORTED (1 << 2) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_MCAST_TOP_SUPPORTED * Name * OSM_CAP2_IS_MCAST_TOP_SUPPORTED * * DESCRIPTION * SwitchInfo.MulticastFDBTop is supported * * SYNOPSIS */ #define OSM_CAP2_IS_MCAST_TOP_SUPPORTED (1 << 3) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_HIERARCHY_SUPPORTED * Name * * DESCRIPTION * Hierarchy info supported * * SYNOPSIS */ #define OSM_CAP2_IS_HIERARCHY_SUPPORTED (1 << 4) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_ALIAS_GUIDS_SUPPORTED * Name * * DESCRIPTION * Alias GUIDs supported * * SYNOPSIS */ #define OSM_CAP2_IS_ALIAS_GUIDS_SUPPORTED (1 << 5) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_FULL_PORTINFO_REC_SUPPORTED * Name * OSM_CAP2_IS_FULL_PORTINFO_REC_SUPPORTED * * DESCRIPTION * Full PortInfoRecords supported * * SYNOPSIS */ #define OSM_CAP2_IS_FULL_PORTINFO_REC_SUPPORTED (1 << 6) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_EXTENDED_SPEEDS_SUPPORTED * Name * OSM_CAP2_IS_EXTENDED_SPEEDS_SUPPORTED * * DESCRIPTION * Extended Link Speeds supported * * SYNOPSIS */ #define OSM_CAP2_IS_EXTENDED_SPEEDS_SUPPORTED (1 << 7) /***********/ /****d* OpenSM: Base/OSM_CAP2_IS_MULTICAST_SERVICE_RECS_SUPPORTED * Name * OSM_CAP2_IS_MULTICAST_SERVICE_RECS_SUPPORTED * * DESCRIPTION * Multicast Service Records supported * * SYNOPSIS */ #define OSM_CAP2_IS_MULTICAST_SERVICE_RECS_SUPPORTED (1 << 8) /****d* OpenSM: Base/OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED * Name * OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED * * DESCRIPTION * CapMask2 matching for PortInfoRecord supported * * SYNOPSIS */ #define OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED (1 << 10) /****d* OpenSM: Base/osm_signal_t * NAME * osm_signal_t * * DESCRIPTION * Enumerates the possible signal codes used by the OSM managers * This cannot be an enum type, since conversion to and from * integral types is necessary when passing signals through * the dispatcher. * * SYNOPSIS */ #define OSM_SIGNAL_NONE 0 #define OSM_SIGNAL_SWEEP 1 #define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST 2 #define OSM_SIGNAL_PERFMGR_SWEEP 3 #define OSM_SIGNAL_GUID_PROCESS_REQUEST 4 #define OSM_SIGNAL_MAX 5 typedef unsigned int osm_signal_t; /***********/ /****d* OpenSM: Base/osm_sm_signal_t * NAME * osm_sm_signal_t * * DESCRIPTION * Enumerates the possible signals used by the OSM_SM_MGR * * SYNOPSIS */ typedef enum _osm_sm_signal { OSM_SM_SIGNAL_NONE = 0, OSM_SM_SIGNAL_DISCOVERY_COMPLETED, OSM_SM_SIGNAL_POLLING_TIMEOUT, OSM_SM_SIGNAL_DISCOVER, OSM_SM_SIGNAL_DISABLE, OSM_SM_SIGNAL_HANDOVER, OSM_SM_SIGNAL_HANDOVER_SENT, OSM_SM_SIGNAL_ACKNOWLEDGE, OSM_SM_SIGNAL_STANDBY, OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED, OSM_SM_SIGNAL_WAIT_FOR_HANDOVER, OSM_SM_SIGNAL_MAX } osm_sm_signal_t; /***********/ /****s* OpenSM: Base/MAX_GUID_FILE_LINE_LENGTH * NAME * MAX_GUID_FILE_LINE_LENGTH * * DESCRIPTION * The maximum line number when reading guid file * * SYNOPSIS */ #define MAX_GUID_FILE_LINE_LENGTH 120 /**********/ /****s* OpenSM: Base/VendorOUIs * NAME * VendorOUIs * * DESCRIPTION * Known device vendor ID and GUID OUIs * * SYNOPSIS */ #define OSM_VENDOR_ID_INTEL 0x00D0B7 #define OSM_VENDOR_ID_MELLANOX 0x0002C9 #define OSM_VENDOR_ID_REDSWITCH 0x000617 #define OSM_VENDOR_ID_SILVERSTORM 0x00066A #define OSM_VENDOR_ID_TOPSPIN 0x0005AD #define OSM_VENDOR_ID_FUJITSU 0x00E000 #define OSM_VENDOR_ID_FUJITSU2 0x000B5D #define OSM_VENDOR_ID_VOLTAIRE 0x0008F1 #define OSM_VENDOR_ID_YOTTAYOTTA 0x000453 #define OSM_VENDOR_ID_PATHSCALE 0x001175 #define OSM_VENDOR_ID_IBM 0x000255 #define OSM_VENDOR_ID_DIVERGENET 0x00084E #define OSM_VENDOR_ID_FLEXTRONICS 0x000B8C #define OSM_VENDOR_ID_AGILENT 0x0030D3 #define OSM_VENDOR_ID_OBSIDIAN 0x001777 #define OSM_VENDOR_ID_BAYMICRO 0x000BC1 #define OSM_VENDOR_ID_LSILOGIC 0x00A0B8 #define OSM_VENDOR_ID_DDN 0x0001FF #define OSM_VENDOR_ID_PANTA 0x001393 #define OSM_VENDOR_ID_HP 0x001708 #define OSM_VENDOR_ID_RIOWORKS 0x005045 #define OSM_VENDOR_ID_SUN 0x0003BA #define OSM_VENDOR_ID_SUN2 0x002128 #define OSM_VENDOR_ID_3LEAFNTWKS 0x0016A1 #define OSM_VENDOR_ID_XSIGO 0x001397 #define OSM_VENDOR_ID_HP2 0x0018FE #define OSM_VENDOR_ID_DELL 0x00188B #define OSM_VENDOR_ID_SUPERMICRO 0x003048 #define OSM_VENDOR_ID_HP3 0x0019BB #define OSM_VENDOR_ID_HP4 0x00237D #define OSM_VENDOR_ID_OPENIB 0x001405 #define OSM_VENDOR_ID_IBM2 0x5CF3FC #define OSM_VENDOR_ID_MELLANOX2 0xF45214 #define OSM_VENDOR_ID_MELLANOX3 0x00258B #define OSM_VENDOR_ID_MELLANOX4 0xE41D2D #define OSM_VENDOR_ID_MELLANOX5 0x7CFE90 /* IPoIB Broadcast Defaults */ #define OSM_IPOIB_BROADCAST_MGRP_QKEY 0x0b1b extern const ib_gid_t osm_ipoib_broadcast_mgid; /**********/ END_C_DECLS #endif /* _OSM_BASE_H_ */ opensm-3.3.20/include/opensm/osm_console.h0000644000205000001450000000340512104655724015435 00000000000000/* * Copyright (c) 2005-2007 Voltaire, Inc. 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. * */ #ifndef _OSM_CONSOLE_H_ #define _OSM_CONSOLE_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS int osm_console(osm_opensm_t * p_osm); END_C_DECLS #endif /* _OSM_CONSOLE_H_ */ opensm-3.3.20/include/opensm/osm_console_io.h0000644000205000001450000000602412104655724016124 00000000000000/* * Copyright (c) 2005-2007 Voltaire, Inc. 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: * Declaration of osm_console_t. * This object represents the OpenSM Console object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_CONSOLE_IO_H_ #define _OSM_CONSOLE_IO_H_ #include #include #define OSM_DISABLE_CONSOLE "off" #define OSM_LOCAL_CONSOLE "local" #ifdef ENABLE_OSM_CONSOLE_SOCKET #define OSM_REMOTE_CONSOLE "socket" #endif #ifdef ENABLE_OSM_CONSOLE_LOOPBACK #define OSM_LOOPBACK_CONSOLE "loopback" #endif #define OSM_CONSOLE_NAME "OSM Console" #define OSM_DEFAULT_CONSOLE OSM_DISABLE_CONSOLE #define OSM_DEFAULT_CONSOLE_PORT 10000 #define OSM_DAEMON_NAME "opensm" #define OSM_COMMAND_PROMPT "$ " #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct osm_console { int socket; int in_fd; int out_fd; int authorized; FILE *in; FILE *out; char client_type[32]; char client_ip[64]; char client_hn[128]; } osm_console_t; void osm_console_prompt(FILE * out); int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log); void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log); int is_console_enabled(osm_subn_opt_t *p_opt); #ifdef ENABLE_OSM_CONSOLE_LOOPBACK int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log); int cio_close(osm_console_t * p_oct, osm_log_t * p_log); int is_authorized(osm_console_t * p_oct); #else #define cio_close(c, log) #endif END_C_DECLS #endif /* _OSM_CONSOLE_IO_H_ */ opensm-3.3.20/include/opensm/osm_db.h0000644000205000001450000002212712272264652014364 00000000000000/* * Copyright (c) 2004-2009 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. * */ #ifndef _OSM_DB_H_ #define _OSM_DB_H_ /* * Abstract: * Declaration of the DB interface. */ #include #include struct osm_log; #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Database * NAME * Database * * DESCRIPTION * The OpenSM database interface provide the means to restore persistent * data, query, modify, delete and eventually commit it back to the * persistent media. * * The interface is defined such that it can is not "data dependent": * All keys and data items are texts. * * The DB implementation should be thread safe, thus callers do not need to * provide serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Eitan Zahavi, Mellanox Technologies LTD * *********/ /****s* OpenSM: Database/osm_db_domain_t * NAME * osm_db_domain_t * * DESCRIPTION * A domain of the database. Can be viewed as a database table. * * The osm_db_domain_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_db_domain { struct osm_db *p_db; void *p_domain_imp; } osm_db_domain_t; /* * FIELDS * p_db * Pointer to the parent database object. * * p_domain_imp * Pointer to the db implementation object * * SEE ALSO * osm_db_t *********/ /****s* OpenSM: Database/osm_db_t * NAME * osm_db_t * * DESCRIPTION * The main database object. * * The osm_db_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_db { void *p_db_imp; struct osm_log *p_log; cl_list_t domains; } osm_db_t; /* * FIELDS * p_db_imp * Pointer to the database implementation object * * p_log * Pointer to the OSM logging facility * * domains * List of initialize domains * * SEE ALSO *********/ /****f* OpenSM: Database/osm_db_construct * NAME * osm_db_construct * * DESCRIPTION * Construct a database. * * SYNOPSIS */ void osm_db_construct(IN osm_db_t * p_db); /* * PARAMETERS * p_db * [in] Pointer to the database object to construct * * RETURN VALUES * NONE * * SEE ALSO * Database, osm_db_init, osm_db_destroy *********/ /****f* OpenSM: Database/osm_db_destroy * NAME * osm_db_destroy * * DESCRIPTION * Destroys the osm_db_t structure. * * SYNOPSIS */ void osm_db_destroy(IN osm_db_t * p_db); /* * PARAMETERS * p_db * [in] Pointer to osm_db_t structure to destroy * * SEE ALSO * Database, osm_db_construct, osm_db_init *********/ /****f* OpenSM: Database/osm_db_init * NAME * osm_db_init * * DESCRIPTION * Initializes the osm_db_t structure. * * SYNOPSIS */ int osm_db_init(IN osm_db_t * p_db, IN struct osm_log * p_log); /* * PARAMETERS * * p_db * [in] Pointer to the database object to initialize * * p_log * [in] Pointer to the OSM logging facility * * RETURN VALUES * 0 on success 1 otherwise * * SEE ALSO * Database, osm_db_construct, osm_db_destroy *********/ /****f* OpenSM: Database/osm_db_domain_init * NAME * osm_db_domain_init * * DESCRIPTION * Initializes the osm_db_domain_t structure. * * SYNOPSIS */ osm_db_domain_t *osm_db_domain_init(IN osm_db_t * p_db, IN const char *domain_name); /* * PARAMETERS * * p_db * [in] Pointer to the database object to initialize * * domain_name * [in] a char array with the domain name. * * RETURN VALUES * pointer to the new domain object or NULL if failed. * * SEE ALSO * Database, osm_db_construct, osm_db_destroy *********/ /****f* OpenSM: Database/osm_db_restore * NAME * osm_db_restore * * DESCRIPTION * Reads the entire domain from persistent storage - overrides all * existing cached data (if any). * * SYNOPSIS */ int osm_db_restore(IN osm_db_domain_t * p_domain); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object to restore * from persistent db * * RETURN VALUES * 0 if successful 1 otherwize * * SEE ALSO * Database, osm_db_domain_init, osm_db_clear, osm_db_store, * osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_clear * NAME * osm_db_clear * * DESCRIPTION * Clears the entire domain values from/in the cache * * SYNOPSIS */ int osm_db_clear(IN osm_db_domain_t * p_domain); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object to clear * * RETURN VALUES * 0 if successful 1 otherwize * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_store, * osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_store * NAME * osm_db_store * * DESCRIPTION * Store the domain cache back to the database (commit) * * SYNOPSIS */ int osm_db_store(IN osm_db_domain_t * p_domain, IN boolean_t fsync_high_avail_files); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object to restore from * persistent db * * fsync_high_avail_files * [in] Boolean that indicates whether or not to synchronize * in-memory high availability files with storage * * RETURN VALUES * 0 if successful 1 otherwize * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_clear, * osm_db_keys, osm_db_lookup, osm_db_update, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_keys * NAME * osm_db_keys * * DESCRIPTION * Retrive all keys of the domain * * SYNOPSIS */ int osm_db_keys(IN osm_db_domain_t * p_domain, OUT cl_list_t * p_key_list); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object * * p_key_list * [out] List of key values. It should be PRE constructed and initialized. * * RETURN VALUES * 0 if successful 1 otherwize * * NOTE: the caller needs to free and destruct the list, * the keys returned are intrnal to the hash and should NOT be free'ed * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, * osm_db_lookup, osm_db_update, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_lookup * NAME * osm_db_lookup * * DESCRIPTION * Lookup an entry in the domain by the given key * * SYNOPSIS */ /* lookup value by key */ char *osm_db_lookup(IN osm_db_domain_t * p_domain, IN char *p_key); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object * * key * [in] The key to look for * * RETURN VALUES * the value as char * or NULL if not found * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, * osm_db_keys, osm_db_update, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_update * NAME * osm_db_update * * DESCRIPTION * Set the value of the given key * * SYNOPSIS */ int osm_db_update(IN osm_db_domain_t * p_domain, IN char *p_key, IN char *p_val); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object * * p_key * [in] The key to update * * p_val * [in] The value to update * * RETURN VALUES * 0 on success * * NOTE: the value will be duplicated so can be free'ed * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, * osm_db_keys, osm_db_lookup, osm_db_delete *********/ /****f* OpenSM: Database/osm_db_delete * NAME * osm_db_delete * * DESCRIPTION * Delete an entry by the given key * * SYNOPSIS */ int osm_db_delete(IN osm_db_domain_t * p_domain, IN char *p_key); /* * PARAMETERS * * p_domain * [in] Pointer to the database domain object * * p_key * [in] The key to look for * * RETURN VALUES * 0 on success * * SEE ALSO * Database, osm_db_domain_init, osm_db_restore, osm_db_clear, osm_db_store, * osm_db_keys, osm_db_lookup, osm_db_update *********/ END_C_DECLS #endif /* _OSM_DB_H_ */ opensm-3.3.20/include/opensm/osm_db_pack.h0000644000205000001450000002764712104655724015374 00000000000000/* * Copyright (c) 2004-2009 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. * */ /****h* OpenSM/DB-Pack * NAME * Database Types * * DESCRIPTION * This module provides packing and unpacking of the database * storage into specific types. * * The following domains/conversions are supported: * guid2lid - key is a guid and data is a lid. * * AUTHOR * Eitan Zahavi, Mellanox Technologies LTD * *********/ #ifndef _OSM_DB_PACK_H_ #define _OSM_DB_PACK_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****f* OpenSM: DB-Pack/osm_db_guid2lid_init * NAME * osm_db_guid2lid_init * * DESCRIPTION * Initialize a domain for the guid2lid table * * SYNOPSIS */ static inline osm_db_domain_t *osm_db_guid2lid_init(IN osm_db_t * p_db) { return (osm_db_domain_init(p_db, "guid2lid")); } /* * PARAMETERS * p_db * [in] Pointer to the database object to construct * * RETURN VALUES * The pointer to the new allocated domain object or NULL. * * NOTE: DB domains are destroyed by the osm_db_destroy * * SEE ALSO * Database, osm_db_init, osm_db_destroy *********/ /****f* OpenSM: DB-Pack/osm_db_guid2lid_init * NAME * osm_db_guid2lid_init * * DESCRIPTION * Initialize a domain for the guid2lid table * * SYNOPSIS */ typedef struct osm_db_guid_elem { cl_list_item_t item; uint64_t guid; } osm_db_guid_elem_t; /* * FIELDS * item * required for list manipulations * * guid * ************/ /****f* OpenSM: DB-Pack/osm_db_guid2lid_guids * NAME * osm_db_guid2lid_guids * * DESCRIPTION * Provides back a list of guid elements. * * SYNOPSIS */ int osm_db_guid2lid_guids(IN osm_db_domain_t * p_g2l, OUT cl_qlist_t * p_guid_list); /* * PARAMETERS * p_g2l * [in] Pointer to the guid2lid domain * * p_guid_list * [out] A quick list of guid elements of type osm_db_guid_elem_t * * RETURN VALUES * 0 if successful * * NOTE: the output qlist should be initialized and each item freed * by the caller, then destroyed. * * SEE ALSO * osm_db_guid2lid_init, osm_db_guid2lid_guids, osm_db_guid2lid_get * osm_db_guid2lid_set, osm_db_guid2lid_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2lid_get * NAME * osm_db_guid2lid_get * * DESCRIPTION * Get a lid range by given guid. * * SYNOPSIS */ int osm_db_guid2lid_get(IN osm_db_domain_t * p_g2l, IN uint64_t guid, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid); /* * PARAMETERS * p_g2l * [in] Pointer to the guid2lid domain * * guid * [in] The guid to look for * * p_min_lid * [out] Pointer to the resulting min lid in host order. * * p_max_lid * [out] Pointer to the resulting max lid in host order. * * RETURN VALUES * 0 if successful. The lid will be set to 0 if not found. * * SEE ALSO * osm_db_guid2lid_init, osm_db_guid2lid_guids * osm_db_guid2lid_set, osm_db_guid2lid_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2lid_set * NAME * osm_db_guid2lid_set * * DESCRIPTION * Set a lid range for the given guid. * * SYNOPSIS */ int osm_db_guid2lid_set(IN osm_db_domain_t * p_g2l, IN uint64_t guid, IN uint16_t min_lid, IN uint16_t max_lid); /* * PARAMETERS * p_g2l * [in] Pointer to the guid2lid domain * * guid * [in] The guid to look for * * min_lid * [in] The min lid value to set * * max_lid * [in] The max lid value to set * * RETURN VALUES * 0 if successful * * SEE ALSO * osm_db_guid2lid_init, osm_db_guid2lid_guids * osm_db_guid2lid_get, osm_db_guid2lid_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2lid_delete * NAME * osm_db_guid2lid_delete * * DESCRIPTION * Delete the entry by the given guid * * SYNOPSIS */ int osm_db_guid2lid_delete(IN osm_db_domain_t * p_g2l, IN uint64_t guid); /* * PARAMETERS * p_g2l * [in] Pointer to the guid2lid domain * * guid * [in] The guid to look for * * RETURN VALUES * 0 if successful otherwise 1 * * SEE ALSO * osm_db_guid2lid_init, osm_db_guid2lid_guids * osm_db_guid2lid_get, osm_db_guid2lid_set *********/ /****f* OpenSM: DB-Pack/osm_db_guid2mkey_init * NAME * osm_db_guid2mkey_init * * DESCRIPTION * Initialize a domain for the guid2mkey table * * SYNOPSIS */ static inline osm_db_domain_t *osm_db_guid2mkey_init(IN osm_db_t * p_db) { return osm_db_domain_init(p_db, "guid2mkey"); } /* * PARAMETERS * p_db * [in] Pointer to the database object to construct * * RETURN VALUES * The pointer to the new allocated domain object or NULL. * * NOTE: DB domains are destroyed by the osm_db_destroy * * SEE ALSO * Database, osm_db_init, osm_db_destroy *********/ /****f* OpenSM: DB-Pack/osm_db_guid2mkey_guids * NAME * osm_db_guid2mkey_guids * * DESCRIPTION * Provides back a list of guid elements. * * SYNOPSIS */ int osm_db_guid2mkey_guids(IN osm_db_domain_t * p_g2m, OUT cl_qlist_t * p_guid_list); /* * PARAMETERS * p_g2l * [in] Pointer to the guid2mkey domain * * p_guid_list * [out] A quick list of guid elements of type osm_db_guid_elem_t * * RETURN VALUES * 0 if successful * * NOTE: the output qlist should be initialized and each item freed * by the caller, then destroyed. * * SEE ALSO * osm_db_guid2mkey_init, osm_db_guid2mkey_guids, osm_db_guid2mkey_get * osm_db_guid2mkey_set, osm_db_guid2mkey_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2mkey_get * NAME * osm_db_guid2mkey_get * * DESCRIPTION * Get the mkey for the given guid. * * SYNOPSIS */ int osm_db_guid2mkey_get(IN osm_db_domain_t * p_g2m, IN uint64_t guid, OUT uint64_t * p_mkey); /* * PARAMETERS * p_g2m * [in] Pointer to the guid2mkey domain * * guid * [in] The guid to look for * * p_mkey * [out] Pointer to the resulting mkey in host order. * * RETURN VALUES * 0 if successful. The lid will be set to 0 if not found. * * SEE ALSO * osm_db_guid2mkey_init, osm_db_guid2mkey_guids * osm_db_guid2mkey_set, osm_db_guid2mkey_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2mkey_set * NAME * osm_db_guid2mkey_set * * DESCRIPTION * Set the mkey for the given guid. * * SYNOPSIS */ int osm_db_guid2mkey_set(IN osm_db_domain_t * p_g2m, IN uint64_t guid, IN uint64_t mkey); /* * PARAMETERS * p_g2m * [in] Pointer to the guid2mkey domain * * guid * [in] The guid to look for * * mkey * [in] The mkey value to set, in host order * * RETURN VALUES * 0 if successful * * SEE ALSO * osm_db_guid2mkey_init, osm_db_guid2mkey_guids * osm_db_guid2mkey_get, osm_db_guid2mkey_delete *********/ /****f* OpenSM: DB-Pack/osm_db_guid2mkey_delete * NAME * osm_db_guid2mkey_delete * * DESCRIPTION * Delete the entry by the given guid * * SYNOPSIS */ int osm_db_guid2mkey_delete(IN osm_db_domain_t * p_g2m, IN uint64_t guid); /* * PARAMETERS * p_g2m * [in] Pointer to the guid2mkey domain * * guid * [in] The guid to look for * * RETURN VALUES * 0 if successful otherwise 1 * * SEE ALSO * osm_db_guid2mkey_init, osm_db_guid2mkey_guids * osm_db_guid2mkey_get, osm_db_guid2mkey_set *********/ /****f* OpenSM: DB-Pack/osm_db_neighbor_init * NAME * osm_db_neighbor_init * * DESCRIPTION * Initialize a domain for the neighbors table * * SYNOPSIS */ static inline osm_db_domain_t *osm_db_neighbor_init(IN osm_db_t * p_db) { return osm_db_domain_init(p_db, "neighbors"); } /* * PARAMETERS * p_db * [in] Pointer to the database object to construct * * RETURN VALUES * The pointer to the new allocated domain object or NULL. * * NOTE: DB domains are destroyed by the osm_db_destroy * * SEE ALSO * Database, osm_db_init, osm_db_destroy *********/ /****f* OpenSM: DB-Pack/osm_db_neighbor_elem * NAME * osm_db_neighbor_elem * * DESCRIPTION * Initialize a domain for the neighbor table * * SYNOPSIS */ typedef struct osm_db_neighbor_elem { cl_list_item_t item; uint64_t guid; uint8_t portnum; } osm_db_neighbor_elem_t; /* * FIELDS * item * required for list manipulations * * guid * portnum * ************/ /****f* OpenSM: DB-Pack/osm_db_neighbor_guids * NAME * osm_db_neighbor_guids * * DESCRIPTION * Provides back a list of neighbor elements. * * SYNOPSIS */ int osm_db_neighbor_guids(IN osm_db_domain_t * p_neighbor, OUT cl_qlist_t * p_guid_list); /* * PARAMETERS * p_neighbor * [in] Pointer to the neighbor domain * * p_guid_list * [out] A quick list of neighbor elements of type osm_db_neighbor_elem_t * * RETURN VALUES * 0 if successful * * NOTE: the output qlist should be initialized and each item freed * by the caller, then destroyed. * * SEE ALSO * osm_db_neighbor_init, osm_db_neighbor_guids, osm_db_neighbor_get * osm_db_neighbor_set, osm_db_neighbor_delete *********/ /****f* OpenSM: DB-Pack/osm_db_neighbor_get * NAME * osm_db_neighbor_get * * DESCRIPTION * Get a neighbor's guid by given guid/port. * * SYNOPSIS */ int osm_db_neighbor_get(IN osm_db_domain_t * p_neighbor, IN uint64_t guid1, IN uint8_t port1, OUT uint64_t * p_guid2, OUT uint8_t * p_port2); /* * PARAMETERS * p_neighbor * [in] Pointer to the neighbor domain * * guid1 * [in] The guid to look for * * port1 * [in] The port to look for * * p_guid2 * [out] Pointer to the resulting guid of the neighboring port. * * p_port2 * [out] Pointer to the resulting port of the neighboring port. * * RETURN VALUES * 0 if successful. The lid will be set to 0 if not found. * * SEE ALSO * osm_db_neighbor_init, osm_db_neighbor_guids * osm_db_neighbor_set, osm_db_neighbor_delete *********/ /****f* OpenSM: DB-Pack/osm_db_neighbor_set * NAME * osm_db_neighbor_set * * DESCRIPTION * Set up a relationship between two ports * * SYNOPSIS */ int osm_db_neighbor_set(IN osm_db_domain_t * p_neighbor, IN uint64_t guid1, IN uint8_t port1, IN uint64_t guid2, IN uint8_t port2); /* * PARAMETERS * p_neighbor * [in] Pointer to the neighbor domain * * guid1 * [in] The first guid in the relationship * * port1 * [in] The first port in the relationship * * guid2 * [in] The second guid in the relationship * * port2 * [in] The second port in the relationship * * RETURN VALUES * 0 if successful * * SEE ALSO * osm_db_neighbor_init, osm_db_neighbor_guids * osm_db_neighbor_get, osm_db_neighbor_delete *********/ /****f* OpenSM: DB-Pack/osm_db_neighbor_delete * NAME * osm_db_neighbor_delete * * DESCRIPTION * Delete the relationship between two ports * * SYNOPSIS */ int osm_db_neighbor_delete(IN osm_db_domain_t * p_neighbor, IN uint64_t guid, IN uint8_t port); /* * PARAMETERS * p_neighbor * [in] Pointer to the neighbor domain * * guid * [in] The guid to look for * * port * [in] The port to look for * * RETURN VALUES * 0 if successful otherwise 1 * * SEE ALSO * osm_db_neighbor_init, osm_db_neighbor_guids * osm_db_neighbor_get, osm_db_neighbor_set *********/ END_C_DECLS #endif /* _OSM_DB_PACK_H_ */ opensm-3.3.20/include/opensm/osm_event_plugin.h0000644000205000001450000001411612326227566016500 00000000000000/* * Copyright (c) 2013 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 The Regents of the University of California. * * 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. * */ #ifndef _OSM_EVENT_PLUGIN_H_ #define _OSM_EVENT_PLUGIN_H_ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM Event plugin interface * DESCRIPTION * Database interface to record subnet events * * Implementations of this object _MUST_ be thread safe. * * AUTHOR * Ira Weiny, LLNL * *********/ #define OSM_EPI_NODE_NAME_LEN (65) struct osm_opensm; /** ========================================================================= * Event types */ typedef enum { OSM_EVENT_ID_PORT_ERRORS = 0, OSM_EVENT_ID_PORT_DATA_COUNTERS, OSM_EVENT_ID_PORT_SELECT, OSM_EVENT_ID_TRAP, OSM_EVENT_ID_SUBNET_UP, OSM_EVENT_ID_HEAVY_SWEEP_START, OSM_EVENT_ID_HEAVY_SWEEP_DONE, OSM_EVENT_ID_UCAST_ROUTING_DONE, OSM_EVENT_ID_STATE_CHANGE, OSM_EVENT_ID_SA_DB_DUMPED, OSM_EVENT_ID_LFT_CHANGE, OSM_EVENT_ID_MAX } osm_epi_event_id_t; typedef struct osm_epi_port_id { uint64_t node_guid; uint8_t port_num; char node_name[OSM_EPI_NODE_NAME_LEN]; } osm_epi_port_id_t; typedef enum { LFT_CHANGED_LFT_TOP = (1 << 0), LFT_CHANGED_BLOCK = (1 << 1) } osm_epi_lft_change_flags_t; typedef enum { UCAST_ROUTING_NONE, UCAST_ROUTING_HEAVY_SWEEP, UCAST_ROUTING_REROUTE } osm_epi_ucast_routing_flags_t; typedef struct osm_epi_lft_change_event { osm_switch_t *p_sw; osm_epi_lft_change_flags_t flags; uint16_t lft_top; uint32_t block_num; } osm_epi_lft_change_event_t; /** ========================================================================= * Port error event * OSM_EVENT_ID_PORT_COUNTER * This is a difference from the last reading. NOT an absolute reading. */ typedef struct osm_epi_pe_event { osm_epi_port_id_t port_id; uint64_t symbol_err_cnt; uint64_t link_err_recover; uint64_t link_downed; uint64_t rcv_err; uint64_t rcv_rem_phys_err; uint64_t rcv_switch_relay_err; uint64_t xmit_discards; uint64_t xmit_constraint_err; uint64_t rcv_constraint_err; uint64_t link_integrity; uint64_t buffer_overrun; uint64_t vl15_dropped; uint64_t xmit_wait; time_t time_diff_s; } osm_epi_pe_event_t; /** ========================================================================= * Port data counter event * This is a difference from the last reading. NOT an absolute reading. */ typedef struct osm_epi_dc_event { osm_epi_port_id_t port_id; uint64_t xmit_data; uint64_t rcv_data; uint64_t xmit_pkts; uint64_t rcv_pkts; uint64_t unicast_xmit_pkts; uint64_t unicast_rcv_pkts; uint64_t multicast_xmit_pkts; uint64_t multicast_rcv_pkts; time_t time_diff_s; } osm_epi_dc_event_t; /** ========================================================================= * Port select event * This is a difference from the last reading. NOT an absolute reading. */ typedef struct osm_api_ps_event { osm_epi_port_id_t port_id; uint64_t xmit_wait; time_t time_diff_s; } osm_epi_ps_event_t; /** ========================================================================= * Plugin creators should allocate an object of this type * (named OSM_EVENT_PLUGIN_IMPL_NAME) * The version should be set to OSM_EVENT_PLUGIN_INTERFACE_VER */ #define OSM_EVENT_PLUGIN_IMPL_NAME "osm_event_plugin" #define OSM_ORIG_EVENT_PLUGIN_INTERFACE_VER 1 #define OSM_EVENT_PLUGIN_INTERFACE_VER 2 typedef struct osm_event_plugin { const char *osm_version; void *(*create) (struct osm_opensm *osm); void (*delete) (void *plugin_data); void (*report) (void *plugin_data, osm_epi_event_id_t event_id, void *event_data); } osm_event_plugin_t; /** ========================================================================= * The plugin structure should be considered opaque */ typedef struct osm_epi_plugin { cl_list_item_t list; void *handle; osm_event_plugin_t *impl; void *plugin_data; char *plugin_name; } osm_epi_plugin_t; /** * functions */ osm_epi_plugin_t *osm_epi_construct(struct osm_opensm *osm, char *plugin_name); void osm_epi_destroy(osm_epi_plugin_t * plugin); /** ========================================================================= * Helper functions */ static inline void osm_epi_create_port_id(osm_epi_port_id_t * port_id, uint64_t node_guid, uint8_t port_num, char *node_name) { port_id->node_guid = node_guid; port_id->port_num = port_num; strncpy(port_id->node_name, node_name, OSM_EPI_NODE_NAME_LEN); port_id->node_name[OSM_EPI_NODE_NAME_LEN - 1] = '\0'; } END_C_DECLS #endif /* _OSM_EVENT_PLUGIN_H_ */ opensm-3.3.20/include/opensm/osm_errors.h0000644000205000001450000000643712104655724015317 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of error code ranges for the various OpenSM modules. */ #ifndef _OSM_ERRORS_H_ #define _OSM_ERRORS_H_ /* Generic Request Controller 0100 - 01FF Node Info Receive Controller 0200 - 02FF Generic Requester 0300 - 03FF Node Info Receiver 0400 - 04FF Node Description Receiver 0500 - 05FF Node Description Receive Controller 0600 - 06FF Port Info Receiver 0700 - 07FF Port Info Receive Controller 0800 - 08FF Mad Pool 0900 - 09FF SM 1000 - 10FF SM MAD Controller 1100 - 11FF VL15 Interface 1200 - 12FF Switch Info Receive Controller 1300 - 13FF Switch Info Receiver 1400 - 14FF State Manager 1500 - 15FF State Manager Controller 1600 - 16FF LID Manager 1700 - 17FF Link Manager 1800 - 18FF Drop Manager 1900 - 19FF Linear Forwarding Receive Controller 2000 - 20FF Linear Forwarding Receiver 2100 - 21FF Vendor Specific 2200 - 22FF SMInfo Receive Controller 2300 - 23FF SMInfo Info Receiver 2400 - 24FF Generic Responder 2500 - 25FF Linear Forwarding Receive Controller 2600 - 26FF Linear Forwarding Receiver 2700 - 27FF SA MAD controller 2800 - 28FF Node Record Controller 2900 - 29FF PortInfo Record Controller 3000 - 30FF Link Record Controller 3100 - 31FF Path Record Controller 3200 - 32FF SMInfo Record Controller 3300 - 33FF Multicast Record Controller 3400 - 34FF Unicast Manager 3500 - 35FF Multicast Manager 3600 - 36FF SA Response 3700 - 37FF Link Record Receiver 3800 - 38FF Multicast Forwarding Receive Controller 3900 - 39FF Multicast Forwarding Receiver 4000 - 40FF SMInfo Record Receiver 4100 - 41FF PortInfo Record Receiver 4200 - 42FF Service Record Receiver 4300 - 43FF */ #endif /* _OSM_ERRORS_H_ */ opensm-3.3.20/include/opensm/osm_file_ids.h0000644000205000001450000001016412104655724015551 00000000000000/* * Copyright (c) 2012 Mellanox Technologies LTD. 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: * Declaration of osm_file_ids_enum. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_FILE_ID_H_ #define _OSM_FILE_ID_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****d* OpenSM: osm_file_ids_enum * NAME * osm_file_ids_enum * * DESCRIPTION * Enumerates all FILE_IDs used for logging support. * * SYNOPSIS */ typedef enum _osm_file_ids_enum { OSM_FILE_MAIN_C = 0, OSM_FILE_CONSOLE_C, OSM_FILE_CONSOLE_IO_C, OSM_FILE_DB_FILES_C, OSM_FILE_DB_PACK_C, OSM_FILE_DROP_MGR_C, OSM_FILE_DUMP_C, OSM_FILE_EVENT_PLUGIN_C, OSM_FILE_GUID_INFO_RCV_C, OSM_FILE_GUID_MGR_C, OSM_FILE_HELPER_C, OSM_FILE_INFORM_C, OSM_FILE_LID_MGR_C, OSM_FILE_LIN_FWD_RCV_C, OSM_FILE_LINK_MGR_C, OSM_FILE_LOG_C, OSM_FILE_MAD_POOL_C, OSM_FILE_MCAST_FWD_RCV_C, OSM_FILE_MCAST_MGR_C, OSM_FILE_MCAST_TBL_C, OSM_FILE_MCM_PORT_C, OSM_FILE_MESH_C, OSM_FILE_MLNX_EXT_PORT_INFO_RCV_C, OSM_FILE_MTREE_C, OSM_FILE_MULTICAST_C, OSM_FILE_NODE_C, OSM_FILE_NODE_DESC_RCV_C, OSM_FILE_NODE_INFO_RCV_C, OSM_FILE_OPENSM_C, OSM_FILE_PERFMGR_C, OSM_FILE_PERFMGR_DB_C, OSM_FILE_PKEY_C, OSM_FILE_PKEY_MGR_C, OSM_FILE_PKEY_RCV_C, OSM_FILE_PORT_C, OSM_FILE_PORT_INFO_RCV_C, OSM_FILE_PRTN_C, OSM_FILE_PRTN_CONFIG_C, OSM_FILE_QOS_C, OSM_FILE_QOS_PARSER_L_L, OSM_FILE_QOS_PARSER_Y_Y, OSM_FILE_QOS_POLICY_C, OSM_FILE_REMOTE_SM_C, OSM_FILE_REQ_C, OSM_FILE_RESP_C, OSM_FILE_ROUTER_C, OSM_FILE_SA_C, OSM_FILE_SA_CLASS_PORT_INFO_C, OSM_FILE_SA_GUIDINFO_RECORD_C, OSM_FILE_SA_INFORMINFO_C, OSM_FILE_SA_LFT_RECORD_C, OSM_FILE_SA_LINK_RECORD_C, OSM_FILE_SA_MAD_CTRL_C, OSM_FILE_SA_MCMEMBER_RECORD_C, OSM_FILE_SA_MFT_RECORD_C, OSM_FILE_SA_MULTIPATH_RECORD_C, OSM_FILE_SA_NODE_RECORD_C, OSM_FILE_SA_PATH_RECORD_C, OSM_FILE_SA_PKEY_RECORD_C, OSM_FILE_SA_PORTINFO_RECORD_C, OSM_FILE_SA_SERVICE_RECORD_C, OSM_FILE_SA_SLVL_RECORD_C, OSM_FILE_SA_SMINFO_RECORD_C, OSM_FILE_SA_SW_INFO_RECORD_C, OSM_FILE_SA_VLARB_RECORD_C, OSM_FILE_SERVICE_C, OSM_FILE_SLVL_MAP_RCV_C, OSM_FILE_SM_C, OSM_FILE_SMINFO_RCV_C, OSM_FILE_SM_MAD_CTRL_C, OSM_FILE_SM_STATE_MGR_C, OSM_FILE_STATE_MGR_C, OSM_FILE_SUBNET_C, OSM_FILE_SW_INFO_RCV_C, OSM_FILE_SWITCH_C, OSM_FILE_TORUS_C, OSM_FILE_TRAP_RCV_C, OSM_FILE_UCAST_CACHE_C, OSM_FILE_UCAST_DNUP_C, OSM_FILE_UCAST_FILE_C, OSM_FILE_UCAST_FTREE_C, OSM_FILE_UCAST_LASH_C, OSM_FILE_UCAST_MGR_C, OSM_FILE_UCAST_UPDN_C, OSM_FILE_VENDOR_IBUMAD_C, OSM_FILE_VL15INTF_C, OSM_FILE_VL_ARB_RCV_C, OSM_FILE_ST_C, OSM_FILE_UCAST_DFSSSP_C, OSM_FILE_CONGESTION_CONTROL_C, } osm_file_ids_enum; /***********/ END_C_DECLS #endif /* _OSM_FILE_ID_H_ */ opensm-3.3.20/include/opensm/osm_guid.h0000644000205000001450000000424712104655724014730 00000000000000/* * Copyright (c) 2011 Mellanox Technologies LTD. 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. * */ #ifndef _OSM_GUID_H_ #define _OSM_GUID_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct osm_guidinfo_work_obj { cl_list_item_t list_item; osm_port_t *p_port; uint8_t block_num; } osm_guidinfo_work_obj_t; osm_guidinfo_work_obj_t *osm_guid_work_obj_new(IN osm_port_t * p_port, IN uint8_t block_num); void osm_guid_work_obj_delete(IN osm_guidinfo_work_obj_t * p_wobj); int osm_queue_guidinfo(IN osm_sa_t *sa, IN osm_port_t *p_port, IN uint8_t block_num); END_C_DECLS #endif /* _OSM_GUID_H_ */ opensm-3.3.20/include/opensm/osm_helper.h0000644000205000001450000004546212272264652015265 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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. * */ #ifndef _OSM_HELPER_H_ #define _OSM_HELPER_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * Abstract: * Declaration of helpful functions. */ /****f* OpenSM: Helper/ib_get_sa_method_str * NAME * ib_get_sa_method_str * * DESCRIPTION * Returns a string for the specified SA Method value. * * SYNOPSIS */ const char *ib_get_sa_method_str(IN uint8_t method); /* * PARAMETERS * method * [in] Network order METHOD ID value. * * RETURN VALUES * Pointer to the method string. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/ib_get_sm_method_str * NAME * ib_get_sm_method_str * * DESCRIPTION * Returns a string for the specified SM Method value. * * SYNOPSIS */ const char *ib_get_sm_method_str(IN uint8_t method); /* * PARAMETERS * method * [in] Network order METHOD ID value. * * RETURN VALUES * Pointer to the method string. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/ib_get_sm_attr_str * NAME * ib_get_sm_attr_str * * DESCRIPTION * Returns a string for the specified SM attribute value. * * SYNOPSIS */ const char *ib_get_sm_attr_str(IN ib_net16_t attr); /* * PARAMETERS * attr * [in] Network order attribute ID value. * * RETURN VALUES * Pointer to the attribute string. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/ib_get_sa_attr_str * NAME * ib_get_sa_attr_str * * DESCRIPTION * Returns a string for the specified SA attribute value. * * SYNOPSIS */ const char *ib_get_sa_attr_str(IN ib_net16_t attr); /* * PARAMETERS * attr * [in] Network order attribute ID value. * * RETURN VALUES * Pointer to the attribute string. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/ib_get_trap_str * NAME * ib_get_trap_str * * DESCRIPTION * Returns a name for the specified trap. * * SYNOPSIS */ const char *ib_get_trap_str(uint16_t trap_num); /* * PARAMETERS * trap_num * [in] Network order trap number. * * RETURN VALUES * Name of the trap. * *********/ extern const ib_gid_t ib_zero_gid; /****f* IBA Base: Types/ib_gid_is_notzero * NAME * ib_gid_is_notzero * * DESCRIPTION * Returns a boolean indicating whether or not the GID is zero. * * SYNOPSIS */ static inline boolean_t ib_gid_is_notzero(IN const ib_gid_t * p_gid) { return memcmp(p_gid, &ib_zero_gid, sizeof(*p_gid)); } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * RETURN VALUES * Returns TRUE if GID is not zero. * FALSE otherwise. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* OpenSM: Helper/osm_dump_port_info * NAME * osm_dump_port_info * * DESCRIPTION * Dumps the PortInfo attribute to the log. * * SYNOPSIS */ void osm_dump_port_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_port_info_t * p_pi, IN osm_log_level_t log_level); void osm_dump_port_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_port_info_t * p_pi, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object * * node_guid * [in] Node GUID that owns this port. * * port_guid * [in] Port GUID for this port. * * port_num * [in] Port number for this port. * * p_pi * [in] Pointer to the PortInfo attribute * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_dump_guid_info * NAME * osm_dump_guid_info * * DESCRIPTION * Dumps the GUIDInfo attribute to the log. * * SYNOPSIS */ void osm_dump_guid_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t block_num, IN const ib_guid_info_t * p_gi, IN osm_log_level_t log_level); void osm_dump_guid_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t block_num, IN const ib_guid_info_t * p_gi, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object. * * node_guid * [in] Node GUID that owns this port. * * port_guid * [in] Port GUID for this port. * * block_num * [in] Block number. * * p_gi * [in] Pointer to the GUIDInfo attribute. * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ void osm_dump_mlnx_ext_port_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_mlnx_ext_port_info_t * p_pi, IN osm_log_level_t log_level); void osm_dump_mlnx_ext_port_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_mlnx_ext_port_info_t * p_pi, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_path_record(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr, IN osm_log_level_t log_level); void osm_dump_path_record_v2(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_multipath_record(IN osm_log_t * p_log, IN const ib_multipath_rec_t * p_mpr, IN osm_log_level_t log_level); void osm_dump_multipath_record_v2(IN osm_log_t * p_log, IN const ib_multipath_rec_t * p_mpr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_node_record(IN osm_log_t * p_log, IN const ib_node_record_t * p_nr, IN osm_log_level_t log_level); void osm_dump_node_record_v2(IN osm_log_t * p_log, IN const ib_node_record_t * p_nr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_mc_record(IN osm_log_t * p_log, IN const ib_member_rec_t * p_mcmr, IN osm_log_level_t log_level); void osm_dump_mc_record_v2(IN osm_log_t * p_log, IN const ib_member_rec_t * p_mcmr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_link_record(IN osm_log_t * p_log, IN const ib_link_record_t * p_lr, IN osm_log_level_t log_level); void osm_dump_link_record_v2(IN osm_log_t * p_log, IN const ib_link_record_t * p_lr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_service_record(IN osm_log_t * p_log, IN const ib_service_record_t * p_sr, IN osm_log_level_t log_level); void osm_dump_service_record_v2(IN osm_log_t * p_log, IN const ib_service_record_t * p_sr, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_portinfo_record(IN osm_log_t * p_log, IN const ib_portinfo_record_t * p_pir, IN osm_log_level_t log_level); void osm_dump_portinfo_record_v2(IN osm_log_t * p_log, IN const ib_portinfo_record_t * p_pir, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_guidinfo_record(IN osm_log_t * p_log, IN const ib_guidinfo_record_t * p_gir, IN osm_log_level_t log_level); void osm_dump_guidinfo_record_v2(IN osm_log_t * p_log, IN const ib_guidinfo_record_t * p_gir, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_inform_info(IN osm_log_t * p_log, IN const ib_inform_info_t * p_ii, IN osm_log_level_t log_level); void osm_dump_inform_info_v2(IN osm_log_t * p_log, IN const ib_inform_info_t * p_ii, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_inform_info_record(IN osm_log_t * p_log, IN const ib_inform_info_record_t * p_iir, IN osm_log_level_t log_level); void osm_dump_inform_info_record_v2(IN osm_log_t * p_log, IN const ib_inform_info_record_t * p_iir, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_switch_info_record(IN osm_log_t * p_log, IN const ib_switch_info_record_t * p_sir, IN osm_log_level_t log_level); void osm_dump_switch_info_record_v2(IN osm_log_t * p_log, IN const ib_switch_info_record_t * p_sir, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_sm_info_record(IN osm_log_t * p_log, IN const ib_sminfo_record_t * p_smir, IN osm_log_level_t log_level); void osm_dump_sm_info_record_v2(IN osm_log_t * p_log, IN const ib_sminfo_record_t * p_smir, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_pkey_block(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint16_t block_num, IN uint8_t port_num, IN const ib_pkey_table_t * p_pkey_tbl, IN osm_log_level_t log_level); void osm_dump_pkey_block_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint16_t block_num, IN uint8_t port_num, IN const ib_pkey_table_t * p_pkey_tbl, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_slvl_map_table(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t in_port_num, IN uint8_t out_port_num, IN const ib_slvl_table_t * p_slvl_tbl, IN osm_log_level_t log_level); void osm_dump_slvl_map_table_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t in_port_num, IN uint8_t out_port_num, IN const ib_slvl_table_t * p_slvl_tbl, IN const int file_id, IN osm_log_level_t log_level); void osm_dump_vl_arb_table(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t block_num, IN uint8_t port_num, IN const ib_vl_arb_table_t * p_vla_tbl, IN osm_log_level_t log_level); void osm_dump_vl_arb_table_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t block_num, IN uint8_t port_num, IN const ib_vl_arb_table_t * p_vla_tbl, IN const int file_id, IN osm_log_level_t log_level); /****f* OpenSM: Helper/osm_dump_port_info * NAME * osm_dump_port_info * * DESCRIPTION * Dumps the PortInfo attribute to the log. * * SYNOPSIS */ void osm_dump_node_info(IN osm_log_t * p_log, IN const ib_node_info_t * p_ni, IN osm_log_level_t log_level); void osm_dump_node_info_v2(IN osm_log_t * p_log, IN const ib_node_info_t * p_ni, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object * * p_ni * [in] Pointer to the NodeInfo attribute * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_dump_sm_info * NAME * osm_dump_sm_info * * DESCRIPTION * Dumps the SMInfo attribute to the log. * * SYNOPSIS */ void osm_dump_sm_info(IN osm_log_t * p_log, IN const ib_sm_info_t * p_smi, IN osm_log_level_t log_level); void osm_dump_sm_info_v2(IN osm_log_t * p_log, IN const ib_sm_info_t * p_smi, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object * * p_smi * [in] Pointer to the SMInfo attribute * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_dump_switch_info * NAME * osm_dump_switch_info * * DESCRIPTION * Dumps the SwitchInfo attribute to the log. * * SYNOPSIS */ void osm_dump_switch_info(IN osm_log_t * p_log, IN const ib_switch_info_t * p_si, IN osm_log_level_t log_level); void osm_dump_switch_info_v2(IN osm_log_t * p_log, IN const ib_switch_info_t * p_si, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object * * p_si * [in] Pointer to the SwitchInfo attribute * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_dump_notice * NAME * osm_dump_notice * * DESCRIPTION * Dumps the Notice attribute to the log. * * SYNOPSIS */ void osm_dump_notice(IN osm_log_t * p_log, IN const ib_mad_notice_attr_t * p_ntci, IN osm_log_level_t log_level); void osm_dump_notice_v2(IN osm_log_t * p_log, IN const ib_mad_notice_attr_t * p_ntci, IN const int file_id, IN osm_log_level_t log_level); /* * PARAMETERS * p_log * [in] Pointer to the osm_log_t object * * p_ntci * [in] Pointer to the Notice attribute * * log_level * [in] Log verbosity level with which to dump the data. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/osm_get_disp_msg_str * NAME * osm_get_disp_msg_str * * DESCRIPTION * Returns a string for the specified Dispatcher message. * * SYNOPSIS */ const char *osm_get_disp_msg_str(IN cl_disp_msgid_t msg); /* * PARAMETERS * msg * [in] Dispatcher message ID value. * * RETURN VALUES * Pointer to the message description string. * * NOTES * * SEE ALSO *********/ void osm_dump_dr_path(IN osm_log_t * p_log, IN const osm_dr_path_t * p_path, IN osm_log_level_t level); void osm_dump_dr_path_v2(IN osm_log_t * p_log, IN const osm_dr_path_t * p_path, IN const int file_id, IN osm_log_level_t level); void osm_dump_smp_dr_path(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN osm_log_level_t level); void osm_dump_smp_dr_path_v2(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN const int file_id, IN osm_log_level_t level); void osm_dump_dr_smp(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN osm_log_level_t level); void osm_dump_dr_smp_v2(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN const int file_id, IN osm_log_level_t level); void osm_dump_sa_mad(IN osm_log_t * p_log, IN const ib_sa_mad_t * p_smp, IN osm_log_level_t level); void osm_dump_sa_mad_v2(IN osm_log_t * p_log, IN const ib_sa_mad_t * p_smp, IN const int file_id, IN osm_log_level_t level); void osm_dump_dr_path_as_buf(IN size_t max_len, IN const osm_dr_path_t * p_path, OUT char* buf); /****f* IBA Base: Types/osm_get_sm_signal_str * NAME * osm_get_sm_signal_str * * DESCRIPTION * Returns a string for the specified SM state. * * SYNOPSIS */ const char *osm_get_sm_signal_str(IN osm_signal_t signal); /* * PARAMETERS * state * [in] Signal value * * RETURN VALUES * Pointer to the signal description string. * * NOTES * * SEE ALSO *********/ const char *osm_get_port_state_str_fixed_width(IN uint8_t port_state); const char *osm_get_node_type_str_fixed_width(IN uint8_t node_type); const char *osm_get_manufacturer_str(IN uint64_t guid_ho); const char *osm_get_mtu_str(IN uint8_t mtu); const char *osm_get_lwa_str(IN uint8_t lwa); const char *osm_get_lsa_str(IN uint8_t lsa, IN uint8_t lsea, IN uint8_t state, IN uint8_t fdr10); /****f* IBA Base: Types/osm_get_sm_mgr_signal_str * NAME * osm_get_sm_mgr_signal_str * * DESCRIPTION * Returns a string for the specified SM manager signal. * * SYNOPSIS */ const char *osm_get_sm_mgr_signal_str(IN osm_sm_signal_t signal); /* * PARAMETERS * signal * [in] SM manager signal * * RETURN VALUES * Pointer to the signal description string. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/osm_get_sm_mgr_state_str * NAME * osm_get_sm_mgr_state_str * * DESCRIPTION * Returns a string for the specified SM manager state. * * SYNOPSIS */ const char *osm_get_sm_mgr_state_str(IN uint16_t state); /* * PARAMETERS * state * [in] SM manager state * * RETURN VALUES * Pointer to the state description string. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_mtu_is_valid * NAME * ib_mtu_is_valid * * DESCRIPTION * Validates encoded MTU * * SYNOPSIS */ int ib_mtu_is_valid(IN const int mtu); /* * PARAMETERS * mtu * [in] Encoded path mtu. * * RETURN VALUES * Returns an int indicating mtu is valid (1) * or invalid (0). * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_rate_is_valid * NAME * ib_rate_is_valid * * DESCRIPTION * Validates encoded rate * * SYNOPSIS */ int ib_rate_is_valid(IN const int rate); /* * PARAMETERS * rate * [in] Encoded path rate. * * RETURN VALUES * Returns an int indicating rate is valid (1) * or invalid (0). * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_path_compare_rates * NAME * ib_path_compare_rates * * DESCRIPTION * Compares the encoded values for two path rates and * return value is based on the ordered comparison of * the path rates (or path rate equivalents). * * SYNOPSIS */ int ib_path_compare_rates(IN const int rate1, IN const int rate2); /* * PARAMETERS * rate1 * [in] Encoded path rate 1. * * rate2 * [in] Encoded path rate 2. * * RETURN VALUES * Returns an int indicating less than (-1), equal to (0), or * greater than (1) rate1 as compared with rate2. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_path_rate_get_prev * NAME * ib_path_rate_get_prev * * DESCRIPTION * Obtains encoded rate for the rate previous to the one requested. * * SYNOPSIS */ int ib_path_rate_get_prev(IN const int rate); /* * PARAMETERS * rate * [in] Encoded path rate. * * RETURN VALUES * Returns an int indicating encoded rate or * 0 if none can be found. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_path_rate_get_next * NAME * ib_path_rate_get_next * * DESCRIPTION * Obtains encoded rate for the rate subsequent to the one requested. * * SYNOPSIS */ int ib_path_rate_get_next(IN const int rate); /* * PARAMETERS * rate * [in] Encoded path rate. * * RETURN VALUES * Returns an int indicating encoded rate or * 0 if none can be found. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_HELPER_H_ */ opensm-3.3.20/include/opensm/osm_inform.h0000644000205000001450000001457612272264652015302 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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: * Declaration of osm_inform_rec_t. * This object represents an IBA Inform Record. * This object is part of the OpenSM family of objects. * * Author: * Eitan Zahavi, Mellanox */ #ifndef _OSM_INFR_H_ #define _OSM_INFR_H_ #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Inform Record * NAME * Inform Record * * DESCRIPTION * The Inform record encapsulates the information needed by the * SA to manage InformInfo registrations and sending Reports(Notice) * when SM receives Traps for registered LIDs. * * The inform records is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Eitan Zahavi, Mellanox * *********/ /****s* OpenSM: Inform Record/osm_infr_t * NAME * osm_infr_t * * DESCRIPTION * Inform Record structure. * * The osm_infr_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_infr { cl_list_item_t list_item; osm_bind_handle_t h_bind; osm_sa_t *sa; osm_mad_addr_t report_addr; ib_inform_info_record_t inform_record; } osm_infr_t; /* * FIELDS * list_item * List Item for qlist linkage. Must be first element!! * * h_bind * A handle of lower level mad srvc * * sa * A pointer to osm_sa object * * report_addr * Report address * * inform_record * The Inform Info Record * * SEE ALSO *********/ /****f* OpenSM: Inform Record/osm_infr_new * NAME * osm_infr_new * * DESCRIPTION * Allocates and initializes a Inform Record for use. * * SYNOPSIS */ osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec); /* * PARAMETERS * p_inf_rec * [in] Pointer to IB Inform Record * * RETURN VALUES * pointer to osm_infr_t structure. * * NOTES * Allows calling other inform record methods. * * SEE ALSO * Inform Record, osm_infr_delete *********/ /****f* OpenSM: Inform Record/osm_infr_delete * NAME * osm_infr_delete * * DESCRIPTION * Destroys and deallocates the osm_infr_t structure. * * SYNOPSIS */ void osm_infr_delete(IN osm_infr_t * p_infr); /* * PARAMETERS * p_infr * [in] Pointer to osm_infr_t structure * * SEE ALSO * Inform Record, osm_infr_new *********/ /****f* OpenSM: Inform Record/osm_infr_get_by_rec * NAME * osm_infr_get_by_rec * * DESCRIPTION * Find a matching osm_infr_t in the subnet DB by inform_info_record * * SYNOPSIS */ osm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr_rec); /* * PARAMETERS * p_subn * [in] Pointer to the subnet object * * p_log * [in] Pointer to the log object * * p_inf_rec * [in] Pointer to an inform_info record * * RETURN * The matching osm_infr_t * SEE ALSO * Inform Record, osm_infr_new, osm_infr_delete *********/ void osm_infr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr); void osm_infr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr); /****f* OpenSM: Inform Record/osm_infr_remove_subscriptions * NAME * osm_infr_remove_subscriptions * * DESCRIPTION * Remove all event subscriptions of a port * * SYNOPSIS */ ib_api_status_t osm_infr_remove_subscriptions(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN ib_net64_t port_guid); /* * PARAMETERS * p_subn * [in] Pointer to the subnet object * * p_log * [in] Pointer to the log object * * port_guid * [in] PortGUID of the subscriber that should be removed * * RETURN * CL_SUCCESS if port_guid had any subscriptions being removed * CL_NOT_FOUND if port_guid did not have any active subscriptions * SEE ALSO *********/ /****f* OpenSM: Inform Record/osm_report_notice * NAME * osm_report_notice * * DESCRIPTION * Once a Trap was received by the osm_trap_rcv, or a Trap sourced in * the SM was sent (Traps 64-67) this routine is called with a copy of * the notice data. * Given a notice attribute - compare and see if it matches the InformInfo * Element and if it does - call the Report(Notice) for the * target QP registered by the address stored in the InformInfo element * * SYNOPSIS */ ib_api_status_t osm_report_notice(IN osm_log_t * p_log, IN osm_subn_t * p_subn, IN ib_mad_notice_attr_t * p_ntc); /* * PARAMETERS * p_rcv * [in] Pointer to the trap receiver * * p_ntc * [in] Pointer to a copy of the incoming trap notice attribute. * * RETURN * IB_SUCCESS on good completion * * SEE ALSO * Inform Record, osm_trap_rcv *********/ END_C_DECLS #endif /* _OSM_INFR_H_ */ opensm-3.3.20/include/opensm/osm_ucast_lash.h0000644000205000001450000000530412104655724016121 00000000000000/* * Copyright (c) 2008,2009 System Fabric Works, Inc. All rights reserved. * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2007 Simula Research Laboratory. All rights reserved. * Copyright (c) 2007 Silicon Graphics Inc. 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: * Declarations for LASH algorithm */ #ifndef OSM_UCAST_LASH_H #define OSM_UCAST_LASH_H #include enum { UNQUEUED, Q_MEMBER, MST_MEMBER, MAX_INT = 9999, NONE = MAX_INT }; typedef struct _cdg_vertex { int from; int to; int seen; int temp; int visiting_number; struct _cdg_vertex *next; int num_temp_depend; int num_using_vertex; int num_deps; struct vertex_deps { struct _cdg_vertex *v; int num_used; } deps[0]; } cdg_vertex_t; typedef struct _switch { osm_switch_t *p_sw; int id; int used_channels; int *dij_channels; int q_state; mesh_node_t *node; struct routing_table { unsigned out_link; unsigned lane; } routing_table[0]; } switch_t; typedef struct _lash { osm_opensm_t *p_osm; int num_switches; uint8_t vl_min; int balance_limit; switch_t **switches; cdg_vertex_t ****cdg_vertex_matrix; int num_mst_in_lane[IB_MAX_NUM_VLS]; int ***virtual_location; } lash_t; #endif opensm-3.3.20/include/opensm/osm_lid_mgr.h0000644000205000001450000001504012353250030015371 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_lid_mgr_t. * This object represents the LID Manager object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_LID_MGR_H_ #define _OSM_LID_MGR_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define OSM_LID_MGR_LIST_SIZE_MIN 256 /****h* OpenSM/LID Manager * NAME * LID Manager * * DESCRIPTION * The LID Manager object encapsulates the information * needed to control LID assignments on the subnet. * * The LID Manager object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ struct osm_sm; /****s* OpenSM: LID Manager/osm_lid_mgr_t * NAME * osm_lid_mgr_t * * DESCRIPTION * LID Manager structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_lid_mgr { struct osm_sm *sm; osm_subn_t *p_subn; osm_db_t *p_db; osm_log_t *p_log; cl_plock_t *p_lock; osm_db_domain_t *p_g2l; cl_qlist_t free_ranges; boolean_t dirty; uint8_t used_lids[IB_LID_UCAST_END_HO + 1]; } osm_lid_mgr_t; /* * FIELDS * sm * Pointer to the SM object. * * p_subn * Pointer to the Subnet object for this subnet. * * p_db * Pointer to the database (persistency) object * * p_log * Pointer to the log object. * * p_lock * Pointer to the serializing lock. * * p_g2l * Pointer to the database domain storing guid to lid mapping. * * free_ranges * A list of available free lid ranges. The list is initialized * by the code that initializes the lid assignment and is consumed * by the procedure that finds a free range. It holds elements of * type osm_lid_mgr_range_t * * dirty * Indicates that lid table was updated * * used_lids * An array of used lids. keeps track of * existing and non existing mapping of guid->lid * * SEE ALSO * LID Manager object *********/ /****f* OpenSM: LID Manager/osm_lid_mgr_construct * NAME * osm_lid_mgr_construct * * DESCRIPTION * This function constructs a LID Manager object. * * SYNOPSIS */ void osm_lid_mgr_construct(IN osm_lid_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to a LID Manager object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows osm_lid_mgr_destroy * * Calling osm_lid_mgr_construct is a prerequisite to calling any other * method except osm_lid_mgr_init. * * SEE ALSO * LID Manager object, osm_lid_mgr_init, * osm_lid_mgr_destroy *********/ /****f* OpenSM: LID Manager/osm_lid_mgr_destroy * NAME * osm_lid_mgr_destroy * * DESCRIPTION * The osm_lid_mgr_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ void osm_lid_mgr_destroy(IN osm_lid_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to the object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified * LID Manager object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_lid_mgr_construct or osm_lid_mgr_init. * * SEE ALSO * LID Manager object, osm_lid_mgr_construct, * osm_lid_mgr_init *********/ /****f* OpenSM: LID Manager/osm_lid_mgr_init * NAME * osm_lid_mgr_init * * DESCRIPTION * The osm_lid_mgr_init function initializes a * LID Manager object for use. * * SYNOPSIS */ ib_api_status_t osm_lid_mgr_init(IN osm_lid_mgr_t * p_mgr, IN struct osm_sm * sm); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_lid_mgr_t object to initialize. * * sm * [in] Pointer to the SM object for this subnet. * * RETURN VALUES * CL_SUCCESS if the LID Manager object was initialized * successfully. * * NOTES * Allows calling other LID Manager methods. * * SEE ALSO * LID Manager object, osm_lid_mgr_construct, * osm_lid_mgr_destroy *********/ /****f* OpenSM: LID Manager/osm_lid_mgr_process_sm * NAME * osm_lid_mgr_process_sm * * DESCRIPTION * Configures the SM's port with its designated LID values. * * SYNOPSIS */ int osm_lid_mgr_process_sm(IN osm_lid_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_lid_mgr_t object. * * RETURN VALUES * Returns 0 on success and non-zero value otherwise. * * NOTES * * SEE ALSO * LID Manager *********/ /****f* OpenSM: LID Manager/osm_lid_mgr_process_subnet * NAME * osm_lid_mgr_process_subnet * * DESCRIPTION * Configures subnet ports (except the SM port itself) with their * designated LID values. * * SYNOPSIS */ int osm_lid_mgr_process_subnet(IN osm_lid_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_lid_mgr_t object. * * RETURN VALUES * Returns 0 on success and non-zero value otherwise. * * NOTES * * SEE ALSO * LID Manager *********/ END_C_DECLS #endif /* _OSM_LID_MGR_H_ */ opensm-3.3.20/include/opensm/osm_log.h0000644000205000001450000003415512104655724014562 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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: * Declaration of osm_log_t. * This object represents the log file. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_LOG_H_ #define _OSM_LOG_H_ #ifndef __WIN__ #include #endif #include #include #include #include #ifdef __GNUC__ #define STRICT_OSM_LOG_FORMAT __attribute__((format(printf, 3, 4))) #define STRICT_OSM_LOG_V2_FORMAT __attribute__((format(printf, 4, 5))) #else #define STRICT_OSM_LOG_FORMAT #define STRICT_OSM_LOG_V2_FORMAT #endif #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define LOG_ENTRY_SIZE_MAX 4096 #define BUF_SIZE LOG_ENTRY_SIZE_MAX #define __func__ __FUNCTION__ #ifdef FILE_ID #define OSM_LOG_ENTER( OSM_LOG_PTR ) \ osm_log_v2( OSM_LOG_PTR, OSM_LOG_FUNCS, FILE_ID, \ "%s: [\n", __func__); #define OSM_LOG_EXIT( OSM_LOG_PTR ) \ osm_log_v2( OSM_LOG_PTR, OSM_LOG_FUNCS, FILE_ID, \ "%s: ]\n", __func__); #define OSM_LOG_IS_ACTIVE_V2( OSM_LOG_PTR, OSM_LOG_FUNCS ) \ osm_log_is_active_v2( OSM_LOG_PTR, OSM_LOG_FUNCS, FILE_ID) #else #define OSM_LOG_ENTER( OSM_LOG_PTR ) \ osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \ "%s: [\n", __func__); #define OSM_LOG_EXIT( OSM_LOG_PTR ) \ osm_log( OSM_LOG_PTR, OSM_LOG_FUNCS, \ "%s: ]\n", __func__); #endif /****h* OpenSM/Log * NAME * Log * * DESCRIPTION * * AUTHOR * *********/ typedef uint8_t osm_log_level_t; #define OSM_LOG_NONE 0x00 #define OSM_LOG_ERROR 0x01 #define OSM_LOG_INFO 0x02 #define OSM_LOG_VERBOSE 0x04 #define OSM_LOG_DEBUG 0x08 #define OSM_LOG_FUNCS 0x10 #define OSM_LOG_FRAMES 0x20 #define OSM_LOG_ROUTING 0x40 #define OSM_LOG_ALL 0x7f #define OSM_LOG_SYS 0x80 /* DEFAULT - turn on ERROR and INFO only */ #define OSM_LOG_DEFAULT_LEVEL OSM_LOG_ERROR | OSM_LOG_INFO /****s* OpenSM: Log/osm_log_t * NAME * osm_log_t * * DESCRIPTION * * SYNOPSIS */ typedef struct osm_log { osm_log_level_t level; cl_spinlock_t lock; unsigned long count; unsigned long max_size; boolean_t flush; FILE *out_port; boolean_t accum_log_file; boolean_t daemon; char *log_file_name; char *log_prefix; osm_log_level_t per_mod_log_tbl[256]; } osm_log_t; /*********/ #define OSM_LOG_MOD_NAME_MAX 32 /****f* OpenSM: Log/osm_get_log_per_module * NAME * osm_get_log_per_module * * DESCRIPTION * This looks up the given file ID in the per module log table. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ osm_log_level_t osm_get_log_per_module(IN osm_log_t * p_log, IN const int file_id); /* * PARAMETERS * p_log * [in] Pointer to a Log object to construct. * * file_id * [in] File ID for module * * RETURN VALUES * The log level from the per module logging structure for this file ID. *********/ /****f* OpenSM: Log/osm_set_log_per_module * NAME * osm_set_log_per_module * * DESCRIPTION * This sets log level for the given file ID in the per module log table. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ void osm_set_log_per_module(IN osm_log_t * p_log, IN const int file_id, IN osm_log_level_t level); /* * PARAMETERS * p_log * [in] Pointer to a Log object to construct. * * file_id * [in] File ID for module * * level * [in] Log level of the module * * RETURN VALUES * This function does not return a value. *********/ /****f* OpenSM: Log/osm_reset_log_per_module * NAME * osm_reset_log_per_module * * DESCRIPTION * This resets log level for the entire per module log table. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ void osm_reset_log_per_module(IN osm_log_t * p_log); /* * PARAMETERS * p_log * [in] Pointer to a Log object to construct. * * RETURN VALUES * This function does not return a value. *********/ /****f* OpenSM: Log/osm_log_construct * NAME * osm_log_construct * * DESCRIPTION * This function constructs a Log object. * * SYNOPSIS */ static inline void osm_log_construct(IN osm_log_t * p_log) { cl_spinlock_construct(&p_log->lock); } /* * PARAMETERS * p_log * [in] Pointer to a Log object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_log_init, osm_log_init_v2, osm_log_destroy * * Calling osm_log_construct is a prerequisite to calling any other * method except osm_log_init or osm_log_init_v2. * * SEE ALSO * Log object, osm_log_init, osm_log_init_v2, * osm_log_destroy *********/ /****f* OpenSM: Log/osm_log_destroy * NAME * osm_log_destroy * * DESCRIPTION * The osm_log_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ static inline void osm_log_destroy(IN osm_log_t * p_log) { cl_spinlock_destroy(&p_log->lock); if (p_log->out_port != stdout) { fclose(p_log->out_port); p_log->out_port = stdout; } closelog(); } /* * PARAMETERS * p_log * [in] Pointer to the object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified * Log object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_log_construct, osm_log_init, or osm_log_init_v2. * * SEE ALSO * Log object, osm_log_construct, * osm_log_init, osm_log_init_v2 *********/ /****f* OpenSM: Log/osm_log_init_v2 * NAME * osm_log_init_v2 * * DESCRIPTION * The osm_log_init_v2 function initializes a * Log object for use. * * SYNOPSIS */ ib_api_status_t osm_log_init_v2(IN osm_log_t * p_log, IN boolean_t flush, IN uint8_t log_flags, IN const char *log_file, IN unsigned long max_size, IN boolean_t accum_log_file); /* * PARAMETERS * p_log * [in] Pointer to the log object. * * flush * [in] Set to TRUE directs the log to flush all log messages * immediately. This severely degrades log performance, * and is normally used for debugging only. * * log_flags * [in] The log verbosity level to be used. * * log_file * [in] if not NULL defines the name of the log file. Otherwise * it is stdout. * * RETURN VALUES * CL_SUCCESS if the Log object was initialized * successfully. * * NOTES * Allows calling other Log methods. * * SEE ALSO * Log object, osm_log_construct, * osm_log_destroy *********/ /****f* OpenSM: Log/osm_log_reopen_file * NAME * osm_log_reopen_file * * DESCRIPTION * The osm_log_reopen_file function reopens the log file * * SYNOPSIS */ int osm_log_reopen_file(osm_log_t * p_log); /* * PARAMETERS * p_log * [in] Pointer to the log object. * * RETURN VALUES * 0 on success or nonzero value otherwise. *********/ /****f* OpenSM: Log/osm_log_init * NAME * osm_log_init * * DESCRIPTION * The osm_log_init function initializes a * Log object for use. It is a wrapper for osm_log_init_v2(). * * SYNOPSIS */ ib_api_status_t osm_log_init(IN osm_log_t * p_log, IN boolean_t flush, IN uint8_t log_flags, IN const char *log_file, IN boolean_t accum_log_file); /* * Same as osm_log_init_v2() but without max_size parameter */ void osm_log(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const char *p_str, ...) STRICT_OSM_LOG_FORMAT; void osm_log_v2(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const int file_id, IN const char *p_str, ...) STRICT_OSM_LOG_V2_FORMAT; /****f* OpenSM: Log/osm_log_get_level * NAME * osm_log_get_level * * DESCRIPTION * Returns the current log level. * * SYNOPSIS */ static inline osm_log_level_t osm_log_get_level(IN const osm_log_t * p_log) { return p_log->level; } /* * PARAMETERS * p_log * [in] Pointer to the log object. * * RETURN VALUES * Returns the current log level. * * NOTES * * SEE ALSO * Log object, osm_log_construct, * osm_log_destroy *********/ /****f* OpenSM: Log/osm_log_set_level * NAME * osm_log_set_level * * DESCRIPTION * Sets the current log level. * * SYNOPSIS */ static inline void osm_log_set_level(IN osm_log_t * p_log, IN osm_log_level_t level) { p_log->level = level; osm_log(p_log, OSM_LOG_ALL, "Setting log level to: 0x%02x\n", level); } /* * PARAMETERS * p_log * [in] Pointer to the log object. * * level * [in] New level to set. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Log object, osm_log_construct, * osm_log_destroy *********/ /****f* OpenSM: Log/osm_log_is_active * NAME * osm_log_is_active * * DESCRIPTION * Returns TRUE if the specified log level would be logged. * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t osm_log_is_active(IN const osm_log_t * p_log, IN osm_log_level_t level) { return ((p_log->level & level) != 0); } /* * PARAMETERS * p_log * [in] Pointer to the log object. * * level * [in] Level to check. * * RETURN VALUES * Returns TRUE if the specified log level would be logged. * FALSE otherwise. * * NOTES * * SEE ALSO * Log object, osm_log_construct, * osm_log_destroy *********/ static inline boolean_t osm_log_is_active_v2(IN const osm_log_t * p_log, IN osm_log_level_t level, IN const int file_id) { if ((p_log->level & level) != 0) return 1; if ((level & p_log->per_mod_log_tbl[file_id])) return 1; return 0; } extern void osm_log_msg_box(osm_log_t *log, osm_log_level_t level, const char *func_name, const char *msg); extern void osm_log_msg_box_v2(osm_log_t *log, osm_log_level_t level, const int file_id, const char *func_name, const char *msg); extern void osm_log_raw(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const char *p_buf); #ifdef FILE_ID #define OSM_LOG(log, level, fmt, ...) do { \ if (osm_log_is_active_v2(log, (level), FILE_ID)) \ osm_log_v2(log, level, FILE_ID, "%s: " fmt, __func__, ## __VA_ARGS__); \ } while (0) #define OSM_LOG_MSG_BOX(log, level, msg) \ osm_log_msg_box_v2(log, level, FILE_ID, __func__, msg) #else #define OSM_LOG(log, level, fmt, ...) do { \ if (osm_log_is_active(log, (level))) \ osm_log(log, level, "%s: " fmt, __func__, ## __VA_ARGS__); \ } while (0) #define OSM_LOG_MSG_BOX(log, level, msg) \ osm_log_msg_box(log, level, __func__, msg) #endif #define DBG_CL_LOCK 0 #define CL_PLOCK_EXCL_ACQUIRE( __exp__ ) \ { \ if (DBG_CL_LOCK) \ printf("cl_plock_excl_acquire: Acquiring %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ cl_plock_excl_acquire( __exp__ ); \ if (DBG_CL_LOCK) \ printf("cl_plock_excl_acquire: Acquired %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ } #define CL_PLOCK_ACQUIRE( __exp__ ) \ { \ if (DBG_CL_LOCK) \ printf("cl_plock_acquire: Acquiring %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ cl_plock_acquire( __exp__ ); \ if (DBG_CL_LOCK) \ printf("cl_plock_acquire: Acquired %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ } #define CL_PLOCK_RELEASE( __exp__ ) \ { \ if (DBG_CL_LOCK) \ printf("cl_plock_release: Releasing %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ cl_plock_release( __exp__ ); \ if (DBG_CL_LOCK) \ printf("cl_plock_release: Released %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ } #define DBG_CL_SPINLOCK 0 #define CL_SPINLOCK_RELEASE( __exp__ ) \ { \ if (DBG_CL_SPINLOCK) \ printf("cl_spinlock_release: Releasing %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ cl_spinlock_release( __exp__ ); \ if (DBG_CL_SPINLOCK) \ printf("cl_spinlock_release: Released %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ } #define CL_SPINLOCK_ACQUIRE( __exp__ ) \ { \ if (DBG_CL_SPINLOCK) \ printf("cl_spinlock_acquire: Acquiring %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ cl_spinlock_acquire( __exp__ ); \ if (DBG_CL_SPINLOCK) \ printf("cl_spinlock_acquire: Acquired %p file %s, line %d\n", \ __exp__,__FILE__, __LINE__); \ } /****f* OpenSM: Helper/osm_is_debug * NAME * osm_is_debug * * DESCRIPTION * The osm_is_debug function returns TRUE if the opensm was compiled * in debug mode, and FALSE otherwise. * * SYNOPSIS */ boolean_t osm_is_debug(void); /* * PARAMETERS * None * * RETURN VALUE * TRUE if compiled in debug version. FALSE otherwise. * * NOTES * *********/ END_C_DECLS #endif /* _OSM_LOG_H_ */ opensm-3.3.20/include/opensm/osm_mad_pool.h0000644000205000001450000002151412104655724015566 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_mad_pool_t. * This object represents a pool of management datagram (MAD) objects. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MAD_POOL_H_ #define _OSM_MAD_POOL_H_ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/MAD Pool * NAME * MAD Pool * * DESCRIPTION * The MAD Pool encapsulates the information needed by the * OpenSM to manage a pool of MAD objects. The OpenSM allocates * one MAD Pool per IBA subnet. * * The MAD Pool is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: MAD Pool/osm_mad_pool_t * NAME * osm_mad_pool_t * * DESCRIPTION * MAD Pool structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_mad_pool { atomic32_t mads_out; } osm_mad_pool_t; /* * FIELDS * mads_out * Running total of the number of MADs outstanding. * * SEE ALSO * MAD Pool *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_construct * NAME * osm_mad_pool_construct * * DESCRIPTION * This function constructs a MAD Pool. * * SYNOPSIS */ void osm_mad_pool_construct(IN osm_mad_pool_t * p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a MAD Pool to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_mad_pool_init, osm_mad_pool_destroy * * Calling osm_mad_pool_construct is a prerequisite to calling any other * method except osm_mad_pool_init. * * SEE ALSO * MAD Pool, osm_mad_pool_init, osm_mad_pool_destroy *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_destroy * NAME * osm_mad_pool_destroy * * DESCRIPTION * The osm_mad_pool_destroy function destroys a node, releasing * all resources. * * SYNOPSIS */ void osm_mad_pool_destroy(IN osm_mad_pool_t * p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a MAD Pool to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified MAD Pool. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_mad_pool_construct or * osm_mad_pool_init. * * SEE ALSO * MAD Pool, osm_mad_pool_construct, osm_mad_pool_init *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_init * NAME * osm_mad_pool_init * * DESCRIPTION * The osm_mad_pool_init function initializes a MAD Pool for use. * * SYNOPSIS */ ib_api_status_t osm_mad_pool_init(IN osm_mad_pool_t * p_pool); /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object to initialize. * * RETURN VALUES * CL_SUCCESS if the MAD Pool was initialized successfully. * * NOTES * Allows calling other MAD Pool methods. * * SEE ALSO * MAD Pool, osm_mad_pool_construct, osm_mad_pool_destroy *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_get * NAME * osm_mad_pool_get * * DESCRIPTION * Gets a MAD wrapper and wire MAD from the pool. * * SYNOPSIS */ osm_madw_t *osm_mad_pool_get(IN osm_mad_pool_t * p_pool, IN osm_bind_handle_t h_bind, IN uint32_t total_size, IN const osm_mad_addr_t * p_mad_addr); /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object. * * h_bind * [in] Handle returned from osm_vendor_bind() call to the * port over which this mad will be sent. * * total_size * [in] Total size, including MAD header of the requested MAD. * * p_mad_addr * [in] Pointer to the MAD address structure. This parameter * may be NULL for directed route MADs. * * RETURN VALUES * Returns a pointer to a MAD wrapper containing the MAD. * A return value of NULL means no MADs are available. * * NOTES * The MAD must eventually be returned to the pool with a call to * osm_mad_pool_put. * * The osm_mad_pool_construct or osm_mad_pool_init must be called before * using this function. * * SEE ALSO * MAD Pool, osm_mad_pool_put *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_put * NAME * osm_mad_pool_put * * DESCRIPTION * Returns a MAD to the pool. * * SYNOPSIS */ void osm_mad_pool_put(IN osm_mad_pool_t * p_pool, IN osm_madw_t * p_madw); /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object. * * p_madw * [in] Pointer to a MAD Wrapper for a MAD that was previously * retrieved from the pool. * * RETURN VALUES * This function does not return a value. * * NOTES * The osm_mad_pool_construct or osm_mad_pool_init must be called before * using this function. * * SEE ALSO * MAD Pool, osm_mad_pool_get *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper * NAME * osm_mad_pool_get_wrapper * * DESCRIPTION * Gets a only MAD wrapper from the pool (no wire MAD). * * SYNOPSIS */ osm_madw_t *osm_mad_pool_get_wrapper(IN osm_mad_pool_t * p_pool, IN osm_bind_handle_t h_bind, IN uint32_t total_size, IN const ib_mad_t * p_mad, IN const osm_mad_addr_t * p_mad_addr); /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object. * * h_bind * [in] Handle returned from osm_vendor_bind() call to the * port for which this mad wrapper will be used. * * total_size * [in] Total size, including MAD header of the MAD that will * be attached to this wrapper. * * p_mad * [in] Pointer to the MAD to attach to this wrapper. * * p_mad_addr * [in] Pointer to the MAD address structure. This parameter * may be NULL for directed route MADs. * * RETURN VALUES * Returns a pointer to a MAD wrapper. * A return value of NULL means no MAD wrappers are available. * * NOTES * The MAD must eventually be returned to the pool with a call to * osm_mad_pool_put. * * The osm_mad_pool_construct or osm_mad_pool_init must be called before * using this function. * * SEE ALSO * MAD Pool, osm_mad_pool_put *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_get_wrapper_raw * NAME * osm_mad_pool_get_wrapper_raw * * DESCRIPTION * Gets a only an uninitialized MAD wrapper from the pool (no wire MAD). * * SYNOPSIS */ osm_madw_t *osm_mad_pool_get_wrapper_raw(IN osm_mad_pool_t * p_pool); /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object. * * RETURN VALUES * Returns a pointer to a MAD wrapper. * A return value of NULL means no MAD wrappers are available. * * NOTES * The MAD must eventually be returned to the pool with a call to * osm_mad_pool_put. * * The osm_mad_pool_construct or osm_mad_pool_init must be called before * using this function. * * SEE ALSO * MAD Pool, osm_mad_pool_put *********/ /****f* OpenSM: MAD Pool/osm_mad_pool_get_outstanding * NAME * osm_mad_pool_get_count * * DESCRIPTION * Returns the running count of MADs currently outstanding from the pool. * * SYNOPSIS */ static inline uint32_t osm_mad_pool_get_outstanding(IN const osm_mad_pool_t * p_pool) { return p_pool->mads_out; } /* * PARAMETERS * p_pool * [in] Pointer to an osm_mad_pool_t object. * * RETURN VALUES * Returns the running count of MADs currently outstanding from the pool. * * NOTES * The osm_mad_pool_construct or osm_mad_pool_init must be called before * using this function. * * SEE ALSO * MAD Pool, osm_mad_pool_get *********/ END_C_DECLS #endif /* _OSM_MAD_POOL_H_ */ opensm-3.3.20/include/opensm/osm_madw.h0000644000205000001450000005625212272264652014735 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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: * Declaration of osm_mad_wrapper_t. * This object represents the context wrapper for OpenSM MAD processing. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MADW_H_ #define _OSM_MADW_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: MAD Wrapper/osm_bind_info_t * NAME * osm_bind_info_t * * DESCRIPTION * * SYNOPSIS */ typedef struct osm_bind_info { ib_net64_t port_guid; uint8_t mad_class; uint8_t class_version; boolean_t is_responder; boolean_t is_trap_processor; boolean_t is_report_processor; uint32_t send_q_size; uint32_t recv_q_size; uint32_t timeout; uint32_t retries; } osm_bind_info_t; /* * FIELDS * portguid * PortGuid of local port * * mad_class * Mgmt Class ID * * class_version * Mgmt Class version * * is_responder * True if this is a GSI Agent * * is_trap_processor * True if GSI Trap msgs are handled * * is_report_processor * True if GSI Report msgs are handled * * send_q_size * SendQueueSize * * recv_q_size * Receive Queue Size * * timeout * Transaction timeout * * retries * Number of retries for transaction * * SEE ALSO *********/ /****h* OpenSM/MAD Wrapper * NAME * MAD Wrapper * * DESCRIPTION * The MAD Wrapper object encapsulates the information needed by the * OpenSM to manage individual MADs. The OpenSM allocates one MAD Wrapper * per MAD. * * The MAD Wrapper is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: MAD Wrapper/osm_ni_context_t * NAME * osm_ni_context_t * * DESCRIPTION * Context needed by recipient of NodeInfo attribute. * * SYNOPSIS */ typedef struct osm_ni_context { ib_net64_t node_guid; uint8_t port_num; ib_net64_t dup_node_guid; uint8_t dup_port_num; unsigned dup_count; } osm_ni_context_t; /* * FIELDS * p_node * Pointer to the node thru which we got to this node. * * p_sw * Pointer to the switch object (if any) of the switch * thru which we got to this node. * * port_num * Port number on the node or switch thru which we got * to this node. * * SEE ALSO *********/ /****s* OpenSM: MAD Wrapper/osm_pi_context_t * NAME * osm_pi_context_t * * DESCRIPTION * Context needed by recipient of PortInfo attribute. * * SYNOPSIS */ typedef struct osm_pi_context { ib_net64_t node_guid; ib_net64_t port_guid; boolean_t set_method; boolean_t light_sweep; boolean_t active_transition; boolean_t client_rereg; } osm_pi_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_gi_context_t * NAME * osm_gi_context_t * * DESCRIPTION * Context needed by recipient of GUIDInfo attribute. * * SYNOPSIS */ typedef struct osm_gi_context { ib_net64_t node_guid; ib_net64_t port_guid; boolean_t set_method; uint8_t port_num; } osm_gi_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_nd_context_t * NAME * osm_nd_context_t * * DESCRIPTION * Context needed by recipient of NodeDescription attribute. * * SYNOPSIS */ typedef struct osm_nd_context { ib_net64_t node_guid; } osm_nd_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_si_context_t * NAME * osm_si_context_t * * DESCRIPTION * Context needed by recipient of SwitchInfo attribute. * * SYNOPSIS */ typedef struct osm_si_context { ib_net64_t node_guid; boolean_t set_method; boolean_t light_sweep; boolean_t lft_top_change; } osm_si_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_lft_context_t * NAME * osm_lft_context_t * * DESCRIPTION * Context needed by recipient of LinearForwardingTable attribute. * * SYNOPSIS */ typedef struct osm_lft_context { ib_net64_t node_guid; boolean_t set_method; } osm_lft_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_mft_context_t * NAME * osm_mft_context_t * * DESCRIPTION * Context needed by recipient of MulticastForwardingTable attribute. * * SYNOPSIS */ typedef struct osm_mft_context { ib_net64_t node_guid; boolean_t set_method; } osm_mft_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_smi_context_t * NAME * osm_smi_context_t * * DESCRIPTION * Context needed by recipient of SMInfo attribute. * * SYNOPSIS */ typedef struct osm_smi_context { ib_net64_t port_guid; boolean_t set_method; boolean_t light_sweep; } osm_smi_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_pkey_context_t * NAME * osm_pkey_context_t * * DESCRIPTION * Context needed by recipient of P_Key attribute. * * SYNOPSIS */ typedef struct osm_pkey_context { ib_net64_t node_guid; ib_net64_t port_guid; boolean_t set_method; } osm_pkey_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_slvl_context_t * NAME * osm_slvl_context_t * * DESCRIPTION * Context needed by recipient of PortInfo attribute. * * SYNOPSIS */ typedef struct osm_slvl_context { ib_net64_t node_guid; ib_net64_t port_guid; boolean_t set_method; } osm_slvl_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_vla_context_t * NAME * osm_vla_context_t * * DESCRIPTION * Context needed by recipient of VL Arb attribute. * * SYNOPSIS */ typedef struct osm_vla_context { ib_net64_t node_guid; ib_net64_t port_guid; boolean_t set_method; } osm_vla_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_perfmgr_context_t * DESCRIPTION * Context for Performance manager queries */ typedef struct osm_perfmgr_context { uint64_t node_guid; uint16_t port; uint8_t mad_method; /* was this a get or a set */ ib_net16_t mad_attr_id; #ifdef ENABLE_OSM_PERF_MGR_PROFILE struct timeval query_start; #endif } osm_perfmgr_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_cc_context_t * DESCRIPTION * Context for Congestion Control MADs */ typedef struct osm_cc_context { ib_net64_t node_guid; ib_net64_t port_guid; uint8_t port; uint8_t mad_method; /* was this a get or a set */ ib_net32_t attr_mod; } osm_cc_context_t; /*********/ #ifndef OSM_VENDOR_INTF_OPENIB /****s* OpenSM: MAD Wrapper/osm_arbitrary_context_t * NAME * osm_arbitrary_context_t * * DESCRIPTION * Context needed by arbitrary recipient. * * SYNOPSIS */ typedef struct osm_arbitrary_context { void *context1; void *context2; } osm_arbitrary_context_t; /*********/ #endif /****s* OpenSM: MAD Wrapper/osm_madw_context_t * NAME * osm_madw_context_t * * DESCRIPTION * Context needed by recipients of MAD responses. * * SYNOPSIS */ typedef union _osm_madw_context { osm_ni_context_t ni_context; osm_pi_context_t pi_context; osm_gi_context_t gi_context; osm_nd_context_t nd_context; osm_si_context_t si_context; osm_lft_context_t lft_context; osm_mft_context_t mft_context; osm_smi_context_t smi_context; osm_slvl_context_t slvl_context; osm_pkey_context_t pkey_context; osm_vla_context_t vla_context; osm_perfmgr_context_t perfmgr_context; osm_cc_context_t cc_context; #ifndef OSM_VENDOR_INTF_OPENIB osm_arbitrary_context_t arb_context; #endif } osm_madw_context_t; /*********/ /****s* OpenSM: MAD Wrapper/osm_mad_addr_t * NAME * osm_mad_addr_t * * DESCRIPTION * * SYNOPSIS */ typedef struct osm_mad_addr { ib_net16_t dest_lid; uint8_t path_bits; uint8_t static_rate; union addr_type { struct _smi { ib_net16_t source_lid; uint8_t port_num; } smi; struct _gsi { ib_net32_t remote_qp; ib_net32_t remote_qkey; uint16_t pkey_ix; uint8_t service_level; boolean_t global_route; ib_grh_t grh_info; } gsi; } addr_type; } osm_mad_addr_t; /* * FIELDS * * SEE ALSO *********/ /****s* OpenSM: MAD Wrapper/osm_madw_t * NAME * osm_madw_t * * DESCRIPTION * Context needed for processing individual MADs * * SYNOPSIS */ typedef struct osm_madw { cl_list_item_t list_item; osm_bind_handle_t h_bind; osm_vend_wrap_t vend_wrap; osm_mad_addr_t mad_addr; osm_bind_info_t bind_info; osm_madw_context_t context; uint32_t mad_size; ib_api_status_t status; cl_disp_msgid_t fail_msg; boolean_t resp_expected; const ib_mad_t *p_mad; } osm_madw_t; /* * FIELDS * list_item * List linkage for lists. MUST BE FIRST MEMBER! * * h_bind * Bind handle for the port on which this MAD will be sent * or was received. * * vend_wrap * Transport vendor specific context. This structure is not * used outside MAD transport vendor specific code. * * context * Union of controller specific contexts needed for this MAD. * This structure allows controllers to indirectly communicate * with each other through the dispatcher. * * mad_size * Size of this MAD in bytes. * * status * Status of completed operation on the MAD. * CL_SUCCESS if the operation was successful. * * fail_msg * Dispatcher message with which to post this MAD on failure. * This value is set by the originator of the MAD. * If an operation on this MAD fails, for example due to a timeout, * then the transport layer will dispose of the MAD by sending * it through the Dispatcher with this message type. Presumably, * there is a controller listening for the failure message that can * properly clean up. * * resp_expected * TRUE if a response is expected to this MAD. * FALSE otherwise. * * p_mad * Pointer to the wire MAD. The MAD itself cannot be part of the * wrapper, since wire MADs typically reside in special memory * registered with the local HCA. * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_init * NAME * osm_madw_init * * DESCRIPTION * Initializes a MAD Wrapper object for use. * * SYNOPSIS */ static inline void osm_madw_init(IN osm_madw_t * p_madw, IN osm_bind_handle_t h_bind, IN uint32_t mad_size, IN const osm_mad_addr_t * p_mad_addr) { memset(p_madw, 0, sizeof(*p_madw)); p_madw->h_bind = h_bind; p_madw->fail_msg = CL_DISP_MSGID_NONE; p_madw->mad_size = mad_size; if (p_mad_addr) p_madw->mad_addr = *p_mad_addr; p_madw->resp_expected = FALSE; } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object to initialize. * * h_bind * [in] Pointer to the wire MAD. * * p_mad_addr * [in] Pointer to the MAD address structure. This parameter may * be NULL for directed route MADs. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_smp_ptr * NAME * osm_madw_get_smp_ptr * * DESCRIPTION * Gets a pointer to the SMP in this MAD. * * SYNOPSIS */ static inline ib_smp_t *osm_madw_get_smp_ptr(IN const osm_madw_t * p_madw) { return ((ib_smp_t *) p_madw->p_mad); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object to initialize. * * RETURN VALUES * Pointer to the start of the SMP MAD. * * NOTES * * SEE ALSO * MAD Wrapper object *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_sa_mad_ptr * NAME * osm_madw_get_sa_mad_ptr * * DESCRIPTION * Gets a pointer to the SA MAD in this MAD wrapper. * * SYNOPSIS */ static inline ib_sa_mad_t *osm_madw_get_sa_mad_ptr(IN const osm_madw_t * p_madw) { return ((ib_sa_mad_t *) p_madw->p_mad); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the SA MAD. * * NOTES * * SEE ALSO * MAD Wrapper object *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_perfmgt_mad_ptr * DESCRIPTION * Gets a pointer to the PerfMgt MAD in this MAD wrapper. * * SYNOPSIS */ static inline ib_perfmgt_mad_t *osm_madw_get_perfmgt_mad_ptr(IN const osm_madw_t * p_madw) { return ((ib_perfmgt_mad_t *) p_madw->p_mad); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the PerfMgt MAD. * * NOTES * * SEE ALSO * MAD Wrapper object *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_cc_mad_ptr * DESCRIPTION * Gets a pointer to the Congestion Control MAD in this MAD wrapper. * * SYNOPSIS */ static inline ib_cc_mad_t *osm_madw_get_cc_mad_ptr(IN const osm_madw_t * p_madw) { return ((ib_cc_mad_t *) p_madw->p_mad); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the Congestion Control MAD. * * NOTES * * SEE ALSO * MAD Wrapper object *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_ni_context_ptr * NAME * osm_madw_get_ni_context_ptr * * DESCRIPTION * Gets a pointer to the NodeInfo context in this MAD. * * SYNOPSIS */ static inline osm_ni_context_t *osm_madw_get_ni_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_ni_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_pi_context_ptr * NAME * osm_madw_get_pi_context_ptr * * DESCRIPTION * Gets a pointer to the PortInfo context in this MAD. * * SYNOPSIS */ static inline osm_pi_context_t *osm_madw_get_pi_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_pi_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_gi_context_ptr * NAME * osm_madw_get_gi_context_ptr * * DESCRIPTION * Gets a pointer to the GUIDInfo context in this MAD. * * SYNOPSIS */ static inline osm_gi_context_t *osm_madw_get_gi_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_gi_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_nd_context_ptr * NAME * osm_madw_get_nd_context_ptr * * DESCRIPTION * Gets a pointer to the NodeDescription context in this MAD. * * SYNOPSIS */ static inline osm_nd_context_t *osm_madw_get_nd_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_nd_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_lft_context_ptr * NAME * osm_madw_get_lft_context_ptr * * DESCRIPTION * Gets a pointer to the LFT context in this MAD. * * SYNOPSIS */ static inline osm_lft_context_t *osm_madw_get_lft_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_lft_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_mft_context_ptr * NAME * osm_madw_get_mft_context_ptr * * DESCRIPTION * Gets a pointer to the MFT context in this MAD. * * SYNOPSIS */ static inline osm_mft_context_t *osm_madw_get_mft_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_mft_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_si_context_ptr * NAME * osm_madw_get_si_context_ptr * * DESCRIPTION * Gets a pointer to the SwitchInfo context in this MAD. * * SYNOPSIS */ static inline osm_si_context_t *osm_madw_get_si_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_si_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_smi_context_ptr * NAME * osm_madw_get_smi_context_ptr * * DESCRIPTION * Gets a pointer to the SMInfo context in this MAD. * * SYNOPSIS */ static inline osm_smi_context_t *osm_madw_get_smi_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_smi_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_pkey_context_ptr * NAME * osm_madw_get_pkey_context_ptr * * DESCRIPTION * Gets a pointer to the P_Key context in this MAD. * * SYNOPSIS */ static inline osm_pkey_context_t *osm_madw_get_pkey_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_pkey_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_slvl_context_ptr * NAME * osm_madw_get_slvl_context_ptr * * DESCRIPTION * Gets a pointer to the PortInfo context in this MAD. * * SYNOPSIS */ static inline osm_slvl_context_t *osm_madw_get_slvl_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_slvl_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_vla_context_ptr * NAME * osm_madw_get_vla_context_ptr * * DESCRIPTION * Gets a pointer to the Vl Arb context in this MAD. * * SYNOPSIS */ static inline osm_vla_context_t *osm_madw_get_vla_context_ptr(IN const osm_madw_t * p_madw) { return ((osm_vla_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ #ifndef OSM_VENDOR_INTF_OPENIB /****f* OpenSM: MAD Wrapper/osm_madw_get_arbitrary_context_ptr * NAME * osm_madw_get_arbitrary_context_ptr * * DESCRIPTION * Gets a pointer to the arbitrary context in this MAD. * * SYNOPSIS */ static inline osm_arbitrary_context_t *osm_madw_get_arbitrary_context_ptr(IN const osm_madw_t * const p_madw) { return ((osm_arbitrary_context_t *) & p_madw->context); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Pointer to the start of the context structure. * * NOTES * * SEE ALSO *********/ #endif /****f* OpenSM: MAD Wrapper/osm_madw_get_vend_ptr * NAME * osm_madw_get_vend_ptr * * DESCRIPTION * Gets a pointer to the vendor specific MAD wrapper component. * * SYNOPSIS */ static inline osm_vend_wrap_t *osm_madw_get_vend_ptr(IN const osm_madw_t * p_madw) { return ((osm_vend_wrap_t *) & p_madw->vend_wrap); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Gets a pointer to the vendor specific MAD wrapper component. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_bind_handle * NAME * osm_madw_get_bind_handle * * DESCRIPTION * Returns the bind handle associated with this MAD. * * SYNOPSIS */ static inline osm_bind_handle_t osm_madw_get_bind_handle(IN const osm_madw_t * p_madw) { return ((osm_bind_handle_t) p_madw->h_bind); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Returns the bind handle associated with this MAD. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_mad_addr_ptr * NAME * osm_madw_get_mad_addr_ptr * * DESCRIPTION * Returns the mad address structure associated with this MAD. * * SYNOPSIS */ static inline osm_mad_addr_t *osm_madw_get_mad_addr_ptr(IN const osm_madw_t * p_madw) { return ((osm_mad_addr_t *) & p_madw->mad_addr); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Returns the mad address structure associated with this MAD. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_mad_ptr * NAME * osm_madw_get_mad_ptr * * DESCRIPTION * Returns the mad address structure associated with this MAD. * * SYNOPSIS */ static inline ib_mad_t *osm_madw_get_mad_ptr(IN const osm_madw_t * p_madw) { return ((ib_mad_t *) p_madw->p_mad); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Returns the mad address structure associated with this MAD. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_get_err_msg * NAME * osm_madw_get_err_msg * * DESCRIPTION * Returns the message with which to post this mad wrapper if * an error occurs during processing the mad. * * SYNOPSIS */ static inline cl_disp_msgid_t osm_madw_get_err_msg(IN const osm_madw_t * p_madw) { return ((cl_disp_msgid_t) p_madw->fail_msg); } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * RETURN VALUES * Returns the message with which to post this mad wrapper if * an error occurs during processing the mad. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_set_mad * NAME * osm_madw_set_mad * * DESCRIPTION * Associates a wire MAD with this MAD Wrapper object. * * SYNOPSIS */ static inline void osm_madw_set_mad(IN osm_madw_t * p_madw, IN const ib_mad_t * p_mad) { p_madw->p_mad = p_mad; } /* * PARAMETERS * p_madw * [in] Pointer to an osm_madw_t object. * * p_mad * [in] Pointer to the wire MAD to attach to this wrapper. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: MAD Wrapper/osm_madw_copy_context * NAME * osm_madw_copy_context * * DESCRIPTION * Copies the controller context from one MAD Wrapper to another. * * SYNOPSIS */ static inline void osm_madw_copy_context(IN osm_madw_t * p_dest, IN const osm_madw_t * p_src) { p_dest->context = p_src->context; } /* * PARAMETERS * p_dest * [in] Pointer to the destination osm_madw_t object. * * p_src * [in] Pointer to the source osm_madw_t object. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_MADW_H_ */ opensm-3.3.20/include/opensm/osm_mcast_tbl.h0000644000205000001450000002434512104655724015751 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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: * Declaration of osm_mcast_tbl_t. * This object represents a multicast forwarding table. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MCAST_TBL_H_ #define _OSM_MCAST_TBL_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: Forwarding Table/osm_mcast_tbl_t * NAME * osm_mcast_tbl_t * * DESCRIPTION * Multicast Forwarding Table structure. * * Callers may directly access this object. * * SYNOPSIS */ typedef struct osm_mcast_fwdbl { uint8_t num_ports; uint8_t max_position; uint16_t max_block; int16_t max_block_in_use; uint16_t num_entries; uint16_t max_mlid_ho; uint16_t mft_depth; uint16_t(*p_mask_tbl)[][IB_MCAST_POSITION_MAX + 1]; } osm_mcast_tbl_t; /* * FIELDS * num_ports * The number of ports in the port mask. This value * is the same as the number of ports on the switch * * max_position * Maximum bit mask position for this table. This value * is computed from the number of ports on the switch. * * max_block * Maximum block number supported in the table. This value * is approximately the number of MLID entries divided by the * number of MLIDs per block * * num_entries * Number of entries in the table (aka number of MLIDs supported). * * max_mlid_ho * Maximum MLID (host order) for the currently allocated multicast * port mask table. * * mft_depth * Number of MLIDs in the currently allocated multicast port mask * table. * * p_mask_tbl * Pointer to a two dimensional array of port_masks for this switch. * The first dimension is MLID offset, second dimension is mask position. * This pointer is null for switches that do not support multicast. * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_init * NAME * osm_mcast_tbl_init * * DESCRIPTION * This function initializes a Multicast Forwarding Table object. * * SYNOPSIS */ void osm_mcast_tbl_init(IN osm_mcast_tbl_t * p_tbl, IN uint8_t num_ports, IN uint16_t capacity); /* * PARAMETERS * num_ports * [in] Number of ports in the switch owning this table. * * capacity * [in] The number of MLID entries (starting at 0xC000) supported * by this switch. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_delete * NAME * osm_mcast_tbl_delete * * DESCRIPTION * This destroys and deallocates a Multicast Forwarding Table object. * * SYNOPSIS */ void osm_mcast_tbl_delete(IN osm_mcast_tbl_t ** pp_tbl); /* * PARAMETERS * pp_tbl * [in] Pointer a Pointer to the Multicast Forwarding Table object. * * RETURN VALUE * On success, returns a pointer to a new Multicast Forwarding Table object * of the specified size. * NULL otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_realloc * NAME * osm_mcast_tbl_realloc * * DESCRIPTION * This function reallocates the multicast port mask table if necessary. * * SYNOPSIS */ int osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl, IN unsigned mlid_offset); /* * PARAMETERS * * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * mlid_offset * [in] Offset of MLID being accessed. * * RETURN VALUE * Returns 0 on success and non-zero value otherwise. * * NOTES * * SEE ALSO */ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_destroy * NAME * osm_mcast_tbl_destroy * * DESCRIPTION * This destroys and deallocates a Multicast Forwarding Table object. * * SYNOPSIS */ void osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * p_tbl); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * RETURN VALUE * None * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_set * NAME * osm_mcast_tbl_set * * DESCRIPTION * Adds the port to the multicast group. * * SYNOPSIS */ void osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho, IN uint8_t port_num); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * mlid_ho * [in] MLID value (host order) for which to set the route. * * port_num * [in] Port to add to the multicast group. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_clear_mlid * NAME * osm_mcast_tbl_clear_mlid * * DESCRIPTION * Removes all multicast paths for the specified MLID. * * SYNOPSIS */ void osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * mlid_ho * [in] MLID value (host order) for which to clear. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_port * NAME * osm_mcast_tbl_is_port * * DESCRIPTION * Returns TRUE if the port is in the multicast group. * * SYNOPSIS */ boolean_t osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho, IN uint8_t port_num); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * mlid_ho * [in] MLID value (host order). * * port_num * [in] Port number on the switch * * RETURN VALUE * Returns the port that routes the specified LID. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_is_any_port * NAME * osm_mcast_tbl_is_any_port * * DESCRIPTION * Returns TRUE if any port is in the multicast group. * * SYNOPSIS */ boolean_t osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * mlid_ho * [in] MLID value (host order). * * RETURN VALUE * Returns TRUE if any port is in the multicast group. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_set_block * NAME * osm_mcast_tbl_set_block * * DESCRIPTION * Copies the specified block into the Multicast Forwarding Table. * * SYNOPSIS */ ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl, IN const ib_net16_t * p_block, IN int16_t block_num, IN uint8_t position); /* * PARAMETERS * p_tbl * [in] Pointer to the Multicast Forwarding Table object. * * p_block * [in] Pointer to the Forwarding Table block. * * block_num * [in] Block number of this block. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_get_tbl_block * NAME * osm_mcast_get_tbl_block * * DESCRIPTION * Retrieve a multicast forwarding table block. * * SYNOPSIS */ boolean_t osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * p_tbl, IN int16_t block_num, IN uint8_t position, OUT ib_net16_t * p_block); /* * PARAMETERS * p_tbl * [in] Pointer to an osm_mcast_tbl_t object. * * p_block * [in] Pointer to the Forwarding Table block. * * block_num * [in] Block number of this block. * * p_block * [out] Pointer to the 32 entry array to store the * forwarding table clock specified by block_id. * * RETURN VALUES * Returns true if there are more blocks necessary to * configure all the MLIDs reachable from this switch. * FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block * NAME * osm_mcast_tbl_get_max_block * * DESCRIPTION * Returns the maximum block ID in this table. * * SYNOPSIS */ static inline uint16_t osm_mcast_tbl_get_max_block(IN osm_mcast_tbl_t * p_tbl) { return p_tbl->max_block; } /* * PARAMETERS * p_tbl * [in] Pointer to an osm_mcast_tbl_t object. * * RETURN VALUES * Returns the maximum block ID in this table. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_block_in_use * NAME * osm_mcast_tbl_get_max_block_in_use * * DESCRIPTION * Returns the maximum block ID in use in this table. * A value of -1 indicates no blocks are in use. * * SYNOPSIS */ static inline int16_t osm_mcast_tbl_get_max_block_in_use(IN osm_mcast_tbl_t * p_tbl) { return (p_tbl->max_block_in_use); } /* * PARAMETERS * p_tbl * [in] Pointer to an osm_mcast_tbl_t object. * * RETURN VALUES * Returns the maximum block ID in use in this table. * A value of -1 indicates no blocks are in use. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Forwarding Table/osm_mcast_tbl_get_max_position * NAME * osm_mcast_tbl_get_max_position * * DESCRIPTION * Returns the maximum position in this table. * * SYNOPSIS */ static inline uint8_t osm_mcast_tbl_get_max_position(IN osm_mcast_tbl_t * p_tbl) { return (p_tbl->max_position); } /* * PARAMETERS * p_tbl * [in] Pointer to an osm_mcast_tbl_t object. * * RETURN VALUES * Returns the maximum position in this table. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_MCAST_TBL_H_ */ opensm-3.3.20/include/opensm/osm_mcm_port.h0000644000205000001450000001426612104655724015622 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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: * Declaration of osm_mcm_port_t. * This object represents the membership of a port in a multicast group. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MCM_PORT_H_ #define _OSM_MCM_PORT_H_ #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS struct osm_mgrp; /****s* OpenSM: MCM Port Object/osm_mcm_port_t * NAME * osm_mcm_port_t * * DESCRIPTION * This object represents a particular port as a member of a * multicast group. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_mcm_port { cl_map_item_t map_item; cl_list_item_t list_item; osm_port_t *port; struct osm_mgrp *mgrp; } osm_mcm_port_t; /* * FIELDS * map_item * Map Item for qmap linkage. Must be first element!! * * list_item * Linkage structure for cl_qlist. * * port * Reference to the parent port * * mgrp * The pointer to multicast group where this port is member of * * SEE ALSO * MCM Port Object *********/ /****f* OpenSM: MCM Port Object/osm_mcm_port_new * NAME * osm_mcm_port_new * * DESCRIPTION * The osm_mcm_port_new function allocates and initializes a * MCM Port Object for use. * * SYNOPSIS */ osm_mcm_port_t *osm_mcm_port_new(IN osm_port_t * port, IN struct osm_mgrp *mgrp); /* * PARAMETERS * port * [in] Pointer to the port object * * mgrp * [in] Pointer to multicast group where this port is joined * * RETURN VALUES * Pointer to the allocated and initialized MCM Port object. * * NOTES * * SEE ALSO * MCM Port Object, osm_mcm_port_delete, *********/ /****f* OpenSM: MCM Port Object/osm_mcm_port_delete * NAME * osm_mcm_port_delete * * DESCRIPTION * The osm_mcm_port_delete function destroys and dellallocates an * MCM Port Object, releasing all resources. * * SYNOPSIS */ void osm_mcm_port_delete(IN osm_mcm_port_t * p_mcm); /* * PARAMETERS * p_mcm * [in] Pointer to a MCM Port Object to delete. * * RETURN VALUE * This function does not return a value. * * NOTES * * SEE ALSO * MCM Port Object, osm_mcm_port_new *********/ /****s* OpenSM: MCM Port Object/osm_mcm_alias_guid_t * NAME * osm_mcm_alias_guid_t * * DESCRIPTION * This object represents an alias guid for a mcm port. * * The osm_mcm_alias_guid_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_mcm_alias_guid { cl_map_item_t map_item; ib_net64_t alias_guid; osm_mcm_port_t *p_base_mcm_port; ib_gid_t port_gid; uint8_t scope_state; boolean_t proxy_join; } osm_mcm_alias_guid_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * alias_guid * Alias GUID for port obtained from SM GUIDInfo attribute * * p_base_mcm_port * Pointer to osm_mcm_port_t for base port GUID * * port_gid * GID of the member port * * scope_state * * proxy_join * If FALSE - Join was performed by the endport identified * by PortGID. If TRUE - Join was performed on behalf of * the endport identified by PortGID by another port within * the same partition. * * SEE ALSO * MCM Port, Physical Port, Physical Port Table */ /****f* OpenSM: MCM Port Object/osm_mcm_alias_guid_new * NAME * osm_mcm_alias_guid_new * * DESCRIPTION * This function allocates and initializes an mcm alias guid object. * * SYNOPSIS */ osm_mcm_alias_guid_t *osm_mcm_alias_guid_new(IN osm_mcm_port_t *p_base_mcm_port, IN ib_member_rec_t *mcmr, IN boolean_t proxy); /* * PARAMETERS * p_base_mcm_port * [in] Pointer to the mcm port for this base GUID * * mcmr * [in] Pointer to MCMember record of the join request * * proxy * [in] proxy_join state analyzed from the request * * RETURN VALUE * Pointer to the initialized mcm alias guid object. * * NOTES * Allows calling other mcm alias guid methods. * * SEE ALSO * MCM Port Object *********/ /****f* OpenSM: MCM Port Object/osm_mcm_alias_guid_delete * NAME * osm_mcm_alias_guid_delete * * DESCRIPTION * This function destroys and deallocates an mcm alias guid object. * * SYNOPSIS */ void osm_mcm_alias_guid_delete(IN OUT osm_mcm_alias_guid_t ** pp_mcm_alias_guid); /* * PARAMETERS * pp_mcm_alias_guid * [in][out] Pointer to a pointer to an mcm alias guid object to * delete. On return, this pointer is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified mcm alias guid object. * * SEE ALSO * MCM Port Object *********/ END_C_DECLS #endif /* _OSM_MCM_PORT_H_ */ opensm-3.3.20/include/opensm/osm_mesh.h0000644000205000001450000000507312104655724014732 00000000000000/* * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2008,2009 System Fabric Works, Inc. 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: * Declarations for mesh analysis */ #ifndef OSM_MESH_H #define OSM_MESH_H struct _lash; struct _switch; /* * per switch to switch link info */ typedef struct _link { int switch_id; int link_id; int next_port; int num_ports; int ports[0]; } link_t; /* * per switch node mesh info */ typedef struct _mesh_node { int *axes; /* used to hold and reorder assigned axes */ int *coord; /* mesh coordinates of switch */ int **matrix; /* distances between adjacant switches */ int *poly; /* characteristic polynomial of matrix */ /* used as an invariant classification */ int dimension; /* apparent dimension of mesh around node */ int temp; /* temporary holder for distance info */ int type; /* index of node type in mesh_info array */ unsigned int num_links; /* number of 'links' to adjacent switches */ link_t *links[0]; /* per link information */ } mesh_node_t; void osm_mesh_node_delete(struct _lash *p_lash, struct _switch *sw); int osm_mesh_node_create(struct _lash *p_lash, struct _switch *sw); int osm_do_mesh_analysis(struct _lash *p_lash); #endif opensm-3.3.20/include/opensm/osm_mtree.h0000644000205000001450000001460512104655724015113 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_mtree_t. * This object represents multicast spanning tree. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MTREE_H_ #define _OSM_MTREE_H_ #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define OSM_MTREE_LEAF ((void*)-1) /****h* OpenSM/Multicast Tree * NAME * Multicast Tree * * DESCRIPTION * The Multicast Tree object encapsulates the information needed by the * OpenSM to manage multicast fabric routes. It is a tree structure * in which each node in the tree represents a switch, and may have a * varying number of children. * * Multicast trees do not contain loops. * * The Multicast Tree is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Multicast Tree/osm_mtree_node_t * NAME * osm_mtree_node_t * * DESCRIPTION * The MTree Node object encapsulates the information needed by the * OpenSM for a particular switch in the multicast tree. * * The MTree Node object is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_mtree_node { cl_map_item_t map_item; const osm_switch_t *p_sw; uint8_t max_children; struct osm_mtree_node *p_up; struct osm_mtree_node *child_array[1]; } osm_mtree_node_t; /* * FIELDS * map_item * Linkage for quick map. MUST BE FIRST ELEMENT!!! * * p_sw * Pointer to the switch represented by this tree node. * * max_children * Maximum number of child nodes of this node. Equal to the * the number of ports on the switch if the switch supports * multicast. Equal to 1 (default route) if the switch does * not support multicast. * * p_up * Pointer to the parent of this node. If this pointer is * NULL, the node is at the root of the tree. * * child_array * Array (indexed by port number) of pointers to the * child osm_mtree_node_t objects of this tree node, if any. * * SEE ALSO *********/ /****f* OpenSM: Multicast Tree/osm_mtree_node_new * NAME * osm_mtree_node_new * * DESCRIPTION * Returns an initialized a Multicast Tree object for use. * * SYNOPSIS */ osm_mtree_node_t *osm_mtree_node_new(IN const osm_switch_t * p_sw); /* * PARAMETERS * p_sw * [in] Pointer to the switch represented by this node. * * RETURN VALUES * Pointer to an initialized tree node. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Tree/osm_mtree_destroy * NAME * osm_mtree_destroy * * DESCRIPTION * Destroys a Multicast Tree object given by the p_mtn * * SYNOPSIS */ void osm_mtree_destroy(IN osm_mtree_node_t * p_mtn); /* * PARAMETERS * p_mtn * [in] Pointer to an osm_mtree_node_t object to destroy. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Tree/osm_mtree_node_get_max_children * NAME * osm_mtree_node_get_max_children * * DESCRIPTION * Returns the number maximum number of children of this node. * The return value is 1 greater than the highest valid port * number on the switch. * * * SYNOPSIS */ static inline uint8_t osm_mtree_node_get_max_children(IN const osm_mtree_node_t * p_mtn) { return (p_mtn->max_children); } /* * PARAMETERS * p_mtn * [in] Pointer to the multicast tree node. * * RETURN VALUES * See description. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Tree/osm_mtree_node_get_child * NAME * osm_mtree_node_get_child * * DESCRIPTION * Returns the specified child node of this node. * * SYNOPSIS */ static inline osm_mtree_node_t *osm_mtree_node_get_child(IN const osm_mtree_node_t * p_mtn, IN uint8_t child) { CL_ASSERT(child < p_mtn->max_children); return (p_mtn->child_array[child]); } /* * PARAMETERS * p_mtn * [in] Pointer to the multicast tree node. * * child * [in] Index of the child to retrieve. * * RETURN VALUES * Returns the specified child node of this node. * * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Tree/osm_mtree_node_get_switch_ptr * NAME * osm_mtree_node_get_switch_ptr * * DESCRIPTION * Returns a pointer to the switch object represented by this tree node. * * SYNOPSIS */ static inline const osm_switch_t *osm_mtree_node_get_switch_ptr(IN const osm_mtree_node_t * p_mtn) { return p_mtn->p_sw; } /* * PARAMETERS * p_mtn * [in] Pointer to the multicast tree node. * * child * [in] Index of the child to retrieve. * * RETURN VALUES * Returns a pointer to the switch object represented by this tree node. * * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_MTREE_H_ */ opensm-3.3.20/include/opensm/osm_multicast.h0000644000205000001450000002362212272264652016005 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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: * Declaration of osm_mgrp_t. * This object represents an IBA Multicast Group. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_MULTICAST_H_ #define _OSM_MULTICAST_H_ #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Multicast Group * NAME * Multicast Group * * DESCRIPTION * The Multicast Group encapsulates the information needed by the * OpenSM to manage Multicast Groups. The OpenSM allocates one * Multicast Group object per Multicast Group in the IBA subnet. * * The Multicast Group is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Multicast Group/osm_mgrp_t * NAME * osm_mgrp_t * * DESCRIPTION * Multicast Group structure. * * The osm_mgrp_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_mgrp { cl_fmap_item_t map_item; cl_list_item_t list_item; ib_net16_t mlid; cl_qmap_t mcm_port_tbl; cl_qmap_t mcm_alias_port_tbl; ib_member_rec_t mcmember_rec; boolean_t well_known; unsigned full_members; } osm_mgrp_t; /* * FIELDS * map_item * Map Item for fmap linkage. Must be first element!! * * list_item * List item for linkage in osm_mgrp_box's mgrp_list qlist. * * mlid * The network ordered LID of this Multicast Group (must be * >= 0xC000). * * mcm_port_tbl * Table (sorted by port GUID) of osm_mcm_port_t objects * representing the member ports of this multicast group. * * mcm_alias_port_tbl * Table (sorted by port alias GUID) of osm_mcm_port_t * objects representing the member ports of this multicast * group. * * mcmember_rec * Holds the parameters of the Multicast Group. * * well_known * Indicates that this is the wellknown multicast group which * is created during the initialization of SM/SA and will be * present even if there are no ports for this group * * SEE ALSO *********/ /****s* OpenSM: Multicast Group/osm_mgrp_box_t * NAME * osm_mgrp_box_t * * DESCRIPTION * Multicast structure which holds all multicast groups with same MLID. * * SYNOPSIS */ typedef struct osm_mgrp_box { uint16_t mlid; cl_qlist_t mgrp_list; osm_mtree_node_t *root; } osm_mgrp_box_t; /* * FIELDS * mlid * The host ordered LID of this Multicast Group (must be * >= 0xC000). * * p_root * Pointer to the root "tree node" in the single spanning tree * for this multicast group. The nodes of the tree represent * switches. Member ports are not represented in the tree. * * mgrp_list * List of multicast groups (mpgr object) having same MLID value. * * SEE ALSO *********/ /****f* OpenSM: Multicast Group/osm_mgrp_new * NAME * osm_mgrp_new * * DESCRIPTION * Allocates and initializes a Multicast Group for use. * * SYNOPSIS */ osm_mgrp_t *osm_mgrp_new(IN osm_subn_t * subn, IN ib_net16_t mlid, IN ib_member_rec_t * mcmr); /* * PARAMETERS * subn * [in] Pointer to osm_subn_t object. * * mlid * [in] Multicast LID for this multicast group. * * mcmr * [in] MCMember Record for this multicast group. * * RETURN VALUES * IB_SUCCESS if initialization was successful. * * NOTES * Allows calling other Multicast Group methods. * * SEE ALSO * Multicast Group, osm_mgrp_delete *********/ /* * Need a forward declaration to work around include loop: * osm_sm.h <- osm_multicast.h */ struct osm_sm; /****f* OpenSM: Multicast Tree/osm_purge_mtree * NAME * osm_purge_mtree * * DESCRIPTION * Frees all the nodes in a multicast spanning tree * * SYNOPSIS */ void osm_purge_mtree(IN struct osm_sm * sm, IN osm_mgrp_box_t * mgb); /* * PARAMETERS * sm * [in] Pointer to osm_sm_t object. * mgb * [in] Pointer to an osm_mgrp_box_t object. * * RETURN VALUES * None. * * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Group/osm_mgrp_is_guid * NAME * osm_mgrp_is_guid * * DESCRIPTION * Indicates if the specified port GUID is a member of the Multicast Group. * * SYNOPSIS */ static inline boolean_t osm_mgrp_is_guid(IN const osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid) { return (cl_qmap_get(&p_mgrp->mcm_port_tbl, port_guid) != cl_qmap_end(&p_mgrp->mcm_port_tbl)); } /* * PARAMETERS * p_mgrp * [in] Pointer to an osm_mgrp_t object. * * port_guid * [in] Port GUID. * * RETURN VALUES * TRUE if the port GUID is a member of the group, * FALSE otherwise. * * NOTES * * SEE ALSO * Multicast Group *********/ /****f* OpenSM: Multicast Group/osm_mgrp_is_empty * NAME * osm_mgrp_is_empty * * DESCRIPTION * Indicates if the multicast group has any member ports. * * SYNOPSIS */ static inline boolean_t osm_mgrp_is_empty(IN const osm_mgrp_t * p_mgrp) { return (cl_qmap_count(&p_mgrp->mcm_port_tbl) == 0); } /* * PARAMETERS * p_mgrp * [in] Pointer to an osm_mgrp_t object. * * RETURN VALUES * TRUE if there are no ports in the multicast group. * FALSE otherwise. * * NOTES * * SEE ALSO * Multicast Group *********/ /****f* OpenSM: Multicast Group/osm_mgrp_get_mlid * NAME * osm_mgrp_get_mlid * * DESCRIPTION * The osm_mgrp_get_mlid function returns the multicast LID of this group. * * SYNOPSIS */ static inline ib_net16_t osm_mgrp_get_mlid(IN const osm_mgrp_t * p_mgrp) { return p_mgrp->mlid; } /* * PARAMETERS * p_mgrp * [in] Pointer to an osm_mgrp_t object. * * RETURN VALUES * MLID of the Multicast Group. * * NOTES * * SEE ALSO * Multicast Group *********/ /****f* OpenSM: Multicast Group/osm_mgrp_add_port * NAME * osm_mgrp_add_port * * DESCRIPTION * Adds a port to the multicast group. * * SYNOPSIS */ osm_mcm_port_t *osm_mgrp_add_port(osm_subn_t *subn, osm_log_t *log, IN osm_mgrp_t * mgrp, IN osm_port_t *port, IN ib_member_rec_t *mcmr, IN boolean_t proxy); /* * PARAMETERS * mgrp * [in] Pointer to an osm_mgrp_t object to initialize. * * port * [in] Pointer to an osm_port_t object * * mcmr * [in] Pointer to MCMember record received for the join * * proxy * [in] The proxy join state for this port in the group. * * RETURN VALUES * IB_SUCCESS * IB_INSUFFICIENT_MEMORY * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Group/osm_mgrp_get_mcm_port * NAME * osm_mgrp_get_mcm_port * * DESCRIPTION * Finds a port in the multicast group. * * SYNOPSIS */ osm_mcm_port_t *osm_mgrp_get_mcm_port(IN const osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid); /* * PARAMETERS * p_mgrp * [in] Pointer to an osm_mgrp_t object. * * port_guid * [in] Port guid. * * RETURN VALUES * Pointer to the mcm port object when present or NULL otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Group/osm_mgrp_get_mcm_alias_guid * NAME * osm_mgrp_get_mcm_alias_guid * * DESCRIPTION * Finds an mcm alias GUID in the multicast group based on an alias GUID. * * SYNOPSIS */ osm_mcm_alias_guid_t *osm_mgrp_get_mcm_alias_guid(IN const osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid); /* * PARAMETERS * p_mgrp * [in] Pointer to an osm_mgrp_t object. * * port_guid * [in] Alias port guid. * * RETURN VALUES * Pointer to the mcm alias GUID object when present or NULL otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Multicast Group/osm_mgrp_delete_port * NAME * osm_mgrp_delete_port * * DESCRIPTION * Removes a port from the multicast group. * * SYNOPSIS */ void osm_mgrp_delete_port(IN osm_subn_t * subn, IN osm_log_t * log, IN osm_mgrp_t * mgrp, IN osm_port_t * port); /* * PARAMETERS * * subn * [in] Pointer to the subnet object * * log * [in] The log object pointer * * mgrp * [in] Pointer to an osm_mgrp_t object. * * port * [in] Pointer to an osm_port_t object for the the departing port. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ boolean_t osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp, osm_mcm_alias_guid_t * mcm_alias_guid, ib_member_rec_t * mcmr); void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mpgr); void osm_mgrp_box_delete(osm_mgrp_box_t *mbox); END_C_DECLS #endif /* _OSM_MULTICAST_H_ */ opensm-3.3.20/include/opensm/osm_msgdef.h0000644000205000001450000001074012104655724015240 00000000000000/* * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 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: * Declaration of Dispatcher message values. */ #ifndef _OSM_MSGDEF_H_ #define _OSM_MSGDEF_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Dispatcher Messages * NAME * Dispatcher Messages * * DESCRIPTION * These constants define the messages sent between OpenSM controllers * attached to the Dispatcher. * * Each message description contains the following information: * Sent by: which controller(s) send this message * Received by: which controller receives this message * Delivery notice: Indicates if the sender requires confirmation * that the message has been delivered. Typically a "yes" here * means that some resources associated with sending the * message must be freed. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_INFO * NAME * OSM_MSG_MAD_NODE_INFO * * DESCRIPTION * Message for received NodeInfo MADs. * * NOTES * Sent by: osm_mad_ctrl_t * Received by: osm_ni_rcv_ctrl_t * Delivery notice: yes * * ***********/ /****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_PORT_INFO * NAME * OSM_MSG_MAD_PORT_INFO * * DESCRIPTION * Message for received PortInfo MADs. * * NOTES * Sent by: osm_mad_ctrl_t * Received by: osm_pi_rcv_ctrl_t * Delivery notice: yes * * ***********/ /****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_SWITCH_INFO * NAME * OSM_MSG_MAD_SWITCH_INFO * * DESCRIPTION * Message for received SwitchInfo MADs. * * NOTES * Sent by: osm_mad_ctrl_t * Received by: osm_si_rcv_ctrl_t * Delivery notice: yes * ***********/ /****s* OpenSM: Dispatcher Messages/OSM_MSG_MAD_NODE_DESC * NAME * OSM_MSG_MAD_NODE_DESC * * DESCRIPTION * Message for received NodeDescription MADs. * * NOTES * Sent by: osm_mad_ctrl_t * Received by: osm_nd_rcv_ctrl_t * Delivery notice: yes * * SOURCE ***********/ enum { OSM_MSG_NONE = 0, OSM_MSG_MAD_NODE_INFO, OSM_MSG_MAD_PORT_INFO, OSM_MSG_MAD_SWITCH_INFO, OSM_MSG_MAD_GUID_INFO, OSM_MSG_MAD_NODE_DESC, OSM_MSG_MAD_NODE_RECORD, OSM_MSG_MAD_PORTINFO_RECORD, OSM_MSG_MAD_SERVICE_RECORD, OSM_MSG_MAD_PATH_RECORD, OSM_MSG_MAD_MCMEMBER_RECORD, OSM_MSG_MAD_LINK_RECORD, OSM_MSG_MAD_SMINFO_RECORD, OSM_MSG_MAD_CLASS_PORT_INFO, OSM_MSG_MAD_INFORM_INFO, OSM_MSG_MAD_LFT_RECORD, OSM_MSG_MAD_LFT, OSM_MSG_MAD_SM_INFO, OSM_MSG_MAD_NOTICE, OSM_MSG_LIGHT_SWEEP_FAIL, OSM_MSG_MAD_MFT, OSM_MSG_MAD_PKEY_TBL_RECORD, OSM_MSG_MAD_VL_ARB_RECORD, OSM_MSG_MAD_SLVL_TBL_RECORD, OSM_MSG_MAD_PKEY, OSM_MSG_MAD_VL_ARB, OSM_MSG_MAD_SLVL, OSM_MSG_MAD_GUIDINFO_RECORD, OSM_MSG_MAD_INFORM_INFO_RECORD, OSM_MSG_MAD_SWITCH_INFO_RECORD, OSM_MSG_MAD_MFT_RECORD, #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) OSM_MSG_MAD_MULTIPATH_RECORD, #endif OSM_MSG_MAD_PORT_COUNTERS, OSM_MSG_MAD_MLNX_EXT_PORT_INFO, OSM_MSG_MAD_CC, OSM_MSG_MAX }; END_C_DECLS #endif /* _OSM_MSGDEF_H_ */ opensm-3.3.20/include/opensm/osm_node.h0000644000205000001450000003476012472731616014733 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_node_t. * This object represents an IBA node. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_NODE_H_ #define _OSM_NODE_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS struct osm_switch; /****h* OpenSM/Node * NAME * Node * * DESCRIPTION * The Node object encapsulates the information needed by the * OpenSM to manage nodes. The OpenSM allocates one Node object * per node in the IBA subnet. * * The Node object is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Node/osm_node_t * NAME * osm_node_t * * DESCRIPTION * Node structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_node { cl_map_item_t map_item; struct osm_switch *sw; ib_node_info_t node_info; ib_node_desc_t node_desc; uint32_t discovery_count; uint32_t physp_tbl_size; char *print_desc; uint8_t *physp_discovered; osm_physp_t physp_table[1]; } osm_node_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * sw * For switch node contains pointer to appropriate osm_switch * structure. NULL for non-switch nodes. Can be used for fast * access to switch object and for simple node type detection * * node_info * The IBA defined NodeInfo data for this node. * * node_desc * The IBA defined NodeDescription data for this node. * * discovery_count * The number of times this node has been discovered * during the current fabric sweep. This number is reset * to zero at the start of a sweep. * * physp_tbl_size * The size of the physp_table array. This value is one greater * than the number of ports in the node, since port numbers * start with 1 for some bizarre reason. * * print_desc * A printable version of the node description. * * physp_discovered * Array of physp_discovered objects for all ports of this node. * Each object indiactes whether the port has been discovered * during the sweep or not. 1 means that the port had been discovered. * * physp_table * Array of physical port objects belonging to this node. * Index is contiguous by local port number. * For switches, port 0 is the always the management port (14.2.5.6). * MUST BE LAST MEMBER! - Since it grows !!!! * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_delete * NAME * osm_node_delete * * DESCRIPTION * The osm_node_delete function destroys a node, releasing * all resources. * * SYNOPSIS */ void osm_node_delete(IN OUT osm_node_t ** p_node); /* * PARAMETERS * p_node * [in][out] Pointer to a Pointer a Node object to destroy. * On return, the pointer to set to NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified Node object. * This function should only be called after a call to osm_node_new. * * SEE ALSO * Node object, osm_node_new *********/ /****f* OpenSM: Node/osm_node_new * NAME * osm_node_new * * DESCRIPTION * The osm_node_new function initializes a Node object for use. * * SYNOPSIS */ osm_node_t *osm_node_new(IN const osm_madw_t * p_madw); /* * PARAMETERS * p_madw * [in] Pointer to a osm_madw_t object containing a mad with * the node's NodeInfo attribute. The caller may discard the * osm_madw_t structure after calling osm_node_new. * * RETURN VALUES * On success, a pointer to the new initialized osm_node_t structure. * NULL otherwise. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_physp_ptr * NAME * osm_node_get_physp_ptr * * DESCRIPTION * Returns a pointer to the physical port object at the * specified local port number. * * SYNOPSIS */ static inline osm_physp_t *osm_node_get_physp_ptr(IN osm_node_t * p_node, IN uint32_t port_num) { CL_ASSERT(port_num < p_node->physp_tbl_size); return osm_physp_is_valid(&p_node->physp_table[port_num]) ? &p_node->physp_table[port_num] : NULL; } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Local port number. * * RETURN VALUES * Returns a pointer to the physical port object at the * specified local port number. * A return value of zero means the port number was out of range. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_type * NAME * osm_node_get_type * * DESCRIPTION * Returns the type of this node. * * SYNOPSIS */ static inline uint8_t osm_node_get_type(IN const osm_node_t * p_node) { return p_node->node_info.node_type; } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * RETURN VALUES * Returns the IBA defined type of this node. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_num_physp * NAME * osm_node_get_num_physp * * DESCRIPTION * Returns the number of osm_physp ports allocated for this node. * For switches, it is the number of external physical ports plus * port 0. For CAs and routers, it is the number of external physical * ports plus 1. * * SYNOPSIS */ static inline uint8_t osm_node_get_num_physp(IN const osm_node_t * p_node) { return (uint8_t) p_node->physp_tbl_size; } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * RETURN VALUES * Returns the IBA defined type of this node. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_remote_node * NAME * osm_node_get_remote_node * * DESCRIPTION * Returns a pointer to the node on the other end of the * specified port. * Returns NULL if no remote node exists. * * SYNOPSIS */ osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node, IN uint8_t port_num, OUT uint8_t * p_remote_port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to get the remote node. * * p_remote_port_num * [out] Port number in the remote's node through which this * link exists. The caller may specify NULL for this pointer * if the port number isn't needed. * * RETURN VALUES * Returns a pointer to the node on the other end of the * specified port. * Returns NULL if no remote node exists. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_base_lid * NAME * osm_node_get_base_lid * * DESCRIPTION * Returns the LID value of the specified port on this node. * * SYNOPSIS */ static inline ib_net16_t osm_node_get_base_lid(IN const osm_node_t * p_node, IN uint32_t port_num) { CL_ASSERT(port_num < p_node->physp_tbl_size); return osm_physp_get_base_lid(&p_node->physp_table[port_num]); } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Local port number. * * RETURN VALUES * Returns a pointer to the physical port object at the * specified local port number. * A return value of zero means the port number was out of range. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_remote_base_lid * NAME * osm_node_get_remote_base_lid * * DESCRIPTION * Returns the base LID value of the port on the other side * of the wire from the specified port on this node. * * SYNOPSIS */ ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node, IN uint32_t port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Local port number. * * RETURN VALUES * Returns a pointer to the physical port object at the * specified local port number. * A return value of zero means the port number was out of range. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_get_lmc * NAME * osm_node_get_lmc * * DESCRIPTION * Returns the LMC value of the specified port on this node. * * SYNOPSIS */ static inline uint8_t osm_node_get_lmc(IN const osm_node_t * p_node, IN uint32_t port_num) { CL_ASSERT(port_num < p_node->physp_tbl_size); return osm_physp_get_lmc(&p_node->physp_table[port_num]); } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Local port number. * * RETURN VALUES * Returns the LMC value of the specified port on this node. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_init_physp * NAME * osm_node_init_physp * * DESCRIPTION * Initializes a physical port for the given node. * * SYNOPSIS */ void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num, IN const osm_madw_t * p_madw); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * p_madw * [in] Pointer to a osm_madw_t object containing a mad with * the node's NodeInfo attribute as discovered through the * Physical Port to add to the node. The caller may discard the * osm_madw_t structure after calling osm_node_new. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * Node object, Physical Port object. *********/ /****f* OpenSM: Node/osm_node_get_node_guid * NAME * osm_node_get_node_guid * * DESCRIPTION * Returns the node GUID of this node. * * SYNOPSIS */ static inline ib_net64_t osm_node_get_node_guid(IN const osm_node_t * p_node) { return p_node->node_info.node_guid; } /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * RETURN VALUES * Returns the node GUID of this node. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_link * NAME * osm_node_link * * DESCRIPTION * Logically connects a node to another node through the specified port. * * SYNOPSIS */ void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to create the link. * * p_remote_node * [in] Pointer to the remote port object. * * remote_port_num * [in] Port number in the remote's node through which to * create this link. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_unlink * NAME * osm_node_unlink * * DESCRIPTION * Logically disconnects a node from another node through * the specified port. * * SYNOPSIS */ void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to unlink. * * p_remote_node * [in] Pointer to the remote port object. * * remote_port_num * [in] Port number in the remote's node through which to unlink. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_link_exists * NAME * osm_node_link_exists * * DESCRIPTION * Return TRUE if a link exists between the specified nodes on * the specified ports. * Returns FALSE otherwise. * * SYNOPSIS */ boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to check the link. * * p_remote_node * [in] Pointer to the remote port object. * * remote_port_num * [in] Port number in the remote's node through which to * check this link. * * RETURN VALUES * Return TRUE if a link exists between the specified nodes on * the specified ports. * Returns FALSE otherwise. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_has_any_link * NAME * osm_node_has_any_link * * DESCRIPTION * Return TRUE if a any link exists from the specified nodes on * the specified port. * Returns FALSE otherwise. * * SYNOPSIS */ boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to check the link. * * RETURN VALUES * Return TRUE if a any link exists from the specified nodes on * the specified port. * Returns FALSE otherwise. * * NOTES * * SEE ALSO * Node object *********/ /****f* OpenSM: Node/osm_node_link_has_valid_ports * NAME * osm_node_link_has_valid_ports * * DESCRIPTION * Return TRUE if both ports in the link are valid (initialized). * Returns FALSE otherwise. * * SYNOPSIS */ boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num); /* * PARAMETERS * p_node * [in] Pointer to an osm_node_t object. * * port_num * [in] Port number in p_node through which to check the link. * * RETURN VALUES * Return TRUE if both ports in the link are valid (initialized). * Returns FALSE otherwise. * * NOTES * * SEE ALSO * Node object *********/ END_C_DECLS #endif /* _OSM_NODE_H_ */ opensm-3.3.20/include/opensm/osm_opensm.h0000644000205000001450000003755512452603453015307 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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: * Declaration of osm_opensm_t. * This object represents the OpenSM super object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_OPENSM_H_ #define _OSM_OPENSM_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/OpenSM * NAME * OpenSM * * DESCRIPTION * The OpenSM object encapsulates the information needed by the * OpenSM to govern itself. The OpenSM is one OpenSM object. * * The OpenSM object is thread safe. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****d* OpenSM: OpenSM/osm_routing_engine_type_t * NAME * osm_routing_engine_type_t * * DESCRIPTION * Enumerates the possible routing engines that * could be used to route a subnet. * * SYNOPSIS */ typedef enum _osm_routing_engine_type { OSM_ROUTING_ENGINE_TYPE_NONE = 0, OSM_ROUTING_ENGINE_TYPE_MINHOP, OSM_ROUTING_ENGINE_TYPE_UPDN, OSM_ROUTING_ENGINE_TYPE_DNUP, OSM_ROUTING_ENGINE_TYPE_FILE, OSM_ROUTING_ENGINE_TYPE_FTREE, OSM_ROUTING_ENGINE_TYPE_LASH, OSM_ROUTING_ENGINE_TYPE_DOR, OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS, OSM_ROUTING_ENGINE_TYPE_SSSP, OSM_ROUTING_ENGINE_TYPE_DFSSSP, OSM_ROUTING_ENGINE_TYPE_UNKNOWN } osm_routing_engine_type_t; /***********/ /****s* OpenSM: OpenSM/osm_routing_engine * NAME * struct osm_routing_engine * * DESCRIPTION * OpenSM routing engine module definition. * NOTES * routing engine structure - multicast callbacks may be * added later. */ struct osm_routing_engine { osm_routing_engine_type_t type; const char *name; void *context; int (*build_lid_matrices) (void *context); int (*ucast_build_fwd_tables) (void *context); void (*ucast_dump_tables) (void *context); void (*update_sl2vl)(void *context, IN osm_physp_t *port, IN uint8_t in_port_num, IN uint8_t out_port_num, IN OUT ib_slvl_table_t *t); void (*update_vlarb)(void *context, IN osm_physp_t *port, IN uint8_t port_num, IN OUT ib_vl_arb_table_t *block, unsigned block_length, unsigned block_num); uint8_t (*path_sl)(void *context, IN uint8_t path_sl_hint, IN const ib_net16_t slid, IN const ib_net16_t dlid); ib_api_status_t (*mcast_build_stree)(void *context, IN OUT osm_mgrp_box_t *mgb); void (*destroy) (void *context); struct osm_routing_engine *next; }; /* * FIELDS * name * The routing engine name (will be used in logs). * * context * The routing engine context. Will be passed as parameter * to the callback functions. * * build_lid_matrices * The callback for lid matrices generation. * * ucast_build_fwd_tables * The callback for unicast forwarding table generation. * * ucast_dump_tables * The callback for dumping unicast routing tables. * * update_sl2vl(void *context, IN osm_physp_t *port, * IN uint8_t in_port_num, IN uint8_t out_port_num, * OUT ib_slvl_table_t *t) * The callback to allow routing engine input for SL2VL maps. * *port is the physical port for which the SL2VL map is to be * updated. For switches, in_port_num/out_port_num identify * which part of the SL2VL map to update. For router/HCA ports, * in_port_num/out_port_num should be ignored. * * update_vlarb(void *context, IN osm_physp_t *port, * IN uint8_t port_num, * IN OUT ib_vl_arb_table_t *block, * unsigned block_length, unsigned block_num) * The callback to allow routing engine input for VLArbitration. * *port is the physical port for which the VLArb table is to be * updated. * * path_sl * The callback for computing path SL. * * mcast_build_stree * The callback for building the spanning tree for multicast * forwarding, called per MLID. * * destroy * The destroy method, may be used for routing engine * internals cleanup. * * next * Pointer to next routing engine in the list. */ /****s* OpenSM: OpenSM/osm_opensm_t * NAME * osm_opensm_t * * DESCRIPTION * OpenSM structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_opensm { const char *osm_version; osm_subn_t subn; osm_sm_t sm; osm_sa_t sa; #ifdef ENABLE_OSM_PERF_MGR osm_perfmgr_t perfmgr; #endif /* ENABLE_OSM_PERF_MGR */ osm_congestion_control_t cc; cl_qlist_t plugin_list; osm_db_t db; boolean_t mad_pool_constructed; osm_mad_pool_t mad_pool; osm_vendor_t *p_vendor; boolean_t vl15_constructed; osm_vl15_t vl15; osm_log_t log; cl_dispatcher_t disp; cl_dispatcher_t sa_set_disp; boolean_t sa_set_disp_initialized; cl_plock_t lock; struct osm_routing_engine *routing_engine_list; struct osm_routing_engine *routing_engine_used; struct osm_routing_engine *default_routing_engine; boolean_t no_fallback_routing_engine; osm_stats_t stats; osm_console_t console; nn_map_t *node_name_map; } osm_opensm_t; /* * FIELDS * osm_version * OpenSM version (as generated in osm_version.h) * * subn * Subnet object for this subnet. * * sm * The Subnet Manager (SM) object for this subnet. * * sa * The Subnet Administration (SA) object for this subnet. * * db * Persistant storage of some data required between sessions. * * mad_pool * Pool of Management Datagram (MAD) objects. * * p_vendor * Pointer to the Vendor specific adapter for various * transport interfaces, such as UMADT, AL, etc. The * particular interface is set at compile time. * * vl15 * The VL15 interface. * * log * Log facility used by all OpenSM components. * * disp * Central dispatcher containing the OpenSM worker threads. * * sa_set_disp * Dispatcher for SA Set and Delete requests. * * sa_set_disp_initialized. * Indicator that sa_set_disp dispatcher was initialized. * * lock * Shared lock guarding most OpenSM structures. * * routing_engine_list * List of routing engines that should be tried for use. * * routing_engine_used * Indicates which routing engine was used to route a subnet. * * no_fallback_routing_engine * Indicates if default routing engine should not be used. * * stats * Open SM statistics block * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_opensm_construct * NAME * osm_opensm_construct * * DESCRIPTION * This function constructs an OpenSM object. * * SYNOPSIS */ void osm_opensm_construct(IN osm_opensm_t * p_osm); /* * PARAMETERS * p_osm * [in] Pointer to a OpenSM object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_opensm_init, osm_opensm_destroy * * Calling osm_opensm_construct is a prerequisite to calling any other * method except osm_opensm_init. * * SEE ALSO * SM object, osm_opensm_init, osm_opensm_destroy *********/ /****f* OpenSM: OpenSM/osm_opensm_construct_finish * NAME * osm_opensm_construct_finish * * DESCRIPTION * The osm_opensm_construct_finish function completes * the second phase of constucting an OpenSM object. * * SYNOPSIS */ void osm_opensm_construct_finish(IN osm_opensm_t * p_osm); /* * PARAMETERS * p_osm * [in] Pointer to a OpenSM object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Calling osm_opensm_construct/osm_construct_finish is a prerequisite * to calling any other method except osm_opensm_init/osm_opensm_init_finish. * * SEE ALSO * SM object, osm_opensm_init, osm_opensm_construct_finish, * osm_opensm_destroy, osm_opensm_destroy_finish *********/ /****f* OpenSM: OpenSM/osm_opensm_destroy * NAME * osm_opensm_destroy * * DESCRIPTION * The osm_opensm_destroy function destroys an SM, releasing * all resources. * * SYNOPSIS */ void osm_opensm_destroy(IN osm_opensm_t * p_osm); /* * PARAMETERS * p_osm * [in] Pointer to a OpenSM object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified OpenSM object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_opensm_construct or * osm_opensm_init. * * SEE ALSO * SM object, osm_opensm_construct, osm_opensm_init *********/ /****f* OpenSM: OpenSM/osm_opensm_destroy_finish * NAME * osm_opensm_destroy_finish * * DESCRIPTION * The osm_opensm_destroy_finish function handles the second phase * of destroying an SM, releasing all resources. * * SYNOPSIS */ void osm_opensm_destroy_finish(IN osm_opensm_t * p_osm); /* * PARAMETERS * p_osm * [in] Pointer to a OpenSM object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs second phase of any necessary cleanup of the specified OpenSM object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_opensm_construct_finish or osm_opensm_init_finish. * * SEE ALSO * SM object, osm_opensm_construct, osm_opensm_construct_finish, * osm_opensm_init, osm_opensm_init_finish *********/ /****f* OpenSM: OpenSM/osm_opensm_init * NAME * osm_opensm_init * * DESCRIPTION * The osm_opensm_init function initializes a OpenSM object for use. * * SYNOPSIS */ ib_api_status_t osm_opensm_init(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt); /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object to initialize. * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * IB_SUCCESS if the OpenSM object was initialized successfully. * * NOTES * Allows calling other OpenSM methods. * * SEE ALSO * SM object, osm_opensm_construct, osm_opensm_destroy *********/ /****f* OpenSM: OpenSM/osm_opensm_init_finish * NAME * osm_opensm_init_finish * * DESCRIPTION * The osm_opensm_init_finish function performs the second phase * of initialization of an OpenSM object. * * SYNOPSIS */ ib_api_status_t osm_opensm_init_finish(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt); /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object to initialize. * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * IB_SUCCESS if the OpenSM object was initialized successfully. * * NOTES * Allows calling other OpenSM methods. * * SEE ALSO * SM object, osm_opensm_construct, osm_opensm_construct_finish, * osm_opensm_destroy, osm_opensm_destroy_finish *********/ /****f* OpenSM: OpenSM/osm_opensm_sweep * NAME * osm_opensm_sweep * * DESCRIPTION * Initiates a subnet sweep. * * SYNOPSIS */ static inline void osm_opensm_sweep(IN osm_opensm_t * p_osm) { osm_sm_sweep(&p_osm->sm); } /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object on which to * initiate a sweep. * * RETURN VALUES * None * * NOTES * If the OpenSM object is not bound to a port, this function * does nothing. * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_opensm_set_log_flags * NAME * osm_opensm_set_log_flags * * DESCRIPTION * Sets the log level. * * SYNOPSIS */ static inline void osm_opensm_set_log_flags(IN osm_opensm_t * p_osm, IN osm_log_level_t log_flags) { osm_log_set_level(&p_osm->log, log_flags); } /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object. * * log_flags * [in] Log level flags to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_opensm_bind * NAME * osm_opensm_bind * * DESCRIPTION * Binds the opensm object to a port guid. * * SYNOPSIS */ ib_api_status_t osm_opensm_bind(IN osm_opensm_t * p_osm, IN ib_net64_t guid); /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object to bind. * * guid * [in] Local port GUID with which to bind. * * RETURN VALUES * None * * NOTES * A given opensm object can only be bound to one port at a time. * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_opensm_wait_for_subnet_up * NAME * osm_opensm_wait_for_subnet_up * * DESCRIPTION * Blocks the calling thread until the subnet is up. * * SYNOPSIS */ static inline cl_status_t osm_opensm_wait_for_subnet_up(IN osm_opensm_t * p_osm, IN uint32_t wait_us, IN boolean_t interruptible) { return osm_sm_wait_for_subnet_up(&p_osm->sm, wait_us, interruptible); } /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object. * * wait_us * [in] Number of microseconds to wait. * * interruptible * [in] Indicates whether the wait operation can be interrupted * by external signals. * * RETURN VALUES * CL_SUCCESS if the wait operation succeeded in response to the event * being set. * * CL_TIMEOUT if the specified time period elapses. * * CL_NOT_DONE if the wait was interrupted by an external signal. * * CL_ERROR if the wait operation failed. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_routing_engine_type_str * NAME * osm_routing_engine_type_str * * DESCRIPTION * Returns a string for the specified routing engine type. * * SYNOPSIS */ const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type); /* * PARAMETERS * type * [in] routing engine type. * * RETURN VALUES * Pointer to routing engine name. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_routing_engine_type * NAME * osm_routing_engine_type * * DESCRIPTION * Returns a routing engine type specified routing engine name string. * * SYNOPSIS */ osm_routing_engine_type_t osm_routing_engine_type(IN const char *str); /* * PARAMETERS * str * [in] routing engine name string. * * RETURN VALUES * Routing engine type. * * NOTES * * SEE ALSO *********/ void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id, void *event_data); /* dump helpers */ void osm_dump_mcast_routes(osm_opensm_t * osm); void osm_dump_all(osm_opensm_t * osm); void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name, cl_qmap_t * map, void (*func) (cl_map_item_t *, FILE *, void *), void *cxt); /****v* OpenSM/osm_exit_flag */ extern volatile unsigned int osm_exit_flag; /* * DESCRIPTION * Set to one to cause all threads to leave *********/ END_C_DECLS #endif /* _OSM_OPENSM_H_ */ opensm-3.3.20/include/opensm/osm_partition.h0000644000205000001450000001430512104655724016005 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 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: * Declaration of osm_prtn_t. * This object represents an IBA Partition. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_PARTITION_H_ #define _OSM_PARTITION_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Partition * NAME * Partition * * DESCRIPTION * The Partition object encapsulates the information needed by the * OpenSM to manage Partitions. The OpenSM allocates one Partition * object per Partition in the IBA subnet. * * The Partition is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Partition/osm_prtn_t * NAME * osm_prtn_t * * DESCRIPTION * Partition structure. * * The osm_prtn_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_prtn { cl_map_item_t map_item; ib_net16_t pkey; uint8_t sl; cl_map_t full_guid_tbl; cl_map_t part_guid_tbl; char name[32]; osm_mgrp_t **mgrps; int nmgrps; } osm_prtn_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * pkey * The IBA defined P_KEY of this Partition. * * sl * The Service Level (SL) associated with this Partiton. * * full_guid_tbl * Container of pointers to all Port objects in the Partition * with full membership, indexed by port GUID. * * part_guid_tbl * Container of pointers to all Port objects in the Partition * with limited membership, indexed by port GUID. * * name * Name of the Partition as specified in partition * configuration. * * mgrps * List of well known Multicast Groups * that were created for this partition (when configured). * This includes the IPoIB broadcast group. * * nmgrps * Number of known Multicast Groups. * * SEE ALSO * Partition *********/ /****f* OpenSM: Partition/osm_prtn_delete * NAME * osm_prtn_delete * * DESCRIPTION * This function destroys and deallocates a Partition object. * * SYNOPSIS */ void osm_prtn_delete(IN osm_subn_t * p_subn, IN OUT osm_prtn_t ** pp_prtn); /* * PARAMETERS * pp_prtn * [in][out] Pointer to a pointer to a Partition object to * delete. On return, this pointer is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified Partition object. * * SEE ALSO * Partition, osm_prtn_new *********/ /****f* OpenSM: Partition/osm_prtn_new * NAME * osm_prtn_new * * DESCRIPTION * This function allocates and initializes a Partition object. * * SYNOPSIS */ osm_prtn_t *osm_prtn_new(IN const char *name, IN uint16_t pkey); /* * PARAMETERS * name * [in] Partition name string * * pkey * [in] Partition P_Key value * * RETURN VALUE * Pointer to the initialize Partition object. * * NOTES * Allows calling other partition methods. * * SEE ALSO * Partition *********/ /****f* OpenSM: Partition/osm_prtn_is_guid * NAME * osm_prtn_is_guid * * DESCRIPTION * Indicates if a port is a member of the partition. * * SYNOPSIS */ static inline boolean_t osm_prtn_is_guid(IN const osm_prtn_t * p_prtn, IN ib_net64_t guid) { return (cl_map_get(&p_prtn->full_guid_tbl, guid) != NULL) || (cl_map_get(&p_prtn->part_guid_tbl, guid) != NULL); } /* * PARAMETERS * p_prtn * [in] Pointer to an osm_prtn_t object. * * guid * [in] Port GUID. * * RETURN VALUES * TRUE if the specified port GUID is a member of the partition, * FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Partition/osm_prtn_make_partitions * NAME * osm_prtn_make_partitions * * DESCRIPTION * Makes all partitions in subnet. * * SYNOPSIS */ ib_api_status_t osm_prtn_make_partitions(IN osm_log_t * p_log, IN osm_subn_t * p_subn); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to subnet object. * * RETURN VALUES * IB_SUCCESS value on success. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Partition/osm_prtn_find_by_name * NAME * osm_prtn_find_by_name * * DESCRIPTION * Fides partition by name. * * SYNOPSIS */ osm_prtn_t *osm_prtn_find_by_name(IN osm_subn_t * p_subn, IN const char *name); /* * PARAMETERS * p_subn * [in] Pointer to a subnet object. * * name * [in] Required partition name. * * RETURN VALUES * Pointer to the partition object on success. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_PARTITION_H_ */ opensm-3.3.20/include/opensm/osm_path.h0000644000205000001450000001176412104655724014736 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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. * */ #ifndef _OSM_PATH_H_ #define _OSM_PATH_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * Abstract: * Declaration of path related objects. * These objects are part of the OpenSM family of objects. */ /****h* OpenSM/DR Path * NAME * DR Path * * DESCRIPTION * The DR Path structure encapsulates a directed route through the subnet. * * This structure allows direct access to member variables. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: DR Path/osm_dr_path_t * NAME * osm_dr_path_t * * DESCRIPTION * Directed Route structure. * * This structure allows direct access to member variables. * * SYNOPSIS */ typedef struct osm_dr_path { uint8_t hop_count; uint8_t path[IB_SUBNET_PATH_HOPS_MAX]; } osm_dr_path_t; /* * FIELDS * h_bind * Bind handle for port to which this path applies. * * hop_count * The number of hops in this path. * * path * The array of port numbers that comprise this path. * * SEE ALSO * DR Path structure *********/ /****f* OpenSM: DR Path/osm_dr_path_construct * NAME * osm_dr_path_construct * * DESCRIPTION * This function constructs a directed route path object. * * SYNOPSIS */ static inline void osm_dr_path_construct(IN osm_dr_path_t * p_path) { /* The first location in the path array is reserved. */ memset(p_path, 0, sizeof(*p_path)); } /* * PARAMETERS * p_path * [in] Pointer to a directed route path object to initialize. * * h_bind * [in] Bind handle for the port on which this path applies. * * hop_count * [in] Hop count needed to reach this node. * * path * [in] Directed route path to reach this node. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: DR Path/osm_dr_path_init * NAME * osm_dr_path_init * * DESCRIPTION * This function initializes a directed route path object. * * SYNOPSIS */ static inline void osm_dr_path_init(IN osm_dr_path_t * p_path, IN uint8_t hop_count, IN const uint8_t path[IB_SUBNET_PATH_HOPS_MAX]) { /* The first location in the path array is reserved. */ CL_ASSERT(path[0] == 0); CL_ASSERT(hop_count < IB_SUBNET_PATH_HOPS_MAX); p_path->hop_count = hop_count; memcpy(p_path->path, path, hop_count + 1); } /* * PARAMETERS * p_path * [in] Pointer to a directed route path object to initialize. * * h_bind * [in] Bind handle for the port on which this path applies. * * hop_count * [in] Hop count needed to reach this node. * * path * [in] Directed route path to reach this node. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: DR Path/osm_dr_path_extend * NAME * osm_dr_path_extend * * DESCRIPTION * Adds a new hop to a path. * * SYNOPSIS */ static inline int osm_dr_path_extend(IN osm_dr_path_t * p_path, IN uint8_t port_num) { p_path->hop_count++; if (p_path->hop_count >= IB_SUBNET_PATH_HOPS_MAX) return -1; /* Location 0 in the path array is reserved per IB spec. */ p_path->path[p_path->hop_count] = port_num; return 0; } /* * PARAMETERS * p_path * [in] Pointer to a directed route path object to initialize. * * port_num * [in] Additional port to add to the DR path. * * RETURN VALUES * 0 indicates path was extended. * Other than 0 indicates path was not extended. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_PATH_H_ */ opensm-3.3.20/include/opensm/osm_perfmgr.h0000644000205000001450000001765612441567062015453 00000000000000/* * Copyright (c) 2007 The Regents of the University of California. * Copyright (c) 2007-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. 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. * */ #ifndef _OSM_PERFMGR_H_ #define _OSM_PERFMGR_H_ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef ENABLE_OSM_PERF_MGR #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /****h* OpenSM/PerfMgr * NAME * PerfMgr * * DESCRIPTION * Performance manager thread which takes care of polling the fabric for * Port counters values. * * The PerfMgr object is thread safe. * * AUTHOR * Ira Weiny, LLNL * *********/ #define OSM_PERFMGR_DEFAULT_SWEEP_TIME_S 180 #define OSM_PERFMGR_DEFAULT_DUMP_FILE "opensm_port_counters.log" #define OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES 500 #define OSM_PERFMGR_DEFAULT_XMIT_WAIT_THRESHOLD 0x0000FFFF /****s* OpenSM: PerfMgr/osm_perfmgr_state_t */ typedef enum { PERFMGR_STATE_DISABLE, PERFMGR_STATE_ENABLED, PERFMGR_STATE_NO_DB } osm_perfmgr_state_t; /****s* OpenSM: PerfMgr/osm_perfmgr_sweep_state_t */ typedef enum { PERFMGR_SWEEP_SLEEP, PERFMGR_SWEEP_ACTIVE, PERFMGR_SWEEP_SUSPENDED, PERFMGR_SWEEP_POST_PROCESSING } osm_perfmgr_sweep_state_t; typedef struct monitored_port { uint16_t pkey_ix; ib_net16_t orig_lid; boolean_t redirection; boolean_t valid; /* Redirection fields from ClassPortInfo */ ib_gid_t gid; ib_net16_t lid; ib_net16_t pkey; ib_net32_t qp; /* ClassPortInfo fields */ boolean_t cpi_valid; ib_net16_t cap_mask; /* Remote end connected to */ boolean_t remote_valid; uint64_t remote_guid; char *remote_name; uint8_t remote_port; } monitored_port_t; /* Node to store information about nodes being monitored */ typedef struct monitored_node { cl_map_item_t map_item; struct monitored_node *next; uint64_t guid; uint8_t node_type; boolean_t esp0; char *name; uint32_t num_ports; monitored_port_t port[1]; } monitored_node_t; struct osm_opensm; /****s* OpenSM: PerfMgr/osm_perfmgr_t * This object should be treated as opaque and should * be manipulated only through the provided functions. */ typedef struct osm_perfmgr { cl_timer_t sweep_timer; struct osm_opensm *osm; osm_subn_t *subn; osm_sm_t *sm; osm_log_t *log; osm_mad_pool_t *mad_pool; atomic32_t trans_id; osm_vendor_t *vendor; osm_bind_handle_t bind_handle; cl_disp_reg_handle_t pc_disp_h; osm_perfmgr_state_t state; osm_perfmgr_sweep_state_t sweep_state; cl_spinlock_t lock; uint16_t sweep_time_s; perfmgr_db_t *db; atomic32_t outstanding_queries; /* this along with sig_query */ cl_event_t sig_query; /* will throttle our queries */ uint32_t max_outstanding_queries; boolean_t ignore_cas; cl_qmap_t monitored_map; /* map the nodes being tracked */ monitored_node_t *remove_list; ib_net64_t port_guid; int16_t local_port; int rm_nodes; boolean_t query_cpi; boolean_t xmit_wait_log; uint32_t xmit_wait_threshold; } osm_perfmgr_t; /* * FIELDS * subn * Subnet object for this subnet. * * log * Pointer to the log object. * * mad_pool * Pointer to the MAD pool. * * mad_ctrl * Mad Controller *********/ /****f* OpenSM: Creation Functions */ void osm_perfmgr_shutdown(osm_perfmgr_t * p_perfmgr); void osm_perfmgr_destroy(osm_perfmgr_t * p_perfmgr); /****f* OpenSM: Inline accessor functions */ inline static void osm_perfmgr_set_state(osm_perfmgr_t * p_perfmgr, osm_perfmgr_state_t state) { p_perfmgr->state = state; if (state == PERFMGR_STATE_ENABLED) { cl_timer_start(&p_perfmgr->sweep_timer, p_perfmgr->sweep_time_s * 1000); } else { cl_timer_stop(&p_perfmgr->sweep_timer); } } inline static osm_perfmgr_state_t osm_perfmgr_get_state(osm_perfmgr_t * perfmgr) { return perfmgr->state; } inline static void osm_perfmgr_set_rm_nodes(osm_perfmgr_t *perfmgr, int rm_nodes) { perfmgr->rm_nodes = rm_nodes; } inline static int osm_perfmgr_get_rm_nodes(osm_perfmgr_t *perfmgr) { return perfmgr->rm_nodes; } inline static void osm_perfmgr_set_query_cpi(osm_perfmgr_t *perfmgr, int query_cpi) { perfmgr->query_cpi = query_cpi; } inline static int osm_perfmgr_get_query_cpi(osm_perfmgr_t *perfmgr) { return perfmgr->query_cpi; } inline static const char *osm_perfmgr_get_state_str(osm_perfmgr_t * p_perfmgr) { switch (p_perfmgr->state) { case PERFMGR_STATE_DISABLE: return "Disabled"; break; case PERFMGR_STATE_ENABLED: return "Enabled"; break; case PERFMGR_STATE_NO_DB: return "No Database"; break; } return "UNKNOWN"; } inline static const char *osm_perfmgr_get_sweep_state_str(osm_perfmgr_t * perfmgr) { switch (perfmgr->sweep_state) { case PERFMGR_SWEEP_SLEEP: return "Sleeping"; break; case PERFMGR_SWEEP_ACTIVE: return "Active"; break; case PERFMGR_SWEEP_SUSPENDED: return "Suspended"; break; case PERFMGR_SWEEP_POST_PROCESSING: return "PostProcessing"; break; } return "UNKNOWN"; } inline static void osm_perfmgr_set_sweep_time_s(osm_perfmgr_t * p_perfmgr, uint16_t time_s) { p_perfmgr->sweep_time_s = time_s; osm_sm_signal(p_perfmgr->sm, OSM_SIGNAL_PERFMGR_SWEEP); } inline static uint16_t osm_perfmgr_get_sweep_time_s(osm_perfmgr_t * p_perfmgr) { return p_perfmgr->sweep_time_s; } inline static unsigned osm_perfmgr_delete_inactive(osm_perfmgr_t * pm) { unsigned rc; perfmgr_db_delete_inactive(pm->db, &rc); return (rc); } void osm_perfmgr_clear_counters(osm_perfmgr_t * p_perfmgr); void osm_perfmgr_dump_counters(osm_perfmgr_t * p_perfmgr, perfmgr_db_dump_t dump_type); void osm_perfmgr_print_counters(osm_perfmgr_t *pm, char *nodename, FILE *fp, char *port, int err_only); void osm_perfmgr_update_nodename(osm_perfmgr_t *pm, uint64_t node_guid, char *nodename); ib_api_status_t osm_perfmgr_bind(osm_perfmgr_t * p_perfmgr, ib_net64_t port_guid); void osm_perfmgr_process(osm_perfmgr_t * pm); /****f* OpenSM: PerfMgr/osm_perfmgr_init */ ib_api_status_t osm_perfmgr_init(osm_perfmgr_t * perfmgr, struct osm_opensm *osm, const osm_subn_opt_t * p_opt); /* * PARAMETERS * perfmgr * [in] Pointer to an osm_perfmgr_t object to initialize. * * osm * [in] Pointer to the OpenSM object. * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * IB_SUCCESS if the PerfMgr object was initialized successfully. *********/ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* ENABLE_OSM_PERF_MGR */ #endif /* _OSM_PERFMGR_H_ */ opensm-3.3.20/include/opensm/osm_perfmgr_db.h0000644000205000001450000001617512331106741016102 00000000000000/* * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 The Regents of the University of California. * Copyright (c) 2009 HNR Consulting. 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. * */ #ifndef _PERFMGR_EVENT_DB_H_ #define _PERFMGR_EVENT_DB_H_ #ifdef ENABLE_OSM_PERF_MGR #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS struct osm_perfmgr; /****h* OpenSM/PerfMgr Event Database * DESCRIPTION * Database interface to record subnet events * * Implementations of this object _MUST_ be thread safe. * * AUTHOR * Ira Weiny, LLNL * *********/ typedef enum { PERFMGR_EVENT_DB_SUCCESS = 0, PERFMGR_EVENT_DB_FAIL, PERFMGR_EVENT_DB_NOMEM, PERFMGR_EVENT_DB_GUIDNOTFOUND, PERFMGR_EVENT_DB_PORTNOTFOUND, PERFMGR_EVENT_DB_NOT_IMPL } perfmgr_db_err_t; /** ========================================================================= * Port error reading */ typedef struct { uint64_t symbol_err_cnt; uint64_t link_err_recover; uint64_t link_downed; uint64_t rcv_err; uint64_t rcv_rem_phys_err; uint64_t rcv_switch_relay_err; uint64_t xmit_discards; uint64_t xmit_constraint_err; uint64_t rcv_constraint_err; uint64_t link_integrity; uint64_t buffer_overrun; uint64_t vl15_dropped; uint64_t xmit_wait; time_t time; } perfmgr_db_err_reading_t; /** ========================================================================= * Port data count reading */ typedef struct { uint64_t xmit_data; /* can be used for std or extended */ uint64_t rcv_data; /* can be used for std or extended */ uint64_t xmit_pkts; /* can be used for std or extended */ uint64_t rcv_pkts; /* can be used for std or extended */ uint64_t unicast_xmit_pkts; uint64_t unicast_rcv_pkts; uint64_t multicast_xmit_pkts; uint64_t multicast_rcv_pkts; time_t time; } perfmgr_db_data_cnt_reading_t; /** ========================================================================= * Dump output options */ typedef enum { PERFMGR_EVENT_DB_DUMP_HR = 0, /* Human readable */ PERFMGR_EVENT_DB_DUMP_MR /* Machine readable */ } perfmgr_db_dump_t; /** ========================================================================= * Port counter object. * Store all the port counters for a single port. */ typedef struct db_port { perfmgr_db_err_reading_t err_total; perfmgr_db_err_reading_t err_previous; perfmgr_db_data_cnt_reading_t dc_total; perfmgr_db_data_cnt_reading_t dc_previous; time_t last_reset; boolean_t valid; } db_port_t; /** ========================================================================= * group port counters for ports into the nodes */ #define NODE_NAME_SIZE (IB_NODE_DESCRIPTION_SIZE + 1) typedef struct db_node { cl_map_item_t map_item; /* must be first */ uint64_t node_guid; boolean_t active; /* activly being monitored */ boolean_t esp0; db_port_t *ports; uint8_t num_ports; char node_name[NODE_NAME_SIZE]; } db_node_t; /** ========================================================================= * all nodes in the subnet. */ typedef struct perfmgr_db { cl_qmap_t pc_data; /* stores type (db_node_t *) */ cl_plock_t lock; struct osm_perfmgr *perfmgr; } perfmgr_db_t; /** * functions */ perfmgr_db_t *perfmgr_db_construct(struct osm_perfmgr *perfmgr); void perfmgr_db_destroy(perfmgr_db_t * db); perfmgr_db_err_t perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid, boolean_t esp0, uint8_t num_ports, char *node_name); perfmgr_db_err_t perfmgr_db_delete_entry(perfmgr_db_t * db, uint64_t guid); perfmgr_db_err_t perfmgr_db_delete_inactive(perfmgr_db_t * db, unsigned *cnt); perfmgr_db_err_t perfmgr_db_update_name(perfmgr_db_t * db, uint64_t node_guid, char *name); perfmgr_db_err_t perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_err_reading_t * reading); perfmgr_db_err_t perfmgr_db_get_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_err_reading_t * reading); perfmgr_db_err_t perfmgr_db_clear_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port); perfmgr_db_err_t perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_data_cnt_reading_t * reading, int ietf_sup); perfmgr_db_err_t perfmgr_db_get_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_data_cnt_reading_t * reading); perfmgr_db_err_t perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port); perfmgr_db_err_t perfmgr_db_mark_active(perfmgr_db_t *db, uint64_t guid, boolean_t active); void perfmgr_db_clear_counters(perfmgr_db_t * db); perfmgr_db_err_t perfmgr_db_dump(perfmgr_db_t * db, char *file, perfmgr_db_dump_t dump_type); void perfmgr_db_print_all(perfmgr_db_t * db, FILE *fp, int err_only); void perfmgr_db_print_by_name(perfmgr_db_t * db, char *nodename, FILE *fp, char *port, int err_only); void perfmgr_db_print_by_guid(perfmgr_db_t * db, uint64_t guid, FILE *fp, char *port, int err_only); /** ========================================================================= * helper functions to fill in the various db objects from wire objects */ void perfmgr_db_fill_err_read(ib_port_counters_t * wire_read, perfmgr_db_err_reading_t * reading, boolean_t xmit_wait_sup); void perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read, perfmgr_db_data_cnt_reading_t * reading); void perfmgr_db_fill_data_cnt_read_pce(ib_port_counters_ext_t * wire_read, perfmgr_db_data_cnt_reading_t * reading, int ietf_sup); END_C_DECLS #endif /* ENABLE_OSM_PERF_MGR */ #endif /* _PERFMGR_PM_DB_H_ */ opensm-3.3.20/include/opensm/osm_pkey.h0000644000205000001450000003773112654642525014761 00000000000000/* * Copyright (c) 2010 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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. * */ #ifndef _OSM_PKEY_H_ #define _OSM_PKEY_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* Forward references. */ struct osm_physp; struct osm_port; struct osm_subn; struct osm_node; struct osm_physp; /* * Abstract: * Declaration of pkey manipulation functions. */ /****s* OpenSM: osm_pkey_tbl_t * NAME * osm_pkey_tbl_t * * DESCRIPTION * This object represents a pkey table. The need for a special object * is required to optimize search performance of a PKey in the IB standard * non sorted table. * * The osm_pkey_tbl_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_pkeybl { cl_map_t accum_pkeys; cl_ptr_vector_t blocks; cl_ptr_vector_t new_blocks; cl_map_t keys; cl_qlist_t pending; uint16_t last_pkey_idx; uint16_t used_blocks; uint16_t max_blocks; uint16_t rcv_blocks_cnt; uint16_t indx0_pkey; } osm_pkey_tbl_t; /* * FIELDS * accum_pkeys * Accumulated pkeys with pkey index. Used to * preserve pkey index. * * blocks * The IBA defined blocks of pkey values, updated from the subnet * * new_blocks * The blocks of pkey values, will be used for updates by SM * * keys * A set holding all keys * * pending * A list of osm_pending_pkey structs that is temporarily set by * the pkey mgr and used during pkey mgr algorithm only * * used_blocks * Tracks the number of blocks having non-zero pkeys * * max_blocks * The maximal number of blocks this partition table might hold * this value is based on node_info (for port 0 or CA) or * switch_info updated on receiving the node_info or switch_info * GetResp * * rcv_blocks_cnt * Counter for the received GetPKeyTable mads. * For every GetPKeyTable mad we send, increase the counter, * and for every GetRespPKeyTable we decrease the counter. * * indx0_pkey * stores the pkey to be inserted at block 0 index 0. * if this field is 0, the default pkey will be inserted. * * NOTES * 'blocks' vector should be used to store pkey values obtained from * the port and SM pkey manager should not change it directly, for this * purpose 'new_blocks' should be used. * * The only pkey values stored in 'blocks' vector will be mapped with * 'keys' map * *********/ /****s* OpenSM: osm_pending_pkey_t * NAME * osm_pending_pkey_t * * DESCRIPTION * This objects stores temporary information on pkeys, their target block, * and index during the pkey manager operation * * SYNOPSIS */ typedef struct osm_pending_pkey { cl_list_item_t list_item; uint16_t pkey; uint16_t block; uint8_t index; boolean_t is_new; } osm_pending_pkey_t; /* * FIELDS * pkey * The actual P_Key * * block * The block index based on the previous table extracted from the * device * * index * The index of the pkey within the block * * is_new * TRUE for new P_Keys such that the block and index are invalid * in that case * *********/ /****f* OpenSM: osm_pkey_tbl_construct * NAME * osm_pkey_tbl_construct * * DESCRIPTION * Constructs the PKey table object * * SYNOPSIS */ void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_init * NAME * osm_pkey_tbl_init * * DESCRIPTION * Inits the PKey table object * * SYNOPSIS */ ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_destroy * NAME * osm_pkey_tbl_destroy * * DESCRIPTION * Destroys the PKey table object * * SYNOPSIS */ void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_get_num_blocks * NAME * osm_pkey_tbl_get_num_blocks * * DESCRIPTION * Obtain the number of blocks in IB PKey table * * SYNOPSIS */ static inline uint16_t osm_pkey_tbl_get_num_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl) { return ((uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks))); } /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * RETURN VALUES * The IB pkey table of that pkey table element * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_block_get * NAME * osm_pkey_tbl_block_get * * DESCRIPTION * Obtain the pointer to the IB PKey table block stored in the object * * SYNOPSIS */ static inline ib_pkey_table_t *osm_pkey_tbl_block_get(const osm_pkey_tbl_t * p_pkey_tbl, uint16_t block) { return ((block < cl_ptr_vector_get_size(&p_pkey_tbl->blocks)) ? (ib_pkey_table_t *)cl_ptr_vector_get( &p_pkey_tbl->blocks, block) : NULL); }; /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * block * [in] The block number to get * * RETURN VALUES * The IB pkey table of that pkey table element * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_new_block_get * NAME * osm_pkey_tbl_new_block_get * * DESCRIPTION * The same as above but for new block * * SYNOPSIS */ static inline ib_pkey_table_t *osm_pkey_tbl_new_block_get(const osm_pkey_tbl_t * p_pkey_tbl, uint16_t block) { return ((block < cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)) ? (ib_pkey_table_t *)cl_ptr_vector_get( &p_pkey_tbl->new_blocks, block) : NULL); }; /****f* OpenSM: osm_pkey_find_last_accum_pkey_index * NAME * osm_pkey_find_last_accum_pkey_index * * DESCRIPTION * Finds the next last accumulated pkey * * SYNOPSIS */ void osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl); /****f* OpenSM: osm_pkey_tbl_set_accum_pkeys * NAME * osm_pkey_tbl_set_accum_pkeys * * DESCRIPTION * Stores the given pkey and pkey index in the "accum_pkeys" array * * SYNOPSIS */ cl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t pkey, IN uint16_t pkey_idx); /* * p_pkey_tbl * [in] Pointer to the PKey table * * pkey * [in] PKey to store * * pkey_idx * [in] The overall index * * RETURN VALUES * CL_SUCCESS if OK * CL_INSUFFICIENT_MEMORY if failed * *********/ /****f* OpenSM: osm_pkey_tbl_set_new_entry * NAME * osm_pkey_tbl_set_new_entry * * DESCRIPTION * Stores the given pkey in the "new" blocks array and update * the "map" to show that on the "old" blocks * * SYNOPSIS */ ib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t block_idx, IN uint8_t pkey_idx, IN uint16_t pkey); /* * p_pkey_tbl * [in] Pointer to the PKey table * * block_idx * [in] The block index to use * * pkey_idx * [in] The index within the block * * pkey * [in] PKey to store * * RETURN VALUES * IB_SUCCESS if OK * IB_ERROR if failed * *********/ /****f* OpenSM: osm_pkey_find_next_free_entry * NAME * osm_pkey_find_next_free_entry * * DESCRIPTION * Find the next free entry in the PKey table starting at the given * index and block number. The user should increment pkey_idx before * next call * Inspect the "new" blocks array for empty space. * * SYNOPSIS */ boolean_t osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl, OUT uint16_t * p_block_idx, OUT uint8_t * p_pkey_idx); /* * p_pkey_tbl * [in] Pointer to the PKey table * * p_block_idx * [out] The block index to use * * p_pkey_idx * [out] The index within the block to use * * RETURN VALUES * TRUE if found * FALSE if did not find * *********/ /****f* OpenSM: osm_pkey_tbl_init_new_blocks * NAME * osm_pkey_tbl_init_new_blocks * * DESCRIPTION * Initializes new_blocks vector content (allocate and clear) * * SYNOPSIS */ void osm_pkey_tbl_init_new_blocks(const osm_pkey_tbl_t * p_pkey_tbl); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_get_block_and_idx * NAME * osm_pkey_tbl_get_block_and_idx * * DESCRIPTION * Set the block index and pkey index the given * pkey is found in. Return IB_NOT_FOUND if could * not find it, IB_SUCCESS if OK * * SYNOPSIS */ ib_api_status_t osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t * p_pkey, OUT uint16_t * block_idx, OUT uint8_t * pkey_index); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object. * * p_pkey * [in] Pointer to the P_Key entry searched * * p_block_idx * [out] Pointer to the block index to be updated * * p_pkey_idx * [out] Pointer to the pkey index (in the block) to be updated * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_set * NAME * osm_pkey_tbl_set * * DESCRIPTION * Set the PKey table block provided in the PKey object. * * SYNOPSIS */ ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t block, IN ib_pkey_table_t * p_tbl, IN boolean_t allow_both_pkeys); /* * p_pkey_tbl * [in] Pointer to osm_pkey_tbl_t object * * block * [in] The block number to set * * p_tbl * [in] The IB PKey block to copy to the object * * allow_both_pkeys * [in] Whether both full and limited membership on same partition * are allowed * * RETURN VALUES * IB_SUCCESS or IB_ERROR * * NOTES * *********/ /****f* OpenSM: osm_physp_share_this_pkey * NAME * osm_physp_share_this_pkey * * DESCRIPTION * Checks if the given physical ports share the specified pkey. * * SYNOPSIS */ boolean_t osm_physp_share_this_pkey(IN const struct osm_physp * p_physp1, IN const struct osm_physp * p_physp2, IN ib_net16_t pkey, IN boolean_t allow_both_pkeys); /* * PARAMETERS * * p_physp1 * [in] Pointer to an osm_physp_t object. * * p_physp2 * [in] Pointer to an osm_physp_t object. * * pkey * [in] value of P_Key to check. * * allow_both_pkeys * [in] whether both pkeys allowed policy is being used. * * RETURN VALUES * Returns TRUE if the two ports are matching. * FALSE otherwise. * * NOTES * *********/ /****f* OpenSM: osm_physp_find_common_pkey * NAME * osm_physp_find_common_pkey * * DESCRIPTION * Returns first matching P_Key values for specified physical ports. * * SYNOPSIS */ ib_net16_t osm_physp_find_common_pkey(IN const struct osm_physp *p_physp1, IN const struct osm_physp *p_physp2, IN boolean_t allow_both_pkeys); /* * PARAMETERS * * p_physp1 * [in] Pointer to an osm_physp_t object. * * p_physp2 * [in] Pointer to an osm_physp_t object. * * allow_both_pkeys * [in] Whether both full and limited membership on same partition * are allowed * * RETURN VALUES * Returns value of first shared P_Key or INVALID P_Key (0x0) if not * found. * * NOTES * *********/ /****f* OpenSM: osm_physp_share_pkey * NAME * osm_physp_share_pkey * * DESCRIPTION * Checks if the given physical ports share a pkey. * The meaning P_Key matching: * 10.9.3 : * In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming * packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against * in the packet's destination endnode. * * If: * * neither M_P_Key nor E_P_Key are the invalid P_Key * * and the low-order 15 bits of the M_P_Key match the low order 15 * bits of the E_P_Key * * and the high order bit(membership type) of both the M_P_Key and * E_P_Key are not both 0 (i.e., both are not Limited members of * the partition) * * then the P_Keys are said to match. * * SYNOPSIS */ boolean_t osm_physp_share_pkey(IN osm_log_t * p_log, IN const struct osm_physp * p_physp_1, IN const struct osm_physp * p_physp_2, IN boolean_t allow_both_pkeys); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_physp_1 * [in] Pointer to an osm_physp_t object. * * p_physp_2 * [in] Pointer to an osm_physp_t object. * * allow_both_pkeys * [in] Whether both full and limited membership on same partition * are allowed * * RETURN VALUES * Returns TRUE if the 2 physical ports are matching. * FALSE otherwise. * * NOTES * *********/ /****f* OpenSM: osm_port_share_pkey * NAME * osm_port_share_pkey * * DESCRIPTION * Checks if the given ports (on their default physical port) share a pkey. * The meaning P_Key matching: * 10.9.3 : * In the following, let M_P_Key(Message P_Key) be the P_Key in the incoming * packet and E_P_Key(Endnode P_Key) be the P_Key it is being compared against * in the packet's destination endnode. * * If: * * neither M_P_Key nor E_P_Key are the invalid P_Key * * and the low-order 15 bits of the M_P_Key match the low order 15 * bits of the E_P_Key * * and the high order bit(membership type) of both the M_P_Key and * E_P_Key are not both 0 (i.e., both are not Limited members of * the partition) * * then the P_Keys are said to match. * * SYNOPSIS */ boolean_t osm_port_share_pkey(IN osm_log_t * p_log, IN const struct osm_port * p_port_1, IN const struct osm_port * p_port_2, IN boolean_t allow_both_pkeys); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_port_1 * [in] Pointer to an osm_port_t object. * * p_port_2 * [in] Pointer to an osm_port_t object. * * RETURN VALUES * Returns TRUE if the 2 ports are matching. * FALSE otherwise. * * NOTES * *********/ /****f* OpenSM: osm_physp_has_pkey * NAME * osm_physp_has_pkey * * DESCRIPTION * Given a physp and a pkey, check if pkey exists in physp pkey table * * SYNOPSIS */ boolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, IN const struct osm_physp *p_physp); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * pkey * [in] pkey number to look for. * * p_physp * [in] Pointer to osm_physp_t object. * * RETURN VALUES * Returns TRUE if the p_physp has the pkey given. False otherwise. * * NOTES * *********/ /****f* OpenSM: osm_pkey_tbl_set_indx0_pkey * NAME * osm_pkey_tbl_set_indx0_pkey * * DESCRIPTION * Sets given pkey at index0 in given pkey_tbl. * * SYNOPSIS */ void osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, IN boolean_t full, OUT osm_pkey_tbl_t * p_pkey_tbl); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * pkey * [in] P_Key. * * full * [in] Indication if this is a full/limited membership pkey. * * p_pkey_tbl * [out] Pointer to osm_pkey_tbl_t object in which to set indx0 pkey. * * RETURN VALUES * None * * NOTES * *********/ END_C_DECLS #endif /* _OSM_PKEY_H_ */ opensm-3.3.20/include/opensm/osm_port.h0000644000205000001450000010503312717400747014762 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 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: * Declaration of port related objects. * These objects comprise an IBA port. * These objects are part of the OpenSM family of objects. */ #ifndef _OSM_PORT_H_ #define _OSM_PORT_H_ #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* Forward references. */ struct osm_port; struct osm_node; struct osm_mgrp; struct osm_sm; /****h* OpenSM/Physical Port * NAME * Physical Port * * DESCRIPTION * The Physical Port object encapsulates the information needed by the * OpenSM to manage physical ports. The OpenSM allocates one Physical Port * per physical port in the IBA subnet. * * In a switch, one multiple Physical Port objects share the same port GUID. * In an end-point, Physical Ports do not share GUID values. * * The Physical Port is not thread safe, thus callers must provide * serialization. * * These objects should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Physical Port/osm_physp_t * NAME * osm_physp_t * * DESCRIPTION * This object represents a physical port on a switch, router or end-point. * * The osm_physp_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_physp { ib_port_info_t port_info; ib_mlnx_ext_port_info_t ext_port_info; ib_net64_t port_guid; ib_net64_t (*p_guids)[]; uint8_t port_num; struct osm_node *p_node; struct osm_physp *p_remote_physp; boolean_t healthy; uint8_t vl_high_limit; unsigned need_update; unsigned is_prof_ignored; osm_dr_path_t dr_path; osm_pkey_tbl_t pkeys; ib_vl_arb_table_t vl_arb[4]; cl_ptr_vector_t slvl_by_port; uint8_t hop_wf; union { struct { ib_sw_cong_setting_t sw_cong_setting; } sw; struct { ib_ca_cong_setting_t ca_cong_setting; ib_cc_tbl_t cc_tbl[OSM_CCT_ENTRY_MAD_BLOCKS]; } ca; } cc; } osm_physp_t; /* * FIELDS * port_info * The IBA defined PortInfo data for this port. * * ext_port_info * Mellanox vendor specific ExtendedPortInfo data for this port. * * port_guid * Port GUID value of this port. For switches, * all ports share the same GUID value. * * p_guids * Pointer to array of GUIDs obtained from GUIDInfo. * This pointer is null for switch physical/external ports * (used for endports only). * * port_num * The port number of this port. The PortInfo also * contains a port_number, but that number is not * the port number of this port, but rather the number * of the port that received the SMP during discovery. * Therefore, we must keep a separate record for this * port's port number. * * p_node * Pointer to the parent Node object of this Physical Port. * * p_remote_physp * Pointer to the Physical Port on the other side of the wire. * If this pointer is NULL no link exists at this port. * * healthy * Tracks the health of the port. Normally should be TRUE but * might change as a result of incoming traps indicating the port * healthy is questionable. * * vl_high_limit * PortInfo:VLHighLimit value which installed by QoS manager * and should be uploaded to port's PortInfo * * need_update * When set indicates that port was probably reset and port * related tables (PKey, SL2VL, VLArb) require refreshing. * * is_prof_ignored * When set indicates that switch port will be ignored by * the link load equalization algorithm. * * dr_path * The directed route path to this port. * * pkeys * osm_pkey_tbl_t object holding the port PKeys. * * vl_arb[] * Each Physical Port has 4 sections of VL Arbitration table. * * slvl_by_port * A vector of pointers to the sl2vl tables (ordered by input port). * Switches have an entry for every other input port (inc SMA=0). * On CAs only one per port. * * hop_wf * Hop weighting factor to be used in the routing. * * sw_cong_setting * Physical port switch congestion settings (switches only) * * ca_cong_setting * Physical port ca congestion settings (cas only) * * cc_tbl * Physical port ca congestion control table (cas only) * * SEE ALSO * Port *********/ /****f* OpenSM: Physical Port/osm_physp_construct * NAME * osm_physp_construct * * DESCRIPTION * Constructs a Physical Port. * * SYNOPSIS */ void osm_physp_construct(IN osm_physp_t * p_physp); /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object to initialize. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_init * NAME * osm_physp_init * * DESCRIPTION * Initializes a Physical Port for use. * * SYNOPSIS */ void osm_physp_init(IN osm_physp_t * p_physp, IN ib_net64_t port_guid, IN uint8_t port_num, IN const struct osm_node *p_node, IN osm_bind_handle_t h_bind, IN uint8_t hop_count, IN const uint8_t * p_initial_path); /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object to initialize. * * port_guid * [in] GUID value of this port. Switch ports all share * the same value. * Caller should use 0 if the guid is unknown. * * port_num * [in] The port number of this port. * * p_node * [in] Pointer to the parent Node object of this Physical Port. * * h_bind * [in] Bind handle on which this port is accessed. * Caller should use OSM_BIND_INVALID_HANDLE if the bind * handle to this port is unknown. * * hop_count * [in] Directed route hop count to reach this port. * Caller should use 0 if the hop count is unknown. * * p_initial_path * [in] Pointer to the directed route path to reach this node. * Caller should use NULL if the path is unknown. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Port/void osm_physp_destroy * NAME * osm_physp_destroy * * DESCRIPTION * This function destroys a Port object. * * SYNOPSIS */ void osm_physp_destroy(IN osm_physp_t * p_physp); /* * PARAMETERS * p_port * [in] Pointer to a PhysPort object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified PhysPort object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_physp_construct or * osm_physp_init. * * SEE ALSO * Port *********/ /****f* OpenSM: Physical Port/osm_physp_is_valid * NAME * osm_physp_is_valid * * DESCRIPTION * Returns TRUE if the Physical Port has been successfully initialized. * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t osm_physp_is_valid(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); return (p_physp->port_guid != 0); } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns TRUE if the Physical Port has been successfully initialized. * FALSE otherwise. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_is_healthy * NAME * osm_physp_is_healthy * * DESCRIPTION * Returns TRUE if the Physical Port has been maked as healthy * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t osm_physp_is_healthy(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); return p_physp->healthy; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns TRUE if the Physical Port has been maked as healthy * FALSE otherwise. * All physical ports are initialized as "healthy" but may be marked * otherwise if a received trap claims otherwise. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_link_is_healthy * NAME * osm_link_is_healthy * * DESCRIPTION * Returns TRUE if the link given by the physical port is health, * and FALSE otherwise. Link is healthy if both its physical ports are * healthy * * SYNOPSIS */ boolean_t osm_link_is_healthy(IN const osm_physp_t * p_physp); /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * TRUE if both physical ports on the link are healthy, and FALSE otherwise. * All physical ports are initialized as "healthy" but may be marked * otherwise if a received trap claiming otherwise. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_set_health * NAME * osm_physp_set_health * * DESCRIPTION * Sets the port health flag. TRUE means the port is healthy and * should be used for packet routing. FALSE means it should be avoided. * * SYNOPSIS */ static inline void osm_physp_set_health(IN osm_physp_t * p_physp, IN boolean_t is_healthy) { CL_ASSERT(p_physp); p_physp->healthy = is_healthy; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * is_healthy * [in] The health value to be assigned to the port. * TRUE if the Physical Port should been maked as healthy * FALSE otherwise. * * RETURN VALUES * NONE * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_set_port_info * NAME * osm_physp_set_port_info * * DESCRIPTION * Copies the PortInfo attribute into the Physical Port object * based on the PortState. * * SYNOPSIS */ void osm_physp_set_port_info(IN osm_physp_t * p_physp, IN const ib_port_info_t * p_pi, IN const struct osm_sm * p_sm); /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * p_pi * [in] Pointer to the IBA defined PortInfo at this port number. * * p_sm * [in] Pointer to an osm_sm_t object. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_set_base_lid * NAME * osm_physp_set_base_lid * * DESCRIPTION * Sets the base lid for this Physical Port. * * SYNOPSIS */ static inline void osm_physp_set_base_lid(IN osm_physp_t * p_physp, IN ib_net16_t base_lid) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); p_physp->port_info.base_lid = base_lid; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * base_lid * [in] Lid to set. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_set_pkey_tbl * NAME * osm_physp_set_pkey_tbl * * DESCRIPTION * Copies the P_Key table into the Physical Port object. * * SYNOPSIS */ void osm_physp_set_pkey_tbl(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN osm_physp_t * p_physp, IN ib_pkey_table_t * p_pkey_tbl, IN uint16_t block_num, IN boolean_t is_set); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to the subnet data structure. * * p_physp * [in] Pointer to an osm_physp_t object. * * p_pkey_tbl * [in] Pointer to the IBA defined P_Key table for this port * number. * * block_num * [in] The part of the P_Key table as defined in the IBA * (valid values 0-2047, and is further limited by the * partitionCap). * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_pkey_tbl * NAME * osm_physp_get_pkey_tbl * * DESCRIPTION * Returns a pointer to the P_Key table object of the Physical Port object. * * SYNOPSIS */ static inline const osm_pkey_tbl_t *osm_physp_get_pkey_tbl(IN const osm_physp_t * p_physp) { CL_ASSERT(osm_physp_is_valid(p_physp)); /* (14.2.5.7) - the block number valid values are 0-2047, and are further limited by the size of the P_Key table specified by the PartitionCap on the node. */ return &p_physp->pkeys; }; /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * The pointer to the P_Key table object. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_set_slvl_tbl * NAME * osm_physp_set_slvl_tbl * * DESCRIPTION * Copies the SLtoVL attribute into the Physical Port object. * * SYNOPSIS */ static inline void osm_physp_set_slvl_tbl(IN osm_physp_t * p_physp, IN ib_slvl_table_t * p_slvl_tbl, IN uint8_t in_port_num) { ib_slvl_table_t *p_tbl; CL_ASSERT(p_slvl_tbl); CL_ASSERT(osm_physp_is_valid(p_physp)); p_tbl = (ib_slvl_table_t *)cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num); *p_tbl = *p_slvl_tbl; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * p_slvl_tbl * [in] Pointer to the IBA defined SLtoVL map table for this * port number. * * in_port_num * [in] Input Port Number for this SLtoVL. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_slvl_tbl * NAME * osm_physp_get_slvl_tbl * * DESCRIPTION * Returns a pointer to the SLtoVL attribute of the Physical Port object. * * SYNOPSIS */ static inline ib_slvl_table_t *osm_physp_get_slvl_tbl(IN const osm_physp_t * p_physp, IN uint8_t in_port_num) { ib_slvl_table_t *p_tbl; CL_ASSERT(osm_physp_is_valid(p_physp)); p_tbl = (ib_slvl_table_t *)cl_ptr_vector_get(&p_physp->slvl_by_port, in_port_num); return p_tbl; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * in_port_num * [in] Input Port Number for this SLtoVL. * * RETURN VALUES * The pointer to the slvl table * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_set_vla_tbl * NAME * osm_physp_set_vla_tbl * * DESCRIPTION * Copies the VL Arbitration attribute into the Physical Port object. * * SYNOPSIS */ static inline void osm_physp_set_vla_tbl(IN osm_physp_t * p_physp, IN ib_vl_arb_table_t * p_vla_tbl, IN uint8_t block_num) { CL_ASSERT(p_vla_tbl); CL_ASSERT(osm_physp_is_valid(p_physp)); CL_ASSERT((1 <= block_num) && (block_num <= 4)); p_physp->vl_arb[block_num - 1] = *p_vla_tbl; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * p_vla_tbl * [in] Pointer to the IBA defined VL Arbitration table for this * port number. * * block_num * [in] The part of the VL arbitration as defined in the IBA * (valid values 1-4) * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_vla_tbl * NAME * osm_physp_get_vla_tbl * * DESCRIPTION * Returns a pointer to the VL Arbitration table of the Physical Port object. * * SYNOPSIS */ static inline ib_vl_arb_table_t *osm_physp_get_vla_tbl(IN osm_physp_t * p_physp, IN uint8_t block_num) { CL_ASSERT(osm_physp_is_valid(p_physp)); CL_ASSERT((1 <= block_num) && (block_num <= 4)); return &(p_physp->vl_arb[block_num - 1]); } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * block_num * [in] The part of the VL arbitration as defined in the IBA * (valid values 1-4) * * RETURN VALUES * The pointer to the VL Arbitration table * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_remote * NAME * osm_physp_get_remote * * DESCRIPTION * Returns a pointer to the Physical Port on the other side the wire. * * SYNOPSIS */ static inline osm_physp_t *osm_physp_get_remote(IN const osm_physp_t * p_physp) { CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->p_remote_physp; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns a pointer to the Physical Port on the other side of * the wire. A return value of NULL means there is no link at this port. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_port_guid * NAME * osm_physp_get_port_guid * * DESCRIPTION * Returns the port guid of this physical port. * * SYNOPSIS */ static inline ib_net64_t osm_physp_get_port_guid(IN const osm_physp_t * p_physp) { CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->port_guid; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the port guid of this physical port. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_subnet_prefix * NAME * osm_physp_get_subnet_prefix * * DESCRIPTION * Returns the subnet prefix for this physical port. * * SYNOPSIS */ static inline ib_net64_t osm_physp_get_subnet_prefix(IN const osm_physp_t * p_physp) { CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->port_info.subnet_prefix; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the subnet prefix for this physical port. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_link_exists * NAME * osm_physp_link_exists * * DESCRIPTION * Returns TRUE if the Physical Port has a link to the specified port. * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t osm_physp_link_exists(IN const osm_physp_t * p_physp, IN const osm_physp_t * p_remote_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); CL_ASSERT(p_remote_physp); CL_ASSERT(osm_physp_is_valid(p_remote_physp)); return ((p_physp->p_remote_physp == p_remote_physp) && (p_remote_physp->p_remote_physp == p_physp)); } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * p_remote_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns TRUE if the Physical Port has a link to another port. * FALSE otherwise. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_link * NAME * osm_physp_link * * DESCRIPTION * Sets the pointers to the Physical Ports on the other side the wire. * * SYNOPSIS */ static inline void osm_physp_link(IN osm_physp_t * p_physp, IN osm_physp_t * p_remote_physp) { CL_ASSERT(p_physp); CL_ASSERT(p_remote_physp); p_physp->p_remote_physp = p_remote_physp; p_remote_physp->p_remote_physp = p_physp; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object to link. * * p_remote_physp * [in] Pointer to the adjacent osm_physp_t object to link. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_unlink * NAME * osm_physp_unlink * * DESCRIPTION * Clears the pointers to the Physical Port on the other side the wire. * * SYNOPSIS */ static inline void osm_physp_unlink(IN osm_physp_t * p_physp, IN osm_physp_t * p_remote_physp) { CL_ASSERT(p_physp); CL_ASSERT(p_remote_physp); CL_ASSERT(osm_physp_link_exists(p_physp, p_remote_physp)); p_physp->p_remote_physp = NULL; p_remote_physp->p_remote_physp = NULL; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object to link. * * p_remote_physp * [in] Pointer to the adjacent osm_physp_t object to link. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_has_any_link * NAME * osm_physp_has_any_link * * DESCRIPTION * Returns TRUE if the Physical Port has a link to another port. * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t osm_physp_has_any_link(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); if (osm_physp_is_valid(p_physp)) return (p_physp->p_remote_physp != NULL); else return FALSE; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns TRUE if the Physical Port has a link to another port. * FALSE otherwise. * * NOTES * * SEE ALSO * Port, Physical Port *********/ /****f* OpenSM: Physical Port/osm_physp_get_port_num * NAME * osm_physp_get_port_num * * DESCRIPTION * Returns the local port number of this Physical Port. * * SYNOPSIS */ static inline uint8_t osm_physp_get_port_num(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->port_num; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the local port number of this Physical Port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_get_node_ptr * NAME * osm_physp_get_node_ptr * * DESCRIPTION * Returns a pointer to the parent Node object for this port. * * SYNOPSIS */ static inline struct osm_node *osm_physp_get_node_ptr(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->p_node; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns a pointer to the parent Node object for this port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_get_port_state * NAME * osm_physp_get_port_state * * DESCRIPTION * Returns the port state of this Physical Port. * * SYNOPSIS */ static inline uint8_t osm_physp_get_port_state(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return ib_port_info_get_port_state(&p_physp->port_info); } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the local port number of this Physical Port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_get_base_lid * NAME * osm_physp_get_base_lid * * DESCRIPTION * Returns the base lid of this Physical Port. * * SYNOPSIS */ static inline ib_net16_t osm_physp_get_base_lid(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return p_physp->port_info.base_lid; } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the base lid of this Physical Port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_get_lmc * NAME * osm_physp_get_lmc * * DESCRIPTION * Returns the LMC value of this Physical Port. * * SYNOPSIS */ static inline uint8_t osm_physp_get_lmc(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return ib_port_info_get_lmc(&p_physp->port_info); } /* * PARAMETERS * p_physp * [in] Pointer to an osm_physp_t object. * * RETURN VALUES * Returns the LMC value of this Physical Port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Physical Port/osm_physp_get_dr_path_ptr * NAME * osm_physp_get_dr_path_ptr * * DESCRIPTION * Returns a pointer to the directed route path for this port. * * SYNOPSIS */ static inline osm_dr_path_t *osm_physp_get_dr_path_ptr(IN const osm_physp_t * p_physp) { CL_ASSERT(p_physp); CL_ASSERT(osm_physp_is_valid(p_physp)); return (osm_dr_path_t *) & p_physp->dr_path; } /* * PARAMETERS * p_physp * [in] Pointer to a Physical Port object. * * RETURN VALUES * Returns a pointer to the directed route path for this port. * * NOTES * * SEE ALSO * Physical Port object *********/ /****h* OpenSM/Port * NAME * Port * * DESCRIPTION * The Port object encapsulates the information needed by the * OpenSM to manage ports. The OpenSM allocates one Port object * per port in the IBA subnet. * * Each Port object is associated with a single port GUID. A Port object * contains 1 or more Physical Port objects. An end point node has * one Physical Port per Port. A switch node has more than * one Physical Port per Port. * * The Port object is not thread safe, thus callers must provide * serialization. * * These objects should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Port/osm_port_t * NAME * osm_port_t * * DESCRIPTION * This object represents a logical port on a switch, router, or CA. * * The osm_port_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_port { cl_map_item_t map_item; cl_list_item_t list_item; struct osm_node *p_node; ib_net64_t guid; uint32_t discovery_count; unsigned is_new; osm_physp_t *p_physp; cl_qlist_t mcm_list; int flag; int use_scatter; unsigned int cc_timeout_count; int cc_unavailable_flag; void *priv; ib_net16_t lid; } osm_port_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * list_item * Linkage structure for cl_qlist. Used by ucast mgr during * LFT calculation. * * p_node * Points to the Node object that owns this port. * * guid * Manufacturer assigned GUID for this port. * * discovery_count * The number of times this port has been discovered * during the current fabric sweep. This number is reset * to zero at the start of a sweep. * * p_physp * The pointer to physical port used when physical * characteristics contained in the Physical Port are needed. * * mcm_list * Multicast member list * * flag * Utility flag for port management * * cc_timeout_count * Count number of times congestion control config times out. * * cc_unavailable_flag * Flag indicating if congestion control is not supported. * * SEE ALSO * Port, Physical Port, Physical Port Table *********/ /****f* OpenSM: Port/osm_port_delete * NAME * osm_port_delete * * DESCRIPTION * This function destroys and deallocates a Port object. * * SYNOPSIS */ void osm_port_delete(IN OUT osm_port_t ** pp_port); /* * PARAMETERS * pp_port * [in][out] Pointer to a pointer to a Port object to delete. * On return, this pointer is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified Port object. * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_new * NAME * osm_port_new * * DESCRIPTION * This function allocates and initializes a Port object. * * SYNOPSIS */ osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni, IN struct osm_node *p_parent_node); /* * PARAMETERS * p_ni * [in] Pointer to the NodeInfo attribute relevant for this port. * * p_parent_node * [in] Pointer to the initialized parent osm_node_t object * that owns this port. * * RETURN VALUE * Pointer to the initialize Port object. * * NOTES * Allows calling other port methods. * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_get_base_lid * NAME * osm_port_get_base_lid * * DESCRIPTION * Gets the base LID of a port. * * SYNOPSIS */ static inline ib_net16_t osm_port_get_base_lid(IN const osm_port_t * p_port) { CL_ASSERT(p_port->p_physp && osm_physp_is_valid(p_port->p_physp)); return osm_physp_get_base_lid(p_port->p_physp); } /* * PARAMETERS * p_port * [in] Pointer to a Port object. * * RETURN VALUE * Base LID of the port. * If the return value is 0, then this port has no assigned LID. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_get_lmc * NAME * osm_port_get_lmc * * DESCRIPTION * Gets the LMC value of a port. * * SYNOPSIS */ static inline uint8_t osm_port_get_lmc(IN const osm_port_t * p_port) { CL_ASSERT(p_port->p_physp && osm_physp_is_valid(p_port->p_physp)); return osm_physp_get_lmc(p_port->p_physp); } /* * PARAMETERS * p_port * [in] Pointer to a Port object. * * RETURN VALUE * Gets the LMC value of a port. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_get_guid * NAME * osm_port_get_guid * * DESCRIPTION * Gets the GUID of a port. * * SYNOPSIS */ static inline ib_net64_t osm_port_get_guid(IN const osm_port_t * p_port) { return p_port->guid; } /* * PARAMETERS * p_port * [in] Pointer to a Port object. * * RETURN VALUE * Manufacturer assigned GUID of the port. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_get_lid_range_ho * NAME * osm_port_get_lid_range_ho * * DESCRIPTION * Returns the HOST ORDER lid min and max values for this port, * based on the lmc value. * * SYNOPSIS */ void osm_port_get_lid_range_ho(IN const osm_port_t * p_port, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid); /* * PARAMETERS * p_port * [in] Pointer to a Port object. * * p_min_lid * [out] Pointer to the minimum LID value occupied by this port. * * p_max_lid * [out] Pointer to the maximum LID value occupied by this port. * * RETURN VALUE * None. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Physical Port/osm_physp_calc_link_mtu * NAME * osm_physp_calc_link_mtu * * DESCRIPTION * Calculate the Port MTU based on current and remote * physical ports MTU CAP values. * * SYNOPSIS */ uint8_t osm_physp_calc_link_mtu(IN osm_log_t * p_log, IN const osm_physp_t * p_physp, IN uint8_t current_mtu); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_physp * [in] Pointer to an osm_physp_t object. * * current_mtu * [in] Current neighbor mtu on this port * * RETURN VALUES * The MTU of the link to be used. * * NOTES * * SEE ALSO * PhysPort object *********/ /****f* OpenSM: Physical Port/osm_physp_calc_link_op_vls * NAME * osm_physp_calc_link_op_vls * * DESCRIPTION * Calculate the Port OP_VLS based on current and remote * physical ports VL CAP values. Allowing user option for a max limit. * * SYNOPSIS */ uint8_t osm_physp_calc_link_op_vls(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN const osm_physp_t * p_physp, IN uint8_t current_op_vls); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to the subnet object for accessing of the options. * * p_physp * [in] Pointer to an osm_physp_t object. * * current_op_vls * [in] Current operational VL on the port * * RETURN VALUES * The OP_VLS of the link to be used. * * NOTES * * SEE ALSO * PhysPort object *********/ /****f* OpenSM: Physical Port/osm_physp_replace_dr_path_with_alternate_dr_path * NAME * osm_physp_replace_dr_path_with_alternate_dr_path * * DESCRIPTION * Replace the direct route path for the given phys port with an * alternate path going through forien set of phys port. * * SYNOPSIS */ void osm_physp_replace_dr_path_with_alternate_dr_path(IN osm_log_t * p_log, IN osm_subn_t const *p_subn, IN osm_physp_t const *p_physp, IN osm_bind_handle_t * h_bind); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to the subnet object for accessing of the options. * * p_physp * [in] Pointer to an osm_physp_t object. * * h_bind * [in] Pointer to osm_bind_handle_t object. * * RETURN VALUES * NONE * * NOTES * * SEE ALSO * PhysPort object *********/ /****s* OpenSM: Port/osm_alias_guid_t * NAME * osm_alias_guid_t * * DESCRIPTION * This object represents an alias guid for an endport. * * The osm_alias_guid_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_alias_guid { cl_map_item_t map_item; ib_net64_t alias_guid; osm_port_t *p_base_port; } osm_alias_guid_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * alias_guid * Alias GUID for port obtained from SM GUIDInfo attribute * * p_base_port * Pointer to osm_port_t for base port GUID * * SEE ALSO * Port, Physical Port, Physical Port Table */ /****f* OpenSM: Port/osm_alias_guid_new * NAME * osm_alias_guid_new * * DESCRIPTION * This function allocates and initializes an alias guid object. * * SYNOPSIS */ osm_alias_guid_t *osm_alias_guid_new(IN const ib_net64_t alias_guid, IN osm_port_t *p_base_port); /* * PARAMETERS * alias_guid * [in] Alias GUID in network order * * p_base_port * [in] Pointer to the port for this base GUID * * RETURN VALUE * Pointer to the initialized alias guid object. * * NOTES * Allows calling other alias guid methods. * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_alias_guid_delete * NAME * osm_alias_guid_delete * * DESCRIPTION * This function destroys and deallocates an alias guid object. * * SYNOPSIS */ void osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid); /* * PARAMETERS * pp_alias_guid * [in][out] Pointer to a pointer to an alias guid object to delete. * On return, this pointer is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified alias guid object. * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_alias_guid_get_alias_guid * NAME * osm_alias_guid_get_alias_guid * * DESCRIPTION * This function retrieves alias guid from alias guid object. * * SYNOPSIS */ static inline ib_net64_t osm_alias_guid_get_alias_guid(IN osm_alias_guid_t *p_alias_guid) { CL_ASSERT(p_alias_guid); return p_alias_guid->alias_guid; } /* * PARAMETERS * p_alias_guid * [in] Pointer to a pointer to an alias guid object. * * RETURN VALUE * This function returns the alias guid or NULL if fails. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_alias_guid_get_base_guid * NAME * osm_alias_guid_get_base_guid * * DESCRIPTION * This function retrieves base guid from alias guid object. * * SYNOPSIS */ static inline ib_net64_t osm_alias_guid_get_base_guid(IN osm_alias_guid_t *p_alias_guid) { CL_ASSERT(p_alias_guid); return osm_port_get_guid(p_alias_guid->p_base_port); } /* * PARAMETERS * p_alias_guid * [in] Pointer to a pointer to an alias guid object. * * RETURN VALUE * This function returns the base guid or NULL if fails. * * NOTES * * SEE ALSO * Port *********/ /****f* OpenSM: Port/osm_port_clear_base_lid * NAME * osm_port_clear_base_lid * * DESCRIPTION * Clear the base lid of a given port. * * SYNOPSIS */ static inline void osm_port_clear_base_lid(OUT osm_port_t * p_port) { CL_ASSERT(p_port); p_port->lid = 0; osm_physp_set_base_lid(p_port->p_physp, 0); } /* * PARAMETERS * p_port * [out] Pointer to a Port object. * * RETURN VALUE * None * * NOTES * * SEE ALSO * Port *********/ END_C_DECLS #endif /* _OSM_PORT_H_ */ opensm-3.3.20/include/opensm/osm_port_profile.h0000644000205000001450000001136312104655724016501 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. 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: * Declaration of Switch/osm_port_profile_t. * This object represents a port profile for an IBA switch. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_PORT_PROFILE_H_ #define _OSM_PORT_PROFILE_H_ #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Port Profile * NAME * Port Profile * * DESCRIPTION * The Port Profile object contains profiling information for * each Physical Port on a switch. The profile information * may be used to optimize path selection. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Switch/osm_port_profile_t * NAME * osm_port_profile_t * * DESCRIPTION * The Port Profile object contains profiling information for * each Physical Port on the switch. The profile information * may be used to optimize path selection. * * This object should be treated as opaque and should be * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_port_profile { uint32_t num_paths; } osm_port_profile_t; /* * FIELDS * num_paths * The number of paths using this port. * * SEE ALSO *********/ /****s* OpenSM: Switch/osm_port_mask_t * NAME * osm_port_mask_t * * DESCRIPTION * The Port Mask object contains a port numbered bit mask * for whether the port should be ignored by the link load * equalization algorithm. * * SYNOPSIS */ typedef long osm_port_mask_t[32 / sizeof(long)]; /* * FIELDS * osm_port_mask_t * Bit mask by port number * * SEE ALSO *********/ /****f* OpenSM: Port Profile/osm_port_prof_construct * NAME * osm_port_prof_construct * * DESCRIPTION * * * SYNOPSIS */ static inline void osm_port_prof_construct(IN osm_port_profile_t * p_prof) { CL_ASSERT(p_prof); memset(p_prof, 0, sizeof(*p_prof)); } /* * PARAMETERS * p_prof * [in] Pointer to the Port Profile object to construct. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Port Profile/osm_port_prof_path_count_inc * NAME * osm_port_prof_path_count_inc * * DESCRIPTION * Increments the count of the number of paths going through this port. * * * SYNOPSIS */ static inline void osm_port_prof_path_count_inc(IN osm_port_profile_t * p_prof) { CL_ASSERT(p_prof); p_prof->num_paths++; } /* * PARAMETERS * p_prof * [in] Pointer to the Port Profile object. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Port Profile/osm_port_prof_path_count_get * NAME * osm_port_prof_path_count_get * * DESCRIPTION * Returns the count of the number of paths going through this port. * * SYNOPSIS */ static inline uint32_t osm_port_prof_path_count_get(IN const osm_port_profile_t * p_prof) { return p_prof->num_paths; } /* * PARAMETERS * p_prof * [in] Pointer to the Port Profile object. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_PORT_PROFILE_H_ */ opensm-3.3.20/include/opensm/osm_prefix_route.h0000644000205000001450000000431212104655724016504 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSM_PREFIX_ROUTE_H_ #define _OSM_PREFIX_ROUTE_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct { cl_list_item_t list_item; /* must be first */ ib_net64_t prefix; /* zero means "any" */ ib_net64_t guid; /* zero means "any" */ } osm_prefix_route_t; #ifdef ROUTER_EXP #error ROUTER_EXP is deprecated, specify prefix routes at runtime instead (see opensm man page for details) #endif END_C_DECLS #endif /* _OSM_PREFIX_ROUTE_H_ */ opensm-3.3.20/include/opensm/osm_qos_policy.h0000644000205000001450000001724512104655724016163 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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: * Declaration of OSM QoS Policy data types and functions. * * Author: * Yevgeny Kliteynik, Mellanox */ #ifndef OSM_QOS_POLICY_H #define OSM_QOS_POLICY_H #include #include #include #include #include #define YYSTYPE char * #define OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH 128 #define OSM_QOS_POLICY_DEFAULT_LEVEL_NAME "default" #define OSM_QOS_POLICY_ULP_SDP_SERVICE_ID 0x0000000000010000ULL #define OSM_QOS_POLICY_ULP_RDS_SERVICE_ID 0x0000000001060000ULL #define OSM_QOS_POLICY_ULP_RDS_PORT 0x48CA #define OSM_QOS_POLICY_ULP_ISER_SERVICE_ID 0x0000000001060000ULL #define OSM_QOS_POLICY_ULP_ISER_PORT 0x0CBC #define OSM_QOS_POLICY_NODE_TYPE_CA (((uint8_t)1)< #include #include #include #include #include #include #include /****s* OpenSM: Base/OSM_DEFAULT_CC_KEY * NAME * OSM_DEFAULT_CC_KEY * * DESCRIPTION * Congestion Control Key used by OpenSM. * * SYNOPSIS */ #define OSM_DEFAULT_CC_KEY 0 #define OSM_CC_DEFAULT_MAX_OUTSTANDING_QUERIES 500 #define OSM_CC_TIMEOUT_COUNT_THRESHOLD 3 /****s* OpenSM: CongestionControl/osm_congestion_control_t * This object should be treated as opaque and should * be manipulated only through the provided functions. */ typedef struct osm_congestion_control { struct osm_opensm *osm; osm_subn_t *subn; osm_sm_t *sm; osm_log_t *log; osm_mad_pool_t *mad_pool; atomic32_t trans_id; osm_vendor_t *vendor; osm_bind_handle_t bind_handle; cl_disp_reg_handle_t cc_disp_h; ib_net64_t port_guid; atomic32_t outstanding_mads; atomic32_t outstanding_mads_on_wire; cl_qlist_t mad_queue; cl_spinlock_t mad_queue_lock; cl_event_t cc_poller_wakeup; cl_event_t outstanding_mads_done_event; cl_event_t sig_mads_on_wire_continue; cl_thread_t cc_poller; osm_thread_state_t thread_state; ib_sw_cong_setting_t sw_cong_setting; ib_ca_cong_setting_t ca_cong_setting; ib_cc_tbl_t cc_tbl[OSM_CCT_ENTRY_MAD_BLOCKS]; unsigned int cc_tbl_mads; } osm_congestion_control_t; /* * FIELDS * subn * Subnet object for this subnet. * * log * Pointer to the log object. * * mad_pool * Pointer to the MAD pool. * * mad_ctrl * Mad Controller *********/ struct osm_opensm; int osm_congestion_control_setup(struct osm_opensm *osm); int osm_congestion_control_wait_pending_transactions(struct osm_opensm *osm); ib_api_status_t osm_congestion_control_init(osm_congestion_control_t * p_cc, struct osm_opensm *osm, const osm_subn_opt_t * p_opt); ib_api_status_t osm_congestion_control_bind(osm_congestion_control_t * p_cc, ib_net64_t port_guid); void osm_congestion_control_shutdown(osm_congestion_control_t * p_cc); void osm_congestion_control_destroy(osm_congestion_control_t * p_cc); #endif /* ifndef OSM_CONGESTION_CONTROL_H */ opensm-3.3.20/include/opensm/osm_remote_sm.h0000644000205000001450000001161012104655724015762 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_sm_t, osm_remote_sm_t. * This object represents an IBA subnet. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_REMOTE_SM_H_ #define _OSM_REMOTE_SM_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Remote SM * NAME * Remote SM * * DESCRIPTION * The Remote SM object encapsulates the information tracked for * other SM ports on the subnet. * * The Remote SM object is thread safe. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Remote SM/osm_remote_sm_t * NAME * osm_remote_sm_t * * DESCRIPTION * Remote Subnet Manager structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_remote_sm { cl_map_item_t map_item; ib_sm_info_t smi; } osm_remote_sm_t; /* * FIELDS * map_item * Linkage for the cl_qmap container. MUST BE FIRST ELEMENT!! * p_port * Pointer to the port object for this SM. * * smi * The SMInfo attribute for this SM. * * SEE ALSO *********/ /****f* OpenSM: SM/osm_remote_sm_construct * NAME * osm_remote_sm_construct * * DESCRIPTION * This function constructs an Remote SM object. * * SYNOPSIS */ void osm_remote_sm_construct(IN osm_remote_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to an Remote SM object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_remote_sm_init, osm_remote_sm_destroy * * Calling osm_remote_sm_construct is a prerequisite to calling any other * method except osm_remote_sm_init. * * SEE ALSO * SM object, osm_remote_sm_init, osm_remote_sm_destroy *********/ /****f* OpenSM: SM/osm_remote_sm_destroy * NAME * osm_remote_sm_destroy * * DESCRIPTION * The osm_remote_sm_destroy function destroys an SM, releasing * all resources. * * SYNOPSIS */ void osm_remote_sm_destroy(IN osm_remote_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to an Remote SM object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified Remote SM object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_remote_sm_construct or osm_remote_sm_init. * * SEE ALSO * Remote SM object, osm_remote_sm_construct, osm_remote_sm_init *********/ /****f* OpenSM: SM/osm_remote_sm_init * NAME * osm_remote_sm_init * * DESCRIPTION * The osm_remote_sm_init function initializes an Remote SM object for use. * * SYNOPSIS */ void osm_remote_sm_init(IN osm_remote_sm_t * p_sm, IN const ib_sm_info_t * p_smi); /* * PARAMETERS * p_sm * [in] Pointer to an osm_remote_sm_t object to initialize. * * p_port * [in] Pointer to the Remote SM's port object. * * p_smi * [in] Pointer to the SMInfo attribute for this SM. * * RETURN VALUES * This function does not return a value. * * NOTES * Allows calling other Remote SM methods. * * SEE ALSO * Remote SM object, osm_remote_sm_construct, osm_remote_sm_destroy *********/ END_C_DECLS #endif /* _OSM_REMOTE_SM_H_ */ opensm-3.3.20/include/opensm/osm_router.h0000644000205000001450000001145212104655724015314 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 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: * Declaration of osm_router_t. * This object represents an IBA router. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_ROUTER_H_ #define _OSM_ROUTER_H_ #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Router * NAME * Router * * DESCRIPTION * The Router object encapsulates the information needed by the * OpenSM to manage routers. The OpenSM allocates one router object * per router in the IBA subnet. * * The Router object is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Hal Rosenstock, Voltaire * *********/ /****s* OpenSM: Router/osm_router_t * NAME * osm_router_t * * DESCRIPTION * Router structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_router { cl_map_item_t map_item; osm_port_t *p_port; } osm_router_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * p_port * Pointer to the Port object for this router. * * SEE ALSO * Router object *********/ /****f* OpenSM: Router/osm_router_delete * NAME * osm_router_delete * * DESCRIPTION * Destroys and deallocates the object. * * SYNOPSIS */ void osm_router_delete(IN OUT osm_router_t ** pp_rtr); /* * PARAMETERS * p_rtr * [in] Pointer to the object to destroy. * * RETURN VALUE * None. * * NOTES * * SEE ALSO * Router object, osm_router_new *********/ /****f* OpenSM: Router/osm_router_new * NAME * osm_router_new * * DESCRIPTION * The osm_router_new function initializes a Router object for use. * * SYNOPSIS */ osm_router_t *osm_router_new(IN osm_port_t * p_port); /* * PARAMETERS * p_node * [in] Pointer to the node object of this router * * RETURN VALUES * Pointer to the new initialized router object. * * NOTES * * SEE ALSO * Router object, osm_router_new *********/ /****f* OpenSM: Router/osm_router_get_port_ptr * NAME * osm_router_get_port_ptr * * DESCRIPTION * Returns a pointer to the Port object for this router. * * SYNOPSIS */ static inline osm_port_t *osm_router_get_port_ptr(IN const osm_router_t * p_rtr) { return p_rtr->p_port; } /* * PARAMETERS * p_rtr * [in] Pointer to an osm_router_t object. * * RETURN VALUES * Returns a pointer to the Port object for this router. * * NOTES * * SEE ALSO * Router object *********/ /****f* OpenSM: Router/osm_router_get_node_ptr * NAME * osm_router_get_node_ptr * * DESCRIPTION * Returns a pointer to the Node object for this router. * * SYNOPSIS */ static inline osm_node_t *osm_router_get_node_ptr(IN const osm_router_t * p_rtr) { return p_rtr->p_port->p_node; } /* * PARAMETERS * p_rtr * [in] Pointer to an osm_router_t object. * * RETURN VALUES * Returns a pointer to the Node object for this router. * * NOTES * * SEE ALSO * Router object *********/ END_C_DECLS #endif /* _OSM_ROUTER_H_ */ opensm-3.3.20/include/opensm/osm_sa.h0000644000205000001450000003352312452603454014401 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_sa_t. * This object represents an IBA subnet. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SA_H_ #define _OSM_SA_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/SA * NAME * SA * * DESCRIPTION * The SA object encapsulates the information needed by the * OpenSM to instantiate subnet administration. The OpenSM * allocates one SA object per subnet manager. * * The SA object is thread safe. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * AUTHOR * Ranjit Pandit, Intel * Anil Keshavamurthy, Intel * *********/ /****d* OpenSM: SA/osm_sa_state_t * NAME * osm_sa_state_t * * DESCRIPTION * Enumerates the possible states of SA object. * * SYNOPSIS */ typedef enum _osm_sa_state { OSM_SA_STATE_INIT = 0, OSM_SA_STATE_READY } osm_sa_state_t; /***********/ /****d* OpenSM: SA/osm_mpr_rec_t * NAME * osm_mpr_rec_t * * DESCRIPTION * SA MultiPathRecord response. * * SYNOPSIS */ typedef struct osm_mpr_rec { ib_path_rec_t path_rec; const osm_port_t *p_src_port; const osm_port_t *p_dest_port; int hops; } osm_mpr_rec_t; /***********/ /****d* OpenSM: SA/osm_sa_item_t * NAME * osm_sa_item_t * * DESCRIPTION * SA response item. * * SYNOPSIS */ typedef struct osm_sa_item { cl_list_item_t list_item; union { char data[0]; ib_guidinfo_record_t guid_rec; ib_inform_info_t inform; ib_inform_info_record_t inform_rec; ib_lft_record_t lft_rec; ib_link_record_t link_rec; ib_member_rec_t mc_rec; ib_mft_record_t mft_rec; osm_mpr_rec_t mpr_rec; ib_node_record_t node_rec; ib_path_rec_t path_rec; ib_pkey_table_record_t pkey_rec; ib_portinfo_record_t port_rec; ib_service_record_t service_rec; ib_slvl_table_record_t slvl_rec; ib_sminfo_record_t sminfo_rec; ib_switch_info_record_t swinfo_rec; ib_vl_arb_table_record_t vlarb_rec; } resp; } osm_sa_item_t; /* * NOTES * Actual structure allocated is based on SA attribute * type. As such, it is variable sized. The allocation * occurs in the SA attribute handling code. * Note also that the size is specified external * to this structure (It's passed as a parameter to * osm_sa_respond). The SA_ITEM_RESP_SIZE macro * facilitates determining the size required. * ***********/ #define SA_ITEM_RESP_SIZE(_m) offsetof(osm_sa_item_t, resp._m) + \ sizeof(((osm_sa_item_t *)NULL)->resp._m) /****s* OpenSM: SM/osm_sa_t * NAME * osm_sa_t * * DESCRIPTION * Subnet Administration structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_sa { osm_sa_state_t state; osm_sm_t *sm; osm_subn_t *p_subn; osm_vendor_t *p_vendor; osm_log_t *p_log; osm_mad_pool_t *p_mad_pool; cl_dispatcher_t *p_disp; cl_dispatcher_t *p_set_disp; cl_plock_t *p_lock; atomic32_t sa_trans_id; osm_sa_mad_ctrl_t mad_ctrl; cl_timer_t sr_timer; boolean_t dirty; cl_disp_reg_handle_t cpi_disp_h; cl_disp_reg_handle_t nr_disp_h; cl_disp_reg_handle_t pir_disp_h; cl_disp_reg_handle_t gir_disp_h; cl_disp_reg_handle_t lr_disp_h; cl_disp_reg_handle_t pr_disp_h; cl_disp_reg_handle_t smir_disp_h; cl_disp_reg_handle_t mcmr_disp_h; cl_disp_reg_handle_t sr_disp_h; #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) cl_disp_reg_handle_t mpr_disp_h; #endif cl_disp_reg_handle_t infr_disp_h; cl_disp_reg_handle_t infir_disp_h; cl_disp_reg_handle_t vlarb_disp_h; cl_disp_reg_handle_t slvl_disp_h; cl_disp_reg_handle_t pkey_disp_h; cl_disp_reg_handle_t lft_disp_h; cl_disp_reg_handle_t sir_disp_h; cl_disp_reg_handle_t mft_disp_h; cl_disp_reg_handle_t infr_set_disp_h; cl_disp_reg_handle_t gir_set_disp_h; cl_disp_reg_handle_t mcmr_set_disp_h; cl_disp_reg_handle_t sr_set_disp_h; } osm_sa_t; /* * FIELDS * state * State of this SA object * * sm * Pointer to the Subnet Manager object. * * p_subn * Pointer to the Subnet object for this subnet. * * p_vendor * Pointer to the vendor specific interfaces object. * * p_log * Pointer to the log object. * * p_mad_pool * Pointer to the MAD pool. * * p_disp * Pointer to dispatcher * * p_set_disp * Pointer to dispatcher for Set requests. * * p_lock * Pointer to Lock for serialization * * sa_trans_id * Transaction ID * * mad_ctrl * Mad Controller * * dirty * A flag that denotes that SA DB is dirty and needs * to be written to the dump file (if dumping is enabled) * * SEE ALSO * SM object *********/ /****f* OpenSM: SA/osm_sa_construct * NAME * osm_sa_construct * * DESCRIPTION * This function constructs an SA object. * * SYNOPSIS */ void osm_sa_construct(IN osm_sa_t * p_sa); /* * PARAMETERS * p_sa * [in] Pointer to a SA object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_sa_destroy. * * Calling osm_sa_construct is a prerequisite to calling any other * method except osm_sa_init. * * SEE ALSO * SA object, osm_sa_init, osm_sa_destroy *********/ /****f* OpenSM: SA/osm_sa_shutdown * NAME * osm_sa_shutdown * * DESCRIPTION * The osm_sa_shutdown function shutdowns an SA, unregistering from all * dispatcher messages and unbinding the QP1 mad service * * SYNOPSIS */ void osm_sa_shutdown(IN osm_sa_t * p_sa); /* * PARAMETERS * p_sa * [in] Pointer to a SA object to shutdown. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * SA object, osm_sa_construct, osm_sa_init *********/ /****f* OpenSM: SA/osm_sa_destroy * NAME * osm_sa_destroy * * DESCRIPTION * The osm_sa_destroy function destroys an SA, releasing * all resources. * * SYNOPSIS */ void osm_sa_destroy(IN osm_sa_t * p_sa); /* * PARAMETERS * p_sa * [in] Pointer to a SA object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified SA object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_sa_construct or * osm_sa_init. * * SEE ALSO * SA object, osm_sa_construct, osm_sa_init *********/ /****f* OpenSM: SA/osm_sa_init * NAME * osm_sa_init * * DESCRIPTION * The osm_sa_init function initializes a SA object for use. * * SYNOPSIS */ ib_api_status_t osm_sa_init(IN osm_sm_t * p_sm, IN osm_sa_t * p_sa, IN osm_subn_t * p_subn, IN osm_vendor_t * p_vendor, IN osm_mad_pool_t * p_mad_pool, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_dispatcher_t * p_set_disp, IN cl_plock_t * p_lock); /* * PARAMETERS * p_sa * [in] Pointer to an osm_sa_t object to initialize. * * p_subn * [in] Pointer to the Subnet object for this subnet. * * p_vendor * [in] Pointer to the vendor specific interfaces object. * * p_mad_pool * [in] Pointer to the MAD pool. * * p_log * [in] Pointer to the log object. * * p_stats * [in] Pointer to the statistics object. * * p_disp * [in] Pointer to the OpenSM central Dispatcher. * * p_set_disp * [in] Pointer to the OpenSM Dispatcher for Set requests. * * p_lock * [in] Pointer to the OpenSM serializing lock. * * RETURN VALUES * CL_SUCCESS if the SA object was initialized successfully. * * NOTES * Allows calling other SA methods. * * SEE ALSO * SA object, osm_sa_construct, osm_sa_destroy *********/ /****f* OpenSM: SA/osm_sa_bind * NAME * osm_sa_bind * * DESCRIPTION * Binds the SA object to a port guid. * * SYNOPSIS */ ib_api_status_t osm_sa_bind(IN osm_sa_t * p_sa, IN ib_net64_t port_guid); /* * PARAMETERS * p_sa * [in] Pointer to an osm_sa_t object to bind. * * port_guid * [in] Local port GUID with which to bind. * * * RETURN VALUES * None * * NOTES * A given SA object can only be bound to one port at a time. * * SEE ALSO *********/ /****f* OpenSM: SA/osm_sa_send * NAME * osm_sa_send * * DESCRIPTION * Sends SA MAD via osm_vendor_send and maintains the QP1 sent statistic * * SYNOPSIS */ ib_api_status_t osm_sa_send(osm_sa_t *sa, IN osm_madw_t * p_madw, IN boolean_t resp_expected); /****f* IBA Base: Types/osm_sa_send_error * NAME * osm_sa_send_error * * DESCRIPTION * Sends a generic SA response with the specified error status. * The payload is simply replicated from the request MAD. * * SYNOPSIS */ void osm_sa_send_error(IN osm_sa_t * sa, IN const osm_madw_t * p_madw, IN ib_net16_t sa_status); /* * PARAMETERS * sa * [in] Pointer to an osm_sa_t object. * * p_madw * [in] Original MAD to which the response must be sent. * * sa_status * [in] Status to send in the response. * * RETURN VALUES * None. * * SEE ALSO * SA object *********/ /****f* OpenSM: SA/osm_sa_respond * NAME * osm_sa_respond * * DESCRIPTION * Sends SA MAD response */ void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size, cl_qlist_t *list); /* * PARAMETERS * sa * [in] Pointer to an osm_sa_t object. * * p_madw * [in] Original MAD to which the response must be sent. * * attr_size * [in] Size of this SA attribute. * * list * [in] List of attribute to respond - it will be freed after * sending. * * RETURN VALUES * None. * * SEE ALSO * SA object *********/ struct osm_opensm; /****f* OpenSM: SA/osm_sa_db_file_dump * NAME * osm_sa_db_file_dump * * DESCRIPTION * Dumps the SA DB to the dump file. * * SYNOPSIS */ int osm_sa_db_file_dump(struct osm_opensm *p_osm); /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object. * * RETURN VALUES * 0 if the SA DB was actually dumped * >0 if there was no need to dump the SA DB * <0 if some error occurred. * *********/ /****f* OpenSM: SA/osm_sa_db_file_load * NAME * osm_sa_db_file_load * * DESCRIPTION * Loads SA DB from the file. * * SYNOPSIS */ int osm_sa_db_file_load(struct osm_opensm *p_osm); /* * PARAMETERS * p_osm * [in] Pointer to an osm_opensm_t object. * * RETURN VALUES * 0 on success, other value on failure. * *********/ /****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_find_or_create_new_mgrp * NAME * osm_mcmr_rcv_find_or_create_new_mgrp * * DESCRIPTION * Create new Multicast group * * SYNOPSIS */ osm_mgrp_t *osm_mcmr_rcv_find_or_create_new_mgrp(IN osm_sa_t * sa, IN ib_net64_t comp_mask, IN ib_member_rec_t * p_recvd_mcmember_rec); /* * PARAMETERS * p_sa * [in] Pointer to an osm_sa_t object. * comp_mask * [in] SA query component mask * p_recvd_mcmember_rec * [in] Received Multicast member record * * RETURN VALUES * The pointer to MC group object found or created, NULL in case of errors * *********/ /** * The following expose functionality of osm_sa_path_record.c for internal use * by sub managers */ typedef struct osm_path_parms { ib_net16_t pkey; uint8_t mtu; uint8_t rate; uint8_t sl; uint8_t pkt_life; boolean_t reversible; int hops; } osm_path_parms_t; ib_api_status_t osm_get_path_params(IN osm_sa_t * sa, IN const osm_port_t * p_src_port, IN const uint16_t slid_ho, IN const osm_port_t * p_dest_port, IN const uint16_t dlid_ho, OUT osm_path_parms_t * p_parms); ib_net16_t osm_pr_get_end_points(IN osm_sa_t * sa, IN const ib_sa_mad_t *sa_mad, OUT const osm_alias_guid_t ** pp_src_alias_guid, OUT const osm_alias_guid_t ** pp_dest_alias_guid, OUT const osm_port_t ** pp_src_port, OUT const osm_port_t ** pp_dest_port, OUT const ib_gid_t ** pp_sgid, OUT const ib_gid_t ** pp_dgid); void osm_pr_process_pair(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_port_t * requester_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list); void osm_pr_process_half(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_port_t * requester_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list); END_C_DECLS #endif /* _OSM_SA_H_ */ opensm-3.3.20/include/opensm/osm_sa_mad_ctrl.h0000644000205000001450000002002712452603456016243 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_sa_mad_ctrl_t. * This object represents a controller that receives the IBA SA * attributes from a node. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SA_MAD_CTRL_H_ #define _OSM_SA_MAD_CTRL_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/SA MAD Controller * NAME * SA MAD Controller * * DESCRIPTION * The SA MAD Controller object encapsulates * the information needed to receive MADs from the transport layer. * * The SA MAD Controller object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Ranjit Pandit, Intel * *********/ struct osm_sa; /****s* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_t * NAME * osm_sa_mad_ctrl_t * * DESCRIPTION * SA MAD Controller structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_sa_mad_ctrl { struct osm_sa *sa; osm_log_t *p_log; osm_mad_pool_t *p_mad_pool; osm_vendor_t *p_vendor; osm_bind_handle_t h_bind; cl_dispatcher_t *p_disp; cl_dispatcher_t *p_set_disp; cl_disp_reg_handle_t h_disp; cl_disp_reg_handle_t h_set_disp; osm_stats_t *p_stats; osm_subn_t *p_subn; } osm_sa_mad_ctrl_t; /* * FIELDS * sa * Pointer to the SA object. * * p_log * Pointer to the log object. * * p_mad_pool * Pointer to the MAD pool. * * p_vendor * Pointer to the vendor specific interfaces object. * * h_bind * Bind handle returned by the transport layer. * * p_disp * Pointer to the Dispatcher. * * p_set_disp * Pointer to the Dispatcher for Set requests. * * h_disp * Handle returned from dispatcher registration. * * h_set_disp * Handle returned from Set requests dispatcher registration. * * p_stats * Pointer to the OpenSM statistics block. * * SEE ALSO * SA MAD Controller object * SA MADr object *********/ /****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_construct * NAME * osm_sa_mad_ctrl_construct * * DESCRIPTION * This function constructs a SA MAD Controller object. * * SYNOPSIS */ void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * p_ctrl); /* * PARAMETERS * p_ctrl * [in] Pointer to a SA MAD Controller * object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_sa_mad_ctrl_init, and osm_sa_mad_ctrl_destroy. * * Calling osm_sa_mad_ctrl_construct is a prerequisite to calling any other * method except osm_sa_mad_ctrl_init. * * SEE ALSO * SA MAD Controller object, osm_sa_mad_ctrl_init, * osm_sa_mad_ctrl_destroy *********/ /****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_destroy * NAME * osm_sa_mad_ctrl_destroy * * DESCRIPTION * The osm_sa_mad_ctrl_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * p_ctrl); /* * PARAMETERS * p_ctrl * [in] Pointer to the object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified * SA MAD Controller object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_sa_mad_ctrl_construct or osm_sa_mad_ctrl_init. * * SEE ALSO * SA MAD Controller object, osm_sa_mad_ctrl_construct, * osm_sa_mad_ctrl_init *********/ /****f* OpenSM: SA MAD Controller/osm_sa_mad_ctrl_init * NAME * osm_sa_mad_ctrl_init * * DESCRIPTION * The osm_sa_mad_ctrl_init function initializes a * SA MAD Controller object for use. * * SYNOPSIS */ ib_api_status_t osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * p_ctrl, IN struct osm_sa * sa, IN osm_mad_pool_t * p_mad_pool, IN osm_vendor_t * p_vendor, IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_dispatcher_t * p_set_disp); /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. * * sa * [in] Pointer to the SA object. * * p_mad_pool * [in] Pointer to the MAD pool. * * p_vendor * [in] Pointer to the vendor specific interfaces object. * * p_log * [in] Pointer to the log object. * * p_stats * [in] Pointer to the OpenSM stastics block. * * p_disp * [in] Pointer to the OpenSM central Dispatcher. * * p_set_disp * [in] Pointer to the OpenSM Dispatcher for Set requests. * * RETURN VALUES * IB_SUCCESS if the SA MAD Controller object was initialized * successfully. * * NOTES * Allows calling other SA MAD Controller methods. * * SEE ALSO * SA MAD Controller object, osm_sa_mad_ctrl_construct, * osm_sa_mad_ctrl_destroy *********/ /****f* OpenSM: SA/osm_sa_mad_ctrl_bind * NAME * osm_sa_mad_ctrl_bind * * DESCRIPTION * Binds the SA MAD Controller object to a port guid. * * SYNOPSIS */ ib_api_status_t osm_sa_mad_ctrl_bind(IN osm_sa_mad_ctrl_t * p_ctrl, IN ib_net64_t port_guid); /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. * * port_guid * [in] Local port GUID with which to bind. * * * RETURN VALUES * None * * NOTES * A given SA MAD Controller object can only be bound to one * port at a time. * * SEE ALSO *********/ /****f* OpenSM: SA/osm_sa_mad_ctrl_unbind * NAME * osm_sa_mad_ctrl_unbind * * DESCRIPTION * Un-Binds the SA MAD Controller object from the IB port * * SYNOPSIS */ ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * p_ctrl); /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sa_mad_ctrl_t object to initialize. * * RETURN VALUES * None * * NOTES * A given SA MAD Controller should be previously bound to IB * port. * * SEE ALSO *********/ /****f* OpenSM: SA/osm_sa_mad_ctrl_get_bind_handle * NAME * osm_sa_mad_ctrl_get_bind_handle * * DESCRIPTION * Returns the bind handle. * * SYNOPSIS */ static inline osm_bind_handle_t osm_sa_mad_ctrl_get_bind_handle(IN const osm_sa_mad_ctrl_t * p_ctrl) { return p_ctrl->h_bind; } /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sa_mad_ctrl_t object. * * RETURN VALUES * Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE * if no port has been bound. * * NOTES * A given SA MAD Controller object can only be bound to one * port at a time. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_SA_MAD_CTRL_H_ */ opensm-3.3.20/include/opensm/osm_service.h0000644000205000001450000001124312104655724015432 00000000000000/* * Copyright (c) 2004-2009 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. * */ #ifndef _OSM_SVCR_H_ #define _OSM_SVCR_H_ /* * Abstract: * Declaration of osm_service_rec_t. * This object represents an IBA Service Record. * This object is part of the OpenSM family of objects. */ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Service Record * NAME * Service Record * * DESCRIPTION * The service record encapsulates the information needed by the * SA to manage service registrations. * * The service records is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Anil S Keshavamurthy, Intel * *********/ /****s* OpenSM: Service Record/osm_svcr_t * NAME * osm_svcr_t * * DESCRIPTION * Service Record structure. * * The osm_svcr_t object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_svcr { cl_list_item_t list_item; ib_service_record_t service_record; uint32_t modified_time; uint32_t lease_period; } osm_svcr_t; /* * FIELDS * map_item * Map Item for qmap linkage. Must be first element!! * * svc_rec * IB Service record structure * * modified_time * Last modified time of this record in milliseconds * * lease_period * Remaining lease period for this record * * * SEE ALSO *********/ /****f* OpenSM: Service Record/osm_svcr_new * NAME * osm_svcr_new * * DESCRIPTION * Allocates and initializes a Service Record for use. * * SYNOPSIS */ osm_svcr_t *osm_svcr_new(IN const ib_service_record_t * p_svc_rec); /* * PARAMETERS * p_svc_rec * [in] Pointer to IB Service Record * * RETURN VALUES * pointer to osm_svcr_t structure. * * NOTES * Allows calling other service record methods. * * SEE ALSO * Service Record, osm_svcr_delete *********/ /****f* OpenSM: Service Record/osm_svcr_init * NAME * osm_svcr_init * * DESCRIPTION * Initializes the osm_svcr_t structure. * * SYNOPSIS */ void osm_svcr_init(IN osm_svcr_t * p_svcr, IN const ib_service_record_t * p_svc_rec); /* * PARAMETERS * p_svc_rec * [in] Pointer to osm_svcr_t structure * p_svc_rec * [in] Pointer to the ib_service_record_t * * SEE ALSO * Service Record *********/ /****f* OpenSM: Service Record/osm_svcr_delete * NAME * osm_svcr_delete * * DESCRIPTION * Deallocates the osm_svcr_t structure. * * SYNOPSIS */ void osm_svcr_delete(IN osm_svcr_t * p_svcr); /* * PARAMETERS * p_svc_rec * [in] Pointer to osm_svcr_t structure * * SEE ALSO * Service Record, osm_svcr_new *********/ osm_svcr_t *osm_svcr_get_by_rid(IN osm_subn_t const *p_subn, IN osm_log_t * p_log, IN ib_service_record_t * p_svc_rec); void osm_svcr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_svcr_t * p_svcr); void osm_svcr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_svcr_t * p_svcr); END_C_DECLS #endif /* _OSM_SVCR_H_ */ opensm-3.3.20/include/opensm/osm_sm.h0000644000205000001450000004353412305351147014414 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 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: * Declaration of osm_sm_t. * This object represents an IBA subnet. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SM_H_ #define _OSM_SM_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/SM * NAME * SM * * DESCRIPTION * The SM object encapsulates the information needed by the * OpenSM to instantiate a subnet manager. The OpenSM allocates * one SM object per subnet manager. * * The SM object is thread safe. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: SM/osm_sm_t * NAME * osm_sm_t * * DESCRIPTION * Subnet Manager structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_sm { osm_thread_state_t thread_state; unsigned signal_mask; cl_spinlock_t signal_lock; cl_spinlock_t state_lock; cl_event_t signal_event; cl_event_t subnet_up_event; cl_timer_t sweep_timer; cl_timer_t polling_timer; cl_event_wheel_t trap_aging_tracker; cl_thread_t sweeper; unsigned master_sm_found; uint32_t retry_number; ib_net64_t master_sm_guid; ib_net64_t polling_sm_guid; osm_subn_t *p_subn; osm_db_t *p_db; osm_vendor_t *p_vendor; osm_log_t *p_log; osm_mad_pool_t *p_mad_pool; osm_vl15_t *p_vl15; cl_dispatcher_t *p_disp; cl_plock_t *p_lock; atomic32_t sm_trans_id; uint16_t mlids_init_max; unsigned mlids_req_max; uint8_t *mlids_req; osm_sm_mad_ctrl_t mad_ctrl; osm_lid_mgr_t lid_mgr; osm_ucast_mgr_t ucast_mgr; cl_disp_reg_handle_t sweep_fail_disp_h; cl_disp_reg_handle_t ni_disp_h; cl_disp_reg_handle_t pi_disp_h; cl_disp_reg_handle_t gi_disp_h; cl_disp_reg_handle_t nd_disp_h; cl_disp_reg_handle_t si_disp_h; cl_disp_reg_handle_t lft_disp_h; cl_disp_reg_handle_t mft_disp_h; cl_disp_reg_handle_t sm_info_disp_h; cl_disp_reg_handle_t trap_disp_h; cl_disp_reg_handle_t slvl_disp_h; cl_disp_reg_handle_t vla_disp_h; cl_disp_reg_handle_t pkey_disp_h; cl_disp_reg_handle_t mlnx_epi_disp_h; } osm_sm_t; /* * FIELDS * p_subn * Pointer to the Subnet object for this subnet. * * p_db * Pointer to the database (persistency) object * * p_vendor * Pointer to the vendor specific interfaces object. * * p_log * Pointer to the log object. * * p_mad_pool * Pointer to the MAD pool. * * p_vl15 * Pointer to the VL15 interface. * * mad_ctrl * MAD Controller. * * p_disp * Pointer to the Dispatcher. * * p_lock * Pointer to the serializing lock. * * SEE ALSO * SM object *********/ /****f* OpenSM: SM/osm_sm_construct * NAME * osm_sm_construct * * DESCRIPTION * This function constructs an SM object. * * SYNOPSIS */ void osm_sm_construct(IN osm_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to a SM object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_sm_init, osm_sm_destroy * * Calling osm_sm_construct is a prerequisite to calling any other * method except osm_sm_init. * * SEE ALSO * SM object, osm_sm_init, osm_sm_destroy *********/ /****f* OpenSM: SM/osm_sm_shutdown * NAME * osm_sm_shutdown * * DESCRIPTION * The osm_sm_shutdown function shutdowns an SM, stopping the sweeper * and unregistering all messages from the dispatcher * * SYNOPSIS */ void osm_sm_shutdown(IN osm_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to a SM object to shutdown. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * SM object, osm_sm_construct, osm_sm_init *********/ /****f* OpenSM: SM/osm_sm_destroy * NAME * osm_sm_destroy * * DESCRIPTION * The osm_sm_destroy function destroys an SM, releasing * all resources. * * SYNOPSIS */ void osm_sm_destroy(IN osm_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to a SM object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified SM object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_sm_construct or * osm_sm_init. * * SEE ALSO * SM object, osm_sm_construct, osm_sm_init *********/ /****f* OpenSM: SM/osm_sm_init * NAME * osm_sm_init * * DESCRIPTION * The osm_sm_init function initializes a SM object for use. * * SYNOPSIS */ ib_api_status_t osm_sm_init(IN osm_sm_t * p_sm, IN osm_subn_t * p_subn, IN osm_db_t * p_db, IN osm_vendor_t * p_vendor, IN osm_mad_pool_t * p_mad_pool, IN osm_vl15_t * p_vl15, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_plock_t * p_lock); /* * PARAMETERS * p_sm * [in] Pointer to an osm_sm_t object to initialize. * * p_subn * [in] Pointer to the Subnet object for this subnet. * * p_vendor * [in] Pointer to the vendor specific interfaces object. * * p_mad_pool * [in] Pointer to the MAD pool. * * p_vl15 * [in] Pointer to the VL15 interface. * * p_log * [in] Pointer to the log object. * * p_stats * [in] Pointer to the statistics object. * * p_disp * [in] Pointer to the OpenSM central Dispatcher. * * p_lock * [in] Pointer to the OpenSM serializing lock. * * RETURN VALUES * IB_SUCCESS if the SM object was initialized successfully. * * NOTES * Allows calling other SM methods. * * SEE ALSO * SM object, osm_sm_construct, osm_sm_destroy *********/ /****f* OpenSM: SM/osm_sm_signal * NAME * osm_sm_signal * * DESCRIPTION * Signal event to SM * * SYNOPSIS */ void osm_sm_signal(IN osm_sm_t * p_sm, osm_signal_t signal); /* * PARAMETERS * p_sm * [in] Pointer to an osm_sm_t object. * * signal * [in] sm signal number. * * NOTES * * SEE ALSO * SM object *********/ /****f* OpenSM: SM/osm_sm_sweep * NAME * osm_sm_sweep * * DESCRIPTION * Initiates a subnet sweep. * * SYNOPSIS */ void osm_sm_sweep(IN osm_sm_t * p_sm); /* * PARAMETERS * p_sm * [in] Pointer to an osm_sm_t object. * * RETURN VALUES * IB_SUCCESS if the sweep completed successfully. * * NOTES * * SEE ALSO * SM object *********/ /****f* OpenSM: SM/osm_sm_bind * NAME * osm_sm_bind * * DESCRIPTION * Binds the sm object to a port guid. * * SYNOPSIS */ ib_api_status_t osm_sm_bind(IN osm_sm_t * p_sm, IN ib_net64_t port_guid); /* * PARAMETERS * p_sm * [in] Pointer to an osm_sm_t object to bind. * * port_guid * [in] Local port GUID with which to bind. * * * RETURN VALUES * None * * NOTES * A given SM object can only be bound to one port at a time. * * SEE ALSO *********/ /****f* OpenSM: SM/osm_req_get * NAME * osm_req_get * * DESCRIPTION * Starts the process to transmit a directed route request for * the attribute. * * SYNOPSIS */ ib_api_status_t osm_req_get(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * p_path * [in] Pointer to the directed route path to the node * from which to retrieve the attribute. * * attr_id * [in] Attribute ID to request. * * attr_mod * [in] Attribute modifier for this request. * * find_mkey * [in] Flag to indicate whether the M_Key should be looked up for * this MAD. * m_key * [in] M_Key value to be send with this MAD. Applied, only when * find_mkey is FALSE. * * err_msg * [in] Message id with which to post this MAD if an error occurs. * * p_context * [in] Mad wrapper context structure to be copied into the wrapper * context, and thus visible to the recipient of the response. * * RETURN VALUES * IB_SUCCESS if the request was successful. * * NOTES * This function asynchronously requests the specified attribute. * The response from the node will be routed through the Dispatcher * to the appropriate receive controller object. *********/ /****f* OpenSM: SM/osm_send_req_mad * NAME * osm_send_req_mad * * DESCRIPTION * Starts the process to transmit a preallocated/predefined directed route * Set() request. * * SYNOPSIS */ void osm_send_req_mad(IN osm_sm_t * sm, IN osm_madw_t *p_madw); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * p_madw * [in] Pointer to a preallocated MAD buffer * *********/ /***f* OpenSM: SM/osm_prepare_req_set * NAME * osm_prepare_req_set * * DESCRIPTION * Preallocate and fill a directed route Set() MAD w/o sending it. * * SYNOPSIS */ osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN const uint8_t * p_payload, IN size_t payload_size, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, IN ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * p_path * [in] Pointer to the directed route path of the recipient. * * p_payload * [in] Pointer to the SMP payload to send. * * payload_size * [in] The size of the payload to be copied to the SMP data field. * * attr_id * [in] Attribute ID to request. * * attr_mod * [in] Attribute modifier for this request. * * find_mkey * [in] Flag to indicate whether the M_Key should be looked up for * this MAD. * m_key * [in] M_Key value to be send with this MAD. Applied, only when * find_mkey is FALSE. * * err_msg * [in] Message id with which to post this MAD if an error occurs. * * p_context * [in] Mad wrapper context structure to be copied into the wrapper * context, and thus visible to the recipient of the response. * * RETURN VALUES * Pointer the MAD buffer in case of success and NULL in case of failure. * *********/ /****f* OpenSM: SM/osm_req_set * NAME * osm_req_set * * DESCRIPTION * Starts the process to transmit a directed route Set() request. * * SYNOPSIS */ ib_api_status_t osm_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN const uint8_t * p_payload, IN size_t payload_size, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, IN ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * p_path * [in] Pointer to the directed route path of the recipient. * * p_payload * [in] Pointer to the SMP payload to send. * * payload_size * [in] The size of the payload to be copied to the SMP data field. * * attr_id * [in] Attribute ID to request. * * attr_mod * [in] Attribute modifier for this request. * * find_mkey * [in] Flag to indicate whether the M_Key should be looked up for * this MAD. * * m_key * [in] M_Key value to be send with this MAD. Applied, only when * find_mkey is FALSE. * * err_msg * [in] Message id with which to post this MAD if an error occurs. * * p_context * [in] Mad wrapper context structure to be copied into the wrapper * context, and thus visible to the recipient of the response. * * RETURN VALUES * IB_SUCCESS if the request was successful. * * NOTES * This function asynchronously requests the specified attribute. * The response from the node will be routed through the Dispatcher * to the appropriate receive controller object. *********/ /****f* OpenSM: SM/osm_resp_send * NAME * osm_resp_send * * DESCRIPTION * Starts the process to transmit a directed route response. * * SYNOPSIS */ ib_api_status_t osm_resp_send(IN osm_sm_t * sm, IN const osm_madw_t * p_req_madw, IN ib_net16_t status, IN const uint8_t * p_payload); /* * PARAMETERS * p_resp * [in] Pointer to an osm_resp_t object. * * p_madw * [in] Pointer to the MAD Wrapper object for the requesting MAD * to which this response is generated. * * status * [in] Status for this response. * * p_payload * [in] Pointer to the payload of the response MAD. * * RETURN VALUES * IB_SUCCESS if the response was successful. * *********/ /****f* OpenSM: SM/osm_sm_reroute_mlid * NAME * osm_sm_reroute_mlid * * DESCRIPTION * Requests (schedules) MLID rerouting * * SYNOPSIS */ void osm_sm_reroute_mlid(osm_sm_t * sm, ib_net16_t mlid); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * mlid * [in] MLID value * * RETURN VALUES * None * * NOTES * * SEE ALSO *********/ /****f* OpenSM: OpenSM/osm_sm_wait_for_subnet_up * NAME * osm_sm_wait_for_subnet_up * * DESCRIPTION * Blocks the calling thread until the subnet is up. * * SYNOPSIS */ static inline cl_status_t osm_sm_wait_for_subnet_up(IN osm_sm_t * p_sm, IN uint32_t wait_us, IN boolean_t interruptible) { return cl_event_wait_on(&p_sm->subnet_up_event, wait_us, interruptible); } /* * PARAMETERS * p_sm * [in] Pointer to an osm_sm_t object. * * wait_us * [in] Number of microseconds to wait. * * interruptible * [in] Indicates whether the wait operation can be interrupted * by external signals. * * RETURN VALUES * CL_SUCCESS if the wait operation succeeded in response to the event * being set. * * CL_TIMEOUT if the specified time period elapses. * * CL_NOT_DONE if the wait was interrupted by an external signal. * * CL_ERROR if the wait operation failed. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: State Manager/osm_sm_is_greater_than * NAME * osm_sm_is_greater_than * * DESCRIPTION * Compares two SM's (14.4.1.2) * * SYNOPSIS */ static inline boolean_t osm_sm_is_greater_than(IN uint8_t l_priority, IN ib_net64_t l_guid, IN uint8_t r_priority, IN ib_net64_t r_guid) { return (l_priority > r_priority || (l_priority == r_priority && cl_ntoh64(l_guid) < cl_ntoh64(r_guid))); } /* * PARAMETERS * l_priority * [in] Priority of the SM on the "left" * * l_guid * [in] GUID of the SM on the "left" * * r_priority * [in] Priority of the SM on the "right" * * r_guid * [in] GUID of the SM on the "right" * * RETURN VALUES * Return TRUE if an sm with l_priority and l_guid is higher than an sm * with r_priority and r_guid, return FALSE otherwise. * * NOTES * * SEE ALSO * State Manager *********/ /****f* OpenSM: SM State Manager/osm_sm_state_mgr_process * NAME * osm_sm_state_mgr_process * * DESCRIPTION * Processes and maintains the states of the SM. * * SYNOPSIS */ ib_api_status_t osm_sm_state_mgr_process(IN osm_sm_t *sm, IN osm_sm_signal_t signal); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * signal * [in] Signal to the state SM engine. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * State Manager *********/ /****f* OpenSM: SM State Manager/osm_sm_state_mgr_signal_master_is_alive * NAME * osm_sm_state_mgr_signal_master_is_alive * * DESCRIPTION * Signals that the remote Master SM is alive. * Need to clear the retry_number variable. * * SYNOPSIS */ void osm_sm_state_mgr_signal_master_is_alive(IN osm_sm_t *sm); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * State Manager *********/ /****f* OpenSM: SM State Manager/osm_sm_state_mgr_check_legality * NAME * osm_sm_state_mgr_check_legality * * DESCRIPTION * Checks the legality of the signal received, according to the * current state of the SM state machine. * * SYNOPSIS */ ib_api_status_t osm_sm_state_mgr_check_legality(IN osm_sm_t *sm, IN osm_sm_signal_t signal); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * signal * [in] Signal to the state SM engine. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * State Manager *********/ void osm_report_sm_state(osm_sm_t *sm); /****f* OpenSM: SM State Manager/osm_send_trap144 * NAME * osm_send_trap144 * * DESCRIPTION * Send trap 144 to the master SM. * * SYNOPSIS */ int osm_send_trap144(osm_sm_t *sm, ib_net16_t local); /* * PARAMETERS * sm * [in] Pointer to an osm_sm_t object. * * local * [in] OtherLocalChanges mask in network byte order. * * RETURN VALUES * 0 on success, non-zero value otherwise. * *********/ void osm_set_sm_priority(osm_sm_t *sm, uint8_t priority); END_C_DECLS #endif /* _OSM_SM_H_ */ opensm-3.3.20/include/opensm/osm_sm_mad_ctrl.h0000644000205000001450000001704412104655724016263 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of osm_sm_mad_ctrl_t. * This object represents a controller that receives the IBA NodeInfo * attribute from a node. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SM_MAD_CTRL_H_ #define _OSM_SM_MAD_CTRL_H_ #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/SM MAD Controller * NAME * SM MAD Controller * * DESCRIPTION * The SM MAD Controller object encapsulates * the information needed to receive MADs from the transport layer. * * The SM MAD Controller object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_t * NAME * osm_sm_mad_ctrl_t * * DESCRIPTION * SM MAD Controller structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_sm_mad_ctrl { osm_log_t *p_log; osm_subn_t *p_subn; osm_mad_pool_t *p_mad_pool; osm_vl15_t *p_vl15; osm_vendor_t *p_vendor; osm_bind_handle_t h_bind; cl_plock_t *p_lock; cl_dispatcher_t *p_disp; cl_disp_reg_handle_t h_disp; osm_stats_t *p_stats; } osm_sm_mad_ctrl_t; /* * FIELDS * p_log * Pointer to the log object. * * p_subn * Pointer to the subnet object. * * p_mad_pool * Pointer to the MAD pool. * * p_vendor * Pointer to the vendor specific interfaces object. * * h_bind * Bind handle returned by the transport layer. * * p_lock * Pointer to the serializing lock. * * p_disp * Pointer to the Dispatcher. * * h_disp * Handle returned from dispatcher registration. * * p_stats * Pointer to the OpenSM statistics block. * * SEE ALSO * SM MAD Controller object * SM MADr object *********/ /****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_construct * NAME * osm_sm_mad_ctrl_construct * * DESCRIPTION * This function constructs a SM MAD Controller object. * * SYNOPSIS */ void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * p_ctrl); /* * PARAMETERS * p_ctrl * [in] Pointer to a SM MAD Controller * object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_sm_mad_ctrl_init, and osm_sm_mad_ctrl_destroy. * * Calling osm_sm_mad_ctrl_construct is a prerequisite to calling any other * method except osm_sm_mad_ctrl_init. * * SEE ALSO * SM MAD Controller object, osm_sm_mad_ctrl_init, * osm_sm_mad_ctrl_destroy *********/ /****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_destroy * NAME * osm_sm_mad_ctrl_destroy * * DESCRIPTION * The osm_sm_mad_ctrl_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * p_ctrl); /* * PARAMETERS * p_ctrl * [in] Pointer to the object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified * SM MAD Controller object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_sm_mad_ctrl_construct or osm_sm_mad_ctrl_init. * * SEE ALSO * SM MAD Controller object, osm_sm_mad_ctrl_construct, * osm_sm_mad_ctrl_init *********/ /****f* OpenSM: SM MAD Controller/osm_sm_mad_ctrl_init * NAME * osm_sm_mad_ctrl_init * * DESCRIPTION * The osm_sm_mad_ctrl_init function initializes a * SM MAD Controller object for use. * * SYNOPSIS */ ib_api_status_t osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_subn_t * p_subn, IN osm_mad_pool_t * p_mad_pool, IN osm_vl15_t * p_vl15, IN osm_vendor_t * p_vendor, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_plock_t * p_lock, IN cl_dispatcher_t * p_disp); /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sm_mad_ctrl_t object to initialize. * * p_mad_pool * [in] Pointer to the MAD pool. * * p_vl15 * [in] Pointer to the VL15 interface object. * * p_vendor * [in] Pointer to the vendor specific interfaces object. * * p_log * [in] Pointer to the log object. * * p_stats * [in] Pointer to the OpenSM stastics block. * * p_lock * [in] Pointer to the OpenSM serializing lock. * * p_disp * [in] Pointer to the OpenSM central Dispatcher. * * RETURN VALUES * IB_SUCCESS if the SM MAD Controller object was initialized * successfully. * * NOTES * Allows calling other SM MAD Controller methods. * * SEE ALSO * SM MAD Controller object, osm_sm_mad_ctrl_construct, * osm_sm_mad_ctrl_destroy *********/ /****f* OpenSM: SM/osm_sm_mad_ctrl_bind * NAME * osm_sm_mad_ctrl_bind * * DESCRIPTION * Binds the SM MAD Controller object to a port guid. * * SYNOPSIS */ ib_api_status_t osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * p_ctrl, IN ib_net64_t port_guid); /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sm_mad_ctrl_t object to initialize. * * port_guid * [in] Local port GUID with which to bind. * * * RETURN VALUES * None * * NOTES * A given SM MAD Controller object can only be bound to one * port at a time. * * SEE ALSO *********/ /****f* OpenSM: SM/osm_sm_mad_ctrl_get_bind_handle * NAME * osm_sm_mad_ctrl_get_bind_handle * * DESCRIPTION * Returns the bind handle. * * SYNOPSIS */ static inline osm_bind_handle_t osm_sm_mad_ctrl_get_bind_handle(IN const osm_sm_mad_ctrl_t * p_ctrl) { return p_ctrl->h_bind; } /* * PARAMETERS * p_ctrl * [in] Pointer to an osm_sm_mad_ctrl_t object. * * RETURN VALUES * Returns the bind handle, which may be OSM_BIND_INVALID_HANDLE * if no port has been bound. * * NOTES * A given SM MAD Controller object can only be bound to one * port at a time. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_SM_MAD_CTRL_H_ */ opensm-3.3.20/include/opensm/st.h0000644000205000001450000000632612104655724013550 00000000000000/* * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 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. * */ /* @(#) st.h 5.1 89/12/14 */ #ifndef ST_INCLUDED #define ST_INCLUDED #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define st_ptr_t uintptr_t typedef st_ptr_t st_data_t; #define ST_DATA_T_DEFINED typedef struct st_table st_table; struct st_hash_type { int (*compare) (void *, void *); st_ptr_t(*hash) (void *); }; struct st_table { struct st_hash_type *type; int num_bins; int num_entries; struct st_table_entry **bins; }; #define st_is_member(table,key) st_lookup(table,key,(st_data_t *)0) enum st_retval { ST_CONTINUE, ST_STOP, ST_DELETE }; st_table *st_init_table(struct st_hash_type *); st_table *st_init_table_with_size(struct st_hash_type *, size_t); st_table *st_init_numtable(void); st_table *st_init_numtable_with_size(size_t); st_table *st_init_strtable(void); st_table *st_init_strtable_with_size(size_t); int st_delete(st_table *, st_data_t *, st_data_t *); int st_delete_safe(st_table *, st_data_t *, st_data_t *, st_data_t); int st_insert(st_table *, st_data_t, st_data_t); int st_lookup(st_table *, st_data_t, st_data_t *); void st_foreach(st_table *, int (*)(st_data_t key, st_data_t val, st_data_t arg), st_data_t); void st_add_direct(st_table *, st_data_t, st_data_t); void st_free_table(st_table *); void st_cleanup_safe(st_table *, st_data_t); st_table *st_copy(st_table *); #define ST_NUMCMP ((int (*)()) 0) #define ST_NUMHASH ((int (*)()) -2) #define st_numcmp ST_NUMCMP #define st_numhash ST_NUMHASH /* int st_strhash(void); */ END_C_DECLS #endif /* ST_INCLUDED */ opensm-3.3.20/include/opensm/osm_stats.h0000644000205000001450000001166112104655724015134 00000000000000/* * Copyright (c) 2004-2008 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: * Declaration of osm_stats_t. * This object represents the OpenSM statistics object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_STATS_H_ #define _OSM_STATS_H_ #ifdef HAVE_LIBPTHREAD #include #else #include #endif #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Statistics * NAME * OpenSM * * DESCRIPTION * The OpenSM object encapsulates the information needed by the * OpenSM to track interesting traffic and internal statistics. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Statistics/osm_stats_t * NAME * osm_stats_t * * DESCRIPTION * OpenSM statistics block. * * SYNOPSIS */ typedef struct osm_stats { atomic32_t qp0_mads_outstanding; atomic32_t qp0_mads_outstanding_on_wire; atomic32_t qp0_mads_rcvd; atomic32_t qp0_mads_sent; atomic32_t qp0_unicasts_sent; atomic32_t qp0_mads_rcvd_unknown; atomic32_t sa_mads_outstanding; atomic32_t sa_mads_rcvd; atomic32_t sa_mads_sent; atomic32_t sa_mads_rcvd_unknown; atomic32_t sa_mads_ignored; #ifdef HAVE_LIBPTHREAD pthread_mutex_t mutex; pthread_cond_t cond; #else cl_event_t event; #endif } osm_stats_t; /* * FIELDS * qp0_mads_outstanding * Contains the number of MADs outstanding on QP0. * When this value reaches zero, OpenSM has discovered all * nodes on the subnet, and finished retrieving attributes. * At that time, subnet configuration may begin. * This variable must be manipulated using atomic instructions. * * qp0_mads_outstanding_on_wire * The number of MADs outstanding on the wire at any moment. * * qp0_mads_rcvd * Total number of QP0 MADs received. * * qp0_mads_sent * Total number of QP0 MADs sent. * * qp0_unicasts_sent * Total number of response-less MADs sent on the wire. This count * includes getresp(), send() and trap() methods. * * qp0_mads_rcvd_unknown * Total number of unknown QP0 MADs received. This includes * unrecognized attribute IDs and methods. * * sa_mads_outstanding * Contains the number of SA MADs outstanding on QP1. * * sa_mads_rcvd * Total number of SA MADs received. * * sa_mads_sent * Total number of SA MADs sent. * * sa_mads_rcvd_unknown * Total number of unknown SA MADs received. This includes * unrecognized attribute IDs and methods. * * sa_mads_ignored * Total number of SA MADs received because SM is not * master or SM is in first time sweep. * * SEE ALSO ***************/ static inline uint32_t osm_stats_inc_qp0_outstanding(osm_stats_t *stats) { uint32_t outstanding; #ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&stats->mutex); outstanding = ++stats->qp0_mads_outstanding; pthread_mutex_unlock(&stats->mutex); #else outstanding = cl_atomic_inc(&stats->qp0_mads_outstanding); #endif return outstanding; } static inline uint32_t osm_stats_dec_qp0_outstanding(osm_stats_t *stats) { uint32_t outstanding; #ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&stats->mutex); outstanding = --stats->qp0_mads_outstanding; if (!outstanding) pthread_cond_signal(&stats->cond); pthread_mutex_unlock(&stats->mutex); #else outstanding = cl_atomic_dec(&stats->qp0_mads_outstanding); if (!outstanding) cl_event_signal(&stats->event); #endif return outstanding; } END_C_DECLS #endif /* _OSM_STATS_H_ */ opensm-3.3.20/include/opensm/osm_subnet.h0000644000205000001450000012102412665335413015273 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. 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: * Declaration of osm_subn_t. * This object represents an IBA subnet. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SUBNET_H_ #define _OSM_SUBNET_H_ #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define OSM_SUBNET_VECTOR_MIN_SIZE 0 #define OSM_SUBNET_VECTOR_GROW_SIZE 1 #define OSM_SUBNET_VECTOR_CAPACITY 256 #define OSM_PARTITION_ENFORCE_BOTH "both" #define OSM_PARTITION_ENFORCE_IN "in" #define OSM_PARTITION_ENFORCE_OUT "out" #define OSM_PARTITION_ENFORCE_OFF "off" typedef enum _osm_partition_enforce_type_enum { OSM_PARTITION_ENFORCE_TYPE_BOTH, OSM_PARTITION_ENFORCE_TYPE_IN, OSM_PARTITION_ENFORCE_TYPE_OUT, OSM_PARTITION_ENFORCE_TYPE_OFF } osm_partition_enforce_type_enum; /* XXX: not actual max, max we're currently going to support */ #define OSM_CCT_ENTRY_MAX 128 #define OSM_CCT_ENTRY_MAD_BLOCKS (OSM_CCT_ENTRY_MAX/64) struct osm_opensm; struct osm_qos_policy; /****h* OpenSM/Subnet * NAME * Subnet * * DESCRIPTION * The Subnet object encapsulates the information needed by the * OpenSM to manage a subnet. The OpenSM allocates one Subnet object * per IBA subnet. * * The Subnet object is not thread safe, thus callers must provide * serialization. * * This object is essentially a container for the various components * of a subnet. Callers may directly access the member variables. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Subnet/osm_qos_options_t * NAME * osm_qos_options_t * * DESCRIPTION * Subnet QoS options structure. This structure contains the various * QoS specific configuration parameters for the subnet. * * SYNOPSIS */ typedef struct osm_qos_options { unsigned max_vls; int high_limit; char *vlarb_high; char *vlarb_low; char *sl2vl; } osm_qos_options_t; /* * FIELDS * * max_vls * The number of maximum VLs on the Subnet (0 == use default) * * high_limit * The limit of High Priority component of VL Arbitration * table (IBA 7.6.9) (-1 == use default) * * vlarb_high * High priority VL Arbitration table template. (NULL == use default) * * vlarb_low * Low priority VL Arbitration table template. (NULL == use default) * * sl2vl * SL2VL Mapping table (IBA 7.6.6) template. (NULL == use default) * *********/ /****s* OpenSM: Subnet/osm_cct_entry_t * NAME * osm_cct_entry_t * * DESCRIPTION * Subnet Congestion Control Table entry. See A10.2.2.1.1 for format details. * * SYNOPSIS */ typedef struct osm_cct_entry { uint8_t shift; //Alex: shift 2 bits uint16_t multiplier; //Alex multiplier 14 bits } osm_cct_entry_t; /* * FIELDS * * shift * shift field in CCT entry. See A10.2.2.1.1. * * multiplier * multiplier field in CCT entry. See A10.2.2.1.1. * *********/ /****s* OpenSM: Subnet/osm_cacongestion_entry_t * NAME * osm_cacongestion_entry_t * * DESCRIPTION * Subnet CA Congestion entry. See A10.4.3.8.4 for format details. * * SYNOPSIS */ typedef struct osm_cacongestion_entry { ib_net16_t ccti_timer; //Alex: ccti_timer and ccti_increase should be replaced uint8_t ccti_increase; uint8_t trigger_threshold; uint8_t ccti_min; } osm_cacongestion_entry_t; /* * FIELDS * * ccti_timer * CCTI Timer * * ccti_increase * CCTI Increase * * trigger_threshold * CCTI trigger for log message * * ccti_min * CCTI Minimum * *********/ /****s* OpenSM: Subnet/osm_cct_t * NAME * osm_cct_t * * DESCRIPTION * Subnet CongestionControlTable. See A10.4.3.9 for format details. * * SYNOPSIS */ typedef struct osm_cct { osm_cct_entry_t entries[OSM_CCT_ENTRY_MAX]; unsigned int entries_len; char *input_str; } osm_cct_t; /* * FIELDS * * entries * Entries in CCT * * entries_len * Length of entries * * input_str * Original str input * *********/ /****s* OpenSM: Subnet/osm_subn_opt_t * NAME * osm_subn_opt_t * * DESCRIPTION * Subnet options structure. This structure contains the various * site specific configuration parameters for the subnet. * * SYNOPSIS */ typedef struct osm_subn_opt { const char *config_file; ib_net64_t guid; ib_net64_t m_key; ib_net64_t sm_key; ib_net64_t sa_key; ib_net64_t subnet_prefix; ib_net16_t m_key_lease_period; uint8_t m_key_protect_bits; boolean_t m_key_lookup; uint32_t sweep_interval; uint32_t max_wire_smps; uint32_t max_wire_smps2; uint32_t max_smps_timeout; uint32_t transaction_timeout; uint32_t transaction_retries; uint8_t sm_priority; uint8_t lmc; boolean_t lmc_esp0; uint8_t max_op_vls; uint8_t force_link_speed; uint8_t force_link_speed_ext; uint8_t fdr10; boolean_t reassign_lids; boolean_t ignore_other_sm; boolean_t single_thread; boolean_t disable_multicast; boolean_t force_log_flush; uint8_t subnet_timeout; uint8_t packet_life_time; uint8_t vl_stall_count; uint8_t leaf_vl_stall_count; uint8_t head_of_queue_lifetime; uint8_t leaf_head_of_queue_lifetime; uint8_t local_phy_errors_threshold; uint8_t overrun_errors_threshold; boolean_t use_mfttop; uint32_t sminfo_polling_timeout; uint32_t polling_retry_number; uint32_t max_msg_fifo_timeout; boolean_t force_heavy_sweep; uint8_t log_flags; char *dump_files_dir; char *log_file; uint32_t log_max_size; char *partition_config_file; boolean_t no_partition_enforcement; char *part_enforce; osm_partition_enforce_type_enum part_enforce_enum; boolean_t allow_both_pkeys; uint8_t sm_assigned_guid; boolean_t qos; char *qos_policy_file; boolean_t suppress_sl2vl_mad_status_errors; boolean_t accum_log_file; char *console; uint16_t console_port; char *port_prof_ignore_file; char *hop_weights_file; char *port_search_ordering_file; boolean_t port_profile_switch_nodes; boolean_t sweep_on_trap; char *routing_engine_names; boolean_t use_ucast_cache; boolean_t connect_roots; char *lid_matrix_dump_file; char *lfts_file; char *root_guid_file; char *cn_guid_file; char *io_guid_file; boolean_t port_shifting; uint32_t scatter_ports; uint16_t max_reverse_hops; char *ids_guid_file; char *guid_routing_order_file; boolean_t guid_routing_order_no_scatter; char *sa_db_file; boolean_t sa_db_dump; char *torus_conf_file; boolean_t do_mesh_analysis; boolean_t exit_on_fatal; boolean_t honor_guid2lid_file; boolean_t daemon; boolean_t sm_inactive; boolean_t babbling_port_policy; boolean_t drop_event_subscriptions; boolean_t ipoib_mcgroup_creation_validation; boolean_t mcgroup_join_validation; boolean_t use_optimized_slvl; boolean_t fsync_high_avail_files; osm_qos_options_t qos_options; osm_qos_options_t qos_ca_options; osm_qos_options_t qos_sw0_options; osm_qos_options_t qos_swe_options; osm_qos_options_t qos_rtr_options; boolean_t congestion_control; ib_net64_t cc_key; uint32_t cc_max_outstanding_mads; ib_net32_t cc_sw_cong_setting_control_map; uint8_t cc_sw_cong_setting_victim_mask[IB_CC_PORT_MASK_DATA_SIZE]; uint8_t cc_sw_cong_setting_credit_mask[IB_CC_PORT_MASK_DATA_SIZE]; uint8_t cc_sw_cong_setting_threshold; uint8_t cc_sw_cong_setting_packet_size; uint8_t cc_sw_cong_setting_credit_starvation_threshold; osm_cct_entry_t cc_sw_cong_setting_credit_starvation_return_delay; ib_net16_t cc_sw_cong_setting_marking_rate; ib_net16_t cc_ca_cong_setting_port_control; ib_net16_t cc_ca_cong_setting_control_map; osm_cacongestion_entry_t cc_ca_cong_entries[IB_CA_CONG_ENTRY_DATA_SIZE]; osm_cct_t cc_cct; boolean_t enable_quirks; boolean_t no_clients_rereg; #ifdef ENABLE_OSM_PERF_MGR boolean_t perfmgr; boolean_t perfmgr_redir; uint16_t perfmgr_sweep_time_s; uint32_t perfmgr_max_outstanding_queries; boolean_t perfmgr_ignore_cas; char *event_db_dump_file; int perfmgr_rm_nodes; boolean_t perfmgr_log_errors; boolean_t perfmgr_query_cpi; boolean_t perfmgr_xmit_wait_log; uint32_t perfmgr_xmit_wait_threshold; #endif /* ENABLE_OSM_PERF_MGR */ char *event_plugin_name; char *event_plugin_options; char *node_name_map_name; char *prefix_routes_file; char *log_prefix; boolean_t consolidate_ipv6_snm_req; struct osm_subn_opt *file_opts; /* used for update */ uint8_t lash_start_vl; /* starting vl to use in lash */ uint8_t sm_sl; /* which SL to use for SM/SA communication */ char *per_module_logging_file; boolean_t quasi_ftree_indexing; } osm_subn_opt_t; /* * FIELDS * * config_file * The name of the config file. * * guid * The port guid that the SM is binding to. * * m_key * M_Key value sent to all ports qualifying all Set(PortInfo). * * sm_key * SM_Key value of the SM used for SM authentication. * * sa_key * SM_Key value to qualify rcv SA queries as "trusted". * * subnet_prefix * Subnet prefix used on this subnet. * * m_key_lease_period * The lease period used for the M_Key on this subnet. * * sweep_interval * The number of seconds between subnet sweeps. A value of 0 * disables sweeping. * * max_wire_smps * The maximum number of SMPs sent in parallel. Default is 4. * * max_wire_smps2 * The maximum number of timeout SMPs allowed to be outstanding. * Default is same as max_wire_smps which disables the timeout * mechanism. * * max_smps_timeout * The wait time in usec for timeout based SMPs. Default is * timeout * retries. * * transaction_timeout * The maximum time in milliseconds allowed for a transaction * to complete. Default is 200. * * transaction_retries * The number of retries for a transaction. Default is 3. * * sm_priority * The priority of this SM as specified by the user. This * value is made available in the SMInfo attribute. * * lmc * The LMC value used on this subnet. * * lmc_esp0 * Whether LMC value used on subnet should be used for * enhanced switch port 0 or not. If TRUE, it is used. * Otherwise (the default), LMC is set to 0 for ESP0. * * max_op_vls * Limit the maximal operational VLs. default is 1. * * reassign_lids * If TRUE cause all lids to be re-assigend. * Otherwise (the default), * OpenSM always tries to preserve as LIDs as much as possible. * * ignore_other_sm_option * This flag is TRUE if other SMs on the subnet should be ignored. * * disable_multicast * This flag is TRUE if OpenSM should disable multicast support. * * max_msg_fifo_timeout * The maximal time a message can stay in the incoming message * queue. If there is more than one message in the queue and the * last message stayed in the queue more than this value the SA * request will be immediately returned with a BUSY status. * * subnet_timeout * The subnet_timeout that will be set for all the ports in the * design SubnSet(PortInfo.vl_stall_life)) * * vl_stall_count * The number of sequential packets dropped that cause the port * to enter the VLStalled state. * * leaf_vl_stall_count * The number of sequential packets dropped that cause the port * to enter the VLStalled state. This is for switch ports driving * a CA or router port. * * head_of_queue_lifetime * The maximal time a packet can live at the head of a VL queue * on any port not driving a CA or router port. * * leaf_head_of_queue_lifetime * The maximal time a packet can live at the head of a VL queue * on switch ports driving a CA or router. * * local_phy_errors_threshold * Threshold of local phy errors for sending Trap 129 * * overrun_errors_threshold * Threshold of credits overrun errors for sending Trap 129 * * sminfo_polling_timeout * Specifies the polling timeout (in milliseconds) - the timeout * between one poll to another. * * packet_life_time * The maximal time a packet can stay in a switch. * The value is send to all switches as * SubnSet(SwitchInfo.life_state) * * dump_files_dir * The directory to be used for opensm-subnet.lst, opensm.fdbs, * opensm.mcfdbs, and default log file (the latter for Windows, * not Linux). * * log_file * Name of the log file (or NULL) for stdout. * * log_max_size * This option defines maximal log file size in MB. When * specified the log file will be truncated upon reaching * this limit. * * qos * Boolean that specifies whether the OpenSM QoS functionality * should be off or on. * * qos_policy_file * Name of the QoS policy file. * * accum_log_file * If TRUE (default) - the log file will be accumulated. * If FALSE - the log file will be erased before starting * current opensm run. * * port_prof_ignore_file * Name of file with port guids to be ignored by port profiling. * * port_profile_switch_nodes * If TRUE will count the number of switch nodes routed through * the link. If FALSE - only CA/RT nodes are counted. * * sweep_on_trap * Received traps will initiate a new sweep. * * routing_engine_names * Name of routing engine(s) to use. * * connect_roots * The option which will enforce root to root connectivity with * up/down and fat-tree routing engines (even if this violates * "pure" deadlock free up/down or fat-tree algorithm) * * use_ucast_cache * When TRUE enables unicast routing cache. * * lid_matrix_dump_file * Name of the lid matrix dump file from where switch * lid matrices (min hops tables) will be loaded * * lfts_file * Name of the unicast LFTs routing file from where switch * forwarding tables will be loaded * * root_guid_file * Name of the file that contains list of root guids that * will be used by fat-tree or up/dn routing (provided by User) * * cn_guid_file * Name of the file that contains list of compute node guids that * will be used by fat-tree routing (provided by User) * * io_guid_file * Name of the file that contains list of I/O node guids that * will be used by fat-tree routing (provided by User) * * port_shifting * This option will turn on port_shifting in routing. * * ids_guid_file * Name of the file that contains list of ids which should be * used by Up/Down algorithm instead of node GUIDs * * guid_routing_order_file * Name of the file that contains list of guids for routing order * that will be used by minhop and up/dn routing (provided by User). * * sa_db_file * Name of the SA database file. * * sa_db_dump * When TRUE causes OpenSM to dump SA DB at the end of every * light sweep regardless the current verbosity level. * * torus_conf_file * Name of the file with extra configuration info for torus-2QoS * routing engine. * * exit_on_fatal * If TRUE (default) - SM will exit on fatal subnet initialization * issues. * If FALSE - SM will not exit. * Fatal initialization issues: * a. SM recognizes 2 different nodes with the same guid, or * 12x link with lane reversal badly configured. * * honor_guid2lid_file * Always honor the guid2lid file if it exists and is valid. This * means that the file will be honored when SM is coming out of * STANDBY. By default this is FALSE. * * daemon * OpenSM will run in daemon mode. * * sm_inactive * OpenSM will start with SM in not active state. * * babbling_port_policy * OpenSM will enforce its "babbling" port policy. * * drop_event_subscriptions * OpenSM will drop event subscriptions if the port goes away. * * ipoib_mcgroup_creation_validation * OpenSM will validate IPoIB non-broadcast group parameters * against IPoIB broadcast group. * * mcgroup_join_validation * OpenSM will validate multicast join parameters against * multicast group parameters when MC group already exists. * * use_optimized_slvl * Use optimized SLtoVLMappingTable programming if * device indicates it supports this. * * fsync_high_avail_files * Synchronize high availability in memory files * with storage. * * perfmgr * Enable or disable the performance manager * * perfmgr_redir * Enable or disable the saving of redirection by PerfMgr * * perfmgr_sweep_time_s * Define the period (in seconds) of PerfMgr sweeps * * event_db_dump_file * File to dump the event database to * * event_plugin_name * Specify the name(s) of the event plugin(s) * * event_plugin_options * Options string that would be passed to the plugin(s) * * qos_options * Default set of QoS options * * qos_ca_options * QoS options for CA ports * * qos_sw0_options * QoS options for switches' port 0 * * qos_swe_options * QoS options for switches' external ports * * qos_rtr_options * QoS options for router ports * * congestion_control * Boolean that specifies whether OpenSM congestion control configuration * should be off or no. * * cc_key * CCkey to use when configuring congestion control. * * cc_max_outstanding_mads * Max number of outstanding CC mads that can be on the wire. * * cc_sw_cong_setting_control_map * Congestion Control Switch Congestion Setting Control Map * configuration setting. * * cc_sw_cong_setting_victim_mask * Congestion Control Switch Congestion Setting Victim Mask * configuration setting. * * cc_sw_cong_setting_credit_mask * Congestion Control Switch Congestion Setting Credit Mask * configuration setting. * * cc_sw_cong_setting_threshold * Congestion Control Switch Congestion Setting Threshold * configuration setting. * * cc_sw_cong_setting_packet_size * Congestion Control Switch Congestion Setting Packet Size * configuration setting. * * cc_sw_cong_setting_credit_starvation_threshold * Congestion Control Switch Congestion Setting Credit Starvation Threshold * configuration setting. * * cc_sw_cong_setting_credit_starvation_return_delay * Congestion Control Switch Congestion Setting Credit Starvation Return Delay * configuration setting. * * cc_sw_cong_setting_marking_rate * Congestion Control Switch Congestion Setting Marking Rate * configuration setting. * * cc_ca_cong_setting_port_control * Congestion Control CA Congestion Setting Port Control * * cc_ca_cong_setting_control_map * Congestion Control CA Congestion Setting Control Map * cc_ca_cong_entries * Congestion Control CA Congestion Setting Entries * * cc_cct * Congestion Control Table array of entries * * enable_quirks * Enable high risk new features and not fully qualified * hardware specific work arounds * * no_clients_rereg * When TRUE disables clients reregistration request * * scatter_ports * When not zero, randomize best possible ports chosen * for a route. The value is used as a random key seed. * * per_module_logging_file * File name of per module logging configuration. * * SEE ALSO * Subnet object *********/ /****s* OpenSM: Subnet/osm_subn_t * NAME * osm_subn_t * * DESCRIPTION * Subnet structure. Callers may directly access member components, * after grabbing a lock. * * TO DO * This structure should probably be volatile. * * SYNOPSIS */ typedef struct osm_subn { struct osm_opensm *p_osm; cl_qmap_t sw_guid_tbl; cl_qmap_t node_guid_tbl; cl_qmap_t port_guid_tbl; cl_qmap_t alias_port_guid_tbl; cl_qmap_t assigned_guids_tbl; cl_qmap_t rtr_guid_tbl; cl_qlist_t prefix_routes_list; cl_qmap_t prtn_pkey_tbl; cl_qmap_t sm_guid_tbl; cl_qlist_t sa_sr_list; cl_qlist_t sa_infr_list; cl_qlist_t alias_guid_list; cl_ptr_vector_t port_lid_tbl; ib_net16_t master_sm_base_lid; ib_net16_t sm_base_lid; ib_net64_t sm_port_guid; uint8_t last_sm_port_state; uint8_t sm_state; osm_subn_opt_t opt; struct osm_qos_policy *p_qos_policy; uint16_t max_ucast_lid_ho; uint16_t max_mcast_lid_ho; uint8_t min_ca_mtu; uint8_t min_ca_rate; uint8_t min_data_vls; uint8_t min_sw_data_vls; boolean_t ignore_existing_lfts; boolean_t subnet_initialization_error; boolean_t force_heavy_sweep; boolean_t force_reroute; boolean_t in_sweep_hop_0; boolean_t force_first_time_master_sweep; boolean_t first_time_master_sweep; boolean_t coming_out_of_standby; boolean_t sweeping_enabled; unsigned need_update; cl_fmap_t mgrp_mgid_tbl; osm_db_domain_t *p_g2m; osm_db_domain_t *p_neighbor; void *mboxes[IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1]; } osm_subn_t; /* * FIELDS * sw_guid_tbl * Container of pointers to all Switch objects in the subnet. * Indexed by node GUID. * * node_guid_tbl * Container of pointers to all Node objects in the subnet. * Indexed by node GUID. * * port_guid_tbl * Container of pointers to all Port objects in the subnet. * Indexed by port GUID. * * rtr_guid_tbl * Container of pointers to all Router objects in the subnet. * Indexed by node GUID. * * prtn_pkey_tbl * Container of pointers to all Partition objects in the subnet. * Indexed by P_KEY. * * sm_guid_tbl * Container of pointers to SM objects representing other SMs * on the subnet. * * port_lid_tbl * Container of pointers to all Port objects in the subnet. * Indexed by port LID. * * master_sm_base_lid * The base LID owned by the subnet's master SM. * * sm_base_lid * The base LID of the local port where the SM is. * * sm_port_guid * This SM's own port GUID. * * last_sm_port_state * Last state of this SM's port. * 0 is down and 1 is up. * * sm_state * The high-level state of the SM. This value is made available * in the SMInfo attribute. * * opt * Subnet options structure contains site specific configuration. * * p_qos_policy * Subnet QoS policy structure. * * max_ucast_lid_ho * The minimal max unicast lid reported by all switches * * max_mcast_lid_ho * The minimal max multicast lid reported by all switches * * min_ca_mtu * The minimal MTU reported by all CAs ports on the subnet * * min_ca_rate * The minimal rate reported by all CA ports on the subnet * * ignore_existing_lfts * This flag is a dynamic flag to instruct the LFT assignment to * ignore existing legal LFT settings. * The value will be set according to : * - Any change to the list of switches will set it to high * - Coming out of STANDBY it will be cleared (other SM worked) * - Set to FALSE upon end of all lft assignments. * * subnet_initalization_error * Similar to the force_heavy_sweep flag. If TRUE - means that * we had errors during initialization (due to SubnSet requests * that failed). We want to declare the subnet as unhealthy, and * force another heavy sweep. * * force_heavy_sweep * If TRUE - we want to force a heavy sweep. This can be done * either due to receiving of trap - meaning there is some change * on the subnet, or we received a handover from a remote sm. * In this case we want to sweep and reconfigure the entire * subnet. This will cause another heavy sweep to occure when * the current sweep is done. * * force_reroute * If TRUE - we want to force switches in the fabric to be * rerouted. * * in_sweep_hop_0 * When in_sweep_hop_0 flag is set to TRUE - this means we are * in sweep_hop_0 - meaning we do not want to continue beyond * the current node. * This is relevant for the case of SM on switch, since in the * switch info we need to signal somehow not to continue * the sweeping. * * force_first_time_master_sweep * This flag is used to avoid race condition when Master SM being * in the middle of very long configuration stage of the heavy sweep, * receives HANDOVER from another MASTER SM. When the current heavy sweep * is finished, new heavy sweep will be started immediately. * At the beginning of the sweep, opensm will set first_time_master_sweep, * force_heavy_sweep and coming_out_of_standby flags in order to allow full * reconfiguration of the fabric. This is required as another MASTER SM could * change configuration of the fabric before sending HANDOVER to MASTER SM. * * first_time_master_sweep * This flag is used for the PortInfo setting. On the first * sweep as master (meaning after moving from Standby|Discovering * state), the SM must send a PortInfoSet to all ports. After * that - we want to minimize the number of PortInfoSet requests * sent, and to send only requests that change the value from * what is updated in the port (or send a first request if this * is a new port). We will set this flag to TRUE when entering * the master state, and set it back to FALSE at the end of the * drop manager. This is done since at the end of the drop manager * we have updated all the ports that are reachable, and from now * on these are the only ports we have data of. We don't want * to send extra set requests to these ports anymore. * * coming_out_of_standby * TRUE on the first sweep after the SM was in standby. * Used for nulling any cache of LID and Routing. * The flag is set true if the SM state was standby and now * changed to MASTER it is reset at the end of the sweep. * * sweeping_enabled * FALSE - sweeping is administratively disabled, all * sweeping is inhibited, TRUE - sweeping is done * normally * * need_update * This flag should be on during first non-master heavy * (including pre-master discovery stage) * * mgrp_mgid_tbl * Container of pointers to all Multicast group objects in * the subnet. Indexed by MGID. * * mboxes * Array of pointers to all Multicast MLID box objects in the * subnet. Indexed by MLID offset from base MLID. * * SEE ALSO * Subnet object *********/ /****s* OpenSM: Subnet/osm_assigned_guids_t * NAME * osm_assigned_guids_t * * DESCRIPTION * SA assigned GUIDs structure. * * SYNOPSIS */ typedef struct osm_assigned_guids { cl_map_item_t map_item; ib_net64_t port_guid; ib_net64_t assigned_guid[1]; } osm_assigned_guids_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * port_guid * Base port GUID. * * assigned_guids * Table of persistent SA assigned GUIDs. * * SEE ALSO * Subnet object *********/ /****f* OpenSM: Subnet/osm_subn_construct * NAME * osm_subn_construct * * DESCRIPTION * This function constructs a Subnet object. * * SYNOPSIS */ void osm_subn_construct(IN osm_subn_t * p_subn); /* * PARAMETERS * p_subn * [in] Pointer to a Subnet object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_subn_init, and osm_subn_destroy. * * Calling osm_subn_construct is a prerequisite to calling any other * method except osm_subn_init. * * SEE ALSO * Subnet object, osm_subn_init, osm_subn_destroy *********/ /****f* OpenSM: Subnet/osm_subn_destroy * NAME * osm_subn_destroy * * DESCRIPTION * The osm_subn_destroy function destroys a subnet, releasing * all resources. * * SYNOPSIS */ void osm_subn_destroy(IN osm_subn_t * p_subn); /* * PARAMETERS * p_subn * [in] Pointer to a Subnet object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified Subnet object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_subn_construct * or osm_subn_init. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_init *********/ /****f* OpenSM: Subnet/osm_subn_init * NAME * osm_subn_init * * DESCRIPTION * The osm_subn_init function initializes a Subnet object for use. * * SYNOPSIS */ ib_api_status_t osm_subn_init(IN osm_subn_t * p_subn, IN struct osm_opensm *p_osm, IN const osm_subn_opt_t * p_opt); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object to initialize. * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * IB_SUCCESS if the Subnet object was initialized successfully. * * NOTES * Allows calling other Subnet methods. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy *********/ /* Forward references. */ struct osm_mad_addr; struct osm_log; struct osm_switch; struct osm_physp; struct osm_port; struct osm_mgrp; /****f* OpenSM: Helper/osm_get_gid_by_mad_addr * NAME * osm_get_gid_by_mad_addr * * DESCRIPTION * Looks for the requester gid in the mad address. * * Note: This code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ ib_api_status_t osm_get_gid_by_mad_addr(IN struct osm_log *p_log, IN const osm_subn_t * p_subn, IN struct osm_mad_addr *p_mad_addr, OUT ib_gid_t * p_gid); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to subnet object. * * p_mad_addr * [in] Pointer to mad address object. * * p_gid * [out] Pointer to the GID structure to fill in. * * RETURN VALUES * IB_SUCCESS if able to find the GID by address given. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_get_physp_by_mad_addr * NAME * osm_get_physp_by_mad_addr * * DESCRIPTION * Looks for the requester physical port in the mad address. * * Note: This code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_physp *osm_get_physp_by_mad_addr(IN struct osm_log *p_log, IN const osm_subn_t * p_subn, IN struct osm_mad_addr *p_mad_addr); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to subnet object. * * p_mad_addr * [in] Pointer to mad address object. * * RETURN VALUES * Pointer to requester physical port object if found. Null otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Helper/osm_get_port_by_mad_addr * NAME * osm_get_port_by_mad_addr * * DESCRIPTION * Looks for the requester port in the mad address. * * Note: This code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_port *osm_get_port_by_mad_addr(IN struct osm_log *p_log, IN const osm_subn_t * p_subn, IN struct osm_mad_addr *p_mad_addr); /* * PARAMETERS * p_log * [in] Pointer to a log object. * * p_subn * [in] Pointer to subnet object. * * p_mad_addr * [in] Pointer to mad address object. * * RETURN VALUES * Pointer to requester port object if found. Null otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Subnet/osm_get_switch_by_guid * NAME * osm_get_switch_by_guid * * DESCRIPTION * Looks for the given switch guid in the subnet table of switches by guid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_switch *osm_get_switch_by_guid(IN const osm_subn_t * p_subn, IN ib_net64_t guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * guid * [in] The node guid in network byte order * * RETURN VALUES * The switch structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy, * osm_switch_t *********/ /****f* OpenSM: Subnet/osm_get_node_by_guid * NAME * osm_get_node_by_guid * * DESCRIPTION * This looks for the given node guid in the subnet table of nodes by guid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_node *osm_get_node_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * guid * [in] The node guid in network byte order * * RETURN VALUES * The node structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy, * osm_node_t *********/ /****f* OpenSM: Subnet/osm_get_port_by_guid * NAME * osm_get_port_by_guid * * DESCRIPTION * This looks for the given port guid in the subnet table of ports by guid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_port *osm_get_port_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * guid * [in] The port guid in network order * * RETURN VALUES * The port structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy, * osm_port_t *********/ /****f* OpenSM: Port/osm_get_port_by_lid_ho * NAME * osm_get_port_by_lid_ho * * DESCRIPTION * Returns a pointer of the port object for given lid value. * * SYNOPSIS */ struct osm_port *osm_get_port_by_lid_ho(const osm_subn_t * subn, uint16_t lid); /* * PARAMETERS * subn * [in] Pointer to the subnet data structure. * * lid * [in] LID requested in host byte order. * * RETURN VALUES * The port structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_port_t *********/ /****f* OpenSM: Subnet/osm_get_alias_guid_by_guid * NAME * osm_get_alias_guid_by_guid * * DESCRIPTION * This looks for the given port guid in the subnet table of ports by * alias guid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_alias_guid *osm_get_alias_guid_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * guid * [in] The alias port guid in network order * * RETURN VALUES * The alias guid structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy, * osm_alias_guid_t *********/ /****f* OpenSM: Subnet/osm_get_port_by_alias_guid * NAME * osm_get_port_by_alias_guid * * DESCRIPTION * This looks for the given port guid in the subnet table of ports by * alias guid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_port *osm_get_port_by_alias_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * guid * [in] The alias port guid in network order * * RETURN VALUES * The port structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy, * osm_port_t *********/ /****f* OpenSM: Port/osm_assigned_guids_new * NAME * osm_assigned_guids_new * * DESCRIPTION * This function allocates and initializes an assigned guids object. * * SYNOPSIS */ osm_assigned_guids_t *osm_assigned_guids_new(IN const ib_net64_t port_guid, IN const uint32_t num_guids); /* * PARAMETERS * port_guid * [in] Base port GUID in network order * * RETURN VALUE * Pointer to the initialized assigned alias guid object. * * SEE ALSO * Subnet object, osm_assigned_guids_t, osm_assigned_guids_delete, * osm_get_assigned_guids_by_guid *********/ /****f* OpenSM: Port/osm_assigned_guids_delete * NAME * osm_assigned_guids_delete * * DESCRIPTION * This function destroys and deallocates an assigned guids object. * * SYNOPSIS */ void osm_assigned_guids_delete(IN OUT osm_assigned_guids_t ** pp_assigned_guids); /* * PARAMETERS * pp_assigned_guids * [in][out] Pointer to a pointer to an assigned guids object to delete. * On return, this pointer is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified assigned guids object. * * SEE ALSO * Subnet object, osm_assigned_guids_new, osm_get_assigned_guids_by_guid *********/ /****f* OpenSM: Subnet/osm_get_assigned_guids_by_guid * NAME * osm_get_assigned_guids_by_guid * * DESCRIPTION * This looks for the given port guid and returns a pointer * to the guid table of SA assigned alias guids for that port. * * SYNOPSIS */ osm_assigned_guids_t *osm_get_assigned_guids_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t port_guid); /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * port_guid * [in] The base port guid in network order * * RETURN VALUES * The osm_assigned_guids structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_assigned_guids_new, osm_assigned_guids_delete, * osm_assigned_guids_t *********/ /****f* OpenSM: Port/osm_get_port_by_lid * NAME * osm_get_port_by_lid * * DESCRIPTION * Returns a pointer of the port object for given lid value. * * SYNOPSIS */ static inline struct osm_port *osm_get_port_by_lid(IN osm_subn_t const * subn, IN ib_net16_t lid) { return osm_get_port_by_lid_ho(subn, cl_ntoh16(lid)); } /* * PARAMETERS * subn * [in] Pointer to the subnet data structure. * * lid * [in] LID requested in network byte order. * * RETURN VALUES * The port structure pointer if found. NULL otherwise. * * SEE ALSO * Subnet object, osm_port_t *********/ /****f* OpenSM: Subnet/osm_get_mgrp_by_mgid * NAME * osm_get_mgrp_by_mgid * * DESCRIPTION * This looks for the given multicast group in the subnet table by mgid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ struct osm_mgrp *osm_get_mgrp_by_mgid(IN osm_subn_t * subn, IN ib_gid_t * mgid); /* * PARAMETERS * subn * [in] Pointer to an osm_subn_t object * * mgid * [in] The multicast group MGID value * * RETURN VALUES * The multicast group structure pointer if found. NULL otherwise. *********/ /****f* OpenSM: Subnet/osm_get_mbox_by_mlid * NAME * osm_get_mbox_by_mlid * * DESCRIPTION * This looks for the given multicast group in the subnet table by mlid. * NOTE: this code is not thread safe. Need to grab the lock before * calling it. * * SYNOPSIS */ static inline struct osm_mgrp_box *osm_get_mbox_by_mlid(osm_subn_t const *p_subn, ib_net16_t mlid) { return (struct osm_mgrp_box *)p_subn->mboxes[cl_ntoh16(mlid) - IB_LID_MCAST_START_HO]; } /* * PARAMETERS * p_subn * [in] Pointer to an osm_subn_t object * * mlid * [in] The multicast group mlid in network order * * RETURN VALUES * The multicast group structure pointer if found. NULL otherwise. *********/ int is_mlnx_ext_port_info_supported(ib_net16_t devid); /****f* OpenSM: Subnet/osm_subn_set_default_opt * NAME * osm_subn_set_default_opt * * DESCRIPTION * The osm_subn_set_default_opt function sets the default options. * * SYNOPSIS */ void osm_subn_set_default_opt(IN osm_subn_opt_t * p_opt); /* * PARAMETERS * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * None * * NOTES * * SEE ALSO * Subnet object, osm_subn_construct, osm_subn_destroy *********/ /****f* OpenSM: Subnet/osm_subn_parse_conf_file * NAME * osm_subn_parse_conf_file * * DESCRIPTION * The osm_subn_parse_conf_file function parses the configuration file * and sets the defaults accordingly. * * SYNOPSIS */ int osm_subn_parse_conf_file(const char *conf_file, osm_subn_opt_t * p_opt); /* * PARAMETERS * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * 0 on success, positive value if file doesn't exist, * negative value otherwise *********/ /****f* OpenSM: Subnet/osm_subn_rescan_conf_files * NAME * osm_subn_rescan_conf_files * * DESCRIPTION * The osm_subn_rescan_conf_files function parses the configuration * files and update selected subnet options * * SYNOPSIS */ int osm_subn_rescan_conf_files(IN osm_subn_t * p_subn); /* * PARAMETERS * * p_subn * [in] Pointer to the subnet structure. * * RETURN VALUES * 0 on success, positive value if file doesn't exist, * negative value otherwise * *********/ /****f* OpenSM: Subnet/osm_subn_output_conf * NAME * osm_subn_output_conf * * DESCRIPTION * Output configuration info * * SYNOPSIS */ void osm_subn_output_conf(FILE *out, IN osm_subn_opt_t * p_opt); /* * PARAMETERS * * out * [in] File stream to output to. * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * This method does not return a value *********/ /****f* OpenSM: Subnet/osm_subn_write_conf_file * NAME * osm_subn_write_conf_file * * DESCRIPTION * Write the configuration file into the cache * * SYNOPSIS */ int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t * p_opt); /* * PARAMETERS * * p_opt * [in] Pointer to the subnet options structure. * * RETURN VALUES * 0 on success, negative value otherwise * * NOTES * Assumes the conf file is part of the cache dir which defaults to * OSM_DEFAULT_CACHE_DIR or OSM_CACHE_DIR the name is opensm.opts *********/ int osm_subn_verify_config(osm_subn_opt_t * p_opt); END_C_DECLS #endif /* _OSM_SUBNET_H_ */ opensm-3.3.20/include/opensm/osm_switch.h0000644000205000001450000006120312571605761015300 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2009 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: * Declaration of osm_switch_t. * This object represents an IBA switch. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_SWITCH_H_ #define _OSM_SWITCH_H_ #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Switch * NAME * Switch * * DESCRIPTION * The Switch object encapsulates the information needed by the * OpenSM to manage switches. The OpenSM allocates one switch object * per switch in the IBA subnet. * * The Switch object is not thread safe, thus callers must provide * serialization. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Switch/osm_switch_t * NAME * osm_switch_t * * DESCRIPTION * Switch structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_switch { cl_map_item_t map_item; osm_node_t *p_node; ib_switch_info_t switch_info; uint16_t max_lid_ho; uint8_t num_ports; uint16_t num_hops; uint8_t **hops; osm_port_profile_t *p_prof; uint8_t *search_ordering_ports; uint8_t *lft; uint8_t *new_lft; uint16_t lft_size; osm_mcast_tbl_t mcast_tbl; int32_t mft_block_num; uint32_t mft_position; unsigned endport_links; unsigned need_update; void *priv; cl_map_item_t mgrp_item; uint32_t num_of_mcm; uint8_t is_mc_member; } osm_switch_t; /* * FIELDS * map_item * Linkage structure for cl_qmap. MUST BE FIRST MEMBER! * * p_node * Pointer to the Node object for this switch. * * switch_info * IBA defined SwitchInfo structure for this switch. * * max_lid_ho * Max LID that is accessible from this switch. * * num_ports * Number of ports for this switch. * * num_hops * Size of hops table for this switch. * * hops * LID Matrix for this switch containing the hop count * to every LID from every port. * * p_prof * Pointer to array of Port Profile objects for this switch. * * lft * This switch's linear forwarding table. * * new_lft * This switch's linear forwarding table, as was * calculated by the last routing engine execution. * * mcast_tbl * Multicast forwarding table for this switch. * * need_update * When set indicates that switch was probably reset, so * fwd tables and rest cached data should be flushed * * mgrp_item * map item for switch in building mcast tree * * num_of_mcm * number of mcast members(ports) connected to switch * * is_mc_member * whether switch is a mcast member itself * * SEE ALSO * Switch object *********/ /****s* OpenSM: Switch/struct osm_remote_guids_count * NAME * struct osm_remote_guids_count * * DESCRIPTION * Stores array of pointers to remote node and the numbers of * times a switch has forwarded to it. * * SYNOPSIS */ struct osm_remote_guids_count { unsigned count; struct osm_remote_node { osm_node_t *node; unsigned forwarded_to; uint8_t port; } guids[0]; }; /* * FIELDS * count * A number of used entries in array. * * node * A pointer to node. * * forwarded_to * A count of lids forwarded to this node. * * port * Port number on the node. *********/ /****f* OpenSM: Switch/osm_switch_delete * NAME * osm_switch_delete * * DESCRIPTION * Destroys and deallocates the object. * * SYNOPSIS */ void osm_switch_delete(IN OUT osm_switch_t ** pp_sw); /* * PARAMETERS * p_sw * [in] Pointer to the object to destroy. * * RETURN VALUE * None. * * NOTES * * SEE ALSO * Switch object, osm_switch_new *********/ /****f* OpenSM: Switch/osm_switch_new * NAME * osm_switch_new * * DESCRIPTION * The osm_switch_new function initializes a Switch object for use. * * SYNOPSIS */ osm_switch_t *osm_switch_new(IN osm_node_t * p_node, IN const osm_madw_t * p_madw); /* * PARAMETERS * p_node * [in] Pointer to the node object of this switch * * p_madw * [in] Pointer to the MAD Wrapper containing the switch's * SwitchInfo attribute. * * RETURN VALUES * Pointer to the new initialized switch object. * * NOTES * * SEE ALSO * Switch object, osm_switch_delete *********/ /****f* OpenSM: Switch/osm_switch_get_hop_count * NAME * osm_switch_get_hop_count * * DESCRIPTION * Returns the hop count at the specified LID/Port intersection. * * SYNOPSIS */ static inline uint8_t osm_switch_get_hop_count(IN const osm_switch_t * p_sw, IN uint16_t lid_ho, IN uint8_t port_num) { return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ? OSM_NO_PATH : p_sw->hops[lid_ho][port_num]; } /* * PARAMETERS * p_sw * [in] Pointer to a Switch object. * * lid_ho * [in] LID value (host order) for which to return the hop count * * port_num * [in] Port number in the switch * * RETURN VALUES * Returns the hop count at the specified LID/Port intersection. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_set_hops * NAME * osm_switch_set_hops * * DESCRIPTION * Sets the hop count at the specified LID/Port intersection. * * SYNOPSIS */ cl_status_t osm_switch_set_hops(IN osm_switch_t * p_sw, IN uint16_t lid_ho, IN uint8_t port_num, IN uint8_t num_hops); /* * PARAMETERS * p_sw * [in] Pointer to a Switch object. * * lid_ho * [in] LID value (host order) for which to set the count. * * port_num * [in] port number for which to set the count. * * num_hops * [in] value to assign to this entry. * * RETURN VALUES * Returns 0 if successfull. -1 if it failed * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_clear_hops * NAME * osm_switch_clear_hops * * DESCRIPTION * Cleanup existing hops tables (lid matrix) * * SYNOPSIS */ void osm_switch_clear_hops(IN osm_switch_t * p_sw); /* * PARAMETERS * p_sw * [in] Pointer to a Switch object. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_least_hops * NAME * osm_switch_get_least_hops * * DESCRIPTION * Returns the number of hops in the short path to this lid from * any port on the switch. * * SYNOPSIS */ static inline uint8_t osm_switch_get_least_hops(IN const osm_switch_t * p_sw, IN uint16_t lid_ho) { return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ? OSM_NO_PATH : p_sw->hops[lid_ho][0]; } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * lid_ho * [in] LID (host order) for which to retrieve the shortest hop count. * * RETURN VALUES * Returns the number of hops in the short path to this lid from * any port on the switch. * * NOTES * * SEE ALSO * Switch object *********/ /****f* OpenSM: Switch/osm_switch_get_port_least_hops * NAME * osm_switch_get_port_least_hops * * DESCRIPTION * Returns the number of hops in the short path to this port from * any port on the switch. * * SYNOPSIS */ uint8_t osm_switch_get_port_least_hops(IN const osm_switch_t * p_sw, IN const osm_port_t * p_port); /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * p_port * [in] Pointer to an osm_port_t object for which to * retrieve the shortest hop count. * * RETURN VALUES * Returns the number of hops in the short path to this lid from * any port on the switch. * * NOTES * * SEE ALSO * Switch object *********/ /****d* OpenSM: osm_lft_type_enum * NAME * osm_lft_type_enum * * DESCRIPTION * Enumerates LFT sets types of a switch. * * SYNOPSIS */ typedef enum osm_lft_type_enum { OSM_LFT = 0, OSM_NEW_LFT } osm_lft_type_enum; /***********/ /****f* OpenSM: Switch/osm_switch_get_port_by_lid * NAME * osm_switch_get_port_by_lid * * DESCRIPTION * Returns the switch port number on which the specified LID is routed. * * SYNOPSIS */ static inline uint8_t osm_switch_get_port_by_lid(IN const osm_switch_t * p_sw, IN uint16_t lid_ho, IN osm_lft_type_enum lft_enum) { if (lid_ho == 0 || lid_ho > p_sw->max_lid_ho) return OSM_NO_PATH; return lft_enum == OSM_LFT ? p_sw->lft[lid_ho] : p_sw->new_lft[lid_ho]; } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * lid_ho * [in] LID (host order) for which to retrieve the shortest hop count. * * lft_enum * [in] Use LFT that was calculated by routing engine, or * current LFT on the switch. * * RETURN VALUES * Returns the switch port on which the specified LID is routed. * * NOTES * * SEE ALSO * Switch object *********/ /****f* OpenSM: Switch/osm_switch_get_route_by_lid * NAME * osm_switch_get_route_by_lid * * DESCRIPTION * Gets the physical port object that routes the specified LID. * * SYNOPSIS */ static inline osm_physp_t *osm_switch_get_route_by_lid(IN const osm_switch_t * p_sw, IN ib_net16_t lid) { uint8_t port_num; CL_ASSERT(p_sw); CL_ASSERT(lid); port_num = osm_switch_get_port_by_lid(p_sw, cl_ntoh16(lid), OSM_NEW_LFT); /* In order to avoid holes in the subnet (usually happens when running UPDN algorithm), i.e. cases where port is unreachable through a switch (we put an OSM_NO_PATH value at the port entry, we do not assert on unreachable lid entries at the fwd table but return NULL */ if (port_num != OSM_NO_PATH) return (osm_node_get_physp_ptr(p_sw->p_node, port_num)); else return NULL; } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * lid * [in] LID for which to find a route. This must be a unicast * LID value < 0xC000. * * RETURN VALUES * Returns a pointer to the Physical Port Object object that * routes the specified LID. A return value of zero means * there is no route for the lid through this switch. * The lid value must be a unicast LID. * * NOTES * * SEE ALSO * Switch object *********/ /****f* OpenSM: Switch/osm_switch_sp0_is_lmc_capable * NAME * osm_switch_sp0_is_lmc_capable * * DESCRIPTION * Returns whether switch port 0 (SP0) can support LMC * */ static inline unsigned osm_switch_sp0_is_lmc_capable(IN const osm_switch_t * p_sw, IN osm_subn_t * p_subn) { return (p_subn->opt.lmc_esp0 && ib_switch_info_is_enhanced_port0(&p_sw->switch_info)) ? 1 : 0; } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * p_subn * [in] Pointer to an osm_subn_t object. * * RETURN VALUES * TRUE if SP0 is enhanced and globally enabled. FALSE otherwise. * * NOTES * This is workaround function, it takes into account user defined * p_subn->opt.lmc_esp0 parameter. * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use * NAME * osm_switch_get_max_block_id_in_use * * DESCRIPTION * Returns the maximum block ID (host order) of this switch that * is used for unicast routing. * * SYNOPSIS */ static inline uint16_t osm_switch_get_max_block_id_in_use(IN const osm_switch_t * p_sw) { return cl_ntoh16(p_sw->switch_info.lin_top) / IB_SMP_DATA_SIZE; } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * RETURN VALUES * Returns the maximum block ID (host order) of this switch. * * NOTES * * SEE ALSO * Switch object *********/ /****f* OpenSM: Switch/osm_switch_get_lft_block * NAME * osm_switch_get_lft_block * * DESCRIPTION * Retrieve a linear forwarding table block. * * SYNOPSIS */ boolean_t osm_switch_get_lft_block(IN const osm_switch_t * p_sw, IN uint16_t block_id, OUT uint8_t * p_block); /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * block_id * [in] The block_id to retrieve. * * p_block * [out] Pointer to the 64 byte array to store the * forwarding table block specified by block_id. * * RETURN VALUES * Returns true if there are more blocks necessary to * configure all the LIDs reachable from this switch. * FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_supports_mcast * NAME * osm_switch_supports_mcast * * DESCRIPTION * Indicates if a switch supports multicast. * * SYNOPSIS */ static inline boolean_t osm_switch_supports_mcast(IN const osm_switch_t * p_sw) { return (p_sw->switch_info.mcast_cap != 0); } /* * PARAMETERS * p_sw * [in] Pointer to an osm_switch_t object. * * RETURN VALUES * Returns TRUE if the switch supports multicast. * FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_set_switch_info * NAME * osm_switch_set_switch_info * * DESCRIPTION * Updates the switch info attribute of this switch. * * SYNOPSIS */ static inline void osm_switch_set_switch_info(IN osm_switch_t * p_sw, IN const ib_switch_info_t * p_si) { CL_ASSERT(p_sw); CL_ASSERT(p_si); p_sw->switch_info = *p_si; } /* * PARAMETERS * p_sw * [in] Pointer to a Switch object. * * p_si * [in] Pointer to the SwitchInfo attribute for this switch. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_count_path * NAME * osm_switch_count_path * * DESCRIPTION * Counts this path in port profile. * * SYNOPSIS */ static inline void osm_switch_count_path(IN osm_switch_t * p_sw, IN uint8_t port) { osm_port_prof_path_count_inc(&p_sw->p_prof[port]); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * port * [in] Port to count path. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_set_lft_block * NAME * osm_switch_set_lft_block * * DESCRIPTION * Copies in the specified block into * the switch's Linear Forwarding Table. * * SYNOPSIS */ static inline ib_api_status_t osm_switch_set_lft_block(IN osm_switch_t * p_sw, IN const uint8_t * p_block, IN uint32_t block_num) { uint16_t lid_start = (uint16_t) (block_num * IB_SMP_DATA_SIZE); CL_ASSERT(p_sw); if (lid_start + IB_SMP_DATA_SIZE > p_sw->lft_size) return IB_INVALID_PARAMETER; memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE); return IB_SUCCESS; } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * p_block * [in] Pointer to the forwarding table block. * * block_num * [in] Block number for this block * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_set_mft_block * NAME * osm_switch_set_mft_block * * DESCRIPTION * Sets a block of multicast port masks into the multicast table. * * SYNOPSIS */ static inline ib_api_status_t osm_switch_set_mft_block(IN osm_switch_t * p_sw, IN const ib_net16_t * p_block, IN uint16_t block_num, IN uint8_t position) { CL_ASSERT(p_sw); return osm_mcast_tbl_set_block(&p_sw->mcast_tbl, p_block, block_num, position); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * p_block * [in] Pointer to the block of port masks to set. * * block_num * [in] Block number (0-511) to set. * * position * [in] Port mask position (0-15) to set. * * RETURN VALUE * IB_SUCCESS on success. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_mft_block * NAME * osm_switch_get_mft_block * * DESCRIPTION * Retrieve a block of multicast port masks from the multicast table. * * SYNOPSIS */ static inline boolean_t osm_switch_get_mft_block(IN osm_switch_t * p_sw, IN uint16_t block_num, IN uint8_t position, OUT ib_net16_t * p_block) { CL_ASSERT(p_sw); return osm_mcast_tbl_get_block(&p_sw->mcast_tbl, block_num, position, p_block); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * block_num * [in] Block number (0-511) to set. * * position * [in] Port mask position (0-15) to set. * * p_block * [out] Pointer to the block of port masks stored. * * RETURN VALUES * Returns true if there are more blocks necessary to * configure all the MLIDs reachable from this switch. * FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_mft_max_block * NAME * osm_switch_get_mft_max_block * * DESCRIPTION * Get the max_block from the associated multicast table. * * SYNOPSIS */ static inline uint16_t osm_switch_get_mft_max_block(IN osm_switch_t * p_sw) { CL_ASSERT(p_sw); return osm_mcast_tbl_get_max_block(&p_sw->mcast_tbl); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * RETURN VALUE */ /****f* OpenSM: Switch/osm_switch_get_mft_max_block_in_use * NAME * osm_switch_get_mft_max_block_in_use * * DESCRIPTION * Get the max_block_in_use from the associated multicast table. * * SYNOPSIS */ static inline int16_t osm_switch_get_mft_max_block_in_use(IN osm_switch_t * p_sw) { CL_ASSERT(p_sw); return osm_mcast_tbl_get_max_block_in_use(&p_sw->mcast_tbl); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * RETURN VALUES * Returns the maximum block ID in use in this switch's mcast table. * A value of -1 indicates no blocks are in use. * * NOTES * * SEE ALSO */ /****f* OpenSM: Switch/osm_switch_get_mft_max_position * NAME * osm_switch_get_mft_max_position * * DESCRIPTION * Get the max_position from the associated multicast table. * * SYNOPSIS */ static inline uint8_t osm_switch_get_mft_max_position(IN osm_switch_t * p_sw) { CL_ASSERT(p_sw); return osm_mcast_tbl_get_max_position(&p_sw->mcast_tbl); } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * RETURN VALUE */ /****f* OpenSM: Switch/osm_switch_get_dimn_port * NAME * osm_switch_get_dimn_port * * DESCRIPTION * Get the routing ordered port * * SYNOPSIS */ static inline uint8_t osm_switch_get_dimn_port(IN const osm_switch_t * p_sw, IN uint8_t port_num) { CL_ASSERT(p_sw); if (p_sw->search_ordering_ports == NULL) return port_num; return p_sw->search_ordering_ports[port_num]; } /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * port_num * [in] Port number in the switch * * RETURN VALUES * Returns the port number ordered for routing purposes. */ /****f* OpenSM: Switch/osm_switch_recommend_path * NAME * osm_switch_recommend_path * * DESCRIPTION * Returns the recommended port on which to route this LID. * In cases where LMC > 0, the remote side system and node * used for the routing are tracked in the provided arrays * (and counts) such that other lid for the same port will * try and avoid going through the same remote system/node. * * SYNOPSIS */ uint8_t osm_switch_recommend_path(IN const osm_switch_t * p_sw, IN osm_port_t * p_port, IN uint16_t lid_ho, IN unsigned start_from, IN boolean_t ignore_existing, IN boolean_t routing_for_lmc, IN boolean_t dor, IN boolean_t port_shifting, IN uint32_t scatter_ports, IN osm_lft_type_enum lft_enum); /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * p_port * [in] Pointer to the port object for which to get a path * advisory. * * lid_ho * [in] LID value (host order) for which to get a path advisory. * * start_from * [in] Port number from where to start balance counting. * * ignore_existing * [in] Set to cause the switch to choose the optimal route * regardless of existing paths. * If false, the switch will choose an existing route if one * exists, otherwise will choose the optimal route. * * routing_for_lmc * [in] We support an enhanced LMC aware routing mode: * In the case of LMC > 0, we can track the remote side * system and node for all of the lids of the target * and try and avoid routing again through the same * system / node. * * Assume if routing_for_lmc is TRUE that this procedure * was provided with the tracking array and counter via * p_port->priv, and we can conduct this algorithm. * * dor * [in] If TRUE, Dimension Order Routing will be done. * * port_shifting * [in] If TRUE, port_shifting will be done. * * scatter_ports * [in] If not zero, randomize the selection of the best ports. * * lft_enum * [in] Use LFT that was calculated by routing engine, or * current LFT on the switch. * * RETURN VALUE * Returns the recommended port on which to route this LID. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_recommend_mcast_path * NAME * osm_switch_recommend_mcast_path * * DESCRIPTION * Returns the recommended port on which to route this LID. * * SYNOPSIS */ uint8_t osm_switch_recommend_mcast_path(IN osm_switch_t * p_sw, IN osm_port_t * p_port, IN uint16_t mlid_ho, IN boolean_t ignore_existing); /* * PARAMETERS * p_sw * [in] Pointer to the switch object. * * p_port * [in] Pointer to the port object for which to get * the multicast path. * * mlid_ho * [in] MLID for the multicast group in question. * * ignore_existing * [in] Set to cause the switch to choose the optimal route * regardless of existing paths. * If false, the switch will choose an existing route if one exists, * otherwise will choose the optimal route. * * RETURN VALUE * Returns the recommended port on which to route this LID. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size * NAME * osm_switch_get_mcast_fwd_tbl_size * * DESCRIPTION * Returns the number of entries available in the multicast forwarding table. * * SYNOPSIS */ static inline uint16_t osm_switch_get_mcast_fwd_tbl_size(IN const osm_switch_t * p_sw) { return cl_ntoh16(p_sw->switch_info.mcast_cap); } /* * PARAMETERS * p_sw * [in] Pointer to the switch. * * RETURN VALUE * Returns the number of entries available in the multicast forwarding table. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_path_count_get * NAME * osm_switch_path_count_get * * DESCRIPTION * Returns the count of the number of paths going through this port. * * SYNOPSIS */ static inline uint32_t osm_switch_path_count_get(IN const osm_switch_t * p_sw, IN uint8_t port_num) { return osm_port_prof_path_count_get(&p_sw->p_prof[port_num]); } /* * PARAMETERS * p_sw * [in] Pointer to the Switch object. * * port_num * [in] Port number for which to get path count. * * RETURN VALUE * Returns the count of the number of paths going through this port. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_prepare_path_rebuild * NAME * osm_switch_prepare_path_rebuild * * DESCRIPTION * Prepares a switch to rebuild pathing information. * * SYNOPSIS */ int osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids); /* * PARAMETERS * p_sw * [in] Pointer to the Switch object. * * max_lids * [in] Max number of lids in the subnet. * * RETURN VALUE * Returns zero on success, or negative value if an error occurred. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr * NAME * osm_switch_get_mcast_tbl_ptr * * DESCRIPTION * Returns a pointer to the switch's multicast table. * * SYNOPSIS */ static inline osm_mcast_tbl_t *osm_switch_get_mcast_tbl_ptr(IN const osm_switch_t * p_sw) { return (osm_mcast_tbl_t *) & p_sw->mcast_tbl; } /* * PARAMETERS * p_sw * [in] Pointer to the switch. * * RETURN VALUE * Returns a pointer to the switch's multicast table. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Switch/osm_switch_is_in_mcast_tree * NAME * osm_switch_is_in_mcast_tree * * DESCRIPTION * Returns true if this switch already belongs in the tree for the specified * multicast group. * * SYNOPSIS */ static inline boolean_t osm_switch_is_in_mcast_tree(IN const osm_switch_t * p_sw, IN uint16_t mlid_ho) { const osm_mcast_tbl_t *p_tbl; p_tbl = &p_sw->mcast_tbl; if (p_tbl) return osm_mcast_tbl_is_any_port(&p_sw->mcast_tbl, mlid_ho); else return FALSE; } /* * PARAMETERS * p_sw * [in] Pointer to the switch. * * mlid_ho * [in] MLID (host order) of the multicast tree to check. * * RETURN VALUE * Returns true if this switch already belongs in the tree for the specified * multicast group. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_SWITCH_H_ */ opensm-3.3.20/include/opensm/osm_ucast_mgr.h0000644000205000001450000001616512272264652015770 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2009 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: * Declaration of osm_ucast_mgr_t. * This object represents the Unicast Manager object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_UCAST_MGR_H_ #define _OSM_UCAST_MGR_H_ #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Unicast Manager * NAME * Unicast Manager * * DESCRIPTION * The Unicast Manager object encapsulates the information * needed to control unicast LID forwarding on the subnet. * * The Unicast Manager object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ struct osm_sm; /****s* OpenSM: Unicast Manager/osm_ucast_mgr_t * NAME * osm_ucast_mgr_t * * DESCRIPTION * Unicast Manager structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_ucast_mgr { struct osm_sm *sm; osm_subn_t *p_subn; osm_log_t *p_log; cl_plock_t *p_lock; uint16_t max_lid; cl_qlist_t port_order_list; boolean_t is_dor; boolean_t some_hop_count_set; cl_qmap_t cache_sw_tbl; boolean_t cache_valid; } osm_ucast_mgr_t; /* * FIELDS * sm * Pointer to the SM object. * * p_subn * Pointer to the Subnet object for this subnet. * * p_log * Pointer to the log object. * * p_lock * Pointer to the serializing lock. * * is_dor * Dimension Order Routing (DOR) will be done * * port_order_list * List of ports ordered for routing. * * some_hop_count_set * Initialized to FALSE at the beginning of each the min hop * tables calculation iteration cycle, set to TRUE to indicate * that some hop count changes were done. * * cache_sw_tbl * Cached switches table. * * cache_valid * TRUE if the unicast cache is valid. * * SEE ALSO * Unicast Manager object *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_construct * NAME * osm_ucast_mgr_construct * * DESCRIPTION * This function constructs a Unicast Manager object. * * SYNOPSIS */ void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to a Unicast Manager object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows osm_ucast_mgr_destroy * * Calling osm_ucast_mgr_construct is a prerequisite to calling any other * method except osm_ucast_mgr_init. * * SEE ALSO * Unicast Manager object, osm_ucast_mgr_init, * osm_ucast_mgr_destroy *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_destroy * NAME * osm_ucast_mgr_destroy * * DESCRIPTION * The osm_ucast_mgr_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to the object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified * Unicast Manager object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to * osm_ucast_mgr_construct or osm_ucast_mgr_init. * * SEE ALSO * Unicast Manager object, osm_ucast_mgr_construct, * osm_ucast_mgr_init *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_init * NAME * osm_ucast_mgr_init * * DESCRIPTION * The osm_ucast_mgr_init function initializes a * Unicast Manager object for use. * * SYNOPSIS */ ib_api_status_t osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr, IN struct osm_sm * sm); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_ucast_mgr_t object to initialize. * * sm * [in] Pointer to the SM object. * * RETURN VALUES * IB_SUCCESS if the Unicast Manager object was initialized * successfully. * * NOTES * Allows calling other Unicast Manager methods. * * SEE ALSO * Unicast Manager object, osm_ucast_mgr_construct, * osm_ucast_mgr_destroy *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_set_fwd_tables * NAME * osm_ucast_mgr_set_fwd_tables * * DESCRIPTION * Setup forwarding table for the switch (from prepared new_lft). * * SYNOPSIS */ void osm_ucast_mgr_set_fwd_tables(IN osm_ucast_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_ucast_mgr_t object. * * SEE ALSO * Unicast Manager *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_build_lid_matrices * NAME * osm_ucast_mgr_build_lid_matrices * * DESCRIPTION * Build switches's lid matrices. * * SYNOPSIS */ int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_ucast_mgr_t object. * * NOTES * This function processes the subnet, configuring switches' * min hops tables (aka lid matrices). * * SEE ALSO * Unicast Manager *********/ /****f* OpenSM: Unicast Manager/osm_ucast_mgr_process * NAME * osm_ucast_mgr_process * * DESCRIPTION * Process and configure the subnet's unicast forwarding tables. * * SYNOPSIS */ int osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to an osm_ucast_mgr_t object. * * RETURN VALUES * Returns zero on success and negative value on failure. * * NOTES * This function processes the subnet, configuring switch * unicast forwarding tables. * * SEE ALSO * Unicast Manager, Node Info Response Controller *********/ int ucast_dummy_build_lid_matrices(void *context); END_C_DECLS #endif /* _OSM_UCAST_MGR_H_ */ opensm-3.3.20/include/opensm/osm_mcast_mgr.h0000644000205000001450000000502312272264652015747 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (C) 2012-2013 Tokyo Institute of Technology. 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: * Declaration of osm_mcast_work_obj_t. * Provide access to a mcast function which searches the root swicth for * a spanning tree. */ #ifndef _OSM_MCAST_MGR_H_ #define _OSM_MCAST_MGR_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct osm_mcast_work_obj { cl_list_item_t list_item; osm_port_t *p_port; cl_map_item_t map_item; } osm_mcast_work_obj_t; int osm_mcast_make_port_list_and_map(cl_qlist_t * list, cl_qmap_t * map, osm_mgrp_box_t * mbox); void osm_mcast_drop_port_list(cl_qlist_t * list); osm_switch_t * osm_mcast_mgr_find_root_switch(osm_sm_t * sm, cl_qlist_t * list); END_C_DECLS #endif /* _OSM_MCAST_MGR_H_ */ opensm-3.3.20/include/opensm/osm_ucast_cache.h0000644000205000001450000001367012104655724016242 00000000000000/* * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2008 Mellanox Technologies LTD. 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: * Header file that describes Unicast Cache functions. * * Environment: * Linux User Mode * * $Revision: 1.4 $ */ #ifndef _OSM_UCAST_CACHE_H_ #define _OSM_UCAST_CACHE_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS struct osm_ucast_mgr; /****h* OpenSM/Unicast Manager/Unicast Cache * NAME * Unicast Cache * * DESCRIPTION * The Unicast Cache object encapsulates the information * needed to cache and write unicast routing of the subnet. * * The Unicast Cache object is NOT thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * AUTHOR * Yevgeny Kliteynik, Mellanox * *********/ /****f* OpenSM: Unicast Cache/osm_ucast_cache_invalidate * NAME * osm_ucast_cache_invalidate * * DESCRIPTION * The osm_ucast_cache_invalidate function purges the * unicast cache and marks the cache as invalid. * * SYNOPSIS */ void osm_ucast_cache_invalidate(struct osm_ucast_mgr *p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to the ucast mgr object. * * RETURN VALUE * This function does not return any value. * * NOTES * * SEE ALSO * Unicast Manager object *********/ /****f* OpenSM: Unicast Cache/osm_ucast_cache_check_new_link * NAME * osm_ucast_cache_check_new_link * * DESCRIPTION * The osm_ucast_cache_check_new_link checks whether * the newly discovered link still allows us to use * cached unicast routing. * * SYNOPSIS */ void osm_ucast_cache_check_new_link(struct osm_ucast_mgr *p_mgr, osm_node_t * p_node_1, uint8_t port_num_1, osm_node_t * p_node_2, uint8_t port_num_2); /* * PARAMETERS * p_mgr * [in] Pointer to the unicast manager object. * * physp1 * [in] Pointer to the first physical port of the link. * * physp2 * [in] Pointer to the second physical port of the link. * * RETURN VALUE * This function does not return any value. * * NOTES * The function checks whether the link was previously * cached/dropped or is this a completely new link. * If it decides that the new link makes cached routing * invalid, the cache is purged and marked as invalid. * * SEE ALSO * Unicast Cache object *********/ /****f* OpenSM: Unicast Cache/osm_ucast_cache_add_link * NAME * osm_ucast_cache_add_link * * DESCRIPTION * The osm_ucast_cache_add_link adds link to the cache. * * SYNOPSIS */ void osm_ucast_cache_add_link(struct osm_ucast_mgr *p_mgr, osm_physp_t * physp1, osm_physp_t * physp2); /* * PARAMETERS * p_mgr * [in] Pointer to the unicast manager object. * * physp1 * [in] Pointer to the first physical port of the link. * * physp2 * [in] Pointer to the second physical port of the link. * * RETURN VALUE * This function does not return any value. * * NOTES * Since the cache operates with ports and not links, * the function adds two port entries (both sides of the * link) to the cache. * If it decides that the dropped link makes cached routing * invalid, the cache is purged and marked as invalid. * * SEE ALSO * Unicast Manager object *********/ /****f* OpenSM: Unicast Cache/osm_ucast_cache_add_node * NAME * osm_ucast_cache_add_node * * DESCRIPTION * The osm_ucast_cache_add_node adds node and all * its links to the cache. * * SYNOPSIS */ void osm_ucast_cache_add_node(struct osm_ucast_mgr *p_mgr, osm_node_t * p_node); /* * PARAMETERS * p_mgr * [in] Pointer to the unicast manager object. * * p_node * [in] Pointer to the node object that should be cached. * * RETURN VALUE * This function does not return any value. * * NOTES * If the function decides that the dropped node makes cached * routing invalid, the cache is purged and marked as invalid. * * SEE ALSO * Unicast Manager object *********/ /****f* OpenSM: Unicast Cache/osm_ucast_cache_process * NAME * osm_ucast_cache_process * * DESCRIPTION * The osm_ucast_cache_process function writes the * cached unicast routing on the subnet switches. * * SYNOPSIS */ int osm_ucast_cache_process(struct osm_ucast_mgr *p_mgr); /* * PARAMETERS * p_mgr * [in] Pointer to the unicast manager object. * * RETURN VALUE * This function returns zero on sucess and non-zero * value otherwise. * * NOTES * Iterates through all the subnet switches and writes * the LFTs that were calculated during the last routing * engine execution to the switches. * * SEE ALSO * Unicast Manager object *********/ END_C_DECLS #endif /* _OSM_UCAST_CACHE_H_ */ opensm-3.3.20/include/opensm/osm_vl15intf.h0000644000205000001450000002172412330455772015451 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 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: * Declaration of osm_vl15_t. * This object represents a VL15 interface object. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_VL15INTF_H_ #define _OSM_VL15INTF_H_ #include #include #include #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/VL15 * NAME * VL15 * * DESCRIPTION * The VL15 object encapsulates the information needed by the * OpenSM to instantiate the VL15 interface. The OpenSM allocates * one VL15 object per subnet. * * The VL15 object transmits MADs to the wire at a throttled rate, * so as to not overload the VL15 buffering of subnet components. * OpenSM modules may post VL15 MADs to the VL15 interface as fast * as possible. * * The VL15 object is thread safe. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * AUTHOR * Steve King, Intel * *********/ /****d* OpenSM: SM/osm_vl15_state_t * NAME * osm_vl15_state_t * * DESCRIPTION * Enumerates the possible states of SM object. * * SYNOPSIS */ typedef enum _osm_vl15_state { OSM_VL15_STATE_INIT = 0, OSM_VL15_STATE_READY } osm_vl15_state_t; /***********/ /****s* OpenSM: VL15/osm_vl15_t * NAME * osm_vl15_t * * DESCRIPTION * VL15 structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct osm_vl15 { osm_thread_state_t thread_state; osm_vl15_state_t state; uint32_t max_wire_smps; uint32_t max_wire_smps2; uint32_t max_smps_timeout; cl_event_t signal; cl_thread_t poller; cl_qlist_t rfifo; cl_qlist_t ufifo; cl_spinlock_t lock; osm_vendor_t *p_vend; osm_log_t *p_log; osm_stats_t *p_stats; osm_subn_t *p_subn; } osm_vl15_t; /* * FIELDS * thread_state * Tracks the thread state of the poller thread. * * state * Tracks the state of the VL15 interface itself. * * max_wire_smps * Maximum number of VL15 MADs allowed on the wire at one time. * * max_wire_smps2 * Maximum number of timeout based SMPs allowed to be outstanding. * * max_smps_timeout * Wait time in usec for timeout based SMPs. * * signal * Event on which the poller sleeps. * * rfifo * First-in First-out queue for outbound VL15 MADs for which * a response is expected, aka the "response fifo" * * ufifo * First-in First-out queue for outbound VL15 MADs for which * no response is expected, aka the "unicast fifo". * * poller * Worker thread pool that services the fifo to transmit VL15 MADs * * lock * Spinlock guarding the FIFO. * * p_vend * Pointer to the vendor transport object. * * p_log * Pointer to the log object. * * p_stats * Pointer to the OpenSM statistics block. * * p_subn * Pointer to the OpenSM subnet object. * * SEE ALSO * VL15 object *********/ /****f* OpenSM: VL15/osm_vl15_construct * NAME * osm_vl15_construct * * DESCRIPTION * This function constructs an VL15 object. * * SYNOPSIS */ void osm_vl15_construct(IN osm_vl15_t * p_vl15); /* * PARAMETERS * p_vl15 * [in] Pointer to a VL15 object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osm_vl15_destroy. * * Calling osm_vl15_construct is a prerequisite to calling any other * method except osm_vl15_init. * * SEE ALSO * VL15 object, osm_vl15_init, osm_vl15_destroy *********/ /****f* OpenSM: VL15/osm_vl15_destroy * NAME * osm_vl15_destroy * * DESCRIPTION * The osm_vl15_destroy function destroys the object, releasing * all resources. * * SYNOPSIS */ void osm_vl15_destroy(IN osm_vl15_t * p_vl15, IN struct osm_mad_pool *p_pool); /* * PARAMETERS * p_vl15 * [in] Pointer to a VL15 object to destroy. * * p_pool * [in] The pointer to the mad pool to return outstanding mads to * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified VL15 object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osm_vl15_construct or * osm_vl15_init. * * SEE ALSO * VL15 object, osm_vl15_construct, osm_vl15_init *********/ /* Initialization. Rate specifies the minimum number of microseconds between transmissions on VL15. */ /****f* OpenSM: VL15/osm_vl15_init * NAME * osm_vl15_init * * DESCRIPTION * The osm_vl15_init function initializes a VL15 object for use. * * SYNOPSIS */ ib_api_status_t osm_vl15_init(IN osm_vl15_t * p_vl15, IN osm_vendor_t * p_vend, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN osm_subn_t * p_subn, IN int32_t max_wire_smps, IN int32_t max_wire_smps2, IN uint32_t max_smps_timeout); /* * PARAMETERS * p_vl15 * [in] Pointer to an osm_vl15_t object to initialize. * * p_vend * [in] Pointer to the vendor transport object. * * p_log * [in] Pointer to the log object. * * p_stats * [in] Pointer to the OpenSM statistics block. * * p_subn * [in] Pointer to the OpenSM subnet object. * * max_wire_smps * [in] Maximum number of SMPs allowed on the wire at one time. * * max_wire_smps2 * [in] Maximum number of timeout based SMPs allowed to be * outstanding. * * max_smps_timeout * [in] Wait time in usec for timeout based SMPs. * * * RETURN VALUES * IB_SUCCESS if the VL15 object was initialized successfully. * * NOTES * Allows calling other VL15 methods. * * SEE ALSO * VL15 object, osm_vl15_construct, osm_vl15_destroy *********/ /****f* OpenSM: VL15/osm_vl15_post * NAME * osm_vl15_post * * DESCRIPTION * Posts a MAD to the VL15 interface for transmission. * * SYNOPSIS */ void osm_vl15_post(IN osm_vl15_t * p_vl15, IN osm_madw_t * p_madw); /* * PARAMETERS * p_vl15 * [in] Pointer to an osm_vl15_t object. * * p_madw * [in] Pointer to a MAD wrapper structure containing the MAD. * * RETURN VALUES * This function does not return a value. * * NOTES * The osm_vl15_construct or osm_vl15_init must be called before using * this function. * * SEE ALSO * VL15 object, osm_vl15_construct, osm_vl15_init *********/ /****f* OpenSM: VL15/osm_vl15_poll * NAME * osm_vl15_poll * * DESCRIPTION * Causes the VL15 Interface to consider sending another QP0 MAD. * * SYNOPSIS */ void osm_vl15_poll(IN osm_vl15_t * p_vl); /* * PARAMETERS * p_vl15 * [in] Pointer to an osm_vl15_t object. * * RETURN VALUES * None. * * NOTES * This function signals the VL15 that it may be possible to send * a SMP. This function checks three criteria before sending a SMP: * 1) The VL15 worker is IDLE * 2) There are no QP0 SMPs currently outstanding * 3) There is something on the VL15 FIFO to send * * SEE ALSO * VL15 object, osm_vl15_construct, osm_vl15_init *********/ /****f* OpenSM: VL15/osm_vl15_shutdown * NAME * osm_vl15_shutdown * * DESCRIPTION * Cleanup all outstanding MADs on both fifo's. * This is required to return all outstanding MAD resources. * * SYNOPSIS */ void osm_vl15_shutdown(IN osm_vl15_t * p_vl, IN osm_mad_pool_t * p_mad_pool); /* * PARAMETERS * p_vl15 * [in] Pointer to an osm_vl15_t object. * * p_mad_pool * [in] The MAD pool owning the mads. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * VL15 object, osm_vl15_construct, osm_vl15_init *********/ END_C_DECLS #endif /* _OSM_VL15INTF_H_ */ opensm-3.3.20/include/opensm/osm_version.h0000644000205000001450000000343712726323450015463 00000000000000/* * Copyright (c) 2004-2008 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. * */ #ifndef _OSM_VERSION_H_ #define _OSM_VERSION_H_ /****s* OpenSM: Base/OSM_VERSION * NAME * OSM_VERSION * * DESCRIPTION * The version string for OpenSM * * SYNOPSIS */ #define OSM_VERSION "OpenSM 3.3.20" /********/ #endif /* _OSM_VERSION_H_ */ opensm-3.3.20/include/opensm/osm_config.h0000644000205000001450000000413112444340277015236 00000000000000/* include/opensm/osm_config.h. Generated from osm_config.h.in by configure. */ /* include/osm_config.h.in * * Defines various OpenSM configuration parameters to be used by various * plugins and third party tools. * * NOTE: Defines used in header files MUST be included here to ensure plugin * compatibility. */ #ifndef _OSM_CONFIG_H_ #define _OSM_CONFIG_H_ 1 /* define 1 if OpenSM build is in a debug mode */ /* #undef OSM_DEBUG */ /* #undef _DEBUG_ */ /* Define as 1 if you want Dual Sided RMPP Support */ #define DUAL_SIDED_RMPP 1 /* Define as 1 if you want to enable a console on a socket connection */ /* #undef ENABLE_OSM_CONSOLE_SOCKET */ /* Define as 1 if you want to enable the event plugin */ /* #undef ENABLE_OSM_DEFAULT_EVENT_PLUGIN */ /* Define as 1 if you want to enable the performance manager */ #define ENABLE_OSM_PERF_MGR 1 /* Define as 1 if you want to enable the performance manager profiling code */ /* #undef ENABLE_OSM_PERF_MGR_PROFILE */ /* Define a default node name map file */ #define HAVE_DEFAULT_NODENAME_MAP "/usr/local/etc/opensm/ib-node-name-map" /* Define a default OpenSM config file */ #define HAVE_DEFAULT_OPENSM_CONFIG_FILE "/usr/local/etc/opensm/opensm.conf" /* Define a Partition config file */ #define HAVE_DEFAULT_PARTITION_CONFIG_FILE "/usr/local/etc/opensm/partitions.conf" /* Define a Prefix Routes config file */ #define HAVE_DEFAULT_PREFIX_ROUTES_FILE "/usr/local/etc/opensm/prefix-routes.conf" /* Define a QOS policy config file */ #define HAVE_DEFAULT_QOS_POLICY_FILE "/usr/local/etc/opensm/qos-policy.conf" /* Define OpenSM config directory */ #define OPENSM_CONFIG_DIR "/usr/local/etc/opensm" /* Define as 1 for vapi vendor */ /* #undef OSM_VENDOR_INTF_MTL */ /* Define as 1 for OpenIB vendor */ #define OSM_VENDOR_INTF_OPENIB 1 /* Define as 1 for sim vendor */ /* #undef OSM_VENDOR_INTF_SIM */ /* Define as 1 for ts vendor */ /* #undef OSM_VENDOR_INTF_TS */ /* Define as 1 if you want Vendor RMPP Support */ #define VENDOR_RMPP_SUPPORT 1 /* Define to 1 if you have the `pthread' library (-lpthread). */ #define HAVE_LIBPTHREAD 1 #endif /* _OSM_CONFIG_H_ */ opensm-3.3.20/include/complib/0000755000205000001450000000000012726324756013156 500000000000000opensm-3.3.20/include/complib/cl_atomic.h0000644000205000001450000001255312104655724015177 00000000000000/* * 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: * Declaration of atomic manipulation functions. */ #ifndef _CL_ATOMIC_H_ #define _CL_ATOMIC_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Atomic Operations * NAME * Atomic Operations * * DESCRIPTION * The Atomic Operations functions allow callers to operate on * 32-bit signed integers in an atomic fashion. *********/ /****f* Component Library: Atomic Operations/cl_atomic_inc * NAME * cl_atomic_inc * * DESCRIPTION * The cl_atomic_inc function atomically increments a 32-bit signed * integer and returns the incremented value. * * SYNOPSIS */ int32_t cl_atomic_inc(IN atomic32_t * const p_value); /* * PARAMETERS * p_value * [in] Pointer to a 32-bit integer to increment. * * RETURN VALUE * Returns the incremented value pointed to by p_value. * * NOTES * The provided value is incremented and its value returned in one atomic * operation. * * cl_atomic_inc maintains data consistency without requiring additional * synchronization mechanisms in multi-threaded environments. * * SEE ALSO * Atomic Operations, cl_atomic_dec, cl_atomic_add, cl_atomic_sub *********/ /****f* Component Library: Atomic Operations/cl_atomic_dec * NAME * cl_atomic_dec * * DESCRIPTION * The cl_atomic_dec function atomically decrements a 32-bit signed * integer and returns the decremented value. * * SYNOPSIS */ int32_t cl_atomic_dec(IN atomic32_t * const p_value); /* * PARAMETERS * p_value * [in] Pointer to a 32-bit integer to decrement. * * RETURN VALUE * Returns the decremented value pointed to by p_value. * * NOTES * The provided value is decremented and its value returned in one atomic * operation. * * cl_atomic_dec maintains data consistency without requiring additional * synchronization mechanisms in multi-threaded environments. * * SEE ALSO * Atomic Operations, cl_atomic_inc, cl_atomic_add, cl_atomic_sub *********/ /****f* Component Library: Atomic Operations/cl_atomic_add * NAME * cl_atomic_add * * DESCRIPTION * The cl_atomic_add function atomically adds a value to a * 32-bit signed integer and returns the resulting value. * * SYNOPSIS */ int32_t cl_atomic_add(IN atomic32_t * const p_value, IN const int32_t increment); /* * PARAMETERS * p_value * [in] Pointer to a 32-bit integer that will be added to. * * increment * [in] Value by which to increment the integer pointed to by p_value. * * RETURN VALUE * Returns the value pointed to by p_value after the addition. * * NOTES * The provided increment is added to the value and the result returned in * one atomic operation. * * cl_atomic_add maintains data consistency without requiring additional * synchronization mechanisms in multi-threaded environments. * * SEE ALSO * Atomic Operations, cl_atomic_inc, cl_atomic_dec, cl_atomic_sub *********/ /****f* Component Library: Atomic Operations/cl_atomic_sub * NAME * cl_atomic_sub * * DESCRIPTION * The cl_atomic_sub function atomically subtracts a value from a * 32-bit signed integer and returns the resulting value. * * SYNOPSIS */ int32_t cl_atomic_sub(IN atomic32_t * const p_value, IN const int32_t decrement); /* * PARAMETERS * p_value * [in] Pointer to a 32-bit integer that will be subtracted from. * * decrement * [in] Value by which to decrement the integer pointed to by p_value. * * RETURN VALUE * Returns the value pointed to by p_value after the subtraction. * * NOTES * The provided decrement is subtracted from the value and the result * returned in one atomic operation. * * cl_atomic_sub maintains data consistency without requiring additional * synchronization mechanisms in multi-threaded environments. * * SEE ALSO * Atomic Operations, cl_atomic_inc, cl_atomic_dec, cl_atomic_add *********/ END_C_DECLS #endif /* _CL_ATOMIC_H_ */ opensm-3.3.20/include/complib/cl_atomic_osd.h0000644000205000001450000000604112104655724016037 00000000000000/* * 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 specific header files for atomic operations. */ #ifndef _CL_ATOMIC_OSD_H_ #define _CL_ATOMIC_OSD_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS extern cl_spinlock_t cl_atomic_spinlock; static inline int32_t cl_atomic_inc(IN atomic32_t * const p_value) { int32_t new_val; cl_spinlock_acquire(&cl_atomic_spinlock); new_val = *p_value + 1; *p_value = new_val; cl_spinlock_release(&cl_atomic_spinlock); return (new_val); } static inline int32_t cl_atomic_dec(IN atomic32_t * const p_value) { int32_t new_val; cl_spinlock_acquire(&cl_atomic_spinlock); new_val = *p_value - 1; *p_value = new_val; cl_spinlock_release(&cl_atomic_spinlock); return (new_val); } static inline int32_t cl_atomic_add(IN atomic32_t * const p_value, IN const int32_t increment) { int32_t new_val; cl_spinlock_acquire(&cl_atomic_spinlock); new_val = *p_value + increment; *p_value = new_val; cl_spinlock_release(&cl_atomic_spinlock); return (new_val); } static inline int32_t cl_atomic_sub(IN atomic32_t * const p_value, IN const int32_t decrement) { int32_t new_val; cl_spinlock_acquire(&cl_atomic_spinlock); new_val = *p_value - decrement; *p_value = new_val; cl_spinlock_release(&cl_atomic_spinlock); return (new_val); } END_C_DECLS #endif /* _CL_ATOMIC_OSD_H_ */ opensm-3.3.20/include/complib/cl_byteswap.h0000644000205000001450000003130712104655724015557 00000000000000/* * 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: * provides byteswapping utilities. Basic functions are obtained from * platform specific implementations from byteswap_osd.h. */ #ifndef _CL_BYTESWAP_H_ #define _CL_BYTESWAP_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Byte Swapping * NAME * Byte Swapping * * DESCRIPTION * The byte swapping functions and macros allow swapping bytes from network * byte order to host byte order. * * All data transmitted between systems should be in network byte order. * In order to utilize such data, it must be converted to host byte order * before use. * * SEE ALSO * Functions: * cl_ntoh16, cl_hton16, cl_ntoh32, cl_hton32, cl_ntoh64, cl_hton64, * cl_ntoh * * Macros: * CL_NTOH16, CL_HTON16, CL_NTOH32, CL_HTON32, CL_NTOH64, CL_HTON64 *********/ /* * The byteswap_osd.h provides the following macros. * __LITTLE_ENDIAN * __BIG_ENDIAN * __BYTE_ORDER * * If the platform provides byte swapping functions, byteswap_osd.h also * provides the following macros. * ntoh16, hton16 * ntoh32, hton32 * ntoh64, hton64 */ #ifndef __BYTE_ORDER #error "__BYTE_ORDER macro undefined. Missing in endian.h?" #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define CPU_LE 1 #define CPU_BE 0 #else #define CPU_LE 0 #define CPU_BE 1 #endif /****d* Component Library: Byte Swapping/CL_NTOH16 * NAME * CL_NTOH16 * * DESCRIPTION * The CL_NTOH16 macro converts a 16-bit value from network byte order to * host byte order. The CL_NTOH16 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_NTOH16 is less efficient * than the cl_ntoh16 function. * * SYNOPSIS * CL_NTOH16( val ); * * PARAMETERS * val * [in] 16-bit value to swap from network byte order to host byte order. * * RESULT * Value of val converted to host byte order. * * NOTES * This macro is analogous to CL_HTON16. * * SEE ALSO * Byte Swapping, CL_HTON16, CL_NTOH32, CL_NTOH64, * cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh *********/ /****d* Component Library: Byte Swapping/CL_HTON16 * NAME * CL_HTON16 * * DESCRIPTION * The CL_HTON16 macro converts a 16-bit value from host byte order to * network byte order. The CL_HTON16 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_HTON16 is less efficient * than the cl_hton16 function. * * SYNOPSIS * CL_HTON16( val ); * * PARAMETERS * val * [in] 16-bit value to swap from host byte order to network byte order. * * RESULT * Value of val converted to network byte order. * * NOTES * This macro is analogous to CL_NTOH16. * * SEE ALSO * Byte Swapping, CL_NTOH16, CL_HTON32, CL_HTON64, * cl_hton16, cl_hton32, cl_hton64, cl_ntoh *********/ #if CPU_LE #define CL_NTOH16( x ) (uint16_t)( \ (((uint16_t)(x) & 0x00FF) << 8) | \ (((uint16_t)(x) & 0xFF00) >> 8) ) #else #define CL_NTOH16( x ) (x) #endif #define CL_HTON16 CL_NTOH16 /****f* Component Library: Byte Swapping/cl_ntoh16 * NAME * cl_ntoh16 * * DESCRIPTION * The cl_ntoh16 function converts a 16-bit value from network byte order to * host byte order. * * SYNOPSIS * uint16_t * cl_ntoh16( * IN const uint16_t val ); * * PARAMETERS * val * [in] Value to swap from network byte order to host byte order. * * RETURN VALUE * Value of val converted to host byte order. * * NOTES * This function is analogous to cl_hton16. * * SEE ALSO * Byte Swapping, cl_hton16, cl_ntoh32, cl_ntoh64, cl_ntoh *********/ /****f* Component Library: Byte Swapping/cl_hton16 * NAME * cl_hton16 * * DESCRIPTION * The cl_hton16 function converts a 16-bit value from host byte order to * network byte order. * * SYNOPSIS * uint16_t * cl_hton16( * IN const uint16_t val ); * * PARAMETERS * val * [in] Value to swap from host byte order to network byte order . * * RETURN VALUE * Value of val converted to network byte order. * * NOTES * This function is analogous to cl_ntoh16. * * SEE ALSO * Byte Swapping, cl_ntoh16, cl_hton32, cl_hton64, cl_ntoh *********/ #ifndef cl_ntoh16 #define cl_ntoh16 CL_NTOH16 #define cl_hton16 CL_HTON16 #endif /****d* Component Library: Byte Swapping/CL_NTOH32 * NAME * CL_NTOH32 * * DESCRIPTION * The CL_NTOH32 macro converts a 32-bit value from network byte order to * host byte order. The CL_NTOH32 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_NTOH32 is less efficient * than the cl_ntoh32 function. * * SYNOPSIS * CL_NTOH32( val ); * * PARAMETERS * val * [in] 32-bit value to swap from network byte order to host byte order. * * RESULT * Value of val converted to host byte order. * * NOTES * This macro is analogous to CL_HTON32. * * SEE ALSO * Byte Swapping, CL_HTON32, CL_NTOH16, CL_NTOH64, * cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh *********/ /****d* Component Library: Byte Swapping/CL_HTON32 * NAME * CL_HTON32 * * DESCRIPTION * The CL_HTON32 macro converts a 32-bit value from host byte order to * network byte order. The CL_HTON32 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_HTON32 is less efficient * than the cl_hton32 function. * * SYNOPSIS * CL_HTON32( val ); * * PARAMETERS * val * [in] 32-bit value to swap from host byte order to network byte order. * * RESULT * Value of val converted to network byte order. * * NOTES * This macro is analogous to CL_NTOH32. * * SEE ALSO * Byte Swapping, CL_NTOH32, CL_HTON16, CL_HTON64, * cl_hton16, cl_hton32, cl_hton64, cl_ntoh *********/ #if CPU_LE #define CL_NTOH32( x ) (uint32_t)( \ (((uint32_t)(x) & 0x000000FF) << 24) | \ (((uint32_t)(x) & 0x0000FF00) << 8) | \ (((uint32_t)(x) & 0x00FF0000) >> 8) | \ (((uint32_t)(x) & 0xFF000000) >> 24) ) #else #define CL_NTOH32( x ) (x) #endif #define CL_HTON32 CL_NTOH32 /****f* Component Library: Byte Swapping/cl_ntoh32 * NAME * cl_ntoh32 * * DESCRIPTION * The cl_ntoh32 function converts a 32-bit value from network byte order to * host byte order. * * SYNOPSIS * uint32_t * cl_ntoh32( * IN const uint32_t val ); * * PARAMETERS * val * [in] Value to swap from network byte order to host byte order. * * RETURN VALUE * Value of val converted in host byte order. * * NOTES * This function is analogous to cl_hton32. * * SEE ALSO * Byte Swapping, cl_hton32, cl_ntoh16, cl_ntoh64, cl_ntoh *********/ /****f* Component Library: Byte Swapping/cl_hton32 * NAME * cl_hton32 * * DESCRIPTION * The cl_hton32 function converts a 32-bit value from host byte order to * network byte order. * * SYNOPSIS * uint32_t * cl_hton32( * IN const uint32_t val ); * * PARAMETERS * val * [in] Value to swap from host byte order to network byte order . * * RETURN VALUE * Value of val converted to network byte order. * * NOTES * This function is analogous to cl_ntoh32. * * SEE ALSO * Byte Swapping, cl_ntoh32, cl_hton16, cl_hton64, cl_ntoh *********/ #ifndef cl_ntoh32 #define cl_ntoh32 CL_NTOH32 #define cl_hton32 CL_HTON32 #endif /****d* Component Library: Byte Swapping/CL_NTOH64 * NAME * CL_NTOH64 * * DESCRIPTION * The CL_NTOH64 macro converts a 64-bit value from network byte order to * host byte order. The CL_NTOH64 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_NTOH64 is less efficient * than the cl_ntoh64 function. * * SYNOPSIS * CL_NTOH64( val ); * * PARAMETERS * val * [in] 64-bit value to swap from network byte order to host byte order. * * RESULT * Value of val converted to host byte order. * * NOTES * This macro is analogous to CL_HTON64. * * SEE ALSO * Byte Swapping, CL_HTON64, CL_NTOH16, CL_NTOH32, * cl_ntoh16, cl_ntoh32, cl_ntoh64, cl_ntoh *********/ /****d* Component Library: Byte Swapping/CL_HTON64 * NAME * CL_HTON64 * * DESCRIPTION * The CL_HTON64 macro converts a 64-bit value from host byte order to * network byte order. The CL_HTON64 macro will cause constant values to be * swapped by the pre-processor. For variables, CL_HTON64 is less efficient * than the cl_hton64 function. * * SYNOPSIS * CL_HTON64( val ); * * PARAMETERS * val * [in] 64-bit value to swap from host byte order to network byte order. * * RESULT * Value of val converted to network byte order. * * NOTES * This macro is analogous to CL_NTOH64. * * SEE ALSO * Byte Swapping, CL_NTOH64, CL_HTON16, CL_HTON32, * cl_hton16, cl_hton32, cl_hton64, cl_ntoh *********/ #if CPU_LE #define CL_NTOH64( x ) (uint64_t)( \ (((uint64_t)(x) & 0x00000000000000FFULL) << 56) | \ (((uint64_t)(x) & 0x000000000000FF00ULL) << 40) | \ (((uint64_t)(x) & 0x0000000000FF0000ULL) << 24) | \ (((uint64_t)(x) & 0x00000000FF000000ULL) << 8 ) | \ (((uint64_t)(x) & 0x000000FF00000000ULL) >> 8 ) | \ (((uint64_t)(x) & 0x0000FF0000000000ULL) >> 24) | \ (((uint64_t)(x) & 0x00FF000000000000ULL) >> 40) | \ (((uint64_t)(x) & 0xFF00000000000000ULL) >> 56) ) #else #define CL_NTOH64( x ) (x) #endif #define CL_HTON64 CL_NTOH64 /****f* Component Library: Byte Swapping/cl_ntoh64 * NAME * cl_ntoh64 * * DESCRIPTION * The cl_ntoh64 function converts a 64-bit value from network byte order to * host byte order. * * SYNOPSIS * uint64_t * cl_ntoh64( * IN const uint64_t val ); * * PARAMETERS * val * [in] Value to swap from network byte order to host byte order. * * RETURN VALUE * Value of val converted in host byte order. * * NOTES * This function is analogous to cl_hton64. * * SEE ALSO * Byte Swapping, cl_hton64, cl_ntoh16, cl_ntoh32, cl_ntoh *********/ /****f* Component Library: Byte Swapping/cl_hton64 * NAME * cl_hton64 * * DESCRIPTION * The cl_hton64 function converts a 64-bit value from host byte order to * network byte order. * * SYNOPSIS * uint64_t * cl_hton64( * IN const uint64_t val ); * * PARAMETERS * val * [in] Value to swap from host byte order to network byte order . * * RETURN VALUE * Value of val converted to network byte order. * * NOTES * This function is analogous to cl_ntoh64. * * SEE ALSO * Byte Swapping, cl_ntoh64, cl_hton16, cl_hton32, cl_ntoh *********/ #ifndef cl_ntoh64 #define cl_ntoh64 CL_NTOH64 #define cl_hton64 CL_HTON64 #endif /****f* Component Library: Byte Swapping/cl_ntoh * NAME * cl_ntoh * * DESCRIPTION * The cl_ntoh function converts a value from network byte order to * host byte order. * * SYNOPSIS */ static inline void cl_ntoh(OUT char *const p_dest, IN const char *const p_src, IN const uint8_t size) { #if CPU_LE uint8_t i; char temp; if (p_src == p_dest) { /* Swap in place if source and destination are the same. */ for (i = 0; i < size / 2; i++) { temp = p_dest[i]; p_dest[i] = p_src[size - 1 - i]; p_dest[size - 1 - i] = temp; } } else { for (i = 0; i < size; i++) p_dest[i] = p_src[size - 1 - i]; } #else /* * If the source and destination are not the same, copy the source to * the destination. */ if (p_src != p_dest) memcpy(p_dest, p_src, size); #endif } /* * PARAMETERS * p_dest * [in] Pointer to a byte array to contain the converted value of p_src. * * p_src * [in] Pointer to a byte array to be converted from network byte * ordering. * * size * [in] Number of bytes to swap.p_dest * * RETURN VALUE * This function does not return a value. * * NOTES * cl_ntoh can perform in place swapping if both p_src and p_dest point to * the same buffer. * * SEE ALSO * Byte Swapping, cl_ntoh16, cl_ntoh32, cl_ntoh64 *********/ END_C_DECLS #endif /* _CL_BYTESWAP_H_ */ opensm-3.3.20/include/complib/cl_byteswap_osd.h0000644000205000001450000000473612104655724016432 00000000000000/* * Copyright (c) 2004, 2005 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: * Provides common macros for dealing with byte swapping issues. */ #ifndef _CL_BYTESWAP_OSD_H_ #define _CL_BYTESWAP_OSD_H_ /* * This provides defines __LITTLE_ENDIAN, __BIG_ENDIAN and __BYTE_ORDER */ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #if __BYTE_ORDER == __LITTLE_ENDIAN #define cl_ntoh16(x) bswap_16(x) #define cl_hton16(x) bswap_16(x) #define cl_ntoh32(x) bswap_32(x) #define cl_hton32(x) bswap_32(x) #define cl_ntoh64(x) (uint64_t)bswap_64(x) #define cl_hton64(x) (uint64_t)bswap_64(x) #else /* Big Endian */ #define cl_ntoh16(x) (x) #define cl_hton16(x) (x) #define cl_ntoh32(x) (x) #define cl_hton32(x) (x) #define cl_ntoh64(x) (x) #define cl_hton64(x) (x) #endif END_C_DECLS #endif /* _CL_BYTESWAP_OSD_H_ */ opensm-3.3.20/include/complib/cl_comppool.h0000644000205000001450000003766612104655724015567 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of the composite pool. * The composite pool managers a pool of composite objects. A composite object is an object * that is made of multiple sub objects. * The pool can grow to meet demand, limited only by system memory. */ #ifndef _CL_COMP_POOL_H_ #define _CL_COMP_POOL_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Composite Pool * NAME * Composite Pool * * DESCRIPTION * The Composite Pool provides a self-contained and self-sustaining pool of * user defined composite objects. * * A composite object is an object that is composed of one or more * sub-objects, each of which needs to be treated separately for * initialization. Objects can be retrieved from the pool as long as there * is memory in the system. * * To aid in object oriented design, the composite pool provides the user * the ability to specify callbacks that are invoked for each object for * construction, initialization, and destruction. Constructor and destructor * callback functions may not fail. * * A composite pool does not return memory to the system as the user returns * objects to the pool. The only method of returning memory to the system is * to destroy the pool. * * The composite pool functions operates on a cl_cpool_t structure which * should be treated as opaque and should be manipulated only through the * provided functions. * * SEE ALSO * Structures: * cl_cpool_t * * Callbacks: * cl_pfn_cpool_init_t, cl_pfn_cpool_dtor_t * * Initialization/Destruction: * cl_cpool_construct, cl_cpool_init, cl_cpool_destroy * * Manipulation: * cl_cpool_get, cl_cpool_put, cl_cpool_grow * * Attributes: * cl_is_cpool_inited, cl_cpool_count *********/ /****d* Component Library: Composite Pool/cl_pfn_cpool_init_t * NAME * cl_pfn_cpool_init_t * * DESCRIPTION * The cl_pfn_cpool_init_t function type defines the prototype for * functions used as initializers for objects being allocated by a * composite pool. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_cpool_init_t) (IN void **const p_comp_array, IN const uint32_t num_components, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object to initialize. * * context * [in] Context provided in a call to cl_cpool_init. * * RETURN VALUES * Return CL_SUCCESS to indicates that initialization of the object * was successful and that initialization of further objects may continue. * * Other cl_status_t values will be returned by cl_cpool_init * and cl_cpool_grow. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_cpool_init function. * * The initializer is invoked once per allocated object, allowing the user * to chain components to form a composite object and perform any necessary * initialization. Returning a status other than CL_SUCCESS aborts a grow * operation, initiated either through cl_cpool_init or cl_cpool_grow, and * causes the initiating function to fail. Any non-CL_SUCCESS status will * be returned by the function that initiated the grow operation. * * All memory for the requested number of components is pre-allocated. * * When later performing a cl_cpool_get call, the return value is a pointer * to the first component. * * SEE ALSO * Composite Pool, cl_cpool_init, cl_cpool_grow *********/ /****d* Component Library: Composite Pool/cl_pfn_cpool_dtor_t * NAME * cl_pfn_cpool_dtor_t * * DESCRIPTION * The cl_pfn_cpool_dtor_t function type defines the prototype for * functions used as destructor for objects being deallocated by a * composite pool. * * SYNOPSIS */ typedef void (*cl_pfn_cpool_dtor_t) (IN void *const p_object, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object to destruct. * * context * [in] Context provided in the call to cl_cpool_init. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_cpool_init function. * * The destructor is invoked once per allocated object, allowing the user * to perform any necessary cleanup. Users should not attempt to deallocate * the memory for the composite object, as the composite pool manages * object allocation and deallocation. * * SEE ALSO * Composite Pool, cl_cpool_init *********/ /****s* Component Library: Composite Pool/cl_cpool_t * NAME * cl_cpool_t * * DESCRIPTION * Composite pool structure. * * The cl_cpool_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_cpool { cl_qcpool_t qcpool; cl_pfn_cpool_init_t pfn_init; cl_pfn_cpool_dtor_t pfn_dtor; const void *context; } cl_cpool_t; /* * FIELDS * qcpool * Quick composite pool that manages all objects. * * pfn_init * Pointer to the user's initializer callback, used by the pool * to translate the quick composite pool's initializer callback to * a composite pool initializer callback. * * pfn_dtor * Pointer to the user's destructor callback, used by the pool * to translate the quick composite pool's destructor callback to * a composite pool destructor callback. * * context * User's provided context for callback functions, used by the pool * to when invoking callbacks. * * SEE ALSO * Composite Pool *********/ /****f* Component Library: Composite Pool/cl_cpool_construct * NAME * cl_cpool_construct * * DESCRIPTION * The cl_cpool_construct function constructs a composite pool. * * SYNOPSIS */ void cl_cpool_construct(IN cl_cpool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_pool_init, cl_cpool_destroy, cl_is_cpool_inited. * * Calling cl_cpool_construct is a prerequisite to calling any other * composite pool function except cl_cpool_init. * * SEE ALSO * Composite Pool, cl_cpool_init, cl_cpool_destroy, cl_is_cpool_inited *********/ /****f* Component Library: Composite Pool/cl_is_cpool_inited * NAME * cl_is_cpool_inited * * DESCRIPTION * The cl_is_cpool_inited function returns whether a composite pool was * successfully initialized. * * SYNOPSIS */ static inline boolean_t cl_is_cpool_inited(IN const cl_cpool_t * const p_pool) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_pool); return (cl_is_qcpool_inited(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure whose initialization state * to check. * * RETURN VALUES * TRUE if the composite pool was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a composite pool to determine if invoking * member functions is appropriate. * * SEE ALSO * Composite Pool *********/ /****f* Component Library: Composite Pool/cl_cpool_init * NAME * cl_cpool_init * * DESCRIPTION * The cl_cpool_init function initializes a composite pool for use. * * SYNOPSIS */ cl_status_t cl_cpool_init(IN cl_cpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN size_t * const component_sizes, IN const uint32_t num_components, IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context); /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure to initialize. * * min_size * [in] Minimum number of objects that the pool should support. All * necessary allocations to allow storing the minimum number of items * are performed at initialization time, and all necessary callbacks * successfully invoked. * * max_size * [in] Maximum number of objects to which the pool is allowed to grow. * A value of zero specifies no maximum. * * grow_size * [in] Number of objects to allocate when incrementally growing the pool. * A value of zero disables automatic growth. * * component_sizes * [in] Pointer to the first entry in an array of sizes describing, * in order, the sizes of the components that make up a composite object. * * num_components * [in] Number of components that make up a composite object. * * pfn_initializer * [in] Initialization callback to invoke for every new object when * growing the pool. This parameter may be NULL only if the objects * stored in the composite pool consist of only one component. * See the cl_pfn_cpool_init function type declaration for details * about the callback function. * * pfn_destructor * [in] Destructor callback to invoke for every object before memory for * that object is freed. This parameter is optional and may be NULL. * See the cl_pfn_cpool_dtor function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * CL_SUCCESS if the composite pool was initialized successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the * composite pool. * * CL_INVALID_SETTING if a NULL constructor was provided for composite objects * consisting of more than one component. Also returns CL_INVALID_SETTING if * the maximum size is non-zero and less than the minimum size. * * Other cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter. * * NOTES * cl_cpool_init initializes, and if necessary, grows the pool to * the capacity desired. * * SEE ALSO * Composite Pool, cl_cpool_construct, cl_cpool_destroy, * cl_cpool_get, cl_cpool_put, cl_cpool_grow, * cl_cpool_count, cl_pfn_cpool_ctor_t, cl_pfn_cpool_init_t, * cl_pfn_cpool_dtor_t *********/ /****f* Component Library: Composite Pool/cl_cpool_destroy * NAME * cl_cpool_destroy * * DESCRIPTION * The cl_cpool_destroy function destroys a composite pool. * * SYNOPSIS */ static inline void cl_cpool_destroy(IN cl_cpool_t * const p_pool) { CL_ASSERT(p_pool); cl_qcpool_destroy(&p_pool->qcpool); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * All memory allocated for composite objects is freed. The destructor * callback, if any, will be invoked for every allocated object. Further * operations on the composite pool should not be attempted after * cl_cpool_destroy is invoked. * * This function should only be called after a call to cl_cpool_construct. * * In a debug build, cl_cpool_destroy asserts that all objects are in * the pool. * * SEE ALSO * Composite Pool, cl_cpool_construct, cl_cpool_init *********/ /****f* Component Library: Composite Pool/cl_cpool_count * NAME * cl_cpool_count * * DESCRIPTION * The cl_cpool_count function returns the number of available objects * in a composite pool. * * SYNOPSIS */ static inline size_t cl_cpool_count(IN cl_cpool_t * const p_pool) { CL_ASSERT(p_pool); return (cl_qcpool_count(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure for which the number of * available objects is requested. * * RETURN VALUE * Returns the number of objects available in the specified * composite pool. * * SEE ALSO * Composite Pool *********/ /****f* Component Library: Composite Pool/cl_cpool_get * NAME * cl_cpool_get * * DESCRIPTION * The cl_cpool_get function retrieves an object from a * composite pool. * * SYNOPSIS */ static inline void *cl_cpool_get(IN cl_cpool_t * const p_pool) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_pool); p_pool_obj = (cl_pool_obj_t *) cl_qcpool_get(&p_pool->qcpool); if (!p_pool_obj) return (NULL); CL_ASSERT(p_pool_obj->p_object); return ((void *)p_pool_obj->p_object); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure from which to retrieve * an object. * * RETURN VALUES * Returns a pointer to the first component of a composite object. * * Returns NULL if the pool is empty and can not be grown automatically. * * NOTES * cl_cpool_get returns the object at the head of the pool. If the pool is * empty, it is automatically grown to accommodate this request unless the * grow_size parameter passed to the cl_cpool_init function was zero. * * SEE ALSO * Composite Pool, cl_cpool_get_tail, cl_cpool_put, cl_cpool_grow, * cl_cpool_count *********/ /****f* Component Library: Composite Pool/cl_cpool_put * NAME * cl_cpool_put * * DESCRIPTION * The cl_cpool_put function returns an object to a composite pool. * * SYNOPSIS */ static inline void cl_cpool_put(IN cl_cpool_t * const p_pool, IN void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_pool); CL_ASSERT(p_object); /* Calculate the offset to the list object representing this object. */ p_pool_obj = (cl_pool_obj_t *) (((uint8_t *) p_object) - sizeof(cl_pool_obj_t)); /* good sanity check */ CL_ASSERT(p_pool_obj->p_object == p_object); cl_qcpool_put(&p_pool->qcpool, &p_pool_obj->pool_item); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure to which to return * an object. * * p_object * [in] Pointer to the first component of an object to return to the pool. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_cpool_put places the returned object at the head of the pool. * * The object specified by the p_object parameter must have been * retrieved from the pool by a previous call to cl_cpool_get. * * SEE ALSO * Composite Pool, cl_cpool_put_tail, cl_cpool_get *********/ /****f* Component Library: Composite Pool/cl_cpool_grow * NAME * cl_cpool_grow * * DESCRIPTION * The cl_cpool_grow function grows a composite pool by * the specified number of objects. * * SYNOPSIS */ static inline cl_status_t cl_cpool_grow(IN cl_cpool_t * const p_pool, IN const uint32_t obj_count) { CL_ASSERT(p_pool); return (cl_qcpool_grow(&p_pool->qcpool, obj_count)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_cpool_t structure whose capacity to grow. * * obj_count * [in] Number of objects by which to grow the pool. * * RETURN VALUES * CL_SUCCESS if the composite pool grew successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the * composite pool. * * cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter passed to the * cl_cpool_init function. * * NOTES * It is not necessary to call cl_cpool_grow if the pool is * configured to grow automatically. * * SEE ALSO * Composite Pool *********/ END_C_DECLS #endif /* _CL_COMP_POOL_H_ */ opensm-3.3.20/include/complib/cl_debug.h0000644000205000001450000003670212104655724015013 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of functions for reporting debug output. */ #ifndef _CL_DEBUG_H_ #define _CL_DEBUG_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Debug Output * NAME * Debug Output * * DESCRIPTION * The debug output functions and macros send debug messages to the current * debug target. *********/ /****f* Component Library: Debug Output/cl_break * NAME * cl_break * * DESCRIPTION * The cl_break function halts execution. * * SYNOPSIS * void * cl_break(); * * RETURN VALUE * This function does not return a value. * * NOTES * In a release build, cl_break has no effect. *********/ /****f* Component Library: Debug Output/cl_is_debug * NAME * cl_is_debug * * DESCRIPTION * The cl_is_debug function returns TRUE if the complib was compiled * in debug mode, and FALSE otherwise. * * SYNOPSIS */ boolean_t cl_is_debug(void); /* * PARAMETERS * None * * RETURN VALUE * TRUE if compiled in debug version. FALSE otherwise. * * NOTES * *********/ #if defined( _DEBUG_ ) #ifndef cl_dbg_out /****f* Component Library: Debug Output/cl_dbg_out * NAME * cl_dbg_out * * DESCRIPTION * The cl_dbg_out function sends a debug message to the debug target in * debug builds only. * * SYNOPSIS */ void cl_dbg_out(IN const char *const debug_message, IN ...); /* * PARAMETERS * debug_message * [in] ANSI string formatted identically as for a call to the standard C * function printf. * * ... * [in] Extra parameters for string formatting, as defined for the * standard C function printf. * * RETURN VALUE * This function does not return a value. * * NOTES * In a release build, cl_dbg_out has no effect. * * The formatting of the debug_message string is the same as for printf * * cl_dbg_out sends the debug message to the current debug target. * * SEE ALSO * Debug Output, cl_msg_out *********/ #endif #else static inline void cl_dbg_out(IN const char *const debug_message, IN ...) { UNUSED_PARAM(debug_message); } #endif /* defined( _DEBUG_ ) */ #ifndef cl_msg_out /****f* Component Library: Debug Output/cl_msg_out * NAME * cl_msg_out * * DESCRIPTION * The cl_msg_out function sends a debug message to the message log target. * * SYNOPSIS */ void cl_msg_out(IN const char *const message, IN ...); /* * PARAMETERS * message * [in] ANSI string formatted identically as for a call to the standard C * function printf. * * ... * [in] Extra parameters for string formatting, as defined for the * standard C function printf. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_msg_out is available in both debug and release builds. * * The formatting of the message string is the same as for printf * * cl_msg_out sends the message to the current message logging target. * * SEE ALSO * Debug Output, cl_dbg_out *********/ #endif /****d* Component Library: Debug Output/Debug Levels * NAME * Debug Levels * * DESCRIPTION * The debug output macros reserve the upper bit of the debug level to * convey an error. * * SYNOPSIS */ #define CL_DBG_DISABLE 0 #define CL_DBG_ERROR 0x80000000 #define CL_DBG_ALL 0xFFFFFFFF /* * VALUES * CL_DBG_DISABLE * Disable all debug output, including errors. * * CL_DBG_ERROR * Enable error debug output. * * CL_DBG_ALL * Enbale all debug output. * * NOTES * Users can define custom debug levels using the lower 31 bits of their * debug level to control non-error debug output. Error messages are * always displayed, regardless of the lower bit definition. * * When specifying the debug output desired for non-error messages * (the CHK_LVL parameter in the debug output macros), users must define * all bits whose output they are interested in. * * SEE ALSO * Debug Output, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE, CL_TRACE_EXIT *********/ #if defined(_DEBUG_) /****d* Component Library: Debug Output/CL_PRINT * NAME * CL_PRINT * * DESCRIPTION * The CL_PRINT macro sends a string to the current debug target if * the requested debug level matches the current debug level. * * SYNOPSIS * CL_PRINT( DBG_LVL, CHK_LVL, STRING ); * * PARAMETERS * DBG_LVL * [in] Debug level for the string to output * * CHK_LVL * [in] Current debug level against which to check DBG_LVL * * STRING * [in] String to send to the current debug target. The string includes * parentheses in order to allow additional parameters. * * RETURN VALUE * This macro does not return a value. * * EXAMPLE * #define MY_FUNC_DBG_LVL 1 * * uint32_t my_dbg_lvl = CL_DBG_ALL; * * void * my_func() * { * CL_PRINT( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") ); * } * * RESULT * Hello world! * * NOTES * The requested string is printed only if all bits set in DBG_LVL are also * set in CHK_LVL unless the most significant bit is set (indicating an * error), in which case the lower bits are ignored. CHK_LVL may have * additional bits set. * * In multi-processor environments where the current processor can be * determined, the zero-based number of the processor on which the output * is generated is prepended to the output. * * SEE ALSO * Debug Output, Debug Levels, CL_ENTER, CL_EXIT, CL_TRACE, CL_TRACE_EXIT *********/ #define CL_PRINT( DBG_LVL, CHK_LVL, STRING ) \ { \ if( DBG_LVL & CL_DBG_ERROR ) \ cl_dbg_out STRING; \ else if( (DBG_LVL & CHK_LVL) == DBG_LVL ) \ cl_dbg_out STRING; \ } /****d* Component Library: Debug Output/CL_ENTER * NAME * CL_ENTER * * DESCRIPTION * The CL_ENTER macro marks the entrance into a function by sending a * string to the current debug target if the requested debug level matches * the current debug level. * * SYNOPSIS * CL_ENTER( DBG_LVL, CHK_LVL ); * * PARAMETERS * DBG_LVL * [in] Debug level for the string to output * * CHK_LVL * [in] Current debug level against which to check DBG_LVL * * RETURN VALUE * This macro does not return a value. * * EXAMPLE * #define __MODULE__ "my_module" * #define MY_FUNC_DBG_LVL 1 * * uint32_t my_dbg_lvl = CL_DBG_ALL; * * void * my_func() * { * CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl ); * CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl ); * } * * RESULT * my_module:my_func() [ * my_module:my_func() ] * * NOTES * The function entrance notification is printed only if all bits set * in DBG_LVL are also set in CHK_LVL. CHK_LVL may have additional bits set. * * If the __MODULE__ preprocessor keyword is defined, that keyword will be * prepended to the function name, separated with a colon. * * In multi-processor environments where the current processor can be * determined, the zero-based number of the processor on which the output * is generated is prepended to the output. * * SEE ALSO * Debug Output, Debug Levels, CL_PRINT, CL_EXIT, CL_TRACE, CL_TRACE_EXIT *********/ #define CL_ENTER( DBG_LVL, CHK_LVL ) \ CL_CHK_STK; \ CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_ENTER ); /****d* Component Library: Debug Output/CL_EXIT * NAME * CL_EXIT * * DESCRIPTION * The CL_EXIT macro marks the exit from a function by sending a string * to the current debug target if the requested debug level matches the * current debug level. * * SYNOPSIS * CL_EXIT( DBG_LVL, CHK_LVL ); * * PARAMETERS * DBG_LVL * [in] Debug level for the string to output * * CHK_LVL * [in] Current debug level against which to check DBG_LVL * * RETURN VALUE * This macro does not return a value. * * EXAMPLE * #define __MODULE__ "my_module" * #define MY_FUNC_DBG_LVL 1 * * uint32_t my_dbg_lvl = CL_DBG_ALL; * * void * my_func() * { * CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl ); * CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl ); * } * * RESULT * my_module:my_func() [ * my_module:my_func() ] * * NOTES * The exit notification is printed only if all bits set in DBG_LVL are also * set in CHK_LVL. CHK_LVL may have additional bits set. * * The CL_EXIT macro must only be used after the CL_ENTRY macro as it * depends on that macro's implementation. * * If the __MODULE__ preprocessor keyword is defined, that keyword will be * prepended to the function name, separated with a colon. * * In multi-processor environments where the current processor can be * determined, the zero-based number of the processor on which the output * is generated is prepended to the output. * * SEE ALSO * Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_TRACE, CL_TRACE_EXIT *********/ #define CL_EXIT( DBG_LVL, CHK_LVL ) \ CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_EXIT ); /****d* Component Library: Debug Output/CL_TRACE * NAME * CL_TRACE * * DESCRIPTION * The CL_TRACE macro sends a string to the current debug target if * the requested debug level matches the current debug level. The * output is prepended with the function name and, depending on the * debug level requested, an indication of the severity of the message. * * SYNOPSIS * CL_TRACE( DBG_LVL, CHK_LVL, STRING ); * * PARAMETERS * DBG_LVL * [in] Debug level for the string to output * * CHK_LVL * [in] Current debug level against which to check DBG_LVL * * STRING * [in] String to send to the current debug target. The string includes * parentheses in order to allow additional parameters. * * RETURN VALUE * This macro does not return a value. * * EXAMPLE * #define __MODULE__ "my_module" * #define MY_FUNC_DBG_LVL 1 * * uint32_t my_dbg_lvl = CL_DBG_ALL; * * void * my_func() * { * CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl ); * CL_TRACE( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") ); * CL_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl ); * } * * RESULT * my_module:my_func() [ * my_module:my_func(): Hello world! * my_module:my_func() ] * * NOTES * The requested string is printed only if all bits set in DBG_LVL are also * set in CHK_LVL. CHK_LVL may have additional bits set. * * The CL_TRACE macro must only be used after the CL_ENTRY macro as it * depends on that macro's implementation. * * If the DBG_LVL has the upper bit set, the output will contain * an "!ERROR!" statement between the function name and STRING. * * If the __MODULE__ preprocessor keyword is defined, that keyword will be * prepended to the function name, separated with a colon. * * In multi-processor environments where the current processor can be * determined, the zero-based number of the processor on which the output * is generated is prepended to the output. * * SEE ALSO * Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE_EXIT *********/ #define CL_TRACE( DBG_LVL, CHK_LVL, STRING ) \ { \ switch( DBG_LVL & CL_DBG_ERROR ) \ { \ case CL_DBG_ERROR: \ CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_ERROR ); \ break; \ default: \ CL_PRINT( DBG_LVL, CHK_LVL, _CL_DBG_INFO ); \ break; \ } \ CL_PRINT( DBG_LVL, CHK_LVL, STRING ); \ } /****d* Component Library: Debug Output/CL_TRACE_EXIT * NAME * CL_TRACE_EXIT * * DESCRIPTION * The CL_TRACE_EXIT macro combines the functionality of the CL_TRACE and * CL_EXIT macros, in that order. * * SYNOPSIS * CL_TRACE_EXIT( DBG_LVL, CHK_LVL, STRING ); * * PARAMETERS * DBG_LVL * [in] Debug level for the string to output * * CHK_LVL * [in] Current debug level against which to check DBG_LVL * * STRING * [in] String to send to the current debug target. The string includes * parentheses in order to allow additional parameters. * * RETURN VALUE * This macro does not return a value. * * EXAMPLE * #define __MODULE__ "my_module" * #define MY_FUNC_DBG_LVL 1 * * uint32_t my_dbg_lvl = CL_DBG_ALL; * * void * my_func() * { * CL_ENTER( MY_FUNC_DBG_LVL, my_dbg_lvl ); * CL_TRACE_EXIT( MY_FUNC_DBG_LVL, my_dbg_lvl, ("Hello %s!\n", "world") ); * } * * RESULT * my_module:my_func() [ * my_module:my_func(): Hello world! * my_module:my_func() ] * * NOTES * The requested string is printed only if all bits set in DBG_LVL are also * set in CHK_LVL. CHK_LVL may have additional bits set. * * The CL_TRACE_EXIT macro must only be used after the CL_ENTRY macro as it * depends on that macro's implementation. * * If the DBG_LVL has the upper bit set, the output will contain * an "!ERROR!" statement between the function name and STRING. * * If the __MODULE__ preprocessor keyword is defined, that keyword will be * prepended to the function name, separated with a colon. * * In multi-processor environments where the current processor can be * determined, the zero-based number of the processor on which the output * is generated is prepended to the output. * * SEE ALSO * Debug Output, Debug Levels, CL_PRINT, CL_ENTER, CL_EXIT, CL_TRACE *********/ #define CL_TRACE_EXIT( DBG_LVL, CHK_LVL, STRING ) \ CL_TRACE( DBG_LVL, CHK_LVL, STRING ); \ CL_EXIT( DBG_LVL, CHK_LVL ); #else /* defined(_DEBUG_) */ /* Define as NULL macros in a free build. */ #define CL_PRINT( DBG_LVL, CHK_LVL, STRING ); #define CL_ENTER( DBG_LVL, CHK_LVL ); #define CL_EXIT( DBG_LVL, CHK_LVL ); #define CL_TRACE( DBG_LVL, CHK_LVL, STRING ); #define CL_TRACE_EXIT( DBG_LVL, CHK_LVL, STRING ); #endif /* defined(_DEBUG_) */ /****d* Component Library: Debug Output/64-bit Print Format * NAME * 64-bit Print Format * * DESCRIPTION * The 64-bit print keywords allow users to use 64-bit values in debug or * console output. * * Different platforms define 64-bit print formats differently. The 64-bit * print formats exposed by the component library are supported in all * platforms. * * VALUES * PRId64 * Print a 64-bit integer in signed decimal format. * PRIx64 * Print a 64-bit integer in hexadecimal format. * PRIo64 * Print a 64-bit integer in octal format. * PRIu64 * Print a 64-bit integer in unsigned decimal format. * * EXAMPLE * uint64 MyVal = 2; * // Print a 64-bit integer in hexadecimal format. * cl_dbg_out( "MyVal: 0x%" PRIx64 "\n", MyVal ); * * NOTES * Standard print flags to specify padding and precision can still be used * following the '%' sign in the string preceding the 64-bit print keyword. * * The above keywords are strings and make use of compilers' string * concatenation ability. *********/ void complib_init(void); void complib_exit(void); END_C_DECLS #endif /* _CL_DEBUG_H_ */ opensm-3.3.20/include/complib/cl_debug_osd.h0000644000205000001450000000556412104655724015662 00000000000000/* * 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: * Debug Macros. */ #ifndef _CL_DEBUG_OSD_H_ #define _CL_DEBUG_OSD_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #if !defined(__MODULE__) #define __MODULE__ "" #define __MOD_DELIMITER__ "" #else /* !defined(__MODULE__) */ #define __MOD_DELIMITER__ ":" #endif /* !defined(__MODULE__) */ /* * Define specifiers for print functions based on the platform */ #ifdef __IA64__ #define PRIdSIZE_T "ld" #else #define PRIdSIZE_T "d" #endif #include #include #define cl_msg_out printf #if defined( _DEBUG_ ) #define cl_dbg_out printf #else #define cl_dbg_out foo #endif /* _DEBUG_ */ /* * The following macros are used internally by the CL_ENTER, CL_TRACE, * CL_TRACE_EXIT, and CL_EXIT macros. */ #define _CL_DBG_ENTER \ ("%s%s%s() [\n", __MODULE__, __MOD_DELIMITER__, __func__) #define _CL_DBG_EXIT \ ("%s%s%s() ]\n", __MODULE__, __MOD_DELIMITER__, __func__) #define _CL_DBG_INFO \ ("%s%s%s(): ", __MODULE__, __MOD_DELIMITER__, __func__) #define _CL_DBG_ERROR \ ("%s%s%s() !ERROR!: ", __MODULE__, __MOD_DELIMITER__, __func__) #define CL_CHK_STK END_C_DECLS #endif /* _CL_DEBUG_OSD_H_ */ opensm-3.3.20/include/complib/cl_dispatcher.h0000644000205000001450000003625512104655724016056 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of dispatcher abstraction. */ #ifndef _CL_DISPATCHER_H_ #define _CL_DISPATCHER_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Dispatcher * NAME * Dispatcher * * DESCRIPTION * The Dispatcher provides a facility for message routing to * asynchronous worker threads. * * The Dispatcher functions operate on a cl_dispatcher_t structure * which should be treated as opaque and should be manipulated * only through the provided functions. * * SEE ALSO * Structures: * cl_dispatcher_t * * Initialization/Destruction: * cl_disp_construct, cl_disp_init, cl_disp_shutdown, cl_disp_destroy * * Manipulation: * cl_disp_post, cl_disp_reset, cl_disp_wait_on *********/ /****s* Component Library: Dispatcher/cl_disp_msgid_t * NAME * cl_disp_msgid_t * * DESCRIPTION * Defines the type of dispatcher messages. * * SYNOPSIS */ typedef uint32_t cl_disp_msgid_t; /**********/ /****s* Component Library: Dispatcher/CL_DISP_MSGID_NONE * NAME * CL_DISP_MSGID_NONE * * DESCRIPTION * Defines a message value that means "no message". * This value is used during registration by Dispatcher clients * that do not wish to receive messages. * * No Dispatcher message is allowed to have this value. * * SYNOPSIS */ #define CL_DISP_MSGID_NONE 0xFFFFFFFF /**********/ /****s* Component Library: Dispatcher/CL_DISP_INVALID_HANDLE * NAME * CL_DISP_INVALID_HANDLE * * DESCRIPTION * Defines the value of an invalid Dispatcher registration handle. * * SYNOPSIS */ #define CL_DISP_INVALID_HANDLE ((cl_disp_reg_handle_t)0) /*********/ /****f* Component Library: Dispatcher/cl_pfn_msgrcv_cb_t * NAME * cl_pfn_msgrcv_cb_t * * DESCRIPTION * This typedef defines the prototype for client functions invoked * by the Dispatcher. The Dispatcher calls the corresponding * client function when delivering a message to the client. * * The client function must be reentrant if the user creates a * Dispatcher with more than one worker thread. * * SYNOPSIS */ typedef void (*cl_pfn_msgrcv_cb_t) (IN void *context, IN void *p_data); /* * PARAMETERS * context * [in] Client specific context specified in a call to * cl_disp_register * * p_data * [in] Pointer to the client specific data payload * of this message. * * RETURN VALUE * This function does not return a value. * * NOTES * This typedef provides a function prototype reference for * the function provided by Dispatcher clients as a parameter * to the cl_disp_register function. * * SEE ALSO * Dispatcher, cl_disp_register *********/ /****f* Component Library: Dispatcher/cl_pfn_msgdone_cb_t * NAME * cl_pfn_msgdone_cb_t * * DESCRIPTION * This typedef defines the prototype for client functions invoked * by the Dispatcher. The Dispatcher calls the corresponding * client function after completing delivery of a message. * * The client function must be reentrant if the user creates a * Dispatcher with more than one worker thread. * * SYNOPSIS */ typedef void (*cl_pfn_msgdone_cb_t) (IN void *context, IN void *p_data); /* * PARAMETERS * context * [in] Client specific context specified in a call to * cl_disp_post * * p_data * [in] Pointer to the client specific data payload * of this message. * * RETURN VALUE * This function does not return a value. * * NOTES * This typedef provides a function prototype reference for * the function provided by Dispatcher clients as a parameter * to the cl_disp_post function. * * SEE ALSO * Dispatcher, cl_disp_post *********/ /****s* Component Library: Dispatcher/cl_dispatcher_t * NAME * cl_dispatcher_t * * DESCRIPTION * Dispatcher structure. * * The Dispatcher is thread safe. * * The cl_dispatcher_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_dispatcher { cl_spinlock_t lock; cl_ptr_vector_t reg_vec; cl_qlist_t reg_list; cl_thread_pool_t worker_threads; cl_qlist_t msg_fifo; cl_qpool_t msg_pool; uint64_t last_msg_queue_time_us; } cl_dispatcher_t; /* * FIELDS * reg_vec * Vector of registration info objects. Indexed by message msg_id. * * lock * Spinlock to guard internal structures. * * msg_fifo * FIFO of messages being processed by the Dispatcher. New * messages are posted to the tail of the FIFO. Worker threads * pull messages from the front. * * worker_threads * Thread pool of worker threads to dispose of posted messages. * * msg_pool * Pool of message objects to be processed through the FIFO. * * reg_count * Count of the number of registrants. * * state * Indicates the state of the object. * * last_msg_queue_time_us * The time that the last message spent in the Q in usec * * SEE ALSO * Dispatcher *********/ /****s* Component Library: Dispatcher/cl_disp_reg_info_t * NAME * cl_disp_reg_info_t * * DESCRIPTION * Defines the dispatcher registration object structure. * * The cl_disp_reg_info_t structure is for internal use by the * Dispatcher only. * * SYNOPSIS */ typedef struct _cl_disp_reg_info { cl_list_item_t list_item; cl_pfn_msgrcv_cb_t pfn_rcv_callback; const void *context; atomic32_t ref_cnt; cl_disp_msgid_t msg_id; cl_dispatcher_t *p_disp; } cl_disp_reg_info_t; /* * FIELDS * pfn_rcv_callback * Client's message receive callback. * * context * Client's context for message receive callback. * * rcv_thread_count * Number of threads currently in the receive callback. * * msg_done_thread_count * Number of threads currently in the message done callback. * * state * State of this registration object. * DISP_REGSTATE_INIT: initialized and inactive * DISP_REGSTATE_ACTIVE: in active use * DISP_REGSTATE_UNREGPEND: unregistration is pending * * msg_id * Dispatcher message msg_id value for this registration object. * * p_disp * Pointer to parent Dispatcher. * * SEE ALSO *********/ /****s* Component Library: Dispatcher/cl_disp_msg_t * NAME * cl_disp_msg_t * * DESCRIPTION * Defines the dispatcher message structure. * * The cl_disp_msg_t structure is for internal use by the * Dispatcher only. * * SYNOPSIS */ typedef struct _cl_disp_msg { cl_pool_item_t item; const void *p_data; cl_disp_reg_info_t *p_src_reg; cl_disp_reg_info_t *p_dest_reg; cl_pfn_msgdone_cb_t pfn_xmt_callback; uint64_t in_time; const void *context; } cl_disp_msg_t; /* * FIELDS * item * List & Pool linkage. Must be first element in the structure!! * * msg_id * The message's numberic ID value. * * p_data * Pointer to the data payload for this message. The payload * is opaque to the Dispatcher. * * p_reg_info * Pointer to the registration info of the sender. * * pfn_xmt_callback * Client's message done callback. * * in_time * The absolute time the message was inserted into the queue * * context * Client's message done callback context. * * SEE ALSO *********/ /****s* Component Library: Dispatcher/cl_disp_reg_info_t * NAME * cl_disp_reg_info_t * * DESCRIPTION * Defines the Dispatcher registration handle. This handle * should be treated as opaque by the client. * * SYNOPSIS */ typedef const struct _cl_disp_reg_info *cl_disp_reg_handle_t; /**********/ /****f* Component Library: Dispatcher/cl_disp_construct * NAME * cl_disp_construct * * DESCRIPTION * This function constructs a Dispatcher object. * * SYNOPSIS */ void cl_disp_construct(IN cl_dispatcher_t * const p_disp); /* * PARAMETERS * p_disp * [in] Pointer to a Dispatcher. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_disp_init and cl_disp_destroy. * * SEE ALSO * Dispatcher, cl_disp_init, cl_disp_destroy *********/ /****f* Component Library: Dispatcher/cl_disp_init * NAME * cl_disp_init * * DESCRIPTION * This function initializes a Dispatcher object. * * SYNOPSIS */ cl_status_t cl_disp_init(IN cl_dispatcher_t * const p_disp, IN const uint32_t thread_count, IN const char *const name); /* * PARAMETERS * p_disp * [in] Pointer to a Dispatcher. * * thread_count * [in] The number of worker threads to create in this Dispatcher. * A value of 0 causes the Dispatcher to create one worker thread * per CPU in the system. When the Dispatcher is created with * only one thread, the Dispatcher guarantees to deliver posted * messages in order. When the Dispatcher is created with more * than one thread, messages may be delivered out of order. * * name * [in] Name to associate with the threads. The name may be up to 16 * characters, including a terminating null character. All threads * created in the Dispatcher have the same name. * * RETURN VALUE * CL_SUCCESS if the operation is successful. * * SEE ALSO * Dispatcher, cl_disp_destoy, cl_disp_register, cl_disp_unregister, * cl_disp_post *********/ /****f* Component Library: Dispatcher/cl_disp_shutdown * NAME * cl_disp_shutdown * * DESCRIPTION * This function shutdown a Dispatcher object. So it unreg all messages and * clears the fifo and waits for the threads to exit * * SYNOPSIS */ void cl_disp_shutdown(IN cl_dispatcher_t * const p_disp); /* * PARAMETERS * p_disp * [in] Pointer to a Dispatcher. * * RETURN VALUE * This function does not return a value. * * NOTES * This function does not returns until all worker threads * have exited client callback functions and been successfully * shutdowned. * * SEE ALSO * Dispatcher, cl_disp_construct, cl_disp_init *********/ /****f* Component Library: Dispatcher/cl_disp_destroy * NAME * cl_disp_destroy * * DESCRIPTION * This function destroys a Dispatcher object. * * SYNOPSIS */ void cl_disp_destroy(IN cl_dispatcher_t * const p_disp); /* * PARAMETERS * p_disp * [in] Pointer to a Dispatcher. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Dispatcher, cl_disp_construct, cl_disp_init *********/ /****f* Component Library: Dispatcher/cl_disp_register * NAME * cl_disp_register * * DESCRIPTION * This function registers a client with a Dispatcher object. * * SYNOPSIS */ cl_disp_reg_handle_t cl_disp_register(IN cl_dispatcher_t * const p_disp, IN const cl_disp_msgid_t msg_id, IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL, IN const void *const context); /* * PARAMETERS * p_disp * [in] Pointer to a Dispatcher. * * msg_id * [in] Numberic message ID for which the client is registering. * If the client does not wish to receive any messages, * (a send-only client) then the caller should set this value * to CL_DISP_MSGID_NONE. For efficiency, numeric message msg_id * values should start with 0 and should be contiguous, or nearly so. * * pfn_callback * [in] Message receive callback. The Dispatcher calls this * function after receiving a posted message with the * appropriate message msg_id value. Send-only clients may specify * NULL for this value. * * context * [in] Client context value passed to the cl_pfn_msgrcv_cb_t * function. * * RETURN VALUE * On success a Dispatcher registration handle. * CL_CL_DISP_INVALID_HANDLE otherwise. * * SEE ALSO * Dispatcher, cl_disp_unregister, cl_disp_post *********/ /****f* Component Library: Dispatcher/cl_disp_unregister * NAME * cl_disp_unregister * * DESCRIPTION * This function unregisters a client from a Dispatcher. * * SYNOPSIS */ void cl_disp_unregister(IN const cl_disp_reg_handle_t handle); /* * PARAMETERS * handle * [in] cl_disp_reg_handle_t value return by cl_disp_register. * * RETURN VALUE * This function does not return a value. * * NOTES * This function will not return until worker threads have exited * the callback functions for this client. Do not invoke this * function from a callback. * * SEE ALSO * Dispatcher, cl_disp_register *********/ /****f* Component Library: Dispatcher/cl_disp_post * NAME * cl_disp_post * * DESCRIPTION * This function posts a message to a Dispatcher object. * * SYNOPSIS */ cl_status_t cl_disp_post(IN const cl_disp_reg_handle_t handle, IN const cl_disp_msgid_t msg_id, IN const void *const p_data, IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL, IN const void *const context); /* * PARAMETERS * handle * [in] cl_disp_reg_handle_t value return by cl_disp_register. * * msg_id * [in] Numeric message msg_id value associated with this message. * * p_data * [in] Data payload for this message. * * pfn_callback * [in] Pointer to a cl_pfn_msgdone_cb_t function. * The Dispatcher calls this function after the message has been * processed by the recipient. * The caller may pass NULL for this value, which indicates no * message done callback is necessary. * * context * [in] Client context value passed to the cl_pfn_msgdone_cb_t * function. * * RETURN VALUE * CL_SUCCESS if the message was successfully queued in the Dispatcher. * * NOTES * The caller must not modify the memory pointed to by p_data until * the Dispatcher call the pfn_callback function. * * SEE ALSO * Dispatcher *********/ /****f* Component Library: Dispatcher/cl_disp_get_queue_status * NAME * cl_disp_get_queue_status * * DESCRIPTION * This function posts a message to a Dispatcher object. * * SYNOPSIS */ void cl_disp_get_queue_status(IN const cl_disp_reg_handle_t handle, OUT uint32_t * p_num_queued_msgs, OUT uint64_t * p_last_msg_queue_time_ms); /* * PARAMETERS * handle * [in] cl_disp_reg_handle_t value return by cl_disp_register. * * p_last_msg_queue_time_ms * [out] pointer to a variable to hold the time the last popped up message * spent in the queue * * p_num_queued_msgs * [out] number of messages in the queue * * RETURN VALUE * Thr time the last popped up message stayed in the queue, in msec * * NOTES * Extarnel Locking is not required. * * SEE ALSO * Dispatcher *********/ END_C_DECLS #endif /* !defined(_CL_DISPATCHER_H_) */ opensm-3.3.20/include/complib/cl_event.h0000644000205000001450000001617712104655724015052 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of event abstraction. */ #ifndef _CL_EVENT_H_ #define _CL_EVENT_H_ /* Indicates that waiting on an event should never timeout */ #define EVENT_NO_TIMEOUT 0xFFFFFFFF #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Event * NAME * Event * * DESCRIPTION * The Event provides the ability to suspend and wakeup a thread. * * The event functions operates on a cl_event_t structure which should be * treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_event_t * * Initialization/Destruction: * cl_event_construct, cl_event_init, cl_event_destroy * * Manipulation: * cl_event_signal, cl_event_reset, cl_event_wait_on *********/ /****f* Component Library: Event/cl_event_construct * NAME * cl_event_construct * * DESCRIPTION * The cl_event_construct function constructs an event. * * SYNOPSIS */ void cl_event_construct(IN cl_event_t * const p_event); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_event_destroy without first calling cl_event_init. * * Calling cl_event_construct is a prerequisite to calling any other event * function except cl_event_init. * * SEE ALSO * Event, cl_event_init, cl_event_destroy *********/ /****f* Component Library: Event/cl_event_init * NAME * cl_event_init * * DESCRIPTION * The cl_event_init function initializes an event for use. * * SYNOPSIS */ cl_status_t cl_event_init(IN cl_event_t * const p_event, IN const boolean_t manual_reset); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure to initialize. * * manual_reset * [in] If FALSE, indicates that the event resets itself after releasing * a single waiter. If TRUE, the event remains in the signalled state * until explicitly reset by a call to cl_event_reset. * * RETURN VALUES * CL_SUCCESS if event initialization succeeded. * * CL_ERROR otherwise. * * NOTES * Allows calling event manipulation functions, such as cl_event_signal, * cl_event_reset, and cl_event_wait_on. * * The event is initially in a reset state. * * SEE ALSO * Event, cl_event_construct, cl_event_destroy, cl_event_signal, * cl_event_reset, cl_event_wait_on *********/ /****f* Component Library: Event/cl_event_destroy * NAME * cl_event_destroy * * DESCRIPTION * The cl_event_destroy function performs any necessary cleanup of an event. * * SYNOPSIS */ void cl_event_destroy(IN cl_event_t * const p_event); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * This function should only be called after a call to cl_event_construct * or cl_event_init. * * SEE ALSO * Event, cl_event_construct, cl_event_init *********/ /****f* Component Library: Event/cl_event_signal * NAME * cl_event_signal * * DESCRIPTION * The cl_event_signal function sets an event to the signalled state and * releases at most one waiting thread. * * SYNOPSIS */ cl_status_t cl_event_signal(IN cl_event_t * const p_event); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure to set. * * RETURN VALUES * CL_SUCCESS if the event was successfully signalled. * * CL_ERROR otherwise. * * NOTES * For auto-reset events, the event is reset automatically once a wait * operation is satisfied. * * Triggering the event multiple times does not guarantee that the same * number of wait operations are satisfied. This is because events are * either in a signalled on non-signalled state, and triggering an event * that is already in the signalled state has no effect. * * SEE ALSO * Event, cl_event_reset, cl_event_wait_on *********/ /****f* Component Library: Event/cl_event_reset * NAME * cl_event_reset * * DESCRIPTION * The cl_event_reset function sets an event to the non-signalled state. * * SYNOPSIS */ cl_status_t cl_event_reset(IN cl_event_t * const p_event); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure to reset. * * RETURN VALUES * CL_SUCCESS if the event was successfully reset. * * CL_ERROR otherwise. * * SEE ALSO * Event, cl_event_signal, cl_event_wait_on *********/ /****f* Component Library: Event/cl_event_wait_on * NAME * cl_event_wait_on * * DESCRIPTION * The cl_event_wait_on function waits for the specified event to be * triggered for a minimum amount of time. * * SYNOPSIS */ cl_status_t cl_event_wait_on(IN cl_event_t * const p_event, IN const uint32_t wait_us, IN const boolean_t interruptible); /* * PARAMETERS * p_event * [in] Pointer to an cl_event_t structure on which to wait. * * wait_us * [in] Number of microseconds to wait. * * interruptible * [in] Indicates whether the wait operation can be interrupted * by external signals. * * RETURN VALUES * CL_SUCCESS if the wait operation succeeded in response to the event * being set. * * CL_TIMEOUT if the specified time period elapses. * * CL_NOT_DONE if the wait was interrupted by an external signal. * * CL_ERROR if the wait operation failed. * * NOTES * If wait_us is set to EVENT_NO_TIMEOUT, the function will wait until the * event is triggered and never timeout. * * If the timeout value is zero, this function simply tests the state of * the event. * * If the event is already on the signalled state at the time of the call * to cl_event_wait_on, the call completes immediately with CL_SUCCESS. * * SEE ALSO * Event, cl_event_signal, cl_event_reset *********/ END_C_DECLS #endif /* _CL_EVENT_H_ */ opensm-3.3.20/include/complib/cl_event_wheel.h0000644000205000001450000002553412272264652016235 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of event wheel abstraction. */ #ifndef _CL_EVENT_WHEEL_H_ #define _CL_EVENT_WHEEL_H_ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Event_Wheel * NAME * Event_Wheel * * DESCRIPTION * The Event_Wheel provides a facility for registering delayed events * and getting called once they timeout. * * The Event_Wheel functions operate on a cl_event_wheel_t structure * which should be treated as opaque and should be manipulated * only through the provided functions. * * SEE ALSO * Structures: * cl_event_wheel_t * * Initialization/Destruction: * cl_event_wheel_construct, cl_event_wheel_init, cl_event_wheel_destroy * * Manipulation: * cl_event_wheel_reg, cl_event_wheel_unreg * *********/ /****f* Component Library: Event_Wheel/cl_pfn_event_aged_cb_t * NAME * cl_pfn_event_aged_cb_t * * DESCRIPTION * This typedef defines the prototype for client functions invoked * by the Event_Wheel. The Event_Wheel calls the corresponding * client function when the specific item has aged. * * SYNOPSIS */ typedef uint64_t (*cl_pfn_event_aged_cb_t) (IN uint64_t key, IN uint32_t num_regs, IN void *context); /* * PARAMETERS * key * [in] The key used for registering the item in the call to * cl_event_wheel_reg. * * num_regs * [in] The number of times this event was registered (pushed in time). * * context * [in] Client specific context specified in a call to * cl_event_wheel_reg * * RETURN VALUE * This function returns the abosolute time the event should fire in [usec]. * If lower then current time means the event should be unregistered * immediatly. * * NOTES * This typedef provides a function prototype reference for * the function provided by Event_Wheel clients as a parameter * to the cl_event_wheel_reg function. * * SEE ALSO * Event_Wheel, cl_event_wheel_reg *********/ /****s* Component Library: Event_Wheel/cl_event_wheel_t * NAME * cl_event_wheel_t * * DESCRIPTION * Event_Wheel structure. * * The Event_Wheel is thread safe. * * The cl_event_wheel_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_event_wheel { cl_spinlock_t lock; cl_spinlock_t *p_external_lock; cl_qmap_t events_map; boolean_t closing; cl_qlist_t events_wheel; cl_timer_t timer; } cl_event_wheel_t; /* * FIELDS * lock * Spinlock to guard internal structures. * * p_external_lock * Reference to external spinlock to guard internal structures * if the event wheel is part of a larger object protected by its own lock * * events_map * A Map holding all registered event items by their key. * * closing * A flag indicating the event wheel is closing. This means that * callbacks that are called when closing == TRUE should just be ignored. * * events_wheel * A list of the events sorted by expiration time. * * timer * The timer scheduling event time propagation. * * SEE ALSO * Event_Wheel *********/ /****s* Component Library: Event_Wheel/cl_event_wheel_reg_info_t * NAME * cl_event_wheel_reg_info_t * * DESCRIPTION * Defines the event_wheel registration object structure. * * The cl_event_wheel_reg_info_t structure is for internal use by the * Event_Wheel only. * * SYNOPSIS */ typedef struct _cl_event_wheel_reg_info { cl_map_item_t map_item; cl_list_item_t list_item; uint64_t key; cl_pfn_event_aged_cb_t pfn_aged_callback; uint64_t aging_time; uint32_t num_regs; void *context; cl_event_wheel_t *p_event_wheel; } cl_event_wheel_reg_info_t; /* * FIELDS * map_item * The map item of this event * * list_item * The sorted by aging time list item * * key * The key by which one can find the event * * pfn_aged_callback * The clients Event-Aged callback * * aging_time * The delta time [msec] for which the event should age. * * num_regs * The number of times the same event (key) was registered * * context * Client's context for event-aged callback. * * p_event_wheel * Pointer to this event wheel object * * SEE ALSO *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_construct * NAME * cl_event_wheel_construct * * DESCRIPTION * This function constructs a Event_Wheel object. * * SYNOPSIS */ void cl_event_wheel_construct(IN cl_event_wheel_t * const p_event_wheel); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_event_wheel_init and cl_event_wheel_destroy. * * SEE ALSO * Event_Wheel, cl_event_wheel_init, cl_event_wheel_destroy *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_init * NAME * cl_event_wheel_init * * DESCRIPTION * This function initializes a Event_Wheel object. * * SYNOPSIS */ cl_status_t cl_event_wheel_init(IN cl_event_wheel_t * const p_event_wheel); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * RETURN VALUE * CL_SUCCESS if the operation is successful. * * SEE ALSO * Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg * *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_init * NAME * cl_event_wheel_init * * DESCRIPTION * This function initializes a Event_Wheel object. * * SYNOPSIS */ cl_status_t cl_event_wheel_init_ex(IN cl_event_wheel_t * const p_event_wheel, IN cl_spinlock_t * p_external_lock); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * p_external_lock * [in] Reference to external spinlock to guard internal structures * if the event wheel is part of a larger object protected by its own lock * * RETURN VALUE * CL_SUCCESS if the operation is successful. * * SEE ALSO * Event_Wheel, cl_event_wheel_destoy, cl_event_wheel_reg, cl_event_wheel_unreg * *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_destroy * NAME * cl_event_wheel_destroy * * DESCRIPTION * This function destroys a Event_Wheel object. * * SYNOPSIS */ void cl_event_wheel_destroy(IN cl_event_wheel_t * const p_event_wheel); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * RETURN VALUE * This function does not return a value. * * NOTES * This function does not returns until all client callback functions * been successfully finished. * * SEE ALSO * Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_dump * NAME * cl_event_wheel_dump * * DESCRIPTION * This function dumps the details of an Event_Whell object. * * SYNOPSIS */ void cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * RETURN VALUE * This function does not return a value. * * NOTES * Note that this function should be called inside a lock of the event wheel! * It doesn't aquire the lock by itself. * * SEE ALSO * Event_Wheel, cl_event_wheel_construct, cl_event_wheel_init *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_reg * NAME * cl_event_wheel_reg * * DESCRIPTION * This function registers a client with a Event_Wheel object. * * SYNOPSIS */ cl_status_t cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel, IN const uint64_t key, IN const uint64_t aging_time_usec, IN cl_pfn_event_aged_cb_t pfn_callback, IN void *const context); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * key * [in] The specifc Key by which events are registered. * * aging_time_usec * [in] The absolute time this event should age in usec * * pfn_callback * [in] Event Aging callback. The Event_Wheel calls this * function after the time the event has registed for has come. * * context * [in] Client context value passed to the cl_pfn_event_aged_cb_t * function. * * RETURN VALUE * On success a Event_Wheel CL_SUCCESS or CL_ERROR otherwise. * * SEE ALSO * Event_Wheel, cl_event_wheel_unreg *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_unreg * NAME * cl_event_wheel_unreg * * DESCRIPTION * This function unregisters a client event from a Event_Wheel. * * SYNOPSIS */ void cl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * key * [in] The key used for registering the event * * RETURN VALUE * This function does not return a value. * * NOTES * After the event has aged it is automatically removed from * the event wheel. So it should only be invoked when the need arises * to remove existing events before they age. * * SEE ALSO * Event_Wheel, cl_event_wheel_reg *********/ /****f* Component Library: Event_Wheel/cl_event_wheel_num_regs * NAME * cl_event_wheel_num_regs * * DESCRIPTION * This function returns the number of times an event was registered. * * SYNOPSIS */ uint32_t cl_event_wheel_num_regs(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key); /* * PARAMETERS * p_event_wheel * [in] Pointer to a Event_Wheel. * * key * [in] The key used for registering the event * * RETURN VALUE * The number of times the event was registered. * 0 if never registered or eventually aged. * * SEE ALSO * Event_Wheel, cl_event_wheel_reg, cl_event_wheel_unreg *********/ END_C_DECLS #endif /* !defined(_CL_EVENT_WHEEL_H_) */ opensm-3.3.20/include/complib/cl_event_osd.h0000644000205000001450000000434612104655724015712 00000000000000/* * 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: * Declaration of event object. */ #ifndef _CL_EVENT_OSD_H_ #define _CL_EVENT_OSD_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #include /* usr/include */ /* * Linux user mode specific data structure for the event object. * Users should not access these variables directly. */ typedef struct _cl_event_t { pthread_cond_t condvar; pthread_mutex_t mutex; boolean_t signaled; boolean_t manual_reset; cl_state_t state; } cl_event_t; END_C_DECLS #endif /* _CL_EVENT_OSD_H_ */ opensm-3.3.20/include/complib/cl_fleximap.h0000644000205000001450000005644012104655724015533 00000000000000/* * Copyright (c) 2004-2009 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: * Declaration of flexi map, a binary tree where the caller always provides * all necessary storage. */ #ifndef _CL_FLEXIMAP_H_ #define _CL_FLEXIMAP_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Flexi Map * NAME * Flexi Map * * DESCRIPTION * Flexi map implements a binary tree that stores user provided cl_fmap_item_t * structures. Each item stored in a flexi map has a unique user defined * key (duplicates are not allowed). Flexi map provides the ability to * efficiently search for an item given a key. Flexi map allows user * defined keys of any size. Storage for keys and a comparison function * are provided by users to allow flexi map to store items with arbitrary * key values. * * Flexi map does not allocate any memory, and can therefore not fail * any operations due to insufficient memory. Flexi map can thus be useful * in minimizing the error paths in code. * * Flexi map is not thread safe, and users must provide serialization when * adding and removing items from the map. * * The flexi map functions operate on a cl_fmap_t structure which should * be treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_fmap_t, cl_fmap_item_t * * Callbacks: * cl_pfn_fmap_apply_t * * Item Manipulation: * cl_fmap_key * * Initialization: * cl_fmap_init * * Iteration: * cl_fmap_end, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_prev * * Manipulation: * cl_fmap_insert, cl_fmap_get, cl_fmap_remove_item, cl_fmap_remove, * cl_fmap_remove_all, cl_fmap_merge, cl_fmap_delta, cl_fmap_get_next * * Search: * cl_fmap_apply_func * * Attributes: * cl_fmap_count, cl_is_fmap_empty, *********/ /****s* Component Library: Flexi Map/cl_fmap_item_t * NAME * cl_fmap_item_t * * DESCRIPTION * The cl_fmap_item_t structure is used by maps to store objects. * * The cl_fmap_item_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_fmap_item { /* Must be first to allow casting. */ cl_pool_item_t pool_item; struct _cl_fmap_item *p_left; struct _cl_fmap_item *p_right; struct _cl_fmap_item *p_up; cl_map_color_t color; const void *p_key; #ifdef _DEBUG_ struct _cl_fmap *p_map; #endif } cl_fmap_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_fmap_t structure. * * color * Indicates whether a node is red or black in the map. * * p_key * Pointer to the value that uniquely represents a node in a map. This * pointer is set by calling cl_fmap_insert and can be retrieved by * calling cl_fmap_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 flexi * 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 flexi 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 * flexi map. * * SEE ALSO * Flexi Map, cl_fmap_insert, cl_fmap_key, cl_pool_item_t, cl_list_item_t *********/ /****d* Component Library: Flexi Map/cl_pfn_fmap_cmp_t * NAME * cl_pfn_fmap_cmp_t * * DESCRIPTION * The cl_pfn_fmap_cmp_t function type defines the prototype for functions * used to compare item keys in a flexi map. * * SYNOPSIS */ typedef int (*cl_pfn_fmap_cmp_t) (IN const void *const p_key1, IN const void *const p_key2); /* * PARAMETERS * p_key1 * [in] Pointer to the first of two keys to compare. * * p_key2 * [in] Pointer to the second of two keys to compare. * * RETURN VALUE * Returns 0 if the keys match. * Returns less than 0 if *p_key1 is less than *p_key2. * Returns greater than 0 if *p_key1 is greater than *p_key2. * * NOTES * This function type is provided as function prototype reference for the * function provided by users as a parameter to the cl_fmap_init function. * * SEE ALSO * Flexi Map, cl_fmap_init *********/ /****s* Component Library: Flexi Map/cl_fmap_t * NAME * cl_fmap_t * * DESCRIPTION * Flexi map structure. * * The cl_fmap_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_fmap { cl_fmap_item_t root; cl_fmap_item_t nil; cl_state_t state; size_t count; cl_pfn_fmap_cmp_t pfn_compare; } cl_fmap_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 * 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. * * pfn_compare * Pointer to a compare function to invoke to compare the keys of * items in the map. * * SEE ALSO * Flexi Map, cl_pfn_fmap_cmp_t *********/ /****d* Component Library: Flexi Map/cl_pfn_fmap_apply_t * NAME * cl_pfn_fmap_apply_t * * DESCRIPTION * The cl_pfn_fmap_apply_t function type defines the prototype for * functions used to iterate items in a flexi map. * * SYNOPSIS */ typedef void (*cl_pfn_fmap_apply_t) (IN cl_fmap_item_t * const p_map_item, IN void *context); /* * PARAMETERS * p_map_item * [in] Pointer to a cl_fmap_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_fmap_apply_func * function. * * SEE ALSO * Flexi Map, cl_fmap_apply_func *********/ /****f* Component Library: Flexi Map/cl_fmap_count * NAME * cl_fmap_count * * DESCRIPTION * The cl_fmap_count function returns the number of items stored * in a flexi map. * * SYNOPSIS */ static inline size_t cl_fmap_count(IN const cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return (p_map->count); } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure whose item count to return. * * RETURN VALUE * Returns the number of items stored in the map. * * SEE ALSO * Flexi Map, cl_is_fmap_empty *********/ /****f* Component Library: Flexi Map/cl_is_fmap_empty * NAME * cl_is_fmap_empty * * DESCRIPTION * The cl_is_fmap_empty function returns whether a flexi map is empty. * * SYNOPSIS */ static inline boolean_t cl_is_fmap_empty(IN const cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return (p_map->count == 0); } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure to test for emptiness. * * RETURN VALUES * TRUE if the flexi map is empty. * * FALSE otherwise. * * SEE ALSO * Flexi Map, cl_fmap_count, cl_fmap_remove_all *********/ /****f* Component Library: Flexi Map/cl_fmap_key * NAME * cl_fmap_key * * DESCRIPTION * The cl_fmap_key function retrieves the key value of a map item. * * SYNOPSIS */ static inline const void *cl_fmap_key(IN const cl_fmap_item_t * const p_item) { CL_ASSERT(p_item); return (p_item->p_key); } /* * PARAMETERS * p_item * [in] Pointer to a map item whose key value to return. * * RETURN VALUE * Returns the a pointer to the key value for the specified map item. * The key value should not be modified to insure proper flexi map operation. * * NOTES * The key value is set in a call to cl_fmap_insert. * * SEE ALSO * Flexi Map, cl_fmap_insert *********/ /****f* Component Library: Flexi Map/cl_fmap_init * NAME * cl_fmap_init * * DESCRIPTION * The cl_fmap_init function initialized a flexi map for use. * * SYNOPSIS */ void cl_fmap_init(IN cl_fmap_t * const p_map, IN cl_pfn_fmap_cmp_t pfn_compare); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure to initialize. * * pfn_compare * [in] Pointer to the compare function used to compare keys. * See the cl_pfn_fmap_cmp_t function type declaration for details * about the callback function. * * RETURN VALUES * This function does not return a value. * * NOTES * Allows calling flexi map manipulation functions. * * SEE ALSO * Flexi Map, cl_fmap_insert, cl_fmap_remove *********/ /****f* Component Library: Flexi Map/cl_fmap_end * NAME * cl_fmap_end * * DESCRIPTION * The cl_fmap_end function returns the end of a flexi map. * * SYNOPSIS */ static inline const cl_fmap_item_t *cl_fmap_end(IN const cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); /* Nil is the end of the map. */ return (&p_map->nil); } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure whose end to return. * * RETURN VALUE * Pointer to the end of the map. * * NOTES * cl_fmap_end is useful for determining the validity of map items returned * by cl_fmap_head, cl_fmap_tail, cl_fmap_next, or cl_fmap_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_fmap_head or cl_fmap_tail, this condition indicates that * the map is empty. * * SEE ALSO * Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_prev *********/ /****f* Component Library: Flexi Map/cl_fmap_head * NAME * cl_fmap_head * * DESCRIPTION * The cl_fmap_head function returns the map item with the lowest key * value stored in a flexi map. * * SYNOPSIS */ static inline cl_fmap_item_t *cl_fmap_head(IN const cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return ((cl_fmap_item_t *) p_map->nil.pool_item.list_item.p_next); } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure whose item with the lowest * key is returned. * * RETURN VALUES * Pointer to the map item with the lowest key in the flexi map. * * Pointer to the map end if the flexi map was empty. * * NOTES * cl_fmap_head does not remove the item from the map. * * SEE ALSO * Flexi Map, cl_fmap_tail, cl_fmap_next, cl_fmap_prev, cl_fmap_end, * cl_fmap_item_t *********/ /****f* Component Library: Flexi Map/cl_fmap_tail * NAME * cl_fmap_tail * * DESCRIPTION * The cl_fmap_tail function returns the map item with the highest key * value stored in a flexi map. * * SYNOPSIS */ static inline cl_fmap_item_t *cl_fmap_tail(IN const cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return ((cl_fmap_item_t *) p_map->nil.pool_item.list_item.p_prev); } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure whose item with the highest key * is returned. * * RETURN VALUES * Pointer to the map item with the highest key in the flexi map. * * Pointer to the map end if the flexi map was empty. * * NOTES * cl_fmap_end does not remove the item from the map. * * SEE ALSO * Flexi Map, cl_fmap_head, cl_fmap_next, cl_fmap_prev, cl_fmap_end, * cl_fmap_item_t *********/ /****f* Component Library: Flexi Map/cl_fmap_next * NAME * cl_fmap_next * * DESCRIPTION * The cl_fmap_next function returns the map item with the next higher * key value than a specified map item. * * SYNOPSIS */ static inline cl_fmap_item_t *cl_fmap_next(IN const cl_fmap_item_t * const p_item) { CL_ASSERT(p_item); return ((cl_fmap_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 flexi map. * * Pointer to the map end if the specified item was the last item in * the flexi map. * * SEE ALSO * Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_prev, cl_fmap_end, * cl_fmap_item_t *********/ /****f* Component Library: Flexi Map/cl_fmap_prev * NAME * cl_fmap_prev * * DESCRIPTION * The cl_fmap_prev function returns the map item with the next lower * key value than a precified map item. * * SYNOPSIS */ static inline cl_fmap_item_t *cl_fmap_prev(IN const cl_fmap_item_t * const p_item) { CL_ASSERT(p_item); return ((cl_fmap_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 flexi map. * * Pointer to the map end if the specifid item was the first item in * the flexi map. * * SEE ALSO * Flexi Map, cl_fmap_head, cl_fmap_tail, cl_fmap_next, cl_fmap_end, * cl_fmap_item_t *********/ /****f* Component Library: Flexi Map/cl_fmap_insert * NAME * cl_fmap_insert * * DESCRIPTION * The cl_fmap_insert function inserts a map item into a flexi map. * * SYNOPSIS */ 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); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure into which to add the item. * * p_key * [in] Pointer to the key value to assign to the item. Storage * for the key must be persistant, as only the pointer is stored. * Users are responsible for maintaining the validity of key * pointers while they are in use. * * p_item * [in] Pointer to a cl_fmap_item_t stucture to insert into the flexi 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 flexi map to rebalance. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_item_t *********/ /****f* Component Library: Flexi Map/cl_fmap_match * NAME * cl_fmap_match * * DESCRIPTION * The cl_fmap_match function returns the map item matching a key. * * SYNOPSIS */ cl_fmap_item_t *cl_fmap_match(IN const cl_fmap_t * const p_map, IN const void *const p_key, IN cl_pfn_fmap_cmp_t pfn_compare); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure from which to retrieve the * item with the specified key. * * p_key * [in] Pointer to a key value used to search for the desired map item. * * pfn_compare * [in] Pointer to a compare function to invoke to compare the * keys of items in the map. Passing NULL here makes such call * to be equivalent to using cl_fmap_get(). * * RETURN VALUES * Pointer to the map item matching the desired key value. * * Pointer to the map end if there was no item matching the desired key * value stored in the flexi map. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_get *********/ /****f* Component Library: Flexi Map/cl_fmap_get * NAME * cl_fmap_get * * DESCRIPTION * The cl_fmap_get function returns the map item associated with a key. * * SYNOPSIS */ cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map, IN const void *const p_key); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure from which to retrieve the * item with the specified key. * * p_key * [in] Pointer to a key value used to search for the desired map item. * * 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 flexi map. * * NOTES * cl_fmap_get does not remove the item from the flexi map. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_get_next *********/ /****f* Component Library: Flexi Map/cl_fmap_get_next * NAME * cl_fmap_get_next * * DESCRIPTION * The cl_fmap_get_next function returns the first map item associated with * a key > the key specified. * * SYNOPSIS */ cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map, IN const void *const p_key); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure from which to retrieve the * item with the specified key. * * p_key * [in] Pointer to a key value used to search for the desired map item. * * RETURN VALUES * Pointer to the first map item with a key > the desired key value. * * Pointer to the map end if there was no item with a key > the desired key * value stored in the flexi map. * * NOTES * cl_fmap_get_next does not remove the item from the flexi map. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_get *********/ /****f* Component Library: Flexi Map/cl_fmap_remove_item * NAME * cl_fmap_remove_item * * DESCRIPTION * The cl_fmap_remove_item function removes the specified map item * from a flexi map. * * SYNOPSIS */ void cl_fmap_remove_item(IN cl_fmap_t * const p_map, IN cl_fmap_item_t * const p_item); /* * PARAMETERS * p_item * [in] Pointer to a map item to remove from its flexi map. * * RETURN VALUES * This function does not return a value. * * In a debug build, cl_fmap_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 flexi map. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_remove_all, cl_fmap_insert *********/ /****f* Component Library: Flexi Map/cl_fmap_remove * NAME * cl_fmap_remove * * DESCRIPTION * The cl_fmap_remove function removes the map item with the specified key * from a flexi map. * * SYNOPSIS */ cl_fmap_item_t *cl_fmap_remove(IN cl_fmap_t * const p_map, IN const void *const p_key); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure from which to remove the * item with the specified key. * * p_key * [in] Pointer to the key value used to search for the map item * to remove. * * 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 * flexi map. * * SEE ALSO * Flexi Map, cl_fmap_remove_item, cl_fmap_remove_all, cl_fmap_insert *********/ /****f* Component Library: Flexi Map/cl_fmap_remove_all * NAME * cl_fmap_remove_all * * DESCRIPTION * The cl_fmap_remove_all function removes all items in a flexi map, * leaving it empty. * * SYNOPSIS */ static inline void cl_fmap_remove_all(IN cl_fmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_map->root.p_left = &p_map->nil; p_map->nil.pool_item.list_item.p_next = &p_map->nil.pool_item.list_item; p_map->nil.pool_item.list_item.p_prev = &p_map->nil.pool_item.list_item; p_map->count = 0; } /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure to empty. * * RETURN VALUES * This function does not return a value. * * SEE ALSO * Flexi Map, cl_fmap_remove, cl_fmap_remove_item *********/ /****f* Component Library: Flexi Map/cl_fmap_merge * NAME * cl_fmap_merge * * DESCRIPTION * The cl_fmap_merge function moves all items from one map to another, * excluding duplicates. * * SYNOPSIS */ void cl_fmap_merge(OUT cl_fmap_t * const p_dest_map, IN OUT cl_fmap_t * const p_src_map); /* * PARAMETERS * p_dest_map * [out] Pointer to a cl_fmap_t structure to which items should be added. * * p_src_map * [in/out] Pointer to a cl_fmap_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_fmap_merge, the flexi map referenced by p_src_map * contains all duplicate items. * * SEE ALSO * Flexi Map, cl_fmap_delta *********/ /****f* Component Library: Flexi Map/cl_fmap_delta * NAME * cl_fmap_delta * * DESCRIPTION * The cl_fmap_delta function computes the differences between two maps. * * SYNOPSIS */ 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); /* * PARAMETERS * p_map1 * [in/out] Pointer to the first of two cl_fmap_t structures whose * differences to compute. * * p_map2 * [in/out] Pointer to the second of two cl_fmap_t structures whose * differences to compute. * * p_new * [out] Pointer to an empty cl_fmap_t structure that contains the * items unique to p_map2 upon return from the function. * * p_old * [out] Pointer to an empty cl_fmap_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 useful 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. * * SEE ALSO * Flexi Map, cl_fmap_merge *********/ /****f* Component Library: Flexi Map/cl_fmap_apply_func * NAME * cl_fmap_apply_func * * DESCRIPTION * The cl_fmap_apply_func function executes a specified function * for every item stored in a flexi map. * * SYNOPSIS */ 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); /* * PARAMETERS * p_map * [in] Pointer to a cl_fmap_t structure. * * pfn_func * [in] Function invoked for every item in the flexi map. * See the cl_pfn_fmap_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 flexi map. * * SEE ALSO * Flexi Map, cl_pfn_fmap_apply_t *********/ END_C_DECLS #endif /* _CL_FLEXIMAP_H_ */ opensm-3.3.20/include/complib/cl_list.h0000644000205000001450000007763112104655724014706 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of list. */ #ifndef _CL_LIST_H_ #define _CL_LIST_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/List * NAME * List * * DESCRIPTION * List stores objects in a doubly linked list. * * Unlike quick list, users pass pointers to the object being stored, rather * than to a cl_list_item_t structure. Insertion operations on a list can * fail, and callers should trap for such failures. * * Use quick list in situations where insertion failures cannot be tolerated. * * List is not thread safe, and users must provide serialization. * * The list functions operates on a cl_list_t structure which should be * treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Types: * cl_list_iterator_t * * Structures: * cl_list_t * * Callbacks: * cl_pfn_list_apply_t, cl_pfn_list_find_t * * Initialization/Destruction: * cl_list_construct, cl_list_init, cl_list_destroy * * Iteration: * cl_list_next, cl_list_prev, cl_list_head, cl_list_tail, * cl_list_end * * Manipulation: * cl_list_insert_head, cl_list_insert_tail, * cl_list_insert_array_head, cl_list_insert_array_tail, * cl_list_insert_prev, cl_list_insert_next, * cl_list_remove_head, cl_list_remove_tail, * cl_list_remove_object, cl_list_remove_item, cl_list_remove_all * * Search: * cl_is_object_in_list, cl_list_find_from_head, cl_list_find_from_tail, * cl_list_apply_func * * Attributes: * cl_list_count, cl_is_list_empty, cl_is_list_inited *********/ /****s* Component Library: List/cl_list_t * NAME * cl_list_t * * DESCRIPTION * List structure. * * The cl_list_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_list { cl_qlist_t list; cl_qpool_t list_item_pool; } cl_list_t; /* * FIELDS * list * Quick list of items stored in the list. * * list_item_pool * Quick pool of list objects for storing objects in the quick list. * * SEE ALSO * List *********/ /****d* Component Library: List/cl_list_iterator_t * NAME * cl_list_iterator_t * * DESCRIPTION * Iterator type used to walk a list. * * SYNOPSIS */ typedef const cl_list_item_t *cl_list_iterator_t; /* * NOTES * The iterator should be treated as opaque to prevent corrupting the list. * * SEE ALSO * List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev, * cl_list_obj *********/ /****d* Component Library: List/cl_pfn_list_apply_t * NAME * cl_pfn_list_apply_t * * DESCRIPTION * The cl_pfn_list_apply_t function type defines the prototype for functions * used to iterate objects in a list. * * SYNOPSIS */ typedef void (*cl_pfn_list_apply_t) (IN void *const p_object, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object stored in a list. * * context * [in] Context provided in a call to cl_list_apply_func. * * 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_list_apply_func * function. * * SEE ALSO * List, cl_list_apply_func *********/ /****d* Component Library: List/cl_pfn_list_find_t * NAME * cl_pfn_list_find_t * * DESCRIPTION * The cl_pfn_list_find_t function type defines the prototype for functions * used to find objects in a list. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_list_find_t) (IN const void *const p_object, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object stored in a list. * * context * [in] Context provided in a call to ListFindFromHead or ListFindFromTail. * * RETURN VALUES * Return CL_SUCCESS if the desired item was found. This stops list iteration. * * Return CL_NOT_FOUND to continue the list iteration. * * NOTES * This function type is provided as function prototype reference for the * function provided by users as a parameter to the cl_list_find_from_head * and cl_list_find_from_tail functions. * * SEE ALSO * List, cl_list_find_from_head, cl_list_find_from_tail *********/ /****f* Component Library: List/cl_list_construct * NAME * cl_list_construct * * DESCRIPTION * The cl_list_construct function constructs a list. * * SYNOPSIS */ void cl_list_construct(IN cl_list_t * const p_list); /* * PARAMETERS * p_list * [in] Pointer to cl_list_t object whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_list_init, cl_list_destroy and cl_is_list_inited. * * Calling cl_list_construct is a prerequisite to calling any other * list function except cl_list_init. * * SEE ALSO * List, cl_list_init, cl_list_destroy, cl_is_list_inited *********/ /****f* Component Library: List/cl_is_list_inited * NAME * cl_is_list_inited * * DESCRIPTION * The cl_is_list_inited function returns whether a list was * initialized successfully. * * SYNOPSIS */ static inline boolean_t cl_is_list_inited(IN const cl_list_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* * The pool is the last thing initialized. If it is initialized, the * list is initialized too. */ return (cl_is_qpool_inited(&p_list->list_item_pool)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure whose initilization state * to check. * * RETURN VALUES * TRUE if the list was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a list to determine if invoking * member functions is appropriate. * * SEE ALSO * List *********/ /****f* Component Library: List/cl_list_init * NAME * cl_list_init * * DESCRIPTION * The cl_list_init function initializes a list for use. * * SYNOPSIS */ cl_status_t cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items); /* * PARAMETERS * p_list * [in] Pointer to cl_list_t structure to initialize. * * min_items * [in] Minimum number of items that can be stored. All necessary * allocations to allow storing the minimum number of items is performed * at initialization time. * * RETURN VALUES * CL_SUCCESS if the list was initialized successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for initialization. * * NOTES * The list will always be able to store at least as many items as specified * by the min_items parameter. * * SEE ALSO * List, cl_list_construct, cl_list_destroy, cl_list_insert_head, * cl_list_insert_tail, cl_list_remove_head, cl_list_remove_tail *********/ /****f* Component Library: List/cl_list_destroy * NAME * cl_list_destroy * * DESCRIPTION * The cl_list_destroy function destroys a list. * * SYNOPSIS */ void cl_list_destroy(IN cl_list_t * const p_list); /* * PARAMETERS * p_list * [in] Pointer to cl_list_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_list_destroy does not affect any of the objects stored in the list, * but does release all memory allocated internally. Further operations * should not be attempted on the list after cl_list_destroy is invoked. * * This function should only be called after a call to cl_list_construct * or cl_list_init. * * In debug builds, cl_list_destroy asserts if the list is not empty. * * SEE ALSO * List, cl_list_construct, cl_list_init *********/ /****f* Component Library: List/cl_is_list_empty * NAME * cl_is_list_empty * * DESCRIPTION * The cl_is_list_empty function returns whether a list is empty. * * SYNOPSIS */ static inline boolean_t cl_is_list_empty(IN const cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_is_qlist_empty(&p_list->list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure. * * RETURN VALUES * TRUE if the specified list is empty. * * FALSE otherwise. * * SEE ALSO * List, cl_list_count, cl_list_remove_all *********/ /****f* Component Library: List/cl_list_insert_head * NAME * cl_list_insert_head * * DESCRIPTION * The cl_list_insert_head function inserts an object at the head of a list. * * SYNOPSIS */ static inline cl_status_t cl_list_insert_head(IN cl_list_t * const p_list, IN const void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* Get a list item to add to the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool); if (!p_pool_obj) return (CL_INSUFFICIENT_MEMORY); p_pool_obj->p_object = p_object; cl_qlist_insert_head(&p_list->list, &p_pool_obj->pool_item.list_item); return (CL_SUCCESS); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the object. * * p_object * [in] Pointer to an object to insert into the list. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * NOTES * Inserts the specified object at the head of the list. List insertion * operations are guaranteed to work for the minimum number of items as * specified in cl_list_init by the min_items parameter. * * SEE ALSO * List, cl_list_insert_tail, cl_list_insert_array_head, * cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next, * cl_list_remove_head *********/ /****f* Component Library: List/cl_list_insert_tail * NAME * cl_list_insert_tail * * DESCRIPTION * The cl_list_insert_tail function inserts an object at the tail of a list. * * SYNOPSIS */ static inline cl_status_t cl_list_insert_tail(IN cl_list_t * const p_list, IN const void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* Get a list item to add to the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool); if (!p_pool_obj) return (CL_INSUFFICIENT_MEMORY); p_pool_obj->p_object = p_object; cl_qlist_insert_tail(&p_list->list, &p_pool_obj->pool_item.list_item); return (CL_SUCCESS); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the object. * * p_object * [in] Pointer to an object to insert into the list. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * NOTES * Inserts the specified object at the tail of the list. List insertion * operations are guaranteed to work for the minimum number of items as * specified in cl_list_init by the min_items parameter. * * SEE ALSO * List, cl_list_insert_head, cl_list_insert_array_head, * cl_list_insert_array_tail, cl_list_insert_prev, cl_list_insert_next, * cl_list_remove_tail *********/ /****f* Component Library: List/cl_list_insert_array_head * NAME * cl_list_insert_array_head * * DESCRIPTION: * The cl_list_insert_array_head function inserts an array of objects * at the head of a list. * * SYNOPSIS */ cl_status_t cl_list_insert_array_head(IN cl_list_t * const p_list, IN const void *const p_array, IN uint32_t item_count, IN const uint32_t item_size); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the objects. * * p_array * [in] Pointer to the first object in an array. * * item_count * [in] Number of objects in the array. * * item_size * [in] Size of the objects added to the list. This is the stride in the * array from one object to the next. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * NOTES * Inserts all objects in the array to the head of the list, preserving the * ordering of the objects. If not successful, no items are added. * List insertion operations are guaranteed to work for the minimum number * of items as specified in cl_list_init by the min_items parameter. * * SEE ALSO * List, cl_list_insert_array_tail, cl_list_insert_head, cl_list_insert_tail, * cl_list_insert_prev, cl_list_insert_next *********/ /****f* Component Library: List/cl_list_insert_array_tail * NAME * cl_list_insert_array_tail * * DESCRIPTION * The cl_list_insert_array_tail function inserts an array of objects * at the tail of a list. * * SYNOPSIS */ cl_status_t cl_list_insert_array_tail(IN cl_list_t * const p_list, IN const void *const p_array, IN uint32_t item_count, IN const uint32_t item_size); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the objects. * * p_array * [in] Pointer to the first object in an array. * * item_count * [in] Number of objects in the array. * * item_size * [in] Size of the objects added to the list. This is the stride in the * array from one object to the next. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * NOTES * Inserts all objects in the array to the tail of the list, preserving the * ordering of the objects. If not successful, no items are added. * List insertion operations are guaranteed to work for the minimum number * of items as specified in cl_list_init by the min_items parameter. * * SEE ALSO * List, cl_list_insert_array_head, cl_list_insert_head, cl_list_insert_tail, * cl_list_insert_prev, cl_list_insert_next *********/ /****f* Component Library: List/cl_list_insert_next * NAME * cl_list_insert_next * * DESCRIPTION * The cl_list_insert_next function inserts an object in a list after * the object associated with a given iterator. * * SYNOPSIS */ static inline cl_status_t cl_list_insert_next(IN cl_list_t * const p_list, IN cl_list_iterator_t iterator, IN const void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* Get a list item to add to the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool); if (!p_pool_obj) return (CL_INSUFFICIENT_MEMORY); p_pool_obj->p_object = p_object; cl_qlist_insert_next(&p_list->list, (cl_list_item_t *) iterator, &p_pool_obj->pool_item.list_item); return (CL_SUCCESS); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the object. * * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev. * * p_object * [in] Pointer to an object to insert into the list. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * SEE ALSO * List, cl_list_insert_prev, cl_list_insert_head, cl_list_insert_tail, * cl_list_insert_array_head, cl_list_insert_array_tail *********/ /****f* Component Library: List/cl_list_insert_prev * NAME * cl_list_insert_prev * * DESCRIPTION * The cl_list_insert_prev function inserts an object in a list before * the object associated with a given iterator. * * SYNOPSIS */ static inline cl_status_t cl_list_insert_prev(IN cl_list_t * const p_list, IN cl_list_iterator_t iterator, IN const void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* Get a list item to add to the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qpool_get(&p_list->list_item_pool); if (!p_pool_obj) return (CL_INSUFFICIENT_MEMORY); p_pool_obj->p_object = p_object; cl_qlist_insert_prev(&p_list->list, (cl_list_item_t *) iterator, &p_pool_obj->pool_item.list_item); return (CL_SUCCESS); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure into which to insert the object. * * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev. * * p_object * [in] Pointer to an object to insert into the list. * * RETURN VALUES * CL_SUCCESS if the insertion was successful. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the insertion. * * SEE ALSO * List, cl_list_insert_next, cl_list_insert_head, cl_list_insert_tail, * cl_list_insert_array_head, cl_list_insert_array_tail *********/ /****f* Component Library: List/cl_list_remove_head * NAME * cl_list_remove_head * * DESCRIPTION * The cl_list_remove_head function removes an object from the head of a list. * * SYNOPSIS */ static inline void *cl_list_remove_head(IN cl_list_t * const p_list) { cl_pool_obj_t *p_pool_obj; void *p_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* See if the list is empty. */ if (cl_is_qlist_empty(&p_list->list)) return (NULL); /* Get the item at the head of the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_head(&p_list->list); p_obj = (void *)p_pool_obj->p_object; /* Place the pool item back into the pool. */ cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item); return (p_obj); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure from which to remove an object. * * RETURN VALUES * Returns the pointer to the object formerly at the head of the list. * * NULL if the list was empty. * * SEE ALSO * List, cl_list_remove_tail, cl_list_remove_all, cl_list_remove_object, * cl_list_remove_item, cl_list_insert_head *********/ /****f* Component Library: List/cl_list_remove_tail * NAME * cl_list_remove_tail * * DESCRIPTION * The cl_list_remove_tail function removes an object from the tail of a list. * * SYNOPSIS */ static inline void *cl_list_remove_tail(IN cl_list_t * const p_list) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* See if the list is empty. */ if (cl_is_qlist_empty(&p_list->list)) return (NULL); /* Get the item at the head of the list. */ p_pool_obj = (cl_pool_obj_t *) cl_qlist_remove_tail(&p_list->list); /* Place the list item back into the pool. */ cl_qpool_put(&p_list->list_item_pool, &p_pool_obj->pool_item); return ((void *)p_pool_obj->p_object); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure from which to remove an object. * * RETURN VALUES * Returns the pointer to the object formerly at the tail of the list. * * NULL if the list was empty. * * SEE ALSO * List, cl_list_remove_head, cl_list_remove_all, cl_list_remove_object, * cl_list_remove_item, cl_list_insert_head *********/ /****f* Component Library: List/cl_list_remove_all * NAME * cl_list_remove_all * * DESCRIPTION * The cl_list_remove_all function removes all objects from a list, * leaving it empty. * * SYNOPSIS */ static inline void cl_list_remove_all(IN cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* Return all the list items to the pool. */ cl_qpool_put_list(&p_list->list_item_pool, &p_list->list); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure from which to remove all objects. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * List, cl_list_remove_head, cl_list_remove_tail, cl_list_remove_object, * cl_list_remove_item *********/ /****f* Component Library: List/cl_list_remove_object * NAME * cl_list_remove_object * * DESCRIPTION * The cl_list_remove_object function removes a specific object from a list. * * SYNOPSIS */ cl_status_t cl_list_remove_object(IN cl_list_t * const p_list, IN const void *const p_object); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure from which to remove the object. * * p_object * [in] Pointer to an object to remove from the list. * * RETURN VALUES * CL_SUCCESS if the object was removed. * * CL_NOT_FOUND if the object was not found in the list. * * NOTES * Removes the first occurrence of an object from a list. * * SEE ALSO * List, cl_list_remove_item, cl_list_remove_head, cl_list_remove_tail, * cl_list_remove_all *********/ /****f* Component Library: List/cl_list_remove_item * NAME * cl_list_remove_item * * DESCRIPTION * The cl_list_remove_item function removes an object from the head of a list. * * SYNOPSIS */ static inline void cl_list_remove_item(IN cl_list_t * const p_list, IN cl_list_iterator_t iterator) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); cl_qlist_remove_item(&p_list->list, (cl_list_item_t *) iterator); /* Place the list item back into the pool. */ cl_qpool_put(&p_list->list_item_pool, (cl_pool_item_t *) iterator); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure from which to remove the item. * * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * List, cl_list_remove_object, cl_list_remove_head, cl_list_remove_tail, * cl_list_remove_all *********/ /****f* Component Library: List/cl_is_object_in_list * NAME * cl_is_object_in_list * * DESCRIPTION * The cl_is_object_in_list function returns whether an object * is stored in a list. * * SYNOPSIS */ boolean_t cl_is_object_in_list(IN const cl_list_t * const p_list, IN const void *const p_object); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure in which to look for the object. * * p_object * [in] Pointer to an object stored in a list. * * RETURN VALUES * TRUE if p_object was found in the list. * * FALSE otherwise. * * SEE ALSO * List *********/ /****f* Component Library: List/cl_list_end * NAME * cl_list_end * * DESCRIPTION * The cl_list_end function returns returns the list iterator for * the end of a list. * * SYNOPSIS */ static inline cl_list_iterator_t cl_list_end(IN const cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_qlist_end(&p_list->list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure for which the iterator for the * object at the head is to be returned. * * RETURN VALUE * cl_list_iterator_t for the end of the list. * * NOTES * Use cl_list_obj to retrieve the object associated with the * returned cl_list_iterator_t. * * SEE ALSO * List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev, * cl_list_obj *********/ /****f* Component Library: List/cl_list_head * NAME * cl_list_head * * DESCRIPTION * The cl_list_head function returns returns a list iterator for * the head of a list. * * SYNOPSIS */ static inline cl_list_iterator_t cl_list_head(IN const cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_qlist_head(&p_list->list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure for which the iterator for the * object at the head is to be returned. * * RETURN VALUES * cl_list_iterator_t for the head of the list. * * cl_list_iterator_t for the end of the list if the list is empty. * * NOTES * Use cl_list_obj to retrieve the object associated with the * returned cl_list_iterator_t. * * SEE ALSO * List, cl_list_tail, cl_list_next, cl_list_prev, cl_list_end, * cl_list_obj *********/ /****f* Component Library: List/cl_list_tail * NAME * cl_list_tail * * DESCRIPTION * The cl_list_tail function returns returns a list iterator for * the tail of a list. * * SYNOPSIS */ static inline cl_list_iterator_t cl_list_tail(IN const cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_qlist_tail(&p_list->list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure for which the iterator for the * object at the tail is to be returned. * * RETURN VALUES * cl_list_iterator_t for the tail of the list. * * cl_list_iterator_t for the end of the list if the list is empty. * * NOTES * Use cl_list_obj to retrieve the object associated with the * * returned cl_list_iterator_t. * * SEE ALSO * List, cl_list_head, cl_list_next, cl_list_prev, cl_list_end, * cl_list_obj *********/ /****f* Component Library: List/cl_list_next * NAME * cl_list_next * * DESCRIPTION * The cl_list_next function returns a list iterator for the object stored * in a list after the object associated with a given list iterator. * * SYNOPSIS */ static inline cl_list_iterator_t cl_list_next(IN cl_list_iterator_t iterator) { CL_ASSERT(iterator); return (cl_qlist_next(iterator)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure for which the iterator for the * next object is to be returned. * * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev. * * RETURN VALUES * cl_list_iterator_t for the object following the object associated with * the list iterator specified by the iterator parameter. * * cl_list_iterator_t for the end of the list if the list is empty. * * NOTES * Use cl_list_obj to retrieve the object associated with the * returned cl_list_iterator_t. * * SEE ALSO * List, cl_list_prev, cl_list_head, cl_list_tail, cl_list_end, * cl_list_obj *********/ /****f* Component Library: List/cl_list_prev * NAME * cl_list_prev * * DESCRIPTION * The cl_list_prev function returns a list iterator for the object stored * in a list before the object associated with a given list iterator. * * SYNOPSIS */ static inline cl_list_iterator_t cl_list_prev(IN cl_list_iterator_t iterator) { CL_ASSERT(iterator); return (cl_qlist_prev(iterator)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure for which the iterator for the * next object is to be returned. * * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev. * * RETURN VALUES * cl_list_iterator_t for the object preceding the object associated with * the list iterator specified by the iterator parameter. * * cl_list_iterator_t for the end of the list if the list is empty. * * NOTES * Use cl_list_obj to retrieve the object associated with the * returned cl_list_iterator_t. * * SEE ALSO * List, cl_list_next, cl_list_head, cl_list_tail, cl_list_end, * cl_list_obj *********/ /****f* Component Library: List/cl_list_obj * NAME * cl_list_obj * * DESCRIPTION * The cl_list_obj function returns the object associated * with a list iterator. * * SYNOPSIS */ static inline void *cl_list_obj(IN cl_list_iterator_t iterator) { CL_ASSERT(iterator); return ((void *)((cl_pool_obj_t *) iterator)->p_object); } /* * PARAMETERS * iterator * [in] cl_list_iterator_t returned by a previous call to cl_list_head, * cl_list_tail, cl_list_next, or cl_list_prev whose object is requested. * * RETURN VALUE * Pointer to the object associated with the list iterator specified * by the iterator parameter. * * SEE ALSO * List, cl_list_head, cl_list_tail, cl_list_next, cl_list_prev *********/ /****f* Component Library: List/cl_list_find_from_head * NAME * cl_list_find_from_head * * DESCRIPTION * The cl_list_find_from_head function uses a specified function * to search for an object starting from the head of a list. * * SYNOPSIS */ cl_list_iterator_t cl_list_find_from_head(IN const cl_list_t * const p_list, IN cl_pfn_list_find_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure to search. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_list_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * Returns the iterator for the object if found. * * Returns the iterator for the list end otherwise. * * NOTES * cl_list_find_from_head does not remove the found object from * the list. The iterator for the object is returned when the function * provided by the pfn_func parameter returns CL_SUCCESS. The function * specified by the pfn_func parameter must not perform any list * operations as these would corrupt the list. * * SEE ALSO * List, cl_list_find_from_tail, cl_list_apply_func_t, * cl_pfn_list_find_t *********/ /****f* Component Library: List/cl_list_find_from_tail * NAME * cl_list_find_from_tail * * DESCRIPTION * The cl_list_find_from_tail function uses a specified function * to search for an object starting from the tail of a list. * * SYNOPSIS */ cl_list_iterator_t cl_list_find_from_tail(IN const cl_list_t * const p_list, IN cl_pfn_list_find_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure to search. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_list_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * Returns the iterator for the object if found. * * Returns the iterator for the list end otherwise. * * NOTES * cl_list_find_from_tail does not remove the found object from * the list. The iterator for the object is returned when the function * provided by the pfn_func parameter returns CL_SUCCESS. The function * specified by the pfn_func parameter must not perform any list * operations as these would corrupt the list. * * SEE ALSO * List, cl_list_find_from_head, cl_list_apply_func_t, * cl_pfn_list_find_t *********/ /****f* Component Library: List/cl_list_apply_func * NAME * cl_list_apply_func * * DESCRIPTION * The cl_list_apply_func function executes a specified function for every * object stored in a list. * * SYNOPSIS */ void cl_list_apply_func(IN const cl_list_t * const p_list, IN cl_pfn_list_apply_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure to iterate. * * pfn_func * [in] Function invoked for every item in a list. * See the cl_pfn_list_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 * cl_list_apply_func invokes the specified callback function for every * object stored in the list, starting from the head. The function specified * by the pfn_func parameter must not perform any list operations as these * would corrupt the list. * * SEE ALSO * List, cl_list_find_from_head, cl_list_find_from_tail, * cl_pfn_list_apply_t *********/ /****f* Component Library: List/cl_list_count * NAME * cl_list_count * * DESCRIPTION * The cl_list_count function returns the number of objects stored in a list. * * SYNOPSIS */ static inline size_t cl_list_count(IN const cl_list_t * const p_list) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_qlist_count(&p_list->list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_list_t structure whose object to count. * * RETURN VALUES * Number of objects stored in the specified list. * * SEE ALSO * List *********/ END_C_DECLS #endif /* _CL_LIST_H_ */ opensm-3.3.20/include/complib/cl_log.h0000644000205000001450000000762612104655724014511 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of logging mechanisms. */ #ifndef _CL_LOG_H_ #define _CL_LOG_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Log Provider * NAME * Log Provider * * DESCRIPTION * The log provider allows users to log information in a system log instead of * the console or debugger target. **********/ /****d* Component Library: Log Provider/cl_log_type_t * NAME * cl_log_type_t * * DESCRIPTION * The cl_log_type_t enumerated type is used to differentiate between * different types of log entries. * * SYNOPSIS */ typedef enum _cl_log_type { CL_LOG_INFO, CL_LOG_WARN, CL_LOG_ERROR } cl_log_type_t; /* * VALUES * CL_LOG_INFO * Indicates a log entry is purely informational. * * CL_LOG_WARN * Indicates a log entry is a warning but non-fatal. * * CL_LOG_ERROR * Indicates a log entry is a fatal error. * * SEE ALSO * Log Provider, cl_log_event *********/ /****f* Component Library: Log Provider/cl_log_event * NAME * cl_log_event * * DESCRIPTION * The cl_log_event function adds a new entry to the system log. * * SYNOPSIS */ void cl_log_event(IN const char *const name, IN const cl_log_type_t type, IN const char *const message, IN const void *const p_data OPTIONAL, IN const uint32_t data_len); /* * PARAMETERS * name * [in] Pointer to an ANSI string containing the name of the source for * the log entry. * * type * [in] Defines the type of log entry to add to the system log. * See the definition of cl_log_type_t for acceptable values. * * message * [in] Pointer to an ANSI string containing the text for the log entry. * The message should not be terminated with a new line, as the log * provider appends a new line to all log entries. * * p_data * [in] Optional pointer to data providing context for the log entry. * At most 256 bytes of data can be successfully logged. * * data_len * [in] Length of the buffer pointed to by the p_data parameter. Ignored * if p_data is NULL. * * RETURN VALUE * This function does not return a value. * * NOTES * If the data length exceeds the maximum supported, the event is logged * without its accompanying data. * * SEE ALSO * Log Provider, cl_log_type_t *********/ END_C_DECLS #endif /* _CL_LOG_H_ */ opensm-3.3.20/include/complib/cl_map.h0000644000205000001450000004661212104655724014503 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of map, a binary tree. */ #ifndef _CL_MAP_H_ #define _CL_MAP_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Map * NAME * Map * * DESCRIPTION * Map implements a binary tree that stores user objects. Each item stored * in a map has a unique 64-bit key (duplicates are not allowed). Map * provides the ability to efficiently search for an item given a key. * * Map may allocate memory when inserting objects, and can therefore fail * operations due to insufficient memory. Use quick map in situations * where such insertion failures cannot be tolerated. * * Map is not thread safe, and users must provide serialization when adding * and removing items from the map. * * The map functions operates on a cl_map_t structure which should be treated * as opaque and should be manipulated only through the provided functions. * * SEE ALSO * Types: * cl_map_iterator_t * * Structures: * cl_map_t, cl_map_item_t, cl_map_obj_t * * Item Manipulation: * cl_map_obj, cl_map_key * * Initialization: * cl_map_construct, cl_map_init, cl_map_destroy * * Iteration: * cl_map_end, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev * * Manipulation * cl_map_insert, cl_map_get, cl_map_remove_item, cl_map_remove, * cl_map_remove_all, cl_map_merge, cl_map_delta, cl_map_get_next * * Attributes: * cl_map_count, cl_is_map_empty, cl_is_map_inited *********/ /****s* Component Library: Map/cl_map_t * NAME * cl_map_t * * DESCRIPTION * Quick map structure. * * The cl_map_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_map { cl_qmap_t qmap; cl_qpool_t pool; } cl_map_t; /* * FIELDS * qmap * Quick map object that maintains the map. * * pool * Pool of cl_map_obj_t structures used to store user objects * in the map. * * SEE ALSO * Map, cl_map_obj_t *********/ /****d* Component Library: Map/cl_map_iterator_t * NAME * cl_map_iterator_t * * DESCRIPTION * Iterator type used to walk a map. * * SYNOPSIS */ typedef const cl_map_item_t *cl_map_iterator_t; /* * NOTES * The iterator should be treated as opaque to prevent corrupting the map. * * SEE ALSO * Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev, cl_map_key *********/ /****f* Component Library: Map/cl_map_count * NAME * cl_map_count * * DESCRIPTION * The cl_map_count function returns the number of items stored * in a map. * * SYNOPSIS */ static inline size_t cl_map_count(IN const cl_map_t * const p_map) { CL_ASSERT(p_map); return (cl_qmap_count(&p_map->qmap)); } /* * PARAMETERS * p_map * [in] Pointer to a map whose item count to return. * * RETURN VALUE * Returns the number of items stored in the map. * * SEE ALSO * Map, cl_is_map_empty *********/ /****f* Component Library: Map/cl_is_map_empty * NAME * cl_is_map_empty * * DESCRIPTION * The cl_is_map_empty function returns whether a map is empty. * * SYNOPSIS */ static inline boolean_t cl_is_map_empty(IN const cl_map_t * const p_map) { CL_ASSERT(p_map); return (cl_is_qmap_empty(&p_map->qmap)); } /* * PARAMETERS * p_map * [in] Pointer to a map to test for emptiness. * * RETURN VALUES * TRUE if the map is empty. * * FALSE otherwise. * * SEE ALSO * Map, cl_map_count, cl_map_remove_all *********/ /****f* Component Library: Map/cl_map_key * NAME * cl_map_key * * DESCRIPTION * The cl_map_key function retrieves the key value of a map item. * * SYNOPSIS */ static inline uint64_t cl_map_key(IN const cl_map_iterator_t itor) { return (cl_qmap_key(itor)); } /* * PARAMETERS * itor * [in] Iterator for the item whose key to return. * * RETURN VALUE * Returns the 64-bit key value for the specified iterator. * * NOTES * The iterator specified by the itor parameter must have been retrived by * a previous call to cl_map_head, cl_map_tail, cl_map_next, or cl_map_prev. * * The key value is set in a call to cl_map_insert. * * SEE ALSO * Map, cl_map_insert, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev *********/ /****f* Component Library: Map/cl_map_construct * NAME * cl_map_construct * * DESCRIPTION * The cl_map_construct function constructs a map. * * SYNOPSIS */ void cl_map_construct(IN cl_map_t * const p_map); /* * PARAMETERS * p_map * [in] Pointer to a cl_map_t structure to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_map_init, cl_map_destroy, and cl_is_map_inited. * * Calling cl_map_construct is a prerequisite to calling any other * map function except cl_map_init. * * SEE ALSO * Map, cl_map_init, cl_map_destroy, cl_is_map_inited *********/ /****f* Component Library: Event/cl_is_map_inited * NAME * cl_is_map_inited * * DESCRIPTION * The cl_is_map_inited function returns whether a map was * successfully initialized. * * SYNOPSIS */ static inline boolean_t cl_is_map_inited(IN const cl_map_t * const p_map) { /* * The map's pool of map items is the last thing initialized. * We can therefore use it to test for initialization. */ return (cl_is_qpool_inited(&p_map->pool)); } /* * PARAMETERS * p_map * [in] Pointer to a cl_map_t structure whose initialization state * to check. * * RETURN VALUES * TRUE if the map was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a map to determine if invoking * member functions is appropriate. * * SEE ALSO * Map *********/ /****f* Component Library: Map/cl_map_init * NAME * cl_map_init * * DESCRIPTION * The cl_map_init function initialized a map for use. * * SYNOPSIS */ cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items); /* * PARAMETERS * p_map * [in] Pointer to a cl_map_t structure to initialize. * * min_items * [in] Minimum number of items that can be stored. All necessary * allocations to allow storing the minimum number of items is * performed at initialization time. * * RETURN VALUES * CL_SUCCESS if the map was initialized successfully. * * NOTES * Allows calling map manipulation functions. * * SEE ALSO * Map, cl_map_destroy, cl_map_insert, cl_map_remove *********/ /****f* Component Library: Map/cl_map_destroy * NAME * cl_map_destroy * * DESCRIPTION * The cl_map_destroy function destroys a map. * * SYNOPSIS */ void cl_map_destroy(IN cl_map_t * const p_map); /* * PARAMETERS * p_map * [in] Pointer to a map to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified map. Further * operations should not be attempted on the map. cl_map_destroy does * not affect any of the objects stored in the map. * This function should only be called after a call to cl_map_construct. * * In debug builds, cl_map_destroy asserts that the map is empty. * * SEE ALSO * Map, cl_map_construct, cl_map_init *********/ /****f* Component Library: Map/cl_map_end * NAME * cl_map_end * * DESCRIPTION * The cl_map_end function returns the iterator for the end of a map. * * SYNOPSIS */ static inline cl_map_iterator_t cl_map_end(IN const cl_map_t * const p_map) { CL_ASSERT(p_map); return (cl_qmap_end(&p_map->qmap)); } /* * PARAMETERS * p_map * [in] Pointer to a cl_map_t structure whose end to return. * * RETURN VALUE * Iterator for the end of the map. * * NOTES * cl_map_end is useful for determining the validity of map items returned * by cl_map_head, cl_map_tail, cl_map_next, cl_map_prev. If the iterator * by any of these functions compares to the end, the end of the map was * encoutered. * When using cl_map_head or cl_map_tail, this condition indicates that * the map is empty. * * SEE ALSO * Map, cl_qmap_head, cl_qmap_tail, cl_qmap_next, cl_qmap_prev *********/ /****f* Component Library: Map/cl_map_head * NAME * cl_map_head * * DESCRIPTION * The cl_map_head function returns the map item with the lowest key * value stored in a map. * * SYNOPSIS */ static inline cl_map_iterator_t cl_map_head(IN const cl_map_t * const p_map) { CL_ASSERT(p_map); return (cl_qmap_head(&p_map->qmap)); } /* * PARAMETERS * p_map * [in] Pointer to a map whose item with the lowest key is returned. * * RETURN VALUES * Iterator for the object with the lowest key in the map. * * Iterator for the map end if the map was empty. * * NOTES * cl_map_head does not remove the object from the map. * * SEE ALSO * Map, cl_map_tail, cl_map_next, cl_map_prev, cl_map_end *********/ /****f* Component Library: Map/cl_map_tail * NAME * cl_map_tail * * DESCRIPTION * The cl_map_tail function returns the map item with the highest key * value stored in a map. * * SYNOPSIS */ static inline cl_map_iterator_t cl_map_tail(IN const cl_map_t * const p_map) { CL_ASSERT(p_map); return (cl_qmap_tail(&p_map->qmap)); } /* * PARAMETERS * p_map * [in] Pointer to a map whose item with the highest key * is returned. * * RETURN VALUES * Iterator for the object with the highest key in the map. * * Iterator for the map end if the map was empty. * * NOTES * cl_map_end does no remove the object from the map. * * SEE ALSO * Map, cl_map_head, cl_map_next, cl_map_prev, cl_map_end *********/ /****f* Component Library: Map/cl_map_next * NAME * cl_map_next * * DESCRIPTION * The cl_map_next function returns the map item with the next higher * key value than a specified map item. * * SYNOPSIS */ static inline cl_map_iterator_t cl_map_next(IN const cl_map_iterator_t itor) { CL_ASSERT(itor); return (cl_qmap_next(itor)); } /* * PARAMETERS * itor * [in] Iterator for an object in a map whose successor to return. * * RETURN VALUES * Iterator for the object with the next higher key value in a map. * * Iterator for the map end if the specified object was the last item in * the map. * * NOTES * The iterator must have been retrieved by a previous call to cl_map_head, * cl_map_tail, cl_map_next, or cl_map_prev. * * SEE ALSO * Map, cl_map_head, cl_map_tail, cl_map_prev, cl_map_end *********/ /****f* Component Library: Map/cl_map_prev * NAME * cl_map_prev * * DESCRIPTION * The cl_map_prev function returns the map item with the next lower * key value than a precified map item. * * SYNOPSIS */ static inline cl_map_iterator_t cl_map_prev(IN const cl_map_iterator_t itor) { CL_ASSERT(itor); return (cl_qmap_prev(itor)); } /* * PARAMETERS * itor * [in] Iterator for an object in a map whose predecessor to return. * * RETURN VALUES * Iterator for the object with the next lower key value in a map. * * Iterator for the map end if the specified object was the first item in * the map. * * NOTES * The iterator must have been retrieved by a previous call to cl_map_head, * cl_map_tail, cl_map_next, or cl_map_prev. * * SEE ALSO * Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_end *********/ /****f* Component Library: Map/cl_map_insert * NAME * cl_map_insert * * DESCRIPTION * The cl_map_insert function inserts a map item into a map. * * SYNOPSIS */ void *cl_map_insert(IN cl_map_t * const p_map, IN const uint64_t key, IN const void *const p_object); /* * PARAMETERS * p_map * [in] Pointer to a map into which to add the item. * * key * [in] Value to associate with the object. * * p_object * [in] Pointer to an object to insert into the map. * * RETURN VALUES * Pointer to the object in the map with the specified key after the call * completes. * * NULL if there was not enough memory to insert the desired item. * * NOTES * Insertion operations may cause the map to rebalance. * * If the map already contains an object already with the specified key, * that object will not be replaced and the pointer to that object is * returned. * * SEE ALSO * Map, cl_map_remove, cl_map_item_t *********/ /****f* Component Library: Map/cl_map_get * NAME * cl_map_get * * DESCRIPTION * The cl_map_get function returns the object associated with a key. * * SYNOPSIS */ void *cl_map_get(IN const cl_map_t * const p_map, IN const uint64_t key); /* * PARAMETERS * p_map * [in] Pointer to a map from which to retrieve the object with * the specified key. * * key * [in] Key value used to search for the desired object. * * RETURN VALUES * Pointer to the object with the desired key value. * * NULL if there was no item with the desired key value stored in * the map. * * NOTES * cl_map_get does not remove the item from the map. * * SEE ALSO * Map, cl_map_remove, cl_map_get_next *********/ /****f* Component Library: Map/cl_map_get_next * NAME * cl_map_get_next * * DESCRIPTION * The cl_qmap_get_next function returns the first object associated with a * key > the key specified. * * SYNOPSIS */ void *cl_map_get_next(IN const cl_map_t * const p_map, IN const uint64_t key); /* * PARAMETERS * p_map * [in] Pointer to a map from which to retrieve the object with * the specified key. * * key * [in] Key value used to search for the desired object. * * RETURN VALUES * Pointer to the first object with a key > the desired key value. * * NULL if there was no item with a key > the desired key * value stored in the map. * * NOTES * cl_map_get does not remove the item from the map. * * SEE ALSO * Map, cl_map_remove, cl_map_get *********/ /****f* Component Library: Map/cl_map_remove_item * NAME * cl_map_remove_item * * DESCRIPTION * The cl_map_remove_item function removes the specified map item * from a map. * * SYNOPSIS */ void cl_map_remove_item(IN cl_map_t * const p_map, IN const cl_map_iterator_t itor); /* * PARAMETERS * p_map * [in] Pointer to a map from which to remove the object associated * with the specified iterator. * * itor * [in] Iterator for an object to remove from its map. * * RETURN VALUE * This function does not return a value. * * NOTES * Removes the object associated with the specifid iterator from its map. * * The specified iterator is no longer valid after the call completes. * * The iterator must have been retrieved by a previous call to cl_map_head, * cl_map_tail, cl_map_next, or cl_map_prev. * * SEE ALSO * Map, cl_map_remove, cl_map_remove_all, cl_map_insert, cl_map_head, * cl_map_tail, cl_map_next, cl_map_prev *********/ /****f* Component Library: Map/cl_map_remove * NAME * cl_map_remove * * DESCRIPTION * The cl_map_remove function removes the map item with the specified key * from a map. * * SYNOPSIS */ void *cl_map_remove(IN cl_map_t * const p_map, IN const uint64_t key); /* * PARAMETERS * p_map * [in] Pointer to a cl_map_t structure from which to remove the * item with the specified key. * * key * [in] Key value used to search for the object to remove. * * RETURN VALUES * Pointer to the object associated with the specified key if * it was found and removed. * * NULL if no object with the specified key exists in the map. * * SEE ALSO * Map, cl_map_remove_item, cl_map_remove_all, cl_map_insert *********/ /****f* Component Library: Map/cl_map_remove_all * NAME * cl_map_remove_all * * DESCRIPTION * The cl_map_remove_all function removes all objects from a map, * leaving it empty. * * SYNOPSIS */ void cl_map_remove_all(IN cl_map_t * const p_map); /* * PARAMETERS * p_map * [in] Pointer to a map to empty. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Map, cl_map_remove, cl_map_remove_item *********/ /****f* Component Library: Map/cl_map_obj * NAME * cl_map_obj * * DESCRIPTION * The cl_map_obj function returns the object associated with an iterator. * * SYNOPSIS */ static inline void *cl_map_obj(IN const cl_map_iterator_t itor) { return (cl_qmap_obj(PARENT_STRUCT(itor, cl_map_obj_t, item))); } /* * PARAMETERS * itor * [in] Iterator whose object to return. * * RETURN VALUES * Returns the value of the object pointer associated with the iterator. * * The iterator must have been retrieved by a previous call to cl_map_head, * cl_map_tail, cl_map_next, or cl_map_prev. * * SEE ALSO * Map, cl_map_head, cl_map_tail, cl_map_next, cl_map_prev *********/ /****f* Component Library: Map/cl_map_merge * NAME * cl_map_merge * * DESCRIPTION * The cl_map_merge function moves all items from one map to another, * excluding duplicates. * * SYNOPSIS */ cl_status_t cl_map_merge(OUT cl_map_t * const p_dest_map, IN OUT cl_map_t * const p_src_map); /* * PARAMETERS * p_dest_map * [out] Pointer to a cl_map_t structure to which items should be added. * * p_src_map * [in/out] Pointer to a cl_map_t structure whose items to add * to p_dest_map. * * RETURN VALUES * CL_SUCCESS if the operation succeeded. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the operation * to succeed. * * NOTES * Items are evaluated based on their keys only. * * Upon return from cl_map_merge, the map referenced by p_src_map contains * all duplicate items. * * SEE ALSO * Map, cl_map_delta *********/ /****f* Component Library: Map/cl_map_delta * NAME * cl_map_delta * * DESCRIPTION * The cl_map_delta function computes the differences between two maps. * * SYNOPSIS */ 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); /* * PARAMETERS * p_map1 * [in/out] Pointer to the first of two cl_map_t structures whose * differences to compute. * * p_map2 * [in/out] Pointer to the second of two cl_map_t structures whose * differences to compute. * * p_new * [out] Pointer to an empty cl_map_t structure that contains the * items unique to p_map2 upon return from the function. * * p_old * [out] Pointer to an empty cl_map_t structure that contains the * items unique to p_map1 upon return from the function. * * RETURN VALUES * CL_SUCCESS if the operation succeeded. * * CL_INSUFFICIENT_MEMORY if there was not enough memory for the operation * to succeed. * * 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 useful in evaluating * changes between two maps. * * Both maps pointed to by p_new and p_old must be empty on input. * * Upon failure, all input maps are restored to their original state. * * SEE ALSO * Map, cl_map_merge *********/ END_C_DECLS #endif /* _CL_MAP_H_ */ opensm-3.3.20/include/complib/cl_math.h0000644000205000001450000000674212104655724014657 00000000000000/* * Copyright (c) 2004, 2005 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: * Defines standard math related macros and functions. */ #ifndef _CL_MATH_H_ #define _CL_MATH_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****d* Component Library: Math/MAX * NAME * MAX * * DESCRIPTION * The MAX macro returns the greater of two values. * * SYNOPSIS * MAX( x, y ); * * PARAMETERS * x * [in] First of two values to compare. * * y * [in] Second of two values to compare. * * RETURN VALUE * Returns the greater of the x and y parameters. * * SEE ALSO * MIN, ROUNDUP *********/ #ifndef MAX #define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /****d* Component Library: Math/MIN * NAME * MIN * * DESCRIPTION * The MIN macro returns the greater of two values. * * SYNOPSIS * MIN( x, y ); * * PARAMETERS * x * [in] First of two values to compare. * * y * [in] Second of two values to compare. * * RETURN VALUE * Returns the lesser of the x and y parameters. * * SEE ALSO * MAX, ROUNDUP *********/ #ifndef MIN #define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /****d* Component Library: Math/ROUNDUP * NAME * ROUNDUP * * DESCRIPTION * The ROUNDUP macro rounds a value up to a given multiple. * * SYNOPSIS * ROUNDUP( val, align ); * * PARAMETERS * val * [in] Value that is to be rounded up. The type of the value is * indeterminate, but must be at most the size of a natural integer * for the platform. * * align * [in] Multiple to which the val parameter must be rounded up. * * RETURN VALUE * Returns a value that is the input value specified by val rounded up to * the nearest multiple of align. * * NOTES * The value provided must be of a type at most the size of a natural integer. *********/ #ifndef ROUNDUP #define ROUNDUP(val, align) \ ((((val) / (align))*(align)) + (((val) % (align)) ? (align) : 0)) #endif END_C_DECLS #endif /* _CL_MATH_H_ */ opensm-3.3.20/include/complib/cl_nodenamemap.h0000644000205000001450000000440012272264652016201 00000000000000/* * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 Lawrence Livermore National Lab * * 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. * */ #ifndef _CL_NODE_NAME_MAP_H_ #define _CL_NODE_NAME_MAP_H_ #include #include #include /* NOTE: this may modify the parameter "nodedesc". */ char *clean_nodedesc(char *nodedesc); typedef struct _name_map_item { cl_map_item_t item; uint64_t guid; char *name; } name_map_item_t; typedef cl_qmap_t nn_map_t; /** * Node name map interface. * It is OK to pass NULL for the node_name_map[_fp] parameters. */ nn_map_t *open_node_name_map(const char *node_name_map); void close_node_name_map(nn_map_t *map); char *remap_node_name(nn_map_t *map, uint64_t target_guid, char *nodedesc); /* NOTE: parameter "nodedesc" may be modified here. */ int parse_node_map(const char *file_name, int (*create)(void *, uint64_t, char *), void *cxt); #endif /* _CL_NODE_NAME_MAP_H_ */ opensm-3.3.20/include/complib/cl_packoff.h0000644000205000001450000000347612104655724015340 00000000000000/* * Copyright (c) 2004, 2005 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: * Turns off byte packing, which is necessary for passing information from * system to system over a network to ensure no padding by the compiler has * taken place. */ #ifdef PACK_SUFFIX #undef PACK_SUFFIX #endif #ifdef _MSC_VER #pragma pack (pop) #endif opensm-3.3.20/include/complib/cl_packon.h0000644000205000001450000000567312104655724015203 00000000000000/* * Copyright (c) 2004, 2005 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: * Turns on byte packing, which is necessary for passing information from * system to system over a network to ensure no padding by the compiler has * taken place. */ /****h* Component Library/Structure Packing * NAME * Structure Packing * * DESCRIPTION * The structure packing header files allow packing structures on byte * boundaries. * * Structure packing should be used whenever a structure is transmitted * between systems, as different platforms pad structures differently if * they are not packed. Packing a structure that is not transmitted between * systems can be detrimental to performance, as fields in the structure may * not align properly for some platforms. Care must be taken when creating * packed structures that the alignment rules for all platforms are followed. * * To pack a structure, include cl_packon.h before defining the structure, and * include cl_packoff.h after the structure definition. Multiple structures * can be packed between the two include statements if desired. * * The structure definition itself must use the PACK_SUFFIX keyword. * * EXAMPLE * #include * * typedef _my_struct_t * { * uint64 large; * uint32 medium; * uint16 small; * * } PACK_SUFFIX my_struct_t; * #include *********/ #ifndef PACK_SUFFIX #define PACK_SUFFIX __attribute__((packed)) #endif #ifdef _MSC_VER #pragma pack (push, 1) #endif opensm-3.3.20/include/complib/cl_passivelock.h0000644000205000001450000001745212104655724016251 00000000000000/* * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 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: * This file contains the passive lock, which synchronizes passive threads. * The passive lock allows multiple readers to access a resource * simultaneously, exclusive from a single thread allowed writing. * Several writer threads are allowed - but only one can write at a given time */ #ifndef _CL_PASSIVE_LOCK_H_ #define _CL_PASSIVE_LOCK_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Passive Lock * NAME * Passive Lock * * DESCRIPTION * The Passive Lock provides synchronization between multiple threads that * are sharing the lock with a single thread holding the lock exclusively. * * Passive lock works exclusively between threads and cannot be used in * situations where the caller cannot be put into a waiting state. * * The passive lock functions operate a cl_plock_t structure which should * be treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_plock_t * * Initialization: * cl_plock_construct, cl_plock_init, cl_plock_destroy * * Manipulation * cl_plock_acquire, cl_plock_excl_acquire, cl_plock_release *********/ /****s* Component Library: Passive Lock/cl_plock_t * NAME * cl_plock_t * * DESCRIPTION * Passive Lock structure. * * The cl_plock_t structure should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_plock { pthread_rwlock_t lock; cl_state_t state; } cl_plock_t; /* * FIELDS * lock * Pthread RWLOCK object * * state * Records the current state of the lock, such as initialized, * destroying, etc. * * SEE ALSO * Passive Lock *********/ /****f* Component Library: Passive Lock/cl_plock_construct * NAME * cl_plock_construct * * DESCRIPTION * The cl_plock_construct function initializes the state of a * passive lock. * * SYNOPSIS */ static inline void cl_plock_construct(IN cl_plock_t * const p_lock) { CL_ASSERT(p_lock); p_lock->state = CL_UNINITIALIZED; } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_plock_destroy without first calling cl_plock_init. * * Calling cl_plock_construct is a prerequisite to calling any other * passive lock function except cl_plock_init. * * SEE ALSO * Passive Lock, cl_plock_init, cl_plock_destroy *********/ /****f* Component Library: Passive Lock/cl_plock_destroy * NAME * cl_plock_destroy * * DESCRIPTION * The cl_plock_destroy function performs any necessary cleanup * of a passive lock. * * SYNOPSIS */ static inline void cl_plock_destroy(IN cl_plock_t * const p_lock) { CL_ASSERT(p_lock); p_lock->state = CL_DESTROYING; pthread_rwlock_destroy(&p_lock->lock); p_lock->state = CL_DESTROYED; } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_plock_destroy performs any necessary cleanup of the specified * passive lock. * * This function must only be called if cl_plock_construct or * cl_plock_init has been called. The passive lock must not be held * when calling this function. * * SEE ALSO * Passive Lock, cl_plock_construct, cl_plock_init *********/ /****f* Component Library: Passive Lock/cl_plock_init * NAME * cl_plock_init * * DESCRIPTION * The cl_plock_init function initializes a passive lock. * * SYNOPSIS */ static inline cl_status_t cl_plock_init(IN cl_plock_t * const p_lock) { cl_status_t status; CL_ASSERT(p_lock); status = pthread_rwlock_init(&p_lock->lock, NULL); if (status) return CL_ERROR; p_lock->state = CL_INITIALIZED; return (CL_SUCCESS); } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure to initialize. * * RETURN VALUES * CL_SUCCESS if the passive lock was initialized successfully. * * CL_ERROR otherwise. * * NOTES * Allows calling cl_plock_acquire, cl_plock_release, * cl_plock_excl_acquire * * SEE ALSO * Passive Lock, cl_plock_construct, cl_plock_destroy, * cl_plock_excl_acquire, cl_plock_acquire, cl_plock_release *********/ /****f* Component Library: Passive Lock/cl_plock_acquire * NAME * cl_plock_acquire * * DESCRIPTION * The cl_plock_acquire function acquires a passive lock for * shared access. * * SYNOPSIS */ static inline void cl_plock_acquire(IN cl_plock_t * const p_lock) { cl_status_t __attribute__((unused)) status; CL_ASSERT(p_lock); CL_ASSERT(p_lock->state == CL_INITIALIZED); status = pthread_rwlock_rdlock(&p_lock->lock); CL_ASSERT(status == 0); } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure to acquire. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Passive Lock, cl_plock_release, cl_plock_excl_acquire *********/ /****f* Component Library: Passive Lock/cl_plock_excl_acquire * NAME * cl_plock_excl_acquire * * DESCRIPTION * The cl_plock_excl_acquire function acquires exclusive access * to a passive lock. * * SYNOPSIS */ static inline void cl_plock_excl_acquire(IN cl_plock_t * const p_lock) { cl_status_t __attribute__((unused)) status; CL_ASSERT(p_lock); CL_ASSERT(p_lock->state == CL_INITIALIZED); status = pthread_rwlock_wrlock(&p_lock->lock); CL_ASSERT(status == 0); } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure to acquire exclusively. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Passive Lock, cl_plock_release, cl_plock_acquire *********/ /****f* Component Library: Passive Lock/cl_plock_release * NAME * cl_plock_release * * DESCRIPTION * The cl_plock_release function releases a passive lock from * shared or exclusive access. * * SYNOPSIS */ static inline void cl_plock_release(IN cl_plock_t * const p_lock) { cl_status_t __attribute__((unused)) status; CL_ASSERT(p_lock); CL_ASSERT(p_lock->state == CL_INITIALIZED); status = pthread_rwlock_unlock(&p_lock->lock); CL_ASSERT(status == 0); } /* * PARAMETERS * p_lock * [in] Pointer to a cl_plock_t structure to release. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Passive Lock, cl_plock_acquire, cl_plock_excl_acquire *********/ END_C_DECLS #endif /* _CL_PASSIVE_LOCK_H_ */ opensm-3.3.20/include/complib/cl_pool.h0000644000205000001450000003424412104655724014675 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of the pool. * The pool manages a pool of objects. * The pool can grow to meet demand, limited only by system memory. */ #ifndef _CL_POOL_H_ #define _CL_POOL_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Pool * NAME * Pool * * DESCRIPTION * The pool provides a self-contained and self-sustaining pool * of user defined objects. * * To aid in object oriented design, the pool provides the user * the ability to specify callbacks that are invoked for each object for * construction, initialization, and destruction. Constructor and destructor * callback functions may not fail. * * A pool does not return memory to the system as the user returns * objects to the pool. The only method of returning memory to the system is * to destroy the pool. * * The Pool functions operate on a cl_pool_t structure which should be treated * as opaque and should be manipulated only through the provided functions. * * SEE ALSO * Structures: * cl_pool_t * * Callbacks: * cl_pfn_pool_init_t, cl_pfn_pool_dtor_t * * Initialization/Destruction: * cl_pool_construct, cl_pool_init, cl_pool_destroy * * Manipulation: * cl_pool_get, cl_pool_put, cl_pool_grow * * Attributes: * cl_is_pool_inited, cl_pool_count *********/ /****d* Component Library: Pool/cl_pfn_pool_init_t * NAME * cl_pfn_pool_init_t * * DESCRIPTION * The cl_pfn_pool_init_t function type defines the prototype for * functions used as initializers for objects being allocated by a * pool. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_pool_init_t) (IN void *const p_object, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object to initialize. * * context * [in] Context provided in a call to cl_pool_init. * * RETURN VALUES * Return CL_SUCCESS to indicates that initialization of the object * was successful and initialization of further objects may continue. * * Other cl_status_t values will be returned by cl_pool_init * and cl_pool_grow. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_pool_init function. * * The initializer is invoked once per allocated object, allowing the user * to trap initialization failures. Returning a status other than CL_SUCCESS * aborts a grow operation, initiated either through cl_pool_init or * cl_pool_grow, and causes the initiating function to fail. * Any non-CL_SUCCESS status will be returned by the function that initiated * the grow operation. * * SEE ALSO * Pool, cl_pool_init, cl_pool_grow *********/ /****d* Component Library: Pool/cl_pfn_pool_dtor_t * NAME * cl_pfn_pool_dtor_t * * DESCRIPTION * The cl_pfn_pool_dtor_t function type defines the prototype for * functions used as destructor for objects being deallocated by a * pool. * * SYNOPSIS */ typedef void (*cl_pfn_pool_dtor_t) (IN void *const p_object, IN void *context); /* * PARAMETERS * p_object * [in] Pointer to an object to destruct. * * context * [in] Context provided in the call to cl_pool_init. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_pool_init function. * * The destructor is invoked once per allocated object, allowing the user * to perform any necessary cleanup. Users should not attempt to deallocate * the memory for the object, as the pool manages object * allocation and deallocation. * * SEE ALSO * Pool, cl_pool_init *********/ /****s* Component Library: Pool/cl_pool_t * NAME * cl_pool_t * * DESCRIPTION * pool structure. * * The cl_pool_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_pool { cl_qcpool_t qcpool; cl_pfn_pool_init_t pfn_init; cl_pfn_pool_dtor_t pfn_dtor; const void *context; } cl_pool_t; /* * FIELDS * qcpool * Quick composite pool that manages all objects. * * pfn_init * Pointer to the user's initializer callback, used by the pool * to translate the quick composite pool's initializer callback to * a pool initializer callback. * * pfn_dtor * Pointer to the user's destructor callback, used by the pool * to translate the quick composite pool's destructor callback to * a pool destructor callback. * * context * User's provided context for callback functions, used by the pool * to when invoking callbacks. * * SEE ALSO * Pool *********/ /****f* Component Library: Pool/cl_pool_construct * NAME * cl_pool_construct * * DESCRIPTION * The cl_pool_construct function constructs a pool. * * SYNOPSIS */ void cl_pool_construct(IN cl_pool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_pool_init, cl_pool_destroy, and cl_is_pool_inited. * * Calling cl_pool_construct is a prerequisite to calling any other * pool function except cl_pool_init. * * SEE ALSO * Pool, cl_pool_init, cl_pool_destroy, cl_is_pool_inited *********/ /****f* Component Library: Pool/cl_is_pool_inited * NAME * cl_is_pool_inited * * DESCRIPTION * The cl_is_pool_inited function returns whether a pool was successfully * initialized. * * SYNOPSIS */ static inline uint32_t cl_is_pool_inited(IN const cl_pool_t * const p_pool) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_pool); return (cl_is_qcpool_inited(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure whose initialization state * to check. * * RETURN VALUES * TRUE if the pool was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a pool to determine if invoking member * functions is appropriate. * * SEE ALSO * Pool *********/ /****f* Component Library: Pool/cl_pool_init * NAME * cl_pool_init * * DESCRIPTION * The cl_pool_init function initializes a pool for use. * * SYNOPSIS */ cl_status_t cl_pool_init(IN cl_pool_t * const p_pool, IN const size_t min_count, IN const size_t max_count, IN const size_t grow_size, IN const size_t object_size, IN cl_pfn_pool_init_t pfn_initializer OPTIONAL, IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL, IN const void *const context); /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure to initialize. * * min_count * [in] Minimum number of objects that the pool should support. All * necessary allocations to allow storing the minimum number of items * are performed at initialization time, and all necessary callbacks * invoked. * * max_count * [in] Maximum number of objects to which the pool is allowed to grow. * A value of zero specifies no maximum. * * grow_size * [in] Number of objects to allocate when incrementally growing the pool. * A value of zero disables automatic growth. * * object_size * [in] Size, in bytes, of each object. * * pfn_initializer * [in] Initialization callback to invoke for every new object when * growing the pool. This parameter is optional and may be NULL. * See the cl_pfn_pool_init_t function type declaration for details * about the callback function. * * pfn_destructor * [in] Destructor callback to invoke for every object before memory for * that object is freed. This parameter is optional and may be NULL. * See the cl_pfn_pool_dtor_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * CL_SUCCESS if the pool was initialized successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the * pool. * * CL_INVALID_SETTING if a the maximum size is non-zero and less than the * minimum size. * * Other cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter. * * NOTES * cl_pool_init initializes, and if necessary, grows the pool to * the capacity desired. * * SEE ALSO * Pool, cl_pool_construct, cl_pool_destroy, * cl_pool_get, cl_pool_put, cl_pool_grow, * cl_pool_count, cl_pfn_pool_init_t, cl_pfn_pool_dtor_t *********/ /****f* Component Library: Pool/cl_pool_destroy * NAME * cl_pool_destroy * * DESCRIPTION * The cl_pool_destroy function destroys a pool. * * SYNOPSIS */ static inline void cl_pool_destroy(IN cl_pool_t * const p_pool) { CL_ASSERT(p_pool); cl_qcpool_destroy(&p_pool->qcpool); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * All memory allocated for objects is freed. The destructor callback, * if any, will be invoked for every allocated object. Further operations * on the pool should not be attempted after cl_pool_destroy * is invoked. * * This function should only be called after a call to * cl_pool_construct or cl_pool_init. * * In a debug build, cl_pool_destroy asserts that all objects are in * the pool. * * SEE ALSO * Pool, cl_pool_construct, cl_pool_init *********/ /****f* Component Library: Pool/cl_pool_count * NAME * cl_pool_count * * DESCRIPTION * The cl_pool_count function returns the number of available objects * in a pool. * * SYNOPSIS */ static inline size_t cl_pool_count(IN cl_pool_t * const p_pool) { CL_ASSERT(p_pool); return (cl_qcpool_count(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure for which the number of * available objects is requested. * * RETURN VALUE * Returns the number of objects available in the specified pool. * * SEE ALSO * Pool *********/ /****f* Component Library: Pool/cl_pool_get * NAME * cl_pool_get * * DESCRIPTION * The cl_pool_get function retrieves an object from a pool. * * SYNOPSIS */ static inline void *cl_pool_get(IN cl_pool_t * const p_pool) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_pool); p_pool_obj = (cl_pool_obj_t *) cl_qcpool_get(&p_pool->qcpool); if (!p_pool_obj) return (NULL); CL_ASSERT(p_pool_obj->p_object); return ((void *)p_pool_obj->p_object); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure from which to retrieve * an object. * * RETURN VALUES * Returns a pointer to an object. * * Returns NULL if the pool is empty and can not be grown automatically. * * NOTES * cl_pool_get returns the object at the head of the pool. If the pool is * empty, it is automatically grown to accommodate this request unless the * grow_size parameter passed to the cl_pool_init function was zero. * * SEE ALSO * Pool, cl_pool_get_tail, cl_pool_put, cl_pool_grow, cl_pool_count *********/ /****f* Component Library: Pool/cl_pool_put * NAME * cl_pool_put * * DESCRIPTION * The cl_pool_put function returns an object to a pool. * * SYNOPSIS */ static inline void cl_pool_put(IN cl_pool_t * const p_pool, IN void *const p_object) { cl_pool_obj_t *p_pool_obj; CL_ASSERT(p_pool); CL_ASSERT(p_object); /* Calculate the offset to the list object representing this object. */ p_pool_obj = (cl_pool_obj_t *) (((uint8_t *) p_object) - sizeof(cl_pool_obj_t)); /* good sanity check */ CL_ASSERT(p_pool_obj->p_object == p_object); cl_qcpool_put(&p_pool->qcpool, &p_pool_obj->pool_item); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure to which to return * an object. * * p_object * [in] Pointer to an object to return to the pool. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_pool_put places the returned object at the head of the pool. * * The object specified by the p_object parameter must have been * retrieved from the pool by a previous call to cl_pool_get. * * SEE ALSO * Pool, cl_pool_put_tail, cl_pool_get *********/ /****f* Component Library: Pool/cl_pool_grow * NAME * cl_pool_grow * * DESCRIPTION * The cl_pool_grow function grows a pool by * the specified number of objects. * * SYNOPSIS */ static inline cl_status_t cl_pool_grow(IN cl_pool_t * const p_pool, IN const size_t obj_count) { CL_ASSERT(p_pool); return (cl_qcpool_grow(&p_pool->qcpool, obj_count)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_pool_t structure whose capacity to grow. * * obj_count * [in] Number of objects by which to grow the pool. * * RETURN VALUES * CL_SUCCESS if the pool grew successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the * pool. * * cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter passed to the * cl_pool_init function. * * NOTES * It is not necessary to call cl_pool_grow if the pool is * configured to grow automatically. * * SEE ALSO * Pool *********/ END_C_DECLS #endif /* _CL_POOL_H_ */ opensm-3.3.20/include/complib/cl_ptr_vector.h0000644000205000001450000005345712104655724016122 00000000000000/* * Copyright (c) 2004, 2005 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: * This file contains pointer vector definitions. Pointer Vector provides * dynmically resizable array functionality. */ #ifndef _CL_PTR_VECTOR_H_ #define _CL_PTR_VECTOR_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Pointer Vector * NAME * Pointer Vector * * DESCRIPTION * The Pointer Vector is a self-sizing array of pointers. Like a traditonal * array, a pointer vector allows efficient constant time access to elements * with a specified index. A pointer vector grows transparently as the * user adds elements to the array. * * The cl_pointer vector_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SEE ALSO * Structures: * cl_ptr_vector_t * * Callbacks: * cl_pfn_ptr_vec_apply_t, cl_pfn_ptr_vec_find_t * * Item Manipulation: * cl_ptr_vector_set, cl_ptr_vector_obj * * Initialization: * cl_ptr_vector_construct, cl_ptr_vector_init, cl_ptr_vector_destroy * * Manipulation: * cl_ptr_vector_get_capacity, cl_ptr_vector_set_capacity, * cl_ptr_vector_get_size, cl_ptr_vector_set_size, cl_ptr_vector_set_min_size * cl_ptr_vector_get_ptr, cl_ptr_vector_get, cl_ptr_vector_at, cl_ptr_vector_set * * Search: * cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end * cl_ptr_vector_apply_func *********/ /****d* Component Library: Pointer Vector/cl_pfn_ptr_vec_apply_t * NAME * cl_pfn_ptr_vec_apply_t * * DESCRIPTION * The cl_pfn_ptr_vec_apply_t function type defines the prototype for * functions used to iterate elements in a pointer vector. * * SYNOPSIS */ typedef void (*cl_pfn_ptr_vec_apply_t) (IN const size_t index, IN void *const element, IN void *context); /* * PARAMETERS * index * [in] Index of the element. * * p_element * [in] Pointer to an element at the specified index in the pointer vector. * * context * [in] Context provided in a call to cl_ptr_vector_apply_func. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function passed by users as a parameter to the cl_ptr_vector_apply_func * function. * * SEE ALSO * Pointer Vector, cl_ptr_vector_apply_func *********/ /****d* Component Library: Pointer Vector/cl_pfn_ptr_vec_find_t * NAME * cl_pfn_ptr_vec_find_t * * DESCRIPTION * The cl_pfn_ptr_vec_find_t function type defines the prototype for * functions used to find elements in a pointer vector. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_ptr_vec_find_t) (IN const size_t index, IN const void *const element, IN void *context); /* * PARAMETERS * index * [in] Index of the element. * * p_element * [in] Pointer to an element at the specified index in the * pointer vector. * * context * [in] Context provided in a call to cl_ptr_vector_find_from_start or * cl_ptr_vector_find_from_end. * * RETURN VALUES * Return CL_SUCCESS if the element was found. This stops pointer vector * iteration. * * CL_NOT_FOUND to continue the pointer vector iteration. * * NOTES * This function type is provided as function prototype reference for the * function provided by users as a parameter to the * cl_ptr_vector_find_from_start and cl_ptr_vector_find_from_end functions. * * SEE ALSO * Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end *********/ /****s* Component Library: Pointer Vector/cl_ptr_vector_t * NAME * cl_ptr_vector_t * * DESCRIPTION * Pointer Vector structure. * * The cl_ptr_vector_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_ptr_vector { size_t size; size_t grow_size; size_t capacity; const void **p_ptr_array; cl_state_t state; } cl_ptr_vector_t; /* * FIELDS * size * Number of elements successfully initialized in the pointer vector. * * grow_size * Number of elements to allocate when growing. * * capacity * total # of elements allocated. * * alloc_list * List of allocations. * * p_ptr_array * Internal array of pointers to elements. * * state * State of the pointer vector. * * SEE ALSO * Pointer Vector *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_construct * NAME * cl_ptr_vector_construct * * DESCRIPTION * The cl_ptr_vector_construct function constructs a pointer vector. * * SYNOPSIS */ void cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_ptr_vector_destroy without first calling * cl_ptr_vector_init. * * Calling cl_ptr_vector_construct is a prerequisite to calling any other * pointer vector function except cl_ptr_vector_init. * * SEE ALSO * Pointer Vector, cl_ptr_vector_init, cl_ptr_vector_destroy *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_init * NAME * cl_ptr_vector_init * * DESCRIPTION * The cl_ptr_vector_init function initializes a pointer vector for use. * * SYNOPSIS */ cl_status_t cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector, IN const size_t min_size, IN const size_t grow_size); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure to inititalize. * * min_size * [in] Initial number of elements. * * grow_size * [in] Number of elements to allocate when incrementally growing * the pointer vector. A value of zero disables automatic growth. * * RETURN VALUES * CL_SUCCESS if the pointer vector was initialized successfully. * * CL_INSUFFICIENT_MEMORY if the initialization failed. * * SEE ALSO * Pointer Vector, cl_ptr_vector_construct, cl_ptr_vector_destroy, * cl_ptr_vector_set, cl_ptr_vector_get, cl_ptr_vector_at *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_destroy * NAME * cl_ptr_vector_destroy * * DESCRIPTION * The cl_ptr_vector_destroy function destroys a pointer vector. * * SYNOPSIS */ void cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_ptr_vector_destroy frees all memory allocated for the pointer vector. * * This function should only be called after a call to cl_ptr_vector_construct * or cl_ptr_vector_init. * * SEE ALSO * Pointer Vector, cl_ptr_vector_construct, cl_ptr_vector_init *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_get_capacity * NAME * cl_ptr_vector_get_capacity * * DESCRIPTION * The cl_ptr_vector_get_capacity function returns the capacity of * a pointer vector. * * SYNOPSIS */ static inline size_t cl_ptr_vector_get_capacity(IN const cl_ptr_vector_t * const p_vector) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); return (p_vector->capacity); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose capacity to return. * * RETURN VALUE * Capacity, in elements, of the pointer vector. * * NOTES * The capacity is the number of elements that the pointer vector can store, * and can be greater than the number of elements stored. To get the number * of elements stored in the pointer vector, use cl_ptr_vector_get_size. * * SEE ALSO * Pointer Vector, cl_ptr_vector_set_capacity, cl_ptr_vector_get_size *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_get_size * NAME * cl_ptr_vector_get_size * * DESCRIPTION * The cl_ptr_vector_get_size function returns the size of a pointer vector. * * SYNOPSIS */ static inline uint32_t cl_ptr_vector_get_size(IN const cl_ptr_vector_t * const p_vector) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); return ((uint32_t) p_vector->size); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose size to return. * * RETURN VALUE * Size, in elements, of the pointer vector. * * SEE ALSO * Pointer Vector, cl_ptr_vector_set_size, cl_ptr_vector_get_capacity *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_get * NAME * cl_ptr_vector_get * * DESCRIPTION * The cl_ptr_vector_get function returns the pointer stored in a * pointer vector at a specified index. * * SYNOPSIS */ static inline void *cl_ptr_vector_get(IN const cl_ptr_vector_t * const p_vector, IN const size_t index) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(p_vector->size > index); return ((void *)p_vector->p_ptr_array[index]); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure from which to get an * element. * * index * [in] Index of the element. * * RETURN VALUE * Value of the pointer stored at the specified index. * * NOTES * cl_ptr_vector_get provides constant access times regardless of the index. * * cl_ptr_vector_get does not perform boundary checking. Callers are * responsible for providing an index that is within the range of the pointer * vector. * * SEE ALSO * Pointer Vector, cl_ptr_vector_at, cl_ptr_vector_set, cl_ptr_vector_get_size *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_at * NAME * cl_ptr_vector_at * * DESCRIPTION * The cl_ptr_vector_at function copies an element stored in a pointer * vector at a specified index, performing boundary checks. * * SYNOPSIS */ cl_status_t cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector, IN const size_t index, OUT void **const p_element); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure from which to get a copy of * an element. * * index * [in] Index of the element. * * p_element * [out] Pointer to storage for the pointer element. Contains a copy of * the desired pointer upon successful completion of the call. * * RETURN VALUES * CL_SUCCESS if an element was found at the specified index. * * CL_INVALID_SETTING if the index was out of range. * * NOTES * cl_ptr_vector_at provides constant time access regardless of * the index, and performs boundary checking on the pointer vector. * * Upon success, the p_element parameter contains a copy of the * desired element. * * SEE ALSO * Pointer Vector, cl_ptr_vector_get *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_set * NAME * cl_ptr_vector_set * * DESCRIPTION * The cl_ptr_vector_set function sets the element at the specified index. * * SYNOPSIS */ cl_status_t cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector, IN const size_t index, IN const void *const element); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure into which to store * an element. * * index * [in] Index of the element. * * element * [in] Pointer to store in the pointer vector. * * RETURN VALUES * CL_SUCCESS if the element was successfully set. * * CL_INSUFFICIENT_MEMORY if the pointer vector could not be resized to * accommodate the new element. * * NOTES * cl_ptr_vector_set grows the pointer vector as needed to accommodate * the new element, unless the grow_size parameter passed into the * cl_ptr_vector_init function was zero. * * SEE ALSO * Pointer Vector, cl_ptr_vector_get *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_insert * NAME * cl_ptr_vector_insert * * DESCRIPTION * The cl_ptr_vector_insert function inserts an element into a pointer vector. * * SYNOPSIS */ static inline cl_status_t cl_ptr_vector_insert(IN cl_ptr_vector_t * const p_vector, IN const void *const element, OUT size_t * const p_index OPTIONAL) { cl_status_t status; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); status = cl_ptr_vector_set(p_vector, p_vector->size, element); if (status == CL_SUCCESS && p_index) *p_index = p_vector->size - 1; return (status); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure into which to store * an element. * * element * [in] Pointer to store in the pointer vector. * * p_index * [out] Pointer to the index of the element. Valid only if * insertion was successful. * * RETURN VALUES * CL_SUCCESS if the element was successfully inserted. * * CL_INSUFFICIENT_MEMORY if the pointer vector could not be resized to * accommodate the new element. * * NOTES * cl_ptr_vector_insert places the new element at the end of * the pointer vector. * * cl_ptr_vector_insert grows the pointer vector as needed to accommodate * the new element, unless the grow_size parameter passed into the * cl_ptr_vector_init function was zero. * * SEE ALSO * Pointer Vector, cl_ptr_vector_remove, cl_ptr_vector_set *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_remove * NAME * cl_ptr_vector_remove * * DESCRIPTION * The cl_ptr_vector_remove function removes and returns the pointer stored * in a pointer vector at a specified index. Items beyond the removed item * are shifted down and the size of the pointer vector is decremented. * * SYNOPSIS */ void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector, IN const size_t index); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure from which to get an * element. * * index * [in] Index of the element. * * RETURN VALUE * Value of the pointer stored at the specified index. * * NOTES * cl_ptr_vector_get does not perform boundary checking. Callers are * responsible for providing an index that is within the range of the pointer * vector. * * SEE ALSO * Pointer Vector, cl_ptr_vector_insert, cl_ptr_vector_get_size *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_set_capacity * NAME * cl_ptr_vector_set_capacity * * DESCRIPTION * The cl_ptr_vector_set_capacity function reserves memory in a * pointer vector for a specified number of pointers. * * SYNOPSIS */ cl_status_t cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector, IN const size_t new_capacity); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose capacity to set. * * new_capacity * [in] Total number of elements for which the pointer vector should * allocate memory. * * RETURN VALUES * CL_SUCCESS if the capacity was successfully set. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to satisfy the * operation. The pointer vector is left unchanged. * * NOTES * cl_ptr_vector_set_capacity increases the capacity of the pointer vector. * It does not change the size of the pointer vector. If the requested * capacity is less than the current capacity, the pointer vector is left * unchanged. * * SEE ALSO * Pointer Vector, cl_ptr_vector_get_capacity, cl_ptr_vector_set_size, * cl_ptr_vector_set_min_size *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_set_size * NAME * cl_ptr_vector_set_size * * DESCRIPTION * The cl_ptr_vector_set_size function resizes a pointer vector, either * increasing or decreasing its size. * * SYNOPSIS */ cl_status_t cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector, IN const size_t size); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose size to set. * * size * [in] Number of elements desired in the pointer vector. * * RETURN VALUES * CL_SUCCESS if the size of the pointer vector was set successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to complete the * operation. The pointer vector is left unchanged. * * NOTES * cl_ptr_vector_set_size sets the pointer vector to the specified size. * If size is smaller than the current size of the pointer vector, the size * is reduced. * * This function can only fail if size is larger than the current capacity. * * SEE ALSO * Pointer Vector, cl_ptr_vector_get_size, cl_ptr_vector_set_min_size, * cl_ptr_vector_set_capacity *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_set_min_size * NAME * cl_ptr_vector_set_min_size * * DESCRIPTION * The cl_ptr_vector_set_min_size function resizes a pointer vector to a * specified size if the pointer vector is smaller than the specified size. * * SYNOPSIS */ cl_status_t cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector, IN const size_t min_size); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose minimum size to set. * * min_size * [in] Minimum number of elements that the pointer vector should contain. * * RETURN VALUES * CL_SUCCESS if the pointer vector size is greater than or equal to min_size. * This could indicate that the pointer vector's capacity was increased to * min_size or that the pointer vector was already of sufficient size. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to resize the * pointer vector. The pointer vector is left unchanged. * * NOTES * If min_size is smaller than the current size of the pointer vector, * the pointer vector is unchanged. The pointer vector is unchanged if the * size could not be changed due to insufficient memory being available to * perform the operation. * * SEE ALSO * Pointer Vector, cl_ptr_vector_get_size, cl_ptr_vector_set_size, * cl_ptr_vector_set_capacity *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_apply_func * NAME * cl_ptr_vector_apply_func * * DESCRIPTION * The cl_ptr_vector_apply_func function invokes a specified function for * every element in a pointer vector. * * SYNOPSIS */ void cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_apply_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure whose elements to iterate. * * pfn_callback * [in] Function invoked for every element in the array. * See the cl_pfn_ptr_vec_apply_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_ptr_vector_apply_func invokes the specified function for every element * in the pointer vector, starting from the beginning of the pointer vector. * * SEE ALSO * Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_find_from_end, * cl_pfn_ptr_vec_apply_t *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_find_from_start * NAME * cl_ptr_vector_find_from_start * * DESCRIPTION * The cl_ptr_vector_find_from_start function uses a specified function to * search for elements in a pointer vector starting from the lowest index. * * SYNOPSIS */ size_t cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_find_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure to inititalize. * * pfn_callback * [in] Function invoked to determine if a match was found. * See the cl_pfn_ptr_vec_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUES * Index of the element, if found. * * Size of the pointer vector if the element was not found. * * NOTES * cl_ptr_vector_find_from_start does not remove the found element from * the pointer vector. The index of the element is returned when the function * provided by the pfn_callback parameter returns CL_SUCCESS. * * SEE ALSO * Pointer Vector, cl_ptr_vector_find_from_end, cl_ptr_vector_apply_func, * cl_pfn_ptr_vec_find_t *********/ /****f* Component Library: Pointer Vector/cl_ptr_vector_find_from_end * NAME * cl_ptr_vector_find_from_end * * DESCRIPTION * The cl_ptr_vector_find_from_end function uses a specified function to * search for elements in a pointer vector starting from the highest index. * * SYNOPSIS */ size_t cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_find_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_ptr_vector_t structure to inititalize. * * pfn_callback * [in] Function invoked to determine if a match was found. * See the cl_pfn_ptr_vec_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUES * Index of the element, if found. * * Size of the pointer vector if the element was not found. * * NOTES * cl_ptr_vector_find_from_end does not remove the found element from * the pointer vector. The index of the element is returned when the function * provided by the pfn_callback parameter returns CL_SUCCESS. * * SEE ALSO * Pointer Vector, cl_ptr_vector_find_from_start, cl_ptr_vector_apply_func, * cl_pfn_ptr_vec_find_t *********/ END_C_DECLS #endif /* _CL_PTR_VECTOR_H_ */ opensm-3.3.20/include/complib/cl_qcomppool.h0000644000205000001450000005143712104655724015740 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of the quick composite pool. The quick composite pool * manages a pool of composite objects. A composite object is an object * that is made of multiple sub objects. * It can grow to meet demand, limited only by system memory. */ #ifndef _CL_QUICK_COMPOSITE_POOL_H_ #define _CL_QUICK_COMPOSITE_POOL_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Quick Composite Pool * NAME * Quick Composite Pool * * DESCRIPTION * The Quick Composite Pool provides a self-contained and self-sustaining * pool of user defined composite objects. * * A composite object is an object that is composed of one or more * sub-objects, each of which needs to be treated separately for * initialization. Objects can be retrieved from the pool as long as there * is memory in the system. * * To aid in object oriented design, the Quick Composite Pool provides users * the ability to specify callbacks that are invoked for each object for * construction, initialization, and destruction. Constructor and destructor * callback functions may not fail. * * A Quick Composite Pool does not return memory to the system as the user * returns objects to the pool. The only method of returning memory to the * system is to destroy the pool. * * The Quick Composite Pool operates on cl_pool_item_t structures that * describe composite objects. This provides for more efficient memory use. * If using a cl_pool_item_t is not desired, the Composite Pool provides * similar functionality but operates on opaque objects. * * The Quick Composit Pool functions operate on a cl_qcpool_t structure * which should be treated as opaque and should be manipulated only through * the provided functions. * * SEE ALSO * Structures: * cl_qcpool_t, cl_pool_item_t * * Callbacks: * cl_pfn_qcpool_init_t, cl_pfn_qcpool_dtor_t * * Initialization/Destruction: * cl_qcpool_construct, cl_qcpool_init, cl_qcpool_destroy * * Manipulation: * cl_qcpool_get, cl_qcpool_put, cl_qcpool_put_list, cl_qcpool_grow * * Attributes: * cl_is_qcpool_inited, cl_qcpool_count *********/ /****s* Component Library: Quick Composite Pool/cl_pool_item_t * NAME * cl_pool_item_t * * DESCRIPTION * The cl_pool_item_t structure is used by pools to store objects. * * SYNOPSIS */ typedef struct _cl_pool_item { cl_list_item_t list_item; #ifdef _DEBUG_ /* Pointer to the owner pool used for sanity checks. */ struct _cl_qcpool *p_pool; #endif } cl_pool_item_t; /* * FIELDS * list_item * Used internally by the pool. Users should not use this field. * * p_pool * Used internally by the pool in debug builds to check for consistency. * * NOTES * The pool item structure is defined in such a way as to safely allow * users to cast from a pool item to a list item for storing items * retrieved from a quick pool in a quick list. * * SEE ALSO * Quick Composite Pool, cl_list_item_t *********/ /****i* Component Library: Quick List/cl_pool_obj_t * NAME * cl_pool_obj_t * * DESCRIPTION * The cl_pool_obj_t structure is used by pools to store objects. * * SYNOPSIS */ typedef struct _cl_pool_obj { /* The pool item must be the first item to allow casting. */ cl_pool_item_t pool_item; const void *p_object; } cl_pool_obj_t; /* * FIELDS * pool_item * Used internally by the pool. Users should not use this field. * * p_object * Pointer to the user's object being stored in the pool. * * NOTES * The pool object structure is used by non-quick pools to store object. * * SEE ALSO * cl_pool_item_t *********/ /****d* Component Library: Quick Composite Pool/cl_pfn_qcpool_init_t * NAME * cl_pfn_qcpool_init_t * * DESCRIPTION * The cl_pfn_qcpool_init_t function type defines the prototype for * functions used as initializer for objects being allocated by a * quick composite pool. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_qcpool_init_t) (IN void **const p_comp_array, IN const uint32_t num_components, IN void *context, OUT cl_pool_item_t ** const pp_pool_item); /* * PARAMETERS * p_comp_array * [in] Pointer to the first entry in an array of pointers, each of * which points to a component that makes up a composite object. * * num_components * [in] Number of components that in the component array. * * context * [in] Context provided in a call to cl_qcpool_init. * * pp_pool_item * [out] Users should set this pointer to reference the cl_pool_item_t * structure that represents the composite object. This pointer must * not be NULL if the function returns CL_SUCCESS. * * RETURN VALUE * Return CL_SUCCESS to indicate that initialization of the object * was successful and that initialization of further objects may continue. * * Other cl_status_t values will be returned by cl_qcpool_init * and cl_qcpool_grow. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as a parameter to the * cl_qcpool_init function. * * The initializer is invoked once per allocated object, allowing the user * to chain components to form a composite object and perform any necessary * initialization. Returning a status other than CL_SUCCESS aborts a grow * operation, initiated either through cl_qcpool_init or cl_qcpool_grow, * and causes the initiating function to fail. Any non-CL_SUCCESS status * will be returned by the function that initiated the grow operation. * * All memory for the requested number of components is pre-allocated. Users * should include space in one of their components for the cl_pool_item_t * structure that will represent the composite object to avoid having to * allocate that structure in the initialization callback. Alternatively, * users may specify an additional component for the cl_pool_item_t structure. * * When later performing a cl_qcpool_get call, the return value is a pointer * to the cl_pool_item_t returned by this function in the pp_pool_item * parameter. Users must set pp_pool_item to a valid pointer to the * cl_pool_item_t representing the object if they return CL_SUCCESS. * * SEE ALSO * Quick Composite Pool, cl_qcpool_init *********/ /****d* Component Library: Quick Composite Pool/cl_pfn_qcpool_dtor_t * NAME * cl_pfn_qcpool_dtor_t * * DESCRIPTION * The cl_pfn_qcpool_dtor_t function type defines the prototype for * functions used as destructor for objects being deallocated by a * quick composite pool. * * SYNOPSIS */ typedef void (*cl_pfn_qcpool_dtor_t) (IN const cl_pool_item_t * const p_pool_item, IN void *context); /* * PARAMETERS * p_pool_item * [in] Pointer to a cl_pool_item_t structure representing an object. * * context * [in] Context provided in a call to cl_qcpool_init. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_qcpool_init function. * * The destructor is invoked once per allocated object, allowing the user * to perform any necessary cleanup. Users should not attempt to deallocate * the memory for the composite object, as the quick composite pool manages * object allocation and deallocation. * * SEE ALSO * Quick Composite Pool, cl_qcpool_init *********/ /****s* Component Library: Quick Composite Pool/cl_qcpool_t * NAME * cl_qcpool_t * * DESCRIPTION * Quick composite pool structure. * * The cl_qcpool_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_qcpool { uint32_t num_components; size_t *component_sizes; void **p_components; size_t num_objects; size_t max_objects; size_t grow_size; cl_pfn_qcpool_init_t pfn_init; cl_pfn_qcpool_dtor_t pfn_dtor; const void *context; cl_qlist_t free_list; cl_qlist_t alloc_list; cl_state_t state; } cl_qcpool_t; /* * FIELDS * num_components * Number of components per object. * * component_sizes * Array of sizes, one for each component. * * p_components * Array of pointers to components, used for the constructor callback. * * num_objects * Number of objects managed by the pool * * grow_size * Number of objects to add when automatically growing the pool. * * pfn_init * Pointer to the user's initializer callback to invoke when initializing * new objects. * * pfn_dtor * Pointer to the user's destructor callback to invoke before deallocating * memory allocated for objects. * * context * User's provided context for callback functions, used by the pool * when invoking callbacks. * * free_list * Quick list of objects available. * * alloc_list * Quick list used to store information about allocations. * * state * State of the pool. * * SEE ALSO * Quick Composite Pool *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_construct * NAME * cl_qcpool_construct * * DESCRIPTION * The cl_qcpool_construct function constructs a quick composite pool. * * SYNOPSIS */ void cl_qcpool_construct(IN cl_qcpool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_qcpool_init, cl_qcpool_destroy, cl_is_qcpool_inited. * * Calling cl_qcpool_construct is a prerequisite to calling any other * quick composite pool function except cl_qcpool_init. * * SEE ALSO * Quick Composite Pool, cl_qcpool_init, cl_qcpool_destroy, * cl_is_qcpool_inited *********/ /****f* Component Library: Quick Composite Pool/cl_is_qcpool_inited * NAME * cl_is_qcpool_inited * * DESCRIPTION * The cl_is_qcpool_inited function returns whether a quick composite pool was * successfully initialized. * * SYNOPSIS */ static inline uint32_t cl_is_qcpool_inited(IN const cl_qcpool_t * const p_pool) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_pool); /* CL_ASSERT that the pool is not in some invalid state. */ CL_ASSERT(cl_is_state_valid(p_pool->state)); return (p_pool->state == CL_INITIALIZED); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure to check. * * RETURN VALUES * TRUE if the quick composite pool was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a quick composite pool to determine if * invoking member functions is appropriate. * * SEE ALSO * Quick Composite Pool *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_init * NAME * cl_qcpool_init * * DESCRIPTION * The cl_qcpool_init function initializes a quick composite pool for use. * * SYNOPSIS */ cl_status_t cl_qcpool_init(IN cl_qcpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN const size_t * const component_sizes, IN const uint32_t num_components, IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure to initialize. * * min_size * [in] Minimum number of objects that the pool should support. All * necessary allocations to allow storing the minimum number of items * are performed at initialization time, and all necessary callbacks * successfully invoked. * * max_size * [in] Maximum number of objects to which the pool is allowed to grow. * A value of zero specifies no maximum. * * grow_size * [in] Number of objects to allocate when incrementally growing the pool. * A value of zero disables automatic growth. * * component_sizes * [in] Pointer to the first entry in an array of sizes describing, * in order, the sizes of the components that make up a composite object. * * num_components * [in] Number of components that make up a composite object. * * pfn_initializer * [in] Initializer callback to invoke for every new object when growing * the pool. This parameter may be NULL only if the objects stored in * the quick composite pool consist of only one component. If NULL, the * pool assumes the cl_pool_item_t structure describing objects is * located at the head of each object. See the cl_pfn_qcpool_init_t * function type declaration for details about the callback function. * * pfn_destructor * [in] Destructor callback to invoke for every object before memory for * that object is freed. This parameter is optional and may be NULL. * See the cl_pfn_qcpool_dtor_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * CL_SUCCESS if the quick composite pool was initialized successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the * quick composite pool. * * CL_INVALID_SETTING if a NULL constructor was provided for composite objects * consisting of more than one component. Also returns CL_INVALID_SETTING if * the maximum size is non-zero and less than the minimum size. * * Other cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter. * * If initialization fails, the pool is left in a destroyed state. Callers * may still safely call cl_qcpool_destroy. * * NOTES * cl_qcpool_init initializes, and if necessary, grows the pool to * the capacity desired. * * SEE ALSO * Quick Composite Pool, cl_qcpool_construct, cl_qcpool_destroy, * cl_qcpool_get, cl_qcpool_put, cl_qcpool_grow, * cl_qcpool_count, cl_pfn_qcpool_init_t, cl_pfn_qcpool_dtor_t *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_destroy * NAME * cl_qcpool_destroy * * DESCRIPTION * The cl_qcpool_destroy function destroys a quick composite pool. * * SYNOPSIS */ void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * All memory allocated for composite objects is freed. The destructor * callback, if any, will be invoked for every allocated object. Further * operations on the composite pool should not be attempted after * cl_qcpool_destroy is invoked. * * This function should only be called after a call to * cl_qcpool_construct or cl_qcpool_init. * * In a debug build, cl_qcpool_destroy asserts that all objects are in * the pool. * * SEE ALSO * Quick Composite Pool, cl_qcpool_construct, cl_qcpool_init *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_count * NAME * cl_qcpool_count * * DESCRIPTION * The cl_qcpool_count function returns the number of available objects * in a quick composite pool. * * SYNOPSIS */ static inline size_t cl_qcpool_count(IN cl_qcpool_t * const p_pool) { CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); return (cl_qlist_count(&p_pool->free_list)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure for which the number of * available objects is requested. * * RETURN VALUE * Returns the number of objects available in the specified * quick composite pool. * * SEE ALSO * Quick Composite Pool *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_get * NAME * cl_qcpool_get * * DESCRIPTION * The cl_qcpool_get function retrieves an object from a * quick composite pool. * * SYNOPSIS */ cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure from which to retrieve * an object. * * RETURN VALUES * Returns a pointer to a cl_pool_item_t for a composite object. * * Returns NULL if the pool is empty and can not be grown automatically. * * NOTES * cl_qcpool_get returns the object at the head of the pool. If the pool is * empty, it is automatically grown to accommodate this request unless the * grow_size parameter passed to the cl_qcpool_init function was zero. * * SEE ALSO * Quick Composite Pool, cl_qcpool_get_tail, cl_qcpool_put, * cl_qcpool_grow, cl_qcpool_count *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_put * NAME * cl_qcpool_put * * DESCRIPTION * The cl_qcpool_put function returns an object to a quick composite pool. * * SYNOPSIS */ static inline void cl_qcpool_put(IN cl_qcpool_t * const p_pool, IN cl_pool_item_t * const p_pool_item) { CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); CL_ASSERT(p_pool_item); /* Make sure items being returned came from the specified pool. */ CL_ASSERT(p_pool_item->p_pool == p_pool); /* return this lil' doggy to the pool */ cl_qlist_insert_head(&p_pool->free_list, &p_pool_item->list_item); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure to which to return * an object. * * p_pool_item * [in] Pointer to a cl_pool_item_t structure for the object * being returned. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_qcpool_put places the returned object at the head of the pool. * * The object specified by the p_pool_item parameter must have been * retrieved from the pool by a previous call to cl_qcpool_get. * * SEE ALSO * Quick Composite Pool, cl_qcpool_put_tail, cl_qcpool_get *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_put_list * NAME * cl_qcpool_put_list * * DESCRIPTION * The cl_qcpool_put_list function returns a list of objects to the head of * a quick composite pool. * * SYNOPSIS */ static inline void cl_qcpool_put_list(IN cl_qcpool_t * const p_pool, IN cl_qlist_t * const p_list) { #ifdef _DEBUG_ cl_list_item_t *p_item; #endif CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); CL_ASSERT(p_list); #ifdef _DEBUG_ /* Chech that all items in the list came from this pool. */ p_item = cl_qlist_head(p_list); while (p_item != cl_qlist_end(p_list)) { CL_ASSERT(((cl_pool_item_t *) p_item)->p_pool == p_pool); p_item = cl_qlist_next(p_item); } #endif /* return these lil' doggies to the pool */ cl_qlist_insert_list_head(&p_pool->free_list, p_list); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure to which to return * a list of objects. * * p_list * [in] Pointer to a cl_qlist_t structure for the list of objects * being returned. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_qcpool_put_list places the returned objects at the head of the pool. * * The objects in the list specified by the p_list parameter must have been * retrieved from the pool by a previous call to cl_qcpool_get. * * SEE ALSO * Quick Composite Pool, cl_qcpool_put, cl_qcpool_put_tail, cl_qcpool_get *********/ /****f* Component Library: Quick Composite Pool/cl_qcpool_grow * NAME * cl_qcpool_grow * * DESCRIPTION * The cl_qcpool_grow function grows a quick composite pool by * the specified number of objects. * * SYNOPSIS */ cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qcpool_t structure whose capacity to grow. * * obj_count * [in] Number of objects by which to grow the pool. * * RETURN VALUES * CL_SUCCESS if the quick composite pool grew successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the * quick composite pool. * * cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter passed to the * cl_qcpool_init function. * * NOTES * It is not necessary to call cl_qcpool_grow if the pool is * configured to grow automatically. * * SEE ALSO * Quick Composite Pool *********/ END_C_DECLS #endif /* _CL_QUICK_COMPOSITE_POOL_H_ */ opensm-3.3.20/include/complib/cl_qlist.h0000644000205000001450000012665012104655724015063 00000000000000/* * Copyright (c) 2004-2008 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: * Declaration of quick list. */ #ifndef _CL_QUICK_LIST_H_ #define _CL_QUICK_LIST_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Quick List * NAME * Quick List * * DESCRIPTION * Quick list implements a doubly linked that stores user provided * cl_list_item_t structures. * Quick list does not allocate any memory, and can therefore not fail any * operations. Quick list can therefore be useful in minimizing the error * paths in code. * * Quick list is not thread safe, and users must provide serialization when * adding and removing items from the list. Note that it is possible to * walk a quick list while simultaneously adding to it. * * The Quick List functions operate on a cl_qlist_t structure which should be * treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_qlist_t, cl_list_item_t, cl_list_obj_t * * Callbacks: * cl_pfn_qlist_apply_t, cl_pfn_qlist_find_t * * Item Manipulation: * cl_qlist_set_obj, cl_qlist_obj * * Initialization: * cl_qlist_init * * Iteration: * cl_qlist_next, cl_qlist_prev, cl_qlist_head, cl_qlist_tail, * cl_qlist_end * * Manipulation: * cl_qlist_insert_head, cl_qlist_insert_tail, * cl_qlist_insert_list_head, cl_qlist_insert_list_tail, * cl_qlist_insert_array_head, cl_qlist_insert_array_tail, * cl_qlist_insert_prev, cl_qlist_insert_next, * cl_qlist_remove_head, cl_qlist_remove_tail, * cl_qlist_remove_item, cl_qlist_remove_all * * Search: * cl_is_item_in_qlist, cl_qlist_find_next, cl_qlist_find_prev, * cl_qlist_find_from_head, cl_qlist_find_from_tail * cl_qlist_apply_func, cl_qlist_move_items * * Attributes: * cl_qlist_count, cl_is_qlist_empty *********/ /****s* Component Library: Quick List/cl_list_item_t * NAME * cl_list_item_t * * DESCRIPTION * The cl_list_item_t structure is used by lists to store objects. * * SYNOPSIS */ typedef struct _cl_list_item { struct _cl_list_item *p_next; struct _cl_list_item *p_prev; #ifdef _DEBUG_ struct _cl_qlist *p_list; #endif } cl_list_item_t; /* * FIELDS * p_next * Used internally by the list. Users should not use this field. * * p_prev * Used internally by the list. Users should not use this field. * * SEE ALSO * Quick List *********/ #define cl_item_obj(item_ptr, obj_ptr, item_field) (typeof(obj_ptr)) \ ((void *)item_ptr - (unsigned long)&((typeof(obj_ptr))0)->item_field) /****s* Component Library: Quick List/cl_list_obj_t * NAME * cl_list_obj_t * * DESCRIPTION * The cl_list_obj_t structure is used by lists to store objects. * * SYNOPSIS */ typedef struct _cl_list_obj { cl_list_item_t list_item; const void *p_object; /* User's context */ } cl_list_obj_t; /* * FIELDS * list_item * Used internally by the list. Users should not use this field. * * p_object * User defined context. Users should not access this field directly. * Use cl_qlist_set_obj and cl_qlist_obj to set and retrieve the value * of this field. * * NOTES * Users can use the cl_qlist_set_obj and cl_qlist_obj functions to store * and retrieve context information in the list item. * * SEE ALSO * Quick List, cl_qlist_set_obj, cl_qlist_obj, cl_list_item_t *********/ /****s* Component Library: Quick List/cl_qlist_t * NAME * cl_qlist_t * * DESCRIPTION * Quick list structure. * * The cl_qlist_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_qlist { cl_list_item_t end; size_t count; cl_state_t state; } cl_qlist_t; /* * FIELDS * end * List item used to mark the end of the list. * * count * Number of items in the list. * * state * State of the quick list. * * SEE ALSO * Quick List *********/ /****d* Component Library: Quick List/cl_pfn_qlist_apply_t * NAME * cl_pfn_qlist_apply_t * * DESCRIPTION * The cl_pfn_qlist_apply_t function type defines the prototype for functions * used to iterate items in a quick list. * * SYNOPSIS */ typedef void (*cl_pfn_qlist_apply_t) (IN cl_list_item_t * const p_list_item, IN void *context); /* * PARAMETERS * p_list_item * [in] Pointer to a cl_list_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_qlist_apply_func * function. * * SEE ALSO * Quick List, cl_qlist_apply_func *********/ /****d* Component Library: Quick List/cl_pfn_qlist_find_t * NAME * cl_pfn_qlist_find_t * * DESCRIPTION * The cl_pfn_qlist_find_t function type defines the prototype for functions * used to find items in a quick list. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_qlist_find_t) (IN const cl_list_item_t * const p_list_item, IN void *context); /* * PARAMETERS * p_list_item * [in] Pointer to a cl_list_item_t. * * context * [in] Value passed to the callback function. * * RETURN VALUES * Return CL_SUCCESS if the desired item was found. This stops list iteration. * * Return CL_NOT_FOUND to continue list iteration. * * NOTES * This function type is provided as function prototype reference for the * function provided by users as a parameter to the cl_qlist_find_from_head, * cl_qlist_find_from_tail, cl_qlist_find_next, and cl_qlist_find_prev * functions. * * SEE ALSO * Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail, * cl_qlist_find_next, cl_qlist_find_prev *********/ /****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 */ static inline void __cl_primitive_insert(IN cl_list_item_t * const p_list_item, IN cl_list_item_t * const p_new_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that a non-null pointer is provided. */ CL_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 */ static inline void __cl_primitive_remove(IN cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_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 defined( _DEBUG_ ) if (p_list_item != p_list_item->p_next) { p_list_item->p_next = NULL; p_list_item->p_prev = NULL; } #endif /* defined( _DEBUG_ ) */ } /* * PARAMETERS * p_list_item * [in] Pointer to cl_list_item_t to remove * * RETURN VALUE * This function does not return a value. *********/ /* * Declaration of quick list functions */ /****f* Component Library: Quick List/cl_qlist_set_obj * NAME * cl_qlist_set_obj * * DESCRIPTION * The cl_qlist_set_obj function sets the object stored in a list object. * * SYNOPSIS */ static inline void cl_qlist_set_obj(IN cl_list_obj_t * const p_list_obj, IN const void *const p_object) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_obj); p_list_obj->p_object = p_object; } /* * PARAMETERS * p_list_obj * [in] Pointer to a cl_list_obj_t structure. * * p_object * [in] User defined context. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Quick List, cl_qlist_obj *********/ /****f* Component Library: Quick List/cl_qlist_obj * NAME * cl_qlist_obj * * DESCRIPTION * The cl_qlist_set_obj function returns the object stored in a list object. * * SYNOPSIS */ static inline void *cl_qlist_obj(IN const cl_list_obj_t * const p_list_obj) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_obj); return ((void *)p_list_obj->p_object); } /* * PARAMETERS * p_list_obj * [in] Pointer to a cl_list_obj_t structure. * * RETURN VALUE * Returns the value of the object pointer stored in the list object. * * SEE ALSO * Quick List, cl_qlist_set_obj *********/ static inline void __cl_qlist_reset(IN cl_qlist_t * const p_list) { /* Point the end item to itself. */ p_list->end.p_next = &p_list->end; p_list->end.p_prev = &p_list->end; #if defined( _DEBUG_ ) p_list->end.p_list = p_list; #endif /* Clear the count. */ p_list->count = 0; } /****f* Component Library: Quick List/cl_qlist_init * NAME * cl_qlist_init * * DESCRIPTION * The cl_qlist_init function initializes a quick list. * * SYNOPSIS */ static inline void cl_qlist_init(IN cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); p_list->state = CL_INITIALIZED; /* Reset the quick list data structure. */ __cl_qlist_reset(p_list); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure to initialize. * * RETURN VALUES * This function does not return a value. * * NOTES * Allows calling quick list manipulation functions. * * SEE ALSO * Quick List, cl_qlist_insert_head, cl_qlist_insert_tail, * cl_qlist_remove_head, cl_qlist_remove_tail *********/ /****f* Component Library: Quick List/cl_qlist_count * NAME * cl_qlist_count * * DESCRIPTION * The cl_qlist_count function returns the number of list items stored * in a quick list. * * SYNOPSIS */ static inline uint32_t cl_qlist_count(IN const cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); return ((uint32_t) p_list->count); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUE * Number of items in the list. This function iterates though the quick * list to count the items. * * SEE ALSO * Quick List, cl_is_qlist_empty *********/ /****f* Component Library: Quick List/cl_is_qlist_empty * NAME * cl_is_qlist_empty * * DESCRIPTION * The cl_is_qlist_empty function returns whether a quick list is empty. * * SYNOPSIS */ static inline boolean_t cl_is_qlist_empty(IN const cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); return (!cl_qlist_count(p_list)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUES * TRUE if the specified quick list is empty. * * FALSE otherwise. * * SEE ALSO * Quick List, cl_qlist_count, cl_qlist_remove_all *********/ /****f* Component Library: Quick List/cl_qlist_next * NAME * cl_qlist_next * * DESCRIPTION * The cl_qlist_next function returns a pointer to the list item following * a given list item in a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_next(IN const cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list_item->p_list->state == CL_INITIALIZED); /* Return the next item. */ return (p_list_item->p_next); } /* * PARAMETERS * p_list_item * [in] Pointer to the cl_list_item_t whose successor to return. * * Returns: * Pointer to the list item following the list item specified by * the p_list_item parameter in the quick list. * * Pointer to the list end if p_list_item was at the tail of the list. * * SEE ALSO * Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_prev, cl_qlist_end, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_prev * NAME * cl_qlist_prev * * DESCRIPTION * The cl_qlist_prev function returns a poirter to the list item preceding * a given list item in a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_prev(IN const cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list_item->p_list->state == CL_INITIALIZED); /* Return the previous item. */ return (p_list_item->p_prev); } /* * PARAMETERS * p_list_item * [in] Pointer to the cl_list_item_t whose predecessor to return. * * Returns: * Pointer to the list item preceding the list item specified by * the p_list_item parameter in the quick list. * * Pointer to the list end if p_list_item was at the tail of the list. * * SEE ALSO * Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_end, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_head * NAME * cl_qlist_head * * DESCRIPTION * The cl_qlist_head function returns the list item at * the head of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_head(IN const cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); return (cl_qlist_next(&p_list->end)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUES * Pointer to the list item at the head of the quick list. * * Pointer to the list end if the list was empty. * * NOTES * cl_qlist_head does not remove the item from the list. * * SEE ALSO * Quick List, cl_qlist_tail, cl_qlist_next, cl_qlist_prev, cl_qlist_end, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_tail * NAME * cl_qlist_tail * * DESCRIPTION * The cl_qlist_tail function returns the list item at * the tail of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_tail(IN const cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); return (cl_qlist_prev(&p_list->end)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUES * Pointer to the list item at the tail of the quick list. * * Pointer to the list end if the list was empty. * * NOTES * cl_qlist_tail does not remove the item from the list. * * SEE ALSO * Quick List, cl_qlist_head, cl_qlist_next, cl_qlist_prev, cl_qlist_end, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_end * NAME * cl_qlist_end * * DESCRIPTION * The cl_qlist_end function returns the end of a quick list. * * SYNOPSIS */ static inline const cl_list_item_t *cl_qlist_end(IN const cl_qlist_t * const p_list) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); return (&p_list->end); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUE * Pointer to the end of the list. * * NOTES * cl_qlist_end is useful for determining the validity of list items returned * by cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_prev, as well as * the cl_qlist_find functions. If the list item pointer returned by any of * these functions compares to the end, the end of the list was encoutered. * When using cl_qlist_head or cl_qlist_tail, this condition indicates that * the list is empty. * * SEE ALSO * Quick List, cl_qlist_head, cl_qlist_tail, cl_qlist_next, cl_qlist_prev, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_head * NAME * cl_qlist_insert_head * * DESCRIPTION * The cl_qlist_insert_head function inserts a list item at the * head of a quick list. * * SYNOPSIS */ static inline void cl_qlist_insert_head(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* * The list item must not already be part of the list. Note that this * assertion may fail if an uninitialized list item happens to have its * list pointer equal to the specified list. The chances of this * happening are acceptable in light of the value of this check. */ CL_ASSERT(p_list_item->p_list != p_list); #if defined( _DEBUG_ ) p_list_item->p_list = p_list; #endif /* Insert before the head. */ __cl_primitive_insert(cl_qlist_head(p_list), p_list_item); p_list->count++; } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to insert the object. * * p_list_item * [in] Pointer to a cl_list_item_t structure to add. * * RETURN VALUE * This function does not return a value. * * NOTES * In debug builds, cl_qlist_insert_head asserts that the specified list item * is not already in the list. * * SEE ALSO * Quick List, cl_qlist_insert_tail, cl_qlist_insert_list_head, * cl_qlist_insert_list_tail, cl_qlist_insert_array_head, * cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next, * cl_qlist_remove_head, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_tail * NAME * cl_qlist_insert_tail * * DESCRIPTION * The cl_qlist_insert_tail function inserts a list item at the tail * of a quick list. * * SYNOPSIS */ static inline void cl_qlist_insert_tail(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* * The list item must not already be part of the list. Note that this * assertion may fail if an uninitialized list item happens to have its * list pointer equal to the specified list. The chances of this * happening are acceptable in light of the value of this check. */ CL_ASSERT(p_list_item->p_list != p_list); #if defined( _DEBUG_ ) p_list_item->p_list = p_list; #endif /* * Put the new element in front of the end which is the same * as being at the tail */ __cl_primitive_insert(&p_list->end, p_list_item); p_list->count++; } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to insert the object. * * p_list_item * [in] Pointer to cl_list_item_t structure to add. * * RETURN VALUE * This function does not return a value. * * NOTES * In debug builds, cl_qlist_insert_tail asserts that the specified list item * is not already in the list. * * SEE ALSO * Quick List, cl_qlist_insert_head, cl_qlist_insert_list_head, * cl_qlist_insert_list_tail, cl_qlist_insert_array_head, * cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next, * cl_qlist_remove_tail, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_list_head * NAME * cl_qlist_insert_list_head * * DESCRIPTION * The cl_qlist_insert_list_head function merges two quick lists by * inserting one at the head of the other. * * SYNOPSIS */ void cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list, IN cl_qlist_t * const p_src_list); /* * PARAMETERS * p_dest_list * [in] Pointer to destination quicklist object. * * p_src_list * [in] Pointer to quicklist to add. * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts all list items in the source list to the head of the * destination list. The ordering of the list items is preserved. * * The list pointed to by the p_src_list parameter is empty when * the call returns. * * SEE ALSO * Quick List, cl_qlist_insert_list_tail, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_array_head, * cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_list_tail * NAME * cl_qlist_insert_list_tail * * DESCRIPTION * The cl_qlist_insert_list_tail function merges two quick lists by * inserting one at the tail of the other. * * SYNOPSIS */ void cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list, IN cl_qlist_t * const p_src_list); /* * PARAMETERS * p_dest_list * [in] Pointer to destination quicklist object * * p_src_list * [in] Pointer to quicklist to add * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts all list items in the source list to the tail of the * destination list. The ordering of the list items is preserved. * * The list pointed to by the p_src_list parameter is empty when * the call returns. * * SEE ALSO * Quick List, cl_qlist_insert_list_head, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_array_head, * cl_qlist_insert_array_tail, cl_qlist_insert_prev, cl_qlist_insert_next, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_array_head * NAME * cl_qlist_insert_array_head * * DESCRIPTION * The cl_qlist_insert_array_head function inserts an array of list items * at the head of a quick list. * * SYNOPSIS */ void cl_qlist_insert_array_head(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_array, IN uint32_t item_count, IN const uint32_t item_size); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to insert * the objects. * * p_array * [in] Pointer to the first list item in an array of cl_list_item_t * structures. * * item_count * [in] Number of cl_list_item_t structures in the array. * * item_size * [in] Size of the items added to the list. This is the stride in the * array from one cl_list_item_t structure to the next. * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts all the list items in the array specified by the p_array parameter * to the head of the quick list specified by the p_list parameter, * preserving ordering of the list items. * * The array pointer passed into the function points to the cl_list_item_t * in the first element of the caller's element array. There is no * restriction on where the element is stored in the parent structure. * * SEE ALSO * Quick List, cl_qlist_insert_array_tail, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail, * cl_qlist_insert_prev, cl_qlist_insert_next, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_array_tail * NAME * cl_qlist_insert_array_tail * * DESCRIPTION * The cl_qlist_insert_array_tail function inserts an array of list items * at the tail of a quick list. * * SYNOPSIS */ void cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_array, IN uint32_t item_count, IN const uint32_t item_size); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to insert * the objects. * * p_array * [in] Pointer to the first list item in an array of cl_list_item_t * structures. * * item_count * [in] Number of cl_list_item_t structures in the array. * * item_size * [in] Size of the items added to the list. This is the stride in the * array from one cl_list_item_t structure to the next. * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts all the list items in the array specified by the p_array parameter * to the tail of the quick list specified by the p_list parameter, * preserving ordering of the list items. * * The array pointer passed into the function points to the cl_list_item_t * in the first element of the caller's element array. There is no * restriction on where the element is stored in the parent structure. * * SEE ALSO * Quick List, cl_qlist_insert_array_head, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail, * cl_qlist_insert_prev, cl_qlist_insert_next, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_prev * NAME * cl_qlist_insert_prev * * DESCRIPTION * The cl_qlist_insert_prev function inserts a list item before a * specified list item in a quick list. * * SYNOPSIS */ static inline void cl_qlist_insert_prev(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_list_item, IN cl_list_item_t * const p_new_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_new_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* * The list item must not already be part of the list. Note that this * assertion may fail if an uninitialized list item happens to have its * list pointer equal to the specified list. The chances of this * happening are acceptable in light of the value of this check. */ CL_ASSERT(p_new_item->p_list != p_list); #if defined( _DEBUG_ ) p_new_item->p_list = p_list; #endif __cl_primitive_insert(p_list_item, p_new_item); p_list->count++; } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to add the new item. * * p_list_item * [in] Pointer to a cl_list_item_t structure. * * p_new_item * [in] Pointer to a cl_list_item_t structure to add to the quick list. * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts the new list item before the list item specified by p_list_item. * * SEE ALSO * Quick List, cl_qlist_insert_next, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail, * cl_qlist_insert_array_head, cl_qlist_insert_array_tail, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_insert_next * NAME * cl_qlist_insert_next * * DESCRIPTION * The cl_qlist_insert_next function inserts a list item after a specified * list item in a quick list. * * SYNOPSIS */ static inline void cl_qlist_insert_next(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_list_item, IN cl_list_item_t * const p_new_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_new_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* * The list item must not already be part of the list. Note that this * assertion may fail if an uninitialized list item happens to have its * list pointer equal to the specified list. The chances of this * happening are acceptable in light of the value of this check. */ CL_ASSERT(p_new_item->p_list != p_list); #if defined( _DEBUG_ ) p_new_item->p_list = p_list; #endif __cl_primitive_insert(cl_qlist_next(p_list_item), p_new_item); p_list->count++; } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure into which to add the new item. * * p_list_item * [in] Pointer to a cl_list_item_t structure. * * p_new_item * [in] Pointer to a cl_list_item_t structure to add to the quick list. * * RETURN VALUE * This function does not return a value. * * NOTES * Inserts the new list item after the list item specified by p_list_item. * The list item specified by p_list_item must be in the quick list. * * SEE ALSO * Quick List, cl_qlist_insert_prev, cl_qlist_insert_head, * cl_qlist_insert_tail, cl_qlist_insert_list_head, cl_qlist_insert_list_tail, * cl_qlist_insert_array_head, cl_qlist_insert_array_tail, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_remove_head * NAME * cl_qlist_remove_head * * DESCRIPTION * The cl_qlist_remove_head function removes and returns the list item * at the head of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_remove_head(IN cl_qlist_t * const p_list) { cl_list_item_t *p_item; /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); p_item = cl_qlist_head(p_list); /* CL_ASSERT that the list item is part of the list. */ CL_ASSERT(p_item->p_list == p_list); if (p_item == cl_qlist_end(p_list)) return (p_item); #if defined( _DEBUG_ ) /* Clear the item's link to the list. */ p_item->p_list = NULL; #endif __cl_primitive_remove(p_item); p_list->count--; return (p_item); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUES * Returns a pointer to the list item formerly at the head of the quick list. * * Pointer to the list end if the list was empty. * * SEE ALSO * Quick List, cl_qlist_remove_tail, cl_qlist_remove_all, cl_qlist_remove_item, * cl_qlist_end, cl_qlist_head, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_remove_tail * NAME * cl_qlist_remove_tail * * DESCRIPTION * The cl_qlist_remove_tail function removes and returns the list item * at the tail of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_remove_tail(IN cl_qlist_t * const p_list) { cl_list_item_t *p_item; /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); p_item = cl_qlist_tail(p_list); /* CL_ASSERT that the list item is part of the list. */ CL_ASSERT(p_item->p_list == p_list); if (p_item == cl_qlist_end(p_list)) return (p_item); #if defined( _DEBUG_ ) /* Clear the item's link to the list. */ p_item->p_list = NULL; #endif __cl_primitive_remove(p_item); p_list->count--; return (p_item); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUES * Returns a pointer to the list item formerly at the tail of the quick list. * * Pointer to the list end if the list was empty. * * SEE ALSO * Quick List, cl_qlist_remove_head, cl_qlist_remove_all, cl_qlist_remove_item, * cl_qlist_end, cl_qlist_tail, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_remove_item * NAME * cl_qlist_remove_item * * DESCRIPTION * The cl_qlist_remove_item function removes a specific list item from a quick list. * * SYNOPSIS */ static inline void cl_qlist_remove_item(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_list_item) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list_item); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* CL_ASSERT that the list item is part of the list. */ CL_ASSERT(p_list_item->p_list == p_list); if (p_list_item == cl_qlist_end(p_list)) return; #if defined( _DEBUG_ ) /* Clear the item's link to the list. */ p_list_item->p_list = NULL; #endif __cl_primitive_remove(p_list_item); p_list->count--; } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure from which to remove the item. * * p_list_item * [in] Pointer to a cl_list_item_t structure to remove. * * RETURN VALUE * This function does not return a value. * * NOTES * Removes the list item pointed to by the p_list_item parameter from * its list. * * SEE ALSO * Quick List, cl_qlist_remove_head, cl_qlist_remove_tail, cl_qlist_remove_all, * cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_remove_all * NAME * cl_qlist_remove_all * * DESCRIPTION * The cl_qlist_remove_all function removes all items from a quick list. * * SYNOPSIS */ static inline void cl_qlist_remove_all(IN cl_qlist_t * const p_list) { #if defined( _DEBUG_ ) cl_list_item_t *p_list_item; /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); p_list_item = cl_qlist_head(p_list); while (p_list_item != cl_qlist_end(p_list)) { p_list_item = cl_qlist_next(p_list_item); cl_qlist_prev(p_list_item)->p_list = NULL; } #endif __cl_qlist_reset(p_list); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Quick List, cl_qlist_remove_head, cl_qlist_remove_tail, * cl_qlist_remove_item, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_is_item_in_qlist * NAME * cl_is_item_in_qlist * * DESCRIPTION * The cl_is_item_in_qlist function checks for the presence of a * list item in a quick list. * * SYNOPSIS */ boolean_t cl_is_item_in_qlist(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * p_list_item * [in] Pointer to the cl_list_item_t to find. * * RETURN VALUES * TRUE if the list item was found in the quick list. * * FALSE otherwise. * * SEE ALSO * Quick List, cl_qlist_remove_item, cl_list_item_t *********/ /****f* Component Library: Quick List/cl_qlist_find_next * NAME * cl_qlist_find_next * * DESCRIPTION * The cl_qlist_find_next function invokes a specified function to * search for an item, starting from a given list item. * * SYNOPSIS */ cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure in which to search. * * p_list_item * [in] Pointer to a cl_list_item_t structure from which to start the search. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_qlist_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context if a * callback function is provided, or value compared to the quick list's * list items. * * Returns: * Pointer to the list item, if found. * * p_list_item if not found. * * NOTES * cl_qlist_find_next does not remove list items from the list. * The list item is returned when the function specified by the pfn_func * parameter returns CL_SUCCESS. The list item from which the search starts is * excluded from the search. * * The function provided by the pfn_func must not perform any list operations, * as these would corrupt the list. * * SEE ALSO * Quick List, cl_qlist_find_prev, cl_qlist_find_from_head, * cl_qlist_find_from_tail, cl_qlist_end, cl_qlist_apply_func, * cl_qlist_move_items, cl_list_item_t, cl_pfn_qlist_find_t *********/ /****f* Component Library: Quick List/cl_qlist_find_prev * NAME * cl_qlist_find_prev * * DESCRIPTION * The cl_qlist_find_prev function invokes a specified function to * search backward for an item, starting from a given list item. * * SYNOPSIS */ cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure in which to search. * * p_list_item * [in] Pointer to a cl_list_item_t structure from which to start the search. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_qlist_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context if a * callback function is provided, or value compared to the quick list's * list items. * * Returns: * Pointer to the list item, if found. * * p_list_item if not found. * * NOTES * cl_qlist_find_prev does not remove list items from the list. * The list item is returned when the function specified by the pfn_func * parameter returns CL_SUCCESS. The list item from which the search starts is * excluded from the search. * * The function provided by the pfn_func must not perform any list operations, * as these would corrupt the list. * * SEE ALSO * Quick List, cl_qlist_find_next, cl_qlist_find_from_head, * cl_qlist_find_from_tail, cl_qlist_end, cl_qlist_apply_func, * cl_qlist_move_items, cl_list_item_t, cl_pfn_qlist_find_t *********/ /****f* Component Library: Quick List/cl_qlist_find_from_head * NAME * cl_qlist_find_from_head * * DESCRIPTION * The cl_qlist_find_from_head function invokes a specified function to * search for an item, starting at the head of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_find_from_head(IN const cl_qlist_t * const p_list, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* CL_ASSERT that a find function is provided. */ CL_ASSERT(pfn_func); return (cl_qlist_find_next(p_list, cl_qlist_end(p_list), pfn_func, context)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_qlist_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context if a * callback function is provided, or value compared to the quick list's * list items. * * Returns: * Pointer to the list item, if found. * * Pointer to the list end otherwise * * NOTES * cl_qlist_find_from_head does not remove list items from the list. * The list item is returned when the function specified by the pfn_func * parameter returns CL_SUCCESS. * * The function provided by the pfn_func parameter must not perform any list * operations, as these would corrupt the list. * * SEE ALSO * Quick List, cl_qlist_find_from_tail, cl_qlist_find_next, cl_qlist_find_prev, * cl_qlist_end, cl_qlist_apply_func, cl_qlist_move_items, cl_list_item_t, * cl_pfn_qlist_find_t *********/ /****f* Component Library: Quick List/cl_qlist_find_from_tail * NAME * cl_qlist_find_from_tail * * DESCRIPTION * The cl_qlist_find_from_tail function invokes a specified function to * search for an item, starting at the tail of a quick list. * * SYNOPSIS */ static inline cl_list_item_t *cl_qlist_find_from_tail(IN const cl_qlist_t * const p_list, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_list); /* CL_ASSERT that the list was initialized. */ CL_ASSERT(p_list->state == CL_INITIALIZED); /* CL_ASSERT that a find function is provided. */ CL_ASSERT(pfn_func); return (cl_qlist_find_prev(p_list, cl_qlist_end(p_list), pfn_func, context)); } /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_qlist_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context if a * callback function is provided, or value compared to the quick list's * list items. * * Returns: * Pointer to the list item, if found. * * Pointer to the list end otherwise * * NOTES * cl_qlist_find_from_tail does not remove list items from the list. * The list item is returned when the function specified by the pfn_func * parameter returns CL_SUCCESS. * * The function provided by the pfn_func parameter must not perform any list * operations, as these would corrupt the list. * * SEE ALSO * Quick List, cl_qlist_find_from_head, cl_qlist_find_next, cl_qlist_find_prev, * cl_qlist_apply_func, cl_qlist_end, cl_qlist_move_items, cl_list_item_t, * cl_pfn_qlist_find_t *********/ /****f* Component Library: Quick List/cl_qlist_apply_func * NAME * cl_qlist_apply_func * * DESCRIPTION * The cl_qlist_apply_func function executes a specified function * for every list item stored in a quick list. * * SYNOPSIS */ void cl_qlist_apply_func(IN const cl_qlist_t * const p_list, IN cl_pfn_qlist_apply_t pfn_func, IN const void *const context); /* * PARAMETERS * p_list * [in] Pointer to a cl_qlist_t structure. * * pfn_func * [in] Function invoked for every item in the quick list. * See the cl_pfn_qlist_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 list operations, as these * would corrupt the quick list. * * SEE ALSO * Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail, * cl_qlist_move_items, cl_pfn_qlist_apply_t *********/ /****f* Component Library: Quick List/cl_qlist_move_items * NAME * cl_qlist_move_items * * DESCRIPTION * The cl_qlist_move_items function moves list items from one list to * another based on the return value of a user supplied function. * * SYNOPSIS */ void cl_qlist_move_items(IN cl_qlist_t * const p_src_list, IN cl_qlist_t * const p_dest_list, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context); /* * PARAMETERS * p_src_list * [in] Pointer to a cl_qlist_t structure from which * list items are removed. * * p_dest_list * [in] Pointer to a cl_qlist_t structure to which the source * list items are added. * * pfn_func * [in] Function invoked to determine if a match was found. * See the cl_pfn_qlist_find_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 * If the function specified by the pfn_func parameter returns CL_SUCCESS, * the related list item is removed from p_src_list and inserted at the tail * of the p_dest_list. * * The cl_qlist_move_items function continues iterating through p_src_list * from the last item moved, allowing multiple items to be located and moved * in a single list iteration. * * The function specified by pfn_func must not perform any list operations, * as these would corrupt the list. * * SEE ALSO * Quick List, cl_qlist_find_from_head, cl_qlist_find_from_tail, * cl_qlist_apply_func, cl_pfn_qlist_find_t *********/ END_C_DECLS #endif /* _CL_QUICK_LIST_H_ */ opensm-3.3.20/include/complib/cl_qmap.h0000644000205000001450000005631712104655724014667 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of quick map, a binary tree where the caller always provides * all necessary storage. */ #ifndef _CL_QMAP_H_ #define _CL_QMAP_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****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, cl_qmap_get_next * * 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_t key; #ifdef _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 *********/ /****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; cl_state_t state; size_t count; } 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 * 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 *********/ /****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 */ static inline uint32_t cl_qmap_count(IN const cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return ((uint32_t) 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 */ static inline boolean_t cl_is_qmap_empty(IN const cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_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 */ static inline void cl_qmap_set_obj(IN cl_map_obj_t * const p_map_obj, IN const void *const p_object) { CL_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 */ static inline void *cl_qmap_obj(IN const cl_map_obj_t * const p_map_obj) { CL_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 */ static inline uint64_t cl_qmap_key(IN const cl_map_item_t * const p_item) { CL_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 */ void cl_qmap_init(IN cl_qmap_t * const p_map); /* * PARAMETERS * p_map * [in] Pointer to a cl_qmap_t structure to initialize. * * 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 */ static inline const cl_map_item_t *cl_qmap_end(IN const cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); /* Nil is the end of the map. */ return (&p_map->nil); } /* * 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 */ static inline cl_map_item_t *cl_qmap_head(IN const cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return ((cl_map_item_t *) p_map->nil.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 */ static inline cl_map_item_t *cl_qmap_tail(IN const cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); return ((cl_map_item_t *) p_map->nil.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 */ static inline cl_map_item_t *cl_qmap_next(IN const cl_map_item_t * const p_item) { CL_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 */ static inline cl_map_item_t *cl_qmap_prev(IN const cl_map_item_t * const p_item) { CL_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. * NOTE: Only if such a key does not alerady exist in the map !!!! * * SYNOPSIS */ cl_map_item_t *cl_qmap_insert(IN cl_qmap_t * const p_map, IN const uint64_t 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. * * 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 - but the new key is NOT inserted... * * 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 * NAME * cl_qmap_get * * DESCRIPTION * The cl_qmap_get function returns the map item associated with a key. * * SYNOPSIS */ cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map, IN const uint64_t 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. * * 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_get_next, cl_qmap_remove *********/ /****f* Component Library: Quick Map/cl_qmap_get_next * NAME * cl_qmap_get_next * * DESCRIPTION * The cl_qmap_get_next function returns the first map item associated with a * key > the key specified. * * SYNOPSIS */ cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map, IN const uint64_t key); /* * PARAMETERS * p_map * [in] Pointer to a cl_qmap_t structure from which to retrieve the * first item with a key > the specified key. * * key * [in] Key value used to search for the desired map item. * * RETURN VALUES * Pointer to the first map item with a key > the desired key value. * * Pointer to the map end if there was no item with a key > the desired key * value stored in the quick map. * * NOTES * cl_qmap_get_next does not remove the item from the quick map. * * SEE ALSO * Quick Map, cl_qmap_get, 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 */ 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_map_item_t *cl_qmap_remove(IN cl_qmap_t * const p_map, IN const uint64_t 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. * * 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_all * NAME * cl_qmap_remove_all * * DESCRIPTION * The cl_qmap_remove_all function removes all items in a quick map, * leaving it empty. * * SYNOPSIS */ static inline void cl_qmap_remove_all(IN cl_qmap_t * const p_map) { CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_map->root.p_left = &p_map->nil; p_map->nil.pool_item.list_item.p_next = &p_map->nil.pool_item.list_item; p_map->nil.pool_item.list_item.p_prev = &p_map->nil.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 */ 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. * * 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 */ 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 useful 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. * * 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 */ 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 *********/ END_C_DECLS #endif /* _CL_QMAP_H_ */ opensm-3.3.20/include/complib/cl_qpool.h0000644000205000001450000004035312104655724015054 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of the quick pool. * The quick pool manages a pool of objects. * The pool can grow to meet demand, limited only by system memory. */ #ifndef _CL_QUICK_POOL_H_ #define _CL_QUICK_POOL_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Quick Pool * NAME * Quick Pool * * DESCRIPTION * The quick pool provides a self-contained and self-sustaining pool * of user defined objects. * * To aid in object oriented design, the quick pool provides the user * the ability to specify callbacks that are invoked for each object for * construction, initialization, and destruction. Constructor and destructor * callback functions may not fail. * * A quick pool does not return memory to the system as the user returns * objects to the pool. The only method of returning memory to the system is * to destroy the pool. * * The quick pool operates on cl_pool_item_t structures that describe * objects. This can provides for more efficient memory use and operation. * If using a cl_pool_item_t is not desired, the Pool provides similar * functionality but operates on opaque objects. * * The quick pool functions operates on a cl_qpool_t structure which should * be treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_qpool_t, cl_pool_item_t * * Callbacks: * cl_pfn_qpool_init_t, cl_pfn_qpool_dtor_t * * Initialization/Destruction: * cl_qpool_construct, cl_qpool_init, cl_qpool_destroy * * Manipulation: * cl_qpool_get, cl_qpool_put, cl_qpool_put_list, cl_qpool_grow * * Attributes: * cl_is_qpool_inited, cl_qpool_count *********/ /****d* Component Library: Quick Pool/cl_pfn_qpool_init_t * NAME * cl_pfn_qpool_init_t * * DESCRIPTION * The cl_pfn_qpool_init_t function type defines the prototype for * functions used as constructor for objects being allocated by a * quick pool. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_qpool_init_t) (IN void *const p_object, IN void *context, OUT cl_pool_item_t ** const pp_pool_item); /* * PARAMETERS * p_object * [in] Pointer to an object to initialize. * * context * [in] Context provided in a call to cl_qpool_init. * * RETURN VALUES * Return CL_SUCCESS to indicate that initialization of the object * was successful and that initialization of further objects may continue. * * Other cl_status_t values will be returned by cl_qcpool_init * and cl_qcpool_grow. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_qpool_init function. * * The initializer is invoked once per allocated object, allowing the user * to perform any necessary initialization. Returning a status other than * CL_SUCCESS aborts a grow operation, initiated either through cl_qcpool_init * or cl_qcpool_grow, causing the initiating function to fail. * Any non-CL_SUCCESS status will be returned by the function that initiated * the grow operation. * * All memory for the object is pre-allocated. Users should include space in * their objects for the cl_pool_item_t structure that will represent the * object to avoid having to allocate that structure in the initialization * callback. * * When later performing a cl_qcpool_get call, the return value is a pointer * to the cl_pool_item_t returned by this function in the pp_pool_item * parameter. Users must set pp_pool_item to a valid pointer to the * cl_pool_item_t representing the object if they return CL_SUCCESS. * * SEE ALSO * Quick Pool, cl_qpool_init *********/ /****d* Component Library: Quick Pool/cl_pfn_qpool_dtor_t * NAME * cl_pfn_qpool_dtor_t * * DESCRIPTION * The cl_pfn_qpool_dtor_t function type defines the prototype for * functions used as destructor for objects being deallocated by a * quick pool. * * SYNOPSIS */ typedef void (*cl_pfn_qpool_dtor_t) (IN const cl_pool_item_t * const p_pool_item, IN void *context); /* * PARAMETERS * p_pool_item * [in] Pointer to a cl_pool_item_t structure representing an object. * * context * [in] Context provided in a call to cl_qpool_init. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function provided by the user as an optional parameter to the * cl_qpool_init function. * * The destructor is invoked once per allocated object, allowing the user * to perform any necessary cleanup. Users should not attempt to deallocate * the memory for the object, as the quick pool manages object * allocation and deallocation. * * SEE ALSO * Quick Pool, cl_qpool_init *********/ /****s* Component Library: Quick Pool/cl_qpool_t * NAME * cl_qpool_t * * DESCRIPTION * Quick pool structure. * * The cl_qpool_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_qpool { cl_qcpool_t qcpool; cl_pfn_qpool_init_t pfn_init; cl_pfn_qpool_dtor_t pfn_dtor; const void *context; } cl_qpool_t; /* * FIELDS * qcpool * Quick composite pool that manages all objects. * * pfn_init * Pointer to the user's initializer callback, used by the pool * to translate the quick composite pool's initializer callback to * a quick pool initializer callback. * * pfn_dtor * Pointer to the user's destructor callback, used by the pool * to translate the quick composite pool's destructor callback to * a quick pool destructor callback. * * context * User's provided context for callback functions, used by the pool * to when invoking callbacks. * * SEE ALSO * Quick Pool *********/ /****f* Component Library: Quick Pool/cl_qpool_construct * NAME * cl_qpool_construct * * DESCRIPTION * The cl_qpool_construct function constructs a quick pool. * * SYNOPSIS */ void cl_qpool_construct(IN cl_qpool_t * const p_pool); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_qpool_init, cl_qpool_destroy, cl_is_qpool_inited. * * Calling cl_qpool_construct is a prerequisite to calling any other * quick pool function except cl_pool_init. * * SEE ALSO * Quick Pool, cl_qpool_init, cl_qpool_destroy, cl_is_qpool_inited. *********/ /****f* Component Library: Quick Pool/cl_is_qpool_inited * NAME * cl_is_qpool_inited * * DESCRIPTION * The cl_is_qpool_inited function returns whether a quick pool was * successfully initialized. * * SYNOPSIS */ static inline uint32_t cl_is_qpool_inited(IN const cl_qpool_t * const p_pool) { /* CL_ASSERT that a non-null pointer is provided. */ CL_ASSERT(p_pool); return (cl_is_qcpool_inited(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure whose initialization state * to check. * * RETURN VALUES * TRUE if the quick pool was initialized successfully. * * FALSE otherwise. * * NOTES * Allows checking the state of a quick pool to determine if * invoking member functions is appropriate. * * SEE ALSO * Quick Pool *********/ /****f* Component Library: Quick Pool/cl_qpool_init * NAME * cl_qpool_init * * DESCRIPTION * The cl_qpool_init function initializes a quick pool for use. * * SYNOPSIS */ cl_status_t cl_qpool_init(IN cl_qpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN const size_t object_size, IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context); /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure to initialize. * * min_size * [in] Minimum number of objects that the pool should support. All * necessary allocations to allow storing the minimum number of items * are performed at initialization time, and all necessary callbacks * successfully invoked. * * max_size * [in] Maximum number of objects to which the pool is allowed to grow. * A value of zero specifies no maximum. * * grow_size * [in] Number of objects to allocate when incrementally growing the pool. * A value of zero disables automatic growth. * * object_size * [in] Size, in bytes, of each object. * * pfn_initializer * [in] Initialization callback to invoke for every new object when * growing the pool. This parameter is optional and may be NULL. If NULL, * the pool assumes the cl_pool_item_t structure describing objects is * located at the head of each object. See the cl_pfn_qpool_init_t * function type declaration for details about the callback function. * * pfn_destructor * [in] Destructor callback to invoke for every object before memory for * that object is freed. This parameter is optional and may be NULL. * See the cl_pfn_qpool_dtor_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * CL_SUCCESS if the quick pool was initialized successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to initialize the * quick pool. * * CL_INVALID_SETTING if a the maximum size is non-zero and less than the * minimum size. * * Other cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter. * * NOTES * cl_qpool_init initializes, and if necessary, grows the pool to * the capacity desired. * * SEE ALSO * Quick Pool, cl_qpool_construct, cl_qpool_destroy, * cl_qpool_get, cl_qpool_put, cl_qpool_grow, * cl_qpool_count, cl_pfn_qpool_init_t, cl_pfn_qpool_init_t, * cl_pfn_qpool_dtor_t *********/ /****f* Component Library: Quick Pool/cl_qpool_destroy * NAME * cl_qpool_destroy * * DESCRIPTION * The cl_qpool_destroy function destroys a quick pool. * * SYNOPSIS */ static inline void cl_qpool_destroy(IN cl_qpool_t * const p_pool) { CL_ASSERT(p_pool); cl_qcpool_destroy(&p_pool->qcpool); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * All memory allocated for objects is freed. The destructor callback, * if any, will be invoked for every allocated object. Further operations * on the pool should not be attempted after cl_qpool_destroy * is invoked. * * This function should only be called after a call to * cl_qpool_construct or cl_qpool_init. * * In a debug build, cl_qpool_destroy asserts that all objects are in * the pool. * * SEE ALSO * Quick Pool, cl_qpool_construct, cl_qpool_init *********/ /****f* Component Library: Quick Pool/cl_qpool_count * NAME * cl_qpool_count * * DESCRIPTION * The cl_qpool_count function returns the number of available objects * in a quick pool. * * SYNOPSIS */ static inline size_t cl_qpool_count(IN cl_qpool_t * const p_pool) { CL_ASSERT(p_pool); return (cl_qcpool_count(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure for which the number of * available objects is requested. * * RETURN VALUE * Returns the number of objects available in the specified quick pool. * * SEE ALSO * Quick Pool *********/ /****f* Component Library: Quick Pool/cl_qpool_get * NAME * cl_qpool_get * * DESCRIPTION * The cl_qpool_get function retrieves an object from a * quick pool. * * SYNOPSIS */ static inline cl_pool_item_t *cl_qpool_get(IN cl_qpool_t * const p_pool) { CL_ASSERT(p_pool); return (cl_qcpool_get(&p_pool->qcpool)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure from which to retrieve * an object. * * RETURN VALUES * Returns a pointer to a cl_pool_item_t for an object. * * Returns NULL if the pool is empty and can not be grown automatically. * * NOTES * cl_qpool_get returns the object at the head of the pool. If the pool is * empty, it is automatically grown to accommodate this request unless the * grow_size parameter passed to the cl_qpool_init function was zero. * * SEE ALSO * Quick Pool, cl_qpool_get_tail, cl_qpool_put, cl_qpool_grow, cl_qpool_count *********/ /****f* Component Library: Quick Pool/cl_qpool_put * NAME * cl_qpool_put * * DESCRIPTION * The cl_qpool_put function returns an object to the head of a quick pool. * * SYNOPSIS */ static inline void cl_qpool_put(IN cl_qpool_t * const p_pool, IN cl_pool_item_t * const p_pool_item) { CL_ASSERT(p_pool); cl_qcpool_put(&p_pool->qcpool, p_pool_item); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure to which to return * an object. * * p_pool_item * [in] Pointer to a cl_pool_item_t structure for the object * being returned. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_qpool_put places the returned object at the head of the pool. * * The object specified by the p_pool_item parameter must have been * retrieved from the pool by a previous call to cl_qpool_get. * * SEE ALSO * Quick Pool, cl_qpool_put_tail, cl_qpool_get *********/ /****f* Component Library: Quick Pool/cl_qpool_put_list * NAME * cl_qpool_put_list * * DESCRIPTION * The cl_qpool_put_list function returns a list of objects to the head * of a quick pool. * * SYNOPSIS */ static inline void cl_qpool_put_list(IN cl_qpool_t * const p_pool, IN cl_qlist_t * const p_list) { CL_ASSERT(p_pool); cl_qcpool_put_list(&p_pool->qcpool, p_list); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure to which to return * a list of objects. * * p_list * [in] Pointer to a cl_qlist_t structure for the list of objects * being returned. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_qpool_put_list places the returned objects at the head of the pool. * * The objects in the list specified by the p_list parameter must have been * retrieved from the pool by a previous call to cl_qpool_get. * * SEE ALSO * Quick Pool, cl_qpool_put, cl_qpool_put_tail, cl_qpool_get *********/ /****f* Component Library: Quick Pool/cl_qpool_grow * NAME * cl_qpool_grow * * DESCRIPTION * The cl_qpool_grow function grows a quick pool by * the specified number of objects. * * SYNOPSIS */ static inline cl_status_t cl_qpool_grow(IN cl_qpool_t * const p_pool, IN const size_t obj_count) { CL_ASSERT(p_pool); return (cl_qcpool_grow(&p_pool->qcpool, obj_count)); } /* * PARAMETERS * p_pool * [in] Pointer to a cl_qpool_t structure whose capacity to grow. * * obj_count * [in] Number of objects by which to grow the pool. * * RETURN VALUES * CL_SUCCESS if the quick pool grew successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to grow the * quick pool. * * cl_status_t value returned by optional initialization callback function * specified by the pfn_initializer parameter passed to the * cl_qpool_init function. * * NOTES * It is not necessary to call cl_qpool_grow if the pool is * configured to grow automatically. * * SEE ALSO * Quick Pool *********/ END_C_DECLS #endif /* _CL_QUICK_POOL_H_ */ opensm-3.3.20/include/complib/cl_spinlock.h0000644000205000001450000001303712104655724015543 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of spin lock object. */ #ifndef _CL_SPINLOCK_H_ #define _CL_SPINLOCK_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Public/Spinlock * NAME * Spinlock * * DESCRIPTION * Spinlock provides synchronization between threads for exclusive access to * a resource. * * The spinlock functions manipulate a cl_spinlock_t structure which should * be treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_spinlock_t * * Initialization: * cl_spinlock_construct, cl_spinlock_init, cl_spinlock_destroy * * Manipulation * cl_spinlock_acquire, cl_spinlock_release *********/ /****f* Component Library: Spinlock/cl_spinlock_construct * NAME * cl_spinlock_construct * * DESCRIPTION * The cl_spinlock_construct function initializes the state of a * spin lock. * * SYNOPSIS */ void cl_spinlock_construct(IN cl_spinlock_t * const p_spinlock); /* * PARAMETERS * p_spin_lock * [in] Pointer to a spin lock structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_spinlock_destroy without first calling * cl_spinlock_init. * * Calling cl_spinlock_construct is a prerequisite to calling any other * spin lock function except cl_spinlock_init. * * SEE ALSO * Spinlock, cl_spinlock_init, cl_spinlock_destroy *********/ /****f* Component Library: Spinlock/cl_spinlock_init * NAME * cl_spinlock_init * * DESCRIPTION * The cl_spinlock_init function initializes a spin lock for use. * * SYNOPSIS */ cl_status_t cl_spinlock_init(IN cl_spinlock_t * const p_spinlock); /* * PARAMETERS * p_spin_lock * [in] Pointer to a spin lock structure to initialize. * * RETURN VALUES * CL_SUCCESS if initialization succeeded. * * CL_ERROR if initialization failed. Callers should call * cl_spinlock_destroy to clean up any resources allocated during * initialization. * * NOTES * Initialize the spin lock structure. Allows calling cl_spinlock_aquire * and cl_spinlock_release. * * SEE ALSO * Spinlock, cl_spinlock_construct, cl_spinlock_destroy, * cl_spinlock_acquire, cl_spinlock_release *********/ /****f* Component Library: Spinlock/cl_spinlock_destroy * NAME * cl_spinlock_destroy * * DESCRIPTION * The cl_spinlock_destroy function performs all necessary cleanup of a * spin lock. * * SYNOPSIS */ void cl_spinlock_destroy(IN cl_spinlock_t * const p_spinlock); /* * PARAMETERS * p_spin_lock * [in] Pointer to a spin lock structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of a spin lock. This function must only * be called if either cl_spinlock_construct or cl_spinlock_init has been * called. * * SEE ALSO * Spinlock, cl_spinlock_construct, cl_spinlock_init *********/ /****f* Component Library: Spinlock/cl_spinlock_acquire * NAME * cl_spinlock_acquire * * DESCRIPTION * The cl_spinlock_acquire function acquires a spin lock. * This version of lock does not prevent an interrupt from * occuring on the processor on which the code is being * executed. * * SYNOPSIS */ void cl_spinlock_acquire(IN cl_spinlock_t * const p_spinlock); /* * PARAMETERS * p_spin_lock * [in] Pointer to a spin lock structure to acquire. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Spinlock, cl_spinlock_release *********/ /****f* Component Library: Spinlock/cl_spinlock_release * NAME * cl_spinlock_release * * DESCRIPTION * The cl_spinlock_release function releases a spin lock object. * * SYNOPSIS */ void cl_spinlock_release(IN cl_spinlock_t * const p_spinlock); /* * PARAMETERS * p_spin_lock * [in] Pointer to a spin lock structure to release. * * RETURN VALUE * This function does not return a value. * * NOTES * Releases a spin lock after a call to cl_spinlock_acquire. * * SEE ALSO * Spinlock, cl_spinlock_acquire *********/ END_C_DECLS #endif /* _CL_SPINLOCK_H_ */ opensm-3.3.20/include/complib/cl_spinlock_osd.h0000644000205000001450000000407012104655724016405 00000000000000/* * 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 spin lock object. */ #ifndef _CL_SPINLOCK_OSD_H_ #define _CL_SPINLOCK_OSD_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #include #include /* usr/include/ */ typedef struct _cl_spinlock_t { pthread_mutex_t mutex; cl_state_t state; } cl_spinlock_t; END_C_DECLS #endif /* _CL_SPINLOCK_OSD_H_ */ opensm-3.3.20/include/complib/cl_thread.h0000644000205000001450000002160212104655724015165 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of thread abstraction and thread related operations. */ #ifndef _CL_THREAD_H_ #define _CL_THREAD_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****i* Component Library/Thread * NAME * Thread * * DESCRIPTION * The Thread provides a separate thread of execution. * * The cl_thread_t structure should be treated as opaque and should be * manipulated only through the provided functions. *********/ /****d* Component Library: Thread/cl_pfn_thread_callback_t * NAME * cl_pfn_thread_callback_t * * DESCRIPTION * The cl_pfn_thread_callback_t function type defines the prototype * for functions invoked by thread objects * * SYNOPSIS */ typedef void (*cl_pfn_thread_callback_t) (IN void *context); /* * PARAMETERS * context * [in] Value specified in a call to cl_thread_init. * * 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 cl_thread_init. * * SEE ALSO * Thread Pool *********/ /****i* Component Library: Thread/cl_thread_t * NAME * cl_thread_t * * DESCRIPTION * Thread structure. * * The cl_thread_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_thread { cl_thread_osd_t osd; cl_pfn_thread_callback_t pfn_callback; const void *context; char name[16]; } cl_thread_t; /* * FIELDS * osd * Implementation specific structure for managing thread information. * * pfn_callback * Callback function for the thread to invoke. * * context * Context to pass to the thread callback function. * * name * Name to assign to the thread. * * SEE ALSO * Thread *********/ /****i* Component Library: Thread/cl_thread_construct * NAME * cl_thread_construct * * DESCRIPTION * The cl_thread_construct function initializes the state of a thread. * * SYNOPSIS */ void cl_thread_construct(IN cl_thread_t * const p_thread); /* * PARAMETERS * p_thread * [in] Pointer to a cl_thread_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_thread_destroy without first calling cl_thread_init. * * Calling cl_thread_construct is a prerequisite to calling any other * thread function except cl_thread_init. * * SEE ALSO * Thread, cl_thread_init, cl_thread_destroy *********/ /****i* Component Library: Thread/cl_thread_init * NAME * cl_thread_init * * DESCRIPTION * The cl_thread_init function creates a new thread of execution. * * SYNOPSIS */ cl_status_t cl_thread_init(IN cl_thread_t * const p_thread, IN cl_pfn_thread_callback_t pfn_callback, IN const void *const context, IN const char *const name); /* * PARAMETERS * p_thread * [in] Pointer to a cl_thread_t structure to initialize. * * pfn_callback * [in] Address of a function to be invoked by a thread. * See the cl_pfn_thread_callback_t function type definition for * details about the callback function. * * context * [in] Value to pass to the callback function. * * name * [in] Name to associate with the thread. The name may be up to 16 * characters, including a terminating null character. * * RETURN VALUES * CL_SUCCESS if thread creation succeeded. * * CL_ERROR if thread creation failed. * * NOTES * The thread created with cl_thread_init will invoke the callback * specified by the callback parameter with context as single parameter. * * The callback function is invoked once, and the thread exits when the * callback returns. * * It is invalid to call cl_thread_destroy from the callback function, * as doing so will result in a deadlock. * * SEE ALSO * Thread, cl_thread_construct, cl_thread_destroy, cl_thread_suspend, * cl_thread_stall, cl_pfn_thread_callback_t *********/ /****i* Component Library: Thread/cl_thread_destroy * NAME * cl_thread_destroy * * DESCRIPTION * The cl_thread_destroy function performs any necessary cleanup to free * resources associated with the specified thread. * * SYNOPSIS */ void cl_thread_destroy(IN cl_thread_t * const p_thread); /* * PARAMETERS * p_thread * [in] Pointer to a cl_thread_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * This function blocks until the thread exits and must not be called by the * thread itself. Callers must therefore ensure that such a blocking call is * possible from the context of the call. * * This function must only be called after a call to cl_thread_construct or * cl_thread_init. * * SEE ALSO * Thread, cl_thread_construct, cl_thread_init *********/ /****f* Component Library: Thread/cl_thread_suspend * NAME * cl_thread_suspend * * DESCRIPTION * The cl_thread_suspend function suspends the calling thread for a minimum * of the specified number of milliseconds. * * SYNOPSIS */ void cl_thread_suspend(IN const uint32_t pause_ms); /* * PARAMETERS * pause_ms * [in] Number of milliseconds to suspend the calling thread. * * RETURN VALUE * This function does not return a value. * * NOTES * This function should only be called if it is valid for the caller's thread * to enter a wait state. For stalling a thread that cannot enter a wait * state, callers should use cl_thread_stall. * * SEE ALSO * Thread, cl_thread_stall *********/ /****f* Component Library: Thread/cl_thread_stall * NAME * cl_thread_stall * * DESCRIPTION * The cl_thread_stall function stalls the calling thread for a minimum of * the specified number of microseconds. * * SYNOPSIS */ void cl_thread_stall(IN const uint32_t pause_us); /* * PARAMETERS * pause_us * [in] Number of microseconds to stall the calling thread. * * RETURN VALUE * This function does not return a value. * * NOTES * The cl_thread_stall function performs a busy wait for the specified * number of microseconds. Care should be taken when using this function as * it does not relinquish its quantum of operation. For longer wait * operations, users should call cl_thread_suspend if possible. * * SEE ALSO * Thread, cl_thread_suspend *********/ /****f* Component Library: Thread/cl_proc_count * NAME * cl_proc_count * * DESCRIPTION * The cl_proc_count function returns the number of processors in the system. * * SYNOPSIS */ int cl_proc_count(void); /* * RETURN VALUE * Returns the number of processors in the system. *********/ /****i* Component Library: Thread/cl_is_current_thread * NAME * cl_is_current_thread * * DESCRIPTION * The cl_is_current_thread function compares the calling thread to the * specified thread and returns whether they are the same. * * SYNOPSIS */ boolean_t cl_is_current_thread(IN const cl_thread_t * const p_thread); /* * PARAMETERS * p_thread * [in] Pointer to a cl_thread_t structure to compare to the * caller's thead. * * RETURN VALUES * TRUE if the thread specified by the p_thread parameter is the * calling thread. * * FALSE otherwise. * * SEE ALSO * Thread, cl_threadinit_t *********/ /****f* Component Library: Thread/cl_is_blockable * NAME * cl_is_blockable * * DESCRIPTION * The cl_is_blockable indicates if the current caller context is * blockable. * * SYNOPSIS */ boolean_t cl_is_blockable(void); /* * RETURN VALUE * TRUE * Current caller context can be blocked, i.e it is safe to perform * a sleep, or call a down operation on a semaphore. * *********/ END_C_DECLS #endif /* _CL_THREAD_H_ */ opensm-3.3.20/include/complib/cl_thread_osd.h0000644000205000001450000000431712104655724016036 00000000000000/* * 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: * Declaration of thread abstraction and thread related operations. */ #ifndef _CL_THREAD_OSD_H_ #define _CL_THREAD_OSD_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #include #include #include /* Linux user mode thread object structure definition. */ typedef struct _cl_thread_osd_t { pthread_t id; cl_state_t state; } cl_thread_osd_t; static inline boolean_t cl_is_blockable(void) { return TRUE; } END_C_DECLS #endif /* _CL_THREAD_OSD_H_ */ opensm-3.3.20/include/complib/cl_threadpool.h0000644000205000001450000001477512272264652016076 00000000000000/* * Copyright (c) 2004-2007 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: * Declaration of thread pool. */ #ifndef _CL_THREAD_POOL_H_ #define _CL_THREAD_POOL_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Thread Pool * NAME * Thread Pool * * DESCRIPTION * The Thread Pool manages a user specified number of threads. * * Each thread in the thread pool waits for a user initiated signal before * invoking a user specified callback function. All threads in the thread * pool invoke the same callback function. * * The thread pool functions operate on a cl_thread_pool_t structure which * should be treated as opaque, and should be manipulated only through the * provided functions. * * SEE ALSO * Structures: * cl_thread_pool_t * * Initialization: * cl_thread_pool_init, cl_thread_pool_destroy * * Manipulation * cl_thread_pool_signal *********/ /****s* Component Library: Thread Pool/cl_thread_pool_t * NAME * cl_thread_pool_t * * DESCRIPTION * Thread pool structure. * * The cl_thread_pool_t structure should be treated as opaque, and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_thread_pool { void (*pfn_callback) (void *); void *context; unsigned running_count; unsigned events; pthread_cond_t cond; pthread_mutex_t mutex; pthread_t *tid; } cl_thread_pool_t; /* * FIELDS * pfn_callback * Callback function for the thread to invoke. * * context * Context to pass to the thread callback function. * * running_count * Number of threads running. * * events * events counter * * mutex * mutex for cond variable protection * * cond * conditional variable to signal an event to thread * * tid * array of allocated thread ids. * * SEE ALSO * Thread Pool *********/ /****f* Component Library: Thread Pool/cl_thread_pool_init * NAME * cl_thread_pool_init * * DESCRIPTION * The cl_thread_pool_init function creates the threads to be * managed by a thread pool. * * SYNOPSIS */ cl_status_t cl_thread_pool_init(IN cl_thread_pool_t * const p_thread_pool, IN unsigned count, IN void (*pfn_callback) (void *), IN void *context, IN const char *const name); /* * PARAMETERS * p_thread_pool * [in] Pointer to a thread pool structure to initialize. * * thread_count * [in] Number of threads to be managed by the thread pool. * * pfn_callback * [in] Address of a function to be invoked by a thread. * See the cl_pfn_thread_callback_t function type definition for * details about the callback function. * * context * [in] Value to pass to the callback function. * * name * [in] Name to associate with the threads. The name may be up to 16 * characters, including a terminating null character. All threads * created in the pool have the same name. * * RETURN VALUES * CL_SUCCESS if the thread pool creation succeeded. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to inititalize * the thread pool. * * CL_ERROR if the threads could not be created. * * NOTES * cl_thread_pool_init creates and starts the specified number of threads. * If thread_count is zero, the thread pool creates as many threads as there * are processors in the system. * * SEE ALSO * Thread Pool, cl_thread_pool_destroy, * cl_thread_pool_signal, cl_pfn_thread_callback_t *********/ /****f* Component Library: Thread Pool/cl_thread_pool_destroy * NAME * cl_thread_pool_destroy * * DESCRIPTION * The cl_thread_pool_destroy function performs any necessary cleanup * for a thread pool. * * SYNOPSIS */ void cl_thread_pool_destroy(IN cl_thread_pool_t * const p_thread_pool); /* * PARAMETERS * p_thread_pool * [in] Pointer to a thread pool structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * This function blocks until all threads exit, and must therefore not * be called from any of the thread pool's threads. Because of its blocking * nature, callers of cl_thread_pool_destroy must ensure that entering a wait * state is valid from the calling thread context. * * This function should only be called after a call to * cl_thread_pool_init. * * SEE ALSO * Thread Pool, cl_thread_pool_init *********/ /****f* Component Library: Thread Pool/cl_thread_pool_signal * NAME * cl_thread_pool_signal * * DESCRIPTION * The cl_thread_pool_signal function signals a single thread of * the thread pool to invoke the thread pool's callback function. * * SYNOPSIS */ cl_status_t cl_thread_pool_signal(IN cl_thread_pool_t * const p_thread_pool); /* * PARAMETERS * p_thread_pool * [in] Pointer to a thread pool structure to signal. * * RETURN VALUES * CL_SUCCESS if the thread pool was successfully signalled. * * CL_ERROR otherwise. * * NOTES * Each call to this function wakes up at most one waiting thread in * the thread pool. * * If all threads are running, cl_thread_pool_signal has no effect. * * SEE ALSO * Thread Pool *********/ END_C_DECLS #endif /* _CL_THREAD_POOL_H_ */ opensm-3.3.20/include/complib/cl_timer.h0000644000205000001450000002102112104655724015031 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of timer abstraction. */ #ifndef _CL_TIMER_H_ #define _CL_TIMER_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Timer * NAME * Timer * * DESCRIPTION * The Timer provides the ability to schedule a function to be invoked at * a given time in the future. * * The timer callback function must not perform any blocking operations. * * The timer functions operate on a cl_timer_t structure which should be * treated as opaque and should be manipulated only through the provided * functions. * * SEE ALSO * Structures: * cl_timer_t * * Callbacks: * cl_pfn_timer_callback_t * * Initialization: * cl_timer_construct, cl_timer_init, cl_timer_destroy * * Manipulation: * cl_timer_start, cl_timer_stop *********/ /****d* Component Library: Timer/cl_pfn_timer_callback_t * NAME * cl_pfn_timer_callback_t * * DESCRIPTION * The cl_pfn_timer_callback_t function type defines the prototype for * functions used to notify users of a timer expiration. * * SYNOPSIS */ typedef void (*cl_pfn_timer_callback_t) (IN void *context); /* * PARAMETERS * context * [in] Value specified in a previous call to cl_timer_init. * * 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_timer_init function. * * SEE ALSO * Timer, cl_timer_init *********/ /* * This include file defines the timer structure, and depends on the timer * callback definition. */ #include /****f* Component Library: Timer/cl_timer_construct * NAME * cl_timer_construct * * DESCRIPTION * The cl_timer_construct function initializes the state of a timer. * * SYNOPSIS */ void cl_timer_construct(IN cl_timer_t * const p_timer); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure whose state to initialize. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_timer_destroy without first calling cl_timer_init. * * Calling cl_timer_construct is a prerequisite to calling any other * timer function except cl_timer_init. * * SEE ALSO * Timer, cl_timer_init, cl_timer_destroy *********/ /****f* Component Library: Timer/cl_timer_init * NAME * cl_timer_init * * DESCRIPTION * The cl_timer_init function initializes a timer for use. * * SYNOPSIS */ cl_status_t cl_timer_init(IN cl_timer_t * const p_timer, IN cl_pfn_timer_callback_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure to initialize. * * pfn_callback * [in] Address of a callback function to be invoked when a timer expires. * See the cl_pfn_timer_callback_t function type definition for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUES * CL_SUCCESS if the timer was successfully initialized. * * CL_ERROR otherwise. * * NOTES * Allows calling cl_timer_start and cl_timer_stop. * * SEE ALSO * Timer, cl_timer_construct, cl_timer_destroy, cl_timer_start, * cl_timer_stop, cl_pfn_timer_callback_t *********/ /****f* Component Library: Timer/cl_timer_destroy * NAME * cl_timer_destroy * * DESCRIPTION * The cl_timer_destroy function performs any necessary cleanup of a timer. * * SYNOPSIS */ void cl_timer_destroy(IN cl_timer_t * const p_timer); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_timer_destroy cancels any pending callbacks. * * This function should only be called after a call to cl_timer_construct * or cl_timer_init. * * SEE ALSO * Timer, cl_timer_construct, cl_timer_init *********/ /****f* Component Library: Timer/cl_timer_start * NAME * cl_timer_start * * DESCRIPTION * The cl_timer_start function sets a timer to expire after a given interval. * * SYNOPSIS */ cl_status_t cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure to schedule. * * time_ms * [in] Time, in milliseconds, before the timer should expire. * * RETURN VALUES * CL_SUCCESS if the timer was successfully scheduled. * * CL_ERROR otherwise. * * NOTES * cl_timer_start implicitly stops the timer before being scheduled. * * The interval specified by the time_ms parameter is a minimum interval. * The timer is guaranteed to expire no sooner than the desired interval, but * may take longer to expire. * * SEE ALSO * Timer, cl_timer_stop, cl_timer_trim *********/ /****f* Component Library: Timer/cl_timer_stop * NAME * cl_timer_stop * * DESCRIPTION * The cl_timer_stop function stops a pending timer from expiring. * * SYNOPSIS */ void cl_timer_stop(IN cl_timer_t * const p_timer); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Timer, cl_timer_start, cl_timer_trim *********/ /****f* Component Library: Timer/cl_timer_trim * NAME * cl_timer_trim * * DESCRIPTION * The cl_timer_trim function pulls in the absolute expiration * time of a timer if the current expiration time exceeds the specified * interval. * * sets a timer to expire after a given * interval if that interval is less than the current timer expiration. * * SYNOPSIS */ cl_status_t cl_timer_trim(IN cl_timer_t * const p_timer, IN const uint32_t time_ms); /* * PARAMETERS * p_timer * [in] Pointer to a cl_timer_t structure to schedule. * * time_ms * [in] Maximum time, in milliseconds, before the timer should expire. * * RETURN VALUES * CL_SUCCESS if the timer was successfully scheduled. * * CL_ERROR otherwise. * * NOTES * cl_timer_trim has no effect if the time interval is greater than the * remaining time when the timer is set. * * If the new interval time is less than the remaining time, cl_timer_trim * implicitly stops the timer before resetting it. * * If the timer is reset, it is guaranteed to expire no sooner than the * new interval, but may take longer to expire. * * SEE ALSO * Timer, cl_timer_start, cl_timer_stop *********/ /****f* Component Library: Time Stamp/cl_get_time_stamp * NAME * cl_get_time_stamp * * DESCRIPTION * The cl_get_time_stamp function returns the current time stamp in * microseconds since the system was booted. * * SYNOPSIS */ uint64_t cl_get_time_stamp(void); /* * RETURN VALUE * Time elapsed, in microseconds, since the system was booted. * * SEE ALSO * Timer, cl_get_time_stamp_sec *********/ /****f* Component Library: Time Stamp/cl_get_time_stamp_sec * NAME * cl_get_time_stamp_sec * * DESCRIPTION * The cl_get_time_stamp_sec function returns the current time stamp in * seconds since the system was booted. * * SYNOPSIS */ uint32_t cl_get_time_stamp_sec(void); /* * RETURN VALUE * Time elapsed, in seconds, since the system was booted. * * SEE ALSO * Timer, cl_get_time_stamp *********/ END_C_DECLS #endif /* _CL_TIMER_H_ */ opensm-3.3.20/include/complib/cl_timer_osd.h0000644000205000001450000000500312104655724015700 00000000000000/* * 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: * Declaration of timer object. */ #ifndef _CL_TIMER_OSD_H_ #define _CL_TIMER_OSD_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #include #include typedef enum _cl_timer_state { CL_TIMER_IDLE, CL_TIMER_QUEUED, CL_TIMER_RUNNING } cl_timer_state_t; typedef struct _cl_timer_t { cl_list_item_t list_item; cl_timer_state_t timer_state; cl_state_t state; cl_pfn_timer_callback_t pfn_callback; const void *context; pthread_cond_t cond; struct timespec timeout; } cl_timer_t; /* Internal functions to create the timer provider. */ cl_status_t __cl_timer_prov_create(void); /* Internal function to destroy the timer provider. */ void __cl_timer_prov_destroy(void); END_C_DECLS #endif /* _CL_TIMER_OSD_H_ */ opensm-3.3.20/include/complib/cl_types.h0000644000205000001450000002632212104655724015066 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 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: * Defines standard return codes, keywords, macros, and debug levels. */ #ifdef __WIN__ #pragma warning(disable : 4996) #endif #ifndef _CL_TYPES_H_ #define _CL_TYPES_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #include #include typedef uint16_t net16_t; typedef uint32_t net32_t; typedef uint64_t net64_t; /* explicit cast of void* to uint32_t */ #ifndef ASSERT_VOIDP2UINTN #if __WORDSIZE == 64 #define ASSERT_VOIDP2UINTN(var) \ CL_ASSERT( (intptr_t)var <= 0xffffffffffffffffL ) #else /* __WORDSIZE == 64 */ #if __WORDSIZE == 32 /* need to cast carefully to avoid the warining of un-needed check */ #define ASSERT_VOIDP2UINTN(var) \ CL_ASSERT( (intptr_t)var <= 0x100000000ULL ) #else /* __WORDSIZE == 32 */ #error "Need to know WORDSIZE to tell how to cast to unsigned long int" #endif /* __WORDSIZE == 32 */ #endif /* __WORDSIZE == 64 */ #endif /* explicit casting of void* to long */ #ifndef CAST_P2LONG #define CAST_P2LONG(var) ((intptr_t)(var)) #endif /****d* Component Library: Pointer Manipulation/offsetof * NAME * offsetof * * DESCRIPTION * The offsetof macro returns the offset of a member within a structure. * * SYNOPSIS * uintptr_t * offsetof( * IN TYPE, * IN MEMBER ); * * PARAMETERS * TYPE * [in] Name of the structure containing the specified member. * * MEMBER * [in] Name of the member whose offset in the specified structure * is to be returned. * * RETURN VALUE * Number of bytes from the beginning of the structure to the * specified member. * * SEE ALSO * PARENT_STRUCT *********/ #ifndef offsetof #define offsetof(TYPE, MEMBER) ((uintptr_t) &((TYPE *)0)->MEMBER) #endif /****d* Component Library: Pointer Manipulation/PARENT_STRUCT * NAME * PARENT_STRUCT * * DESCRIPTION * The PARENT_STRUCT macro returns a pointer to a structure * given a name and pointer to one of its members. * * SYNOPSIS * PARENT_TYPE* * PARENT_STRUCT( * IN void* const p_member, * IN PARENT_TYPE, * IN MEMBER_NAME ); * * PARAMETERS * p_member * [in] Pointer to the MEMBER_NAME member of a PARENT_TYPE structure. * * PARENT_TYPE * [in] Name of the structure containing the specified member. * * MEMBER_NAME * [in] Name of the member whose address is passed in the p_member * parameter. * * RETURN VALUE * Pointer to a structure of type PARENT_TYPE whose MEMBER_NAME member is * located at p_member. * * SEE ALSO * offsetof *********/ #define PARENT_STRUCT(p_member, PARENT_TYPE, MEMBER_NAME) \ ((PARENT_TYPE*)((uint8_t*)(p_member) - offsetof(PARENT_TYPE, MEMBER_NAME))) /****d* Component Library/Parameter Keywords * NAME * Parameter Keywords * * DESCRIPTION * The Parameter Keywords can be used to clarify the usage of function * parameters to users. * * VALUES * IN * Designates that the parameter is used as input to a function. * * OUT * Designates that the parameter's value will be set by the function. * * OPTIONAL * Designates that the parameter is optional, and may be NULL. * The OPTIONAL keyword, if used, follows the parameter name. * * EXAMPLE * // Function declaration. * void* * my_func( * IN void* const p_param1, * OUT void** const p_handle OPTIONAL ); * * NOTES * Multiple keywords can apply to a single parameter. The IN and OUT * keywords precede the parameter type. The OPTIONAL * keyword, if used, follows the parameter name. *********/ #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 . %% %% %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ /****d* Component Library/Data Types * NAME * Data Types * * DESCRIPTION * The component library provides and uses explicitly sized types. * * VALUES * char * 8-bit, defined by compiler. * * void * 0-bit, defined by compiler. * * int8_t * 8-bit signed integer. * * uint8_t * 8-bit unsigned integer. * * int16_t * 16-bit signed integer. * * uint16_t * 16-bit unsigned integer. * * net16_t * 16-bit network byte order value. * * int32_t * 32-bit signed integer. * * uint32_t * 32-bit unsigned integer. * * net32_t * 32-bit network byte order value. * * int64_t * 64-bit signed integer. * * uint64_t * 64-bit unsigned integer. * * net64_t * 64-bit network byte order value. * * boolean_t * integral sized. Set to TRUE or FALSE and used in logical expressions. * * NOTES * Pointer types are not defined as these provide no value and can potentially * lead to naming confusion. *********/ /****d* Component Library: Data Types/cl_status_t * NAME * cl_status_t * * DESCRIPTION * The cl_status_t return types are used by the component library to * provide detailed function return values. * * SYNOPSIS */ #define CL_SUCCESS 0 #define CL_ERROR 1 #define CL_INVALID_STATE 2 #define CL_INVALID_OPERATION 3 #define CL_INVALID_SETTING 4 #define CL_INVALID_PARAMETER 5 #define CL_INSUFFICIENT_RESOURCES 6 #define CL_INSUFFICIENT_MEMORY 7 #define CL_INVALID_PERMISSION 8 #define CL_COMPLETED 9 #define CL_NOT_DONE 10 #define CL_PENDING 11 #define CL_TIMEOUT 12 #define CL_CANCELED 13 #define CL_REJECT 14 #define CL_OVERRUN 15 #define CL_NOT_FOUND 16 #define CL_UNAVAILABLE 17 #define CL_BUSY 18 #define CL_DISCONNECT 19 #define CL_DUPLICATE 20 #define CL_STATUS_COUNT 21 /* should be the last value */ typedef int cl_status_t; /* * SEE ALSO * Data Types, CL_STATUS_MSG *********/ /* Status values above converted to text for easier printing. */ extern const char *cl_status_text[]; #ifndef cl_panic /****f* Component Library: Error Trapping/cl_panic * NAME * cl_panic * * DESCRIPTION * Halts execution of the current process. Halts the system if called in * from the kernel. * * SYNOPSIS */ void cl_panic(IN const char *const message, IN ...); /* * PARAMETERS * message * [in] ANSI string formatted identically as for a call to the standard C * function printf describing the cause for the panic. * * ... * [in] Extra parameters for string formatting, as defined for the * standard C function printf. * * RETURN VALUE * This function does not return. * * NOTES * The formatting of the message string is the same as for printf * * cl_panic sends the message to the current message logging target. *********/ #endif /* cl_panic */ /****d* Component Library: Data Types/CL_STATUS_MSG * NAME * CL_STATUS_MSG * * DESCRIPTION * The CL_STATUS_MSG macro returns a textual representation of * an cl_status_t code. * * SYNOPSIS * const char* * CL_STATUS_MSG( * IN cl_status_t errcode ); * * PARAMETERS * errcode * [in] cl_status_t code for which to return a text representation. * * RETURN VALUE * Pointer to a string containing a textual representation of the errcode * parameter. * * NOTES * This function performs boundary checking on the cl_status_t value, * masking off the upper 24-bits. If the value is out of bounds, the string * "invalid status code" is returned. * * SEE ALSO * cl_status_t *********/ #define CL_STATUS_MSG( errcode ) \ ((errcode < CL_STATUS_COUNT)?cl_status_text[errcode]:"invalid status code") #if !defined( FALSE ) #define FALSE 0 #endif /* !defined( FALSE ) */ #if !defined( TRUE ) #define TRUE (!FALSE) #endif /* !defined( TRUE ) */ /****d* Component Library: Unreferenced Parameters/UNUSED_PARAM * NAME * UNUSED_PARAM * * DESCRIPTION * The UNUSED_PARAM macro can be used to eliminates compiler warnings related * to intentionally unused formal parameters in function implementations. * * SYNOPSIS * UNUSED_PARAM( P ) * * EXAMPLE * void my_func( int32_t value ) * { * UNUSED_PARAM( value ); * } *********/ /****d* Component Library/Object States * NAME * Object States * * DESCRIPTION * The object states enumerated type defines the valid states of components. * * SYNOPSIS */ typedef enum _cl_state { CL_UNINITIALIZED = 1, CL_INITIALIZED, CL_DESTROYING, CL_DESTROYED } cl_state_t; /* * VALUES * CL_UNINITIALIZED * Indicates that initialization was not invoked successfully. * * CL_INITIALIZED * Indicates initialization was successful. * * CL_DESTROYING * Indicates that the object is undergoing destruction. * * CL_DESTROYED * Indicates that the object's destructor has already been called. Most * objects set their final state to CL_DESTROYED before freeing the * memory associated with the object. *********/ /****d* Component Library: Object States/cl_is_state_valid * NAME * cl_is_state_valid * * DESCRIPTION * The cl_is_state_valid function returns whether a state has a valid value. * * SYNOPSIS */ static inline boolean_t cl_is_state_valid(IN const cl_state_t state) { return ((state == CL_UNINITIALIZED) || (state == CL_INITIALIZED) || (state == CL_DESTROYING) || (state == CL_DESTROYED)); } /* * PARAMETERS * state * State whose value to validate. * * RETURN VALUES * TRUE if the specified state has a valid value. * * FALSE otherwise. * * NOTES * This function is used in debug builds to check for valid states. If an * uninitialized object is passed, the memory for the state may cause the * state to have an invalid value. * * SEE ALSO * Object States *********/ END_C_DECLS #endif /* _DATA_TYPES_H_ */ opensm-3.3.20/include/complib/cl_types_osd.h0000644000205000001450000000550312104655724015731 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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: * Defines sized datatypes for Linux User mode * exported sizes are int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t * int64_t, uint64_t. */ #ifndef _CL_TYPES_OSD_H_ #define _CL_TYPES_OSD_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #if defined (_DEBUG_) #ifdef __IA64__ #define cl_break() asm(" break 0") #else /* __IA64__ */ #define cl_break() asm(" int $3") #endif /* __IA64__ */ #else /* _DEBUG_ */ #define cl_break #endif #include #include #include /* * Branch prediction hints */ #if defined(HAVE_BUILTIN_EXPECT) #define PT(exp) __builtin_expect( ((uintptr_t)(exp)), 1 ) #define PF(exp) __builtin_expect( ((uintptr_t)(exp)), 0 ) #else #define PT(exp) (exp) #define PF(exp) (exp) #endif #if defined (_DEBUG_) #define CL_ASSERT assert #else /* _DEBUG_ */ #define CL_ASSERT( __exp__ ) #endif /* _DEBUG_ */ /* * Types not explicitly defined are native to the platform. */ typedef int boolean_t; typedef volatile int32_t atomic32_t; #ifndef NULL #define NULL (void*)0 #endif #define UNUSED_PARAM( P ) END_C_DECLS #endif /* _CL_TYPES_OSD_H_ */ opensm-3.3.20/include/complib/cl_vector.h0000644000205000001450000006016312104655724015225 00000000000000/* * Copyright (c) 2004, 2005 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: * This file contains vector definitions. Vector provides dynmically * resizable array functionality. Objects in a Vector are not relocated * when the array is resized. */ #ifndef _CL_VECTOR_H_ #define _CL_VECTOR_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* Component Library/Vector * NAME * Vector * * DESCRIPTION * The Vector is a self-sizing array. Like a traditonal array, a vector * allows efficient constant time access to elements with a specified index. * A vector grows transparently as the user adds elements to the array. * * As the vector grows in size, it does not relocate existing elements in * memory. This allows using pointers to elements stored in a Vector. * * Users can supply an initializer functions that allow a vector to ensure * that new items added to the vector are properly initialized. A vector * calls the initializer function on a per object basis when growing the * array. The initializer is optional. * * The initializer function can fail, and returns a cl_status_t. The vector * will call the destructor function, if provided, for an element that * failed initialization. If an initializer fails, a vector does not call * the initializer for objects in the remainder of the new memory allocation. * * The cl_vector_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SEE ALSO * Structures: * cl_vector_t * * Callbacks: * cl_pfn_vec_init_t, cl_pfn_vec_dtor_t, cl_pfn_vec_apply_t, * cl_pfn_vec_find_t * * Item Manipulation: * cl_vector_set_obj, cl_vector_obj * * Initialization: * cl_vector_construct, cl_vector_init, cl_vector_destroy * * Manipulation: * cl_vector_get_capacity, cl_vector_set_capacity, * cl_vector_get_size, cl_vector_set_size, cl_vector_set_min_size * cl_vector_get_ptr, cl_vector_get, cl_vector_at, cl_vector_set * * Search: * cl_vector_find_from_start, cl_vector_find_from_end * cl_vector_apply_func *********/ /****d* Component Library: Vector/cl_pfn_vec_init_t * NAME * cl_pfn_vec_init_t * * DESCRIPTION * The cl_pfn_vec_init_t function type defines the prototype for functions * used as initializer for elements being allocated by a vector. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_vec_init_t) (IN void *const p_element, IN void *context); /* * PARAMETERS * p_element * [in] Pointer to an element being added to a vector. * * context * [in] Context provided in a call to cl_vector_init. * * RETURN VALUES * Return CL_SUCCESS to indicate that the element was initialized successfully. * * Other cl_status_t values will be returned by the cl_vector_init, * cl_vector_set_size, and cl_vector_set_min_size functions. * * In situations where the vector's size needs to grows in order to satisfy * a call to cl_vector_set, a non-successful status returned by the * initializer callback causes the growth to stop. * * NOTES * This function type is provided as function prototype reference for * the initializer function provided by users as an optional parameter to * the cl_vector_init function. * * SEE ALSO * Vector, cl_vector_init *********/ /****d* Component Library: Vector/cl_pfn_vec_dtor_t * NAME * cl_pfn_vec_dtor_t * * DESCRIPTION * The cl_pfn_vec_dtor_t function type defines the prototype for functions * used as destructor for elements being deallocated from a vector. * * SYNOPSIS */ typedef void (*cl_pfn_vec_dtor_t) (IN void *const p_element, IN void *context); /* * PARAMETERS * p_element * [in] Pointer to an element being deallocated from a vector. * * context * [in] Context provided in a call to cl_vector_init. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the destructor function provided by users as an optional parameter to * the cl_vector_init function. * * SEE ALSO * Vector, cl_vector_init *********/ /****d* Component Library: Vector/cl_pfn_vec_apply_t * NAME * cl_pfn_vec_apply_t * * DESCRIPTION * The cl_pfn_vec_apply_t function type defines the prototype for functions * used to iterate elements in a vector. * * SYNOPSIS */ typedef void (*cl_pfn_vec_apply_t) (IN const size_t index, IN void *const p_element, IN void *context); /* * PARAMETERS * index * [in] Index of the element. * * p_element * [in] Pointer to an element at the specified index in the vector. * * context * [in] Context provided in a call to cl_vector_apply_func. * * RETURN VALUE * This function does not return a value. * * NOTES * This function type is provided as function prototype reference for * the function passed by users as a parameter to the cl_vector_apply_func * function. * * SEE ALSO * Vector, cl_vector_apply_func *********/ /****d* Component Library: Vector/cl_pfn_vec_find_t * NAME * cl_pfn_vec_find_t * * DESCRIPTION * The cl_pfn_vec_find_t function type defines the prototype for functions * used to find elements in a vector. * * SYNOPSIS */ typedef cl_status_t (*cl_pfn_vec_find_t) (IN const size_t index, IN const void *const p_element, IN void *context); /* * PARAMETERS * index * [in] Index of the element. * * p_element * [in] Pointer to an element at the specified index in the vector. * * context * [in] Context provided in a call to cl_vector_find_from_start or * cl_vector_find_from_end. * * RETURN VALUES * Return CL_SUCCESS if the element was found. This stops vector iteration. * * CL_NOT_FOUND to continue the vector iteration. * * NOTES * This function type is provided as function prototype reference for the * function provided by users as a parameter to the cl_vector_find_from_start * and cl_vector_find_from_end functions. * * SEE ALSO * Vector, cl_vector_find_from_start, cl_vector_find_from_end *********/ /****i* Component Library: Vector/cl_pfn_vec_copy_t * NAME * cl_pfn_vec_copy_t * * DESCRIPTION * The cl_pfn_vec_copy_t function type defines the prototype for functions * used to copy elements in a vector. * * SYNOPSIS */ typedef void (*cl_pfn_vec_copy_t) (IN void *const p_dest, IN const void *const p_src, IN const size_t size); /* * PARAMETERS * p_dest * [in] Pointer to the destination buffer into which to copy p_src. * * p_src * [in] Pointer to the destination buffer from which to copy. * * size * [in] Number of bytes to copy. * * RETURN VALUE * This function does not return a value. * * SEE ALSO * Vector *********/ /****s* Component Library: Vector/cl_vector_t * NAME * cl_vector_t * * DESCRIPTION * Vector structure. * * The cl_vector_t structure should be treated as opaque and should be * manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _cl_vector { size_t size; size_t grow_size; size_t capacity; size_t element_size; cl_pfn_vec_init_t pfn_init; cl_pfn_vec_dtor_t pfn_dtor; cl_pfn_vec_copy_t pfn_copy; const void *context; cl_qlist_t alloc_list; void **p_ptr_array; cl_state_t state; } cl_vector_t; /* * FIELDS * size * Number of elements successfully initialized in the vector. * * grow_size * Number of elements to allocate when growing. * * capacity * total # of elements allocated. * * element_size * Size of each element. * * pfn_init * User supplied element initializer. * * pfn_dtor * User supplied element destructor. * * pfn_copy * Copy operator. * * context * User context for callbacks. * * alloc_list * List of allocations. * * p_ptr_array * Internal array of pointers to elements. * * state * State of the vector. * * SEE ALSO * Vector *********/ /****f* Component Library: Vector/cl_vector_construct * NAME * cl_vector_construct * * DESCRIPTION * The cl_vector_construct function constructs a vector. * * SYNOPSIS */ void cl_vector_construct(IN cl_vector_t * const p_vector); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling cl_vector_destroy without first calling cl_vector_init. * * Calling cl_vector_construct is a prerequisite to calling any other * vector function except cl_vector_init. * * SEE ALSO * Vector, cl_vector_init, cl_vector_destroy *********/ /****f* Component Library: Vector/cl_vector_init * NAME * cl_vector_init * * DESCRIPTION * The cl_vector_init function initializes a vector for use. * * SYNOPSIS */ cl_status_t cl_vector_init(IN cl_vector_t * const p_vector, IN const size_t min_size, IN const size_t grow_size, IN const size_t element_size, IN cl_pfn_vec_init_t pfn_init OPTIONAL, IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure to inititalize. * * min_size * [in] Initial number of elements. * * grow_size * [in] Number of elements to allocate when incrementally growing * the vector. A value of zero disables automatic growth. * * element_size * [in] Size of each element. * * pfn_init * [in] Initializer callback to invoke for every new element. * See the cl_pfn_vec_init_t function type declaration for details about * the callback function. * * pfn_dtor * [in] Destructor callback to invoke for elements being deallocated. * See the cl_pfn_vec_dtor_t function type declaration for details about * the callback function. * * context * [in] Value to pass to the callback functions to provide context. * * RETURN VALUES * CL_SUCCESS if the vector was initialized successfully. * * CL_INSUFFICIENT_MEMORY if the initialization failed. * * cl_status_t value returned by optional initializer function specified by * the pfn_init parameter. * * NOTES * The constructor and initializer functions, if any, are invoked for every * new element in the array. * * SEE ALSO * Vector, cl_vector_construct, cl_vector_destroy, cl_vector_set, * cl_vector_get, cl_vector_get_ptr, cl_vector_at *********/ /****f* Component Library: Vector/cl_vector_destroy * NAME * cl_vector_destroy * * DESCRIPTION * The cl_vector_destroy function destroys a vector. * * SYNOPSIS */ void cl_vector_destroy(IN cl_vector_t * const p_vector); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_vector_destroy frees all memory allocated for the vector. The vector * is left initialized to a zero capacity and size. * * This function should only be called after a call to cl_vector_construct * or cl_vector_init. * * SEE ALSO * Vector, cl_vector_construct, cl_vector_init *********/ /****f* Component Library: Vector/cl_vector_get_capacity * NAME * cl_vector_get_capacity * * DESCRIPTION * The cl_vector_get_capacity function returns the capacity of a vector. * * SYNOPSIS */ static inline size_t cl_vector_get_capacity(IN const cl_vector_t * const p_vector) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); return (p_vector->capacity); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose capacity to return. * * RETURN VALUE * Capacity, in elements, of the vector. * * NOTES * The capacity is the number of elements that the vector can store, and * can be greater than the number of elements stored. To get the number of * elements stored in the vector, use cl_vector_get_size. * * SEE ALSO * Vector, cl_vector_set_capacity, cl_vector_get_size *********/ /****f* Component Library: Vector/cl_vector_get_size * NAME * cl_vector_get_size * * DESCRIPTION * The cl_vector_get_size function returns the size of a vector. * * SYNOPSIS */ static inline size_t cl_vector_get_size(IN const cl_vector_t * const p_vector) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); return (p_vector->size); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose size to return. * * RETURN VALUE * Size, in elements, of the vector. * * SEE ALSO * Vector, cl_vector_set_size, cl_vector_get_capacity *********/ /****f* Component Library: Vector/cl_vector_get_ptr * NAME * cl_vector_get_ptr * * DESCRIPTION * The cl_vector_get_ptr function returns a pointer to an element * stored in a vector at a specified index. * * SYNOPSIS */ static inline void *cl_vector_get_ptr(IN const cl_vector_t * const p_vector, IN const size_t index) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); return (p_vector->p_ptr_array[index]); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure from which to get a * pointer to an element. * * index * [in] Index of the element. * * RETURN VALUE * Pointer to the element stored at specified index. * * NOTES * cl_vector_get_ptr provides constant access times regardless of the index. * * cl_vector_get_ptr does not perform boundary checking. Callers are * responsible for providing an index that is within the range of the vector. * * SEE ALSO * Vector, cl_vector_get, cl_vector_at, cl_vector_set, cl_vector_get_size *********/ /****f* Component Library: Vector/cl_vector_get * NAME * cl_vector_get * * DESCRIPTION * The cl_vector_get function copies an element stored in a vector at a * specified index. * * SYNOPSIS */ static inline void cl_vector_get(IN const cl_vector_t * const p_vector, IN const size_t index, OUT void *const p_element) { void *p_src; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(p_element); /* Get a pointer to the element. */ p_src = cl_vector_get_ptr(p_vector, index); p_vector->pfn_copy(p_src, p_element, p_vector->element_size); } /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure from which to get a copy of * an element. * * index * [in] Index of the element. * * p_element * [out] Pointer to storage for the element. Contains a copy of the * desired element upon successful completion of the call. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_vector_get provides constant time access regardless of the index. * * cl_vector_get does not perform boundary checking on the vector, and * callers are responsible for providing an index that is within the range * of the vector. To access elements after performing boundary checks, * use cl_vector_at. * * The p_element parameter contains a copy of the desired element upon * return from this function. * * SEE ALSO * Vector, cl_vector_get_ptr, cl_vector_at *********/ /****f* Component Library: Vector/cl_vector_at * NAME * cl_vector_at * * DESCRIPTION * The cl_vector_at function copies an element stored in a vector at a * specified index, performing boundary checks. * * SYNOPSIS */ cl_status_t cl_vector_at(IN const cl_vector_t * const p_vector, IN const size_t index, OUT void *const p_element); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure from which to get a copy of * an element. * * index * [in] Index of the element. * * p_element * [out] Pointer to storage for the element. Contains a copy of the * desired element upon successful completion of the call. * * RETURN VALUES * CL_SUCCESS if an element was found at the specified index. * * CL_INVALID_SETTING if the index was out of range. * * NOTES * cl_vector_at provides constant time access regardless of the index, and * performs boundary checking on the vector. * * Upon success, the p_element parameter contains a copy of the desired element. * * SEE ALSO * Vector, cl_vector_get, cl_vector_get_ptr *********/ /****f* Component Library: Vector/cl_vector_set * NAME * cl_vector_set * * DESCRIPTION * The cl_vector_set function sets the element at the specified index. * * SYNOPSIS */ cl_status_t cl_vector_set(IN cl_vector_t * const p_vector, IN const size_t index, IN void *const p_element); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure into which to store * an element. * * index * [in] Index of the element. * * p_element * [in] Pointer to an element to store in the vector. * * RETURN VALUES * CL_SUCCESS if the element was successfully set. * * CL_INSUFFICIENT_MEMORY if the vector could not be resized to accommodate * the new element. * * NOTES * cl_vector_set grows the vector as needed to accommodate the new element, * unless the grow_size parameter passed into the cl_vector_init function * was zero. * * SEE ALSO * Vector, cl_vector_get *********/ /****f* Component Library: Vector/cl_vector_set_capacity * NAME * cl_vector_set_capacity * * DESCRIPTION * The cl_vector_set_capacity function reserves memory in a vector for a * specified number of elements. * * SYNOPSIS */ cl_status_t cl_vector_set_capacity(IN cl_vector_t * const p_vector, IN const size_t new_capacity); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose capacity to set. * * new_capacity * [in] Total number of elements for which the vector should * allocate memory. * * RETURN VALUES * CL_SUCCESS if the capacity was successfully set. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to satisfy the * operation. The vector is left unchanged. * * NOTES * cl_vector_set_capacity increases the capacity of the vector. It does * not change the size of the vector. If the requested capacity is less * than the current capacity, the vector is left unchanged. * * SEE ALSO * Vector, cl_vector_get_capacity, cl_vector_set_size, * cl_vector_set_min_size *********/ /****f* Component Library: Vector/cl_vector_set_size * NAME * cl_vector_set_size * * DESCRIPTION * The cl_vector_set_size function resizes a vector, either increasing or * decreasing its size. * * SYNOPSIS */ cl_status_t cl_vector_set_size(IN cl_vector_t * const p_vector, IN const size_t size); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose size to set. * * size * [in] Number of elements desired in the vector. * * RETURN VALUES * CL_SUCCESS if the size of the vector was set successfully. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to complete the * operation. The vector is left unchanged. * * NOTES * cl_vector_set_size sets the vector to the specified size. If size is * smaller than the current size of the vector, the size is reduced. * The destructor function, if any, will be invoked for all elements that * are above size. Likewise, the constructor and initializer, if any, will * be invoked for all new elements. * * This function can only fail if size is larger than the current capacity. * * SEE ALSO * Vector, cl_vector_get_size, cl_vector_set_min_size, * cl_vector_set_capacity *********/ /****f* Component Library: Vector/cl_vector_set_min_size * NAME * cl_vector_set_min_size * * DESCRIPTION * The cl_vector_set_min_size function resizes a vector to a specified size * if the vector is smaller than the specified size. * * SYNOPSIS */ cl_status_t cl_vector_set_min_size(IN cl_vector_t * const p_vector, IN const size_t min_size); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose minimum size to set. * * min_size * [in] Minimum number of elements that the vector should contain. * * RETURN VALUES * CL_SUCCESS if the vector size is greater than or equal to min_size. This * could indicate that the vector's capacity was increased to min_size or * that the vector was already of sufficient size. * * CL_INSUFFICIENT_MEMORY if there was not enough memory to resize the vector. * The vector is left unchanged. * * NOTES * If min_size is smaller than the current size of the vector, the vector is * unchanged. The vector is unchanged if the size could not be changed due * to insufficient memory being available to perform the operation. * * SEE ALSO * Vector, cl_vector_get_size, cl_vector_set_size, cl_vector_set_capacity *********/ /****f* Component Library: Vector/cl_vector_apply_func * NAME * cl_vector_apply_func * * DESCRIPTION * The cl_vector_apply_func function invokes a specified function for every * element in a vector. * * SYNOPSIS */ void cl_vector_apply_func(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_apply_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure whose elements to iterate. * * pfn_callback * [in] Function invoked for every element in the array. * See the cl_pfn_vec_apply_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUE * This function does not return a value. * * NOTES * cl_vector_apply_func invokes the specified function for every element * in the vector, starting from the beginning of the vector. * * SEE ALSO * Vector, cl_vector_find_from_start, cl_vector_find_from_end, * cl_pfn_vec_apply_t *********/ /****f* Component Library: Vector/cl_vector_find_from_start * NAME * cl_vector_find_from_start * * DESCRIPTION * The cl_vector_find_from_start function uses a specified function to * search for elements in a vector starting from the lowest index. * * SYNOPSIS */ size_t cl_vector_find_from_start(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_find_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure to inititalize. * * pfn_callback * [in] Function invoked to determine if a match was found. * See the cl_pfn_vec_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUES * Index of the element, if found. * * Size of the vector if the element was not found. * * NOTES * cl_vector_find_from_start does not remove the found element from * the vector. The index of the element is returned when the function * provided by the pfn_callback parameter returns CL_SUCCESS. * * SEE ALSO * Vector, cl_vector_find_from_end, cl_vector_apply_func, cl_pfn_vec_find_t *********/ /****f* Component Library: Vector/cl_vector_find_from_end * NAME * cl_vector_find_from_end * * DESCRIPTION * The cl_vector_find_from_end function uses a specified function to search * for elements in a vector starting from the highest index. * * SYNOPSIS */ size_t cl_vector_find_from_end(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_find_t pfn_callback, IN const void *const context); /* * PARAMETERS * p_vector * [in] Pointer to a cl_vector_t structure to inititalize. * * pfn_callback * [in] Function invoked to determine if a match was found. * See the cl_pfn_vec_find_t function type declaration for details * about the callback function. * * context * [in] Value to pass to the callback function. * * RETURN VALUES * Index of the element, if found. * * Size of the vector if the element was not found. * * NOTES * cl_vector_find_from_end does not remove the found element from * the vector. The index of the element is returned when the function * provided by the pfn_callback parameter returns CL_SUCCESS. * * SEE ALSO * Vector, cl_vector_find_from_start, cl_vector_apply_func, * cl_pfn_vec_find_t *********/ END_C_DECLS #endif /* _CL_VECTOR_H_ */ opensm-3.3.20/include/vendor/0000755000205000001450000000000012726325000013005 500000000000000opensm-3.3.20/include/vendor/osm_vendor_api.h0000644000205000001450000002554212104655724016123 00000000000000/* * Copyright (c) 2004, 2005 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: * Specification of the OpenSM transport API. This API is OpenSM's view * of the Infiniband transport. */ #ifndef _OSM_VENDOR_API_H_ #define _OSM_VENDOR_API_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM Vendor API/osm_vend_mad_recv_callback_t * NAME * osm_vend_mad_recv_callback_t * * DESCRIPTION * Function prototype for the vendor MAD receive callback. * The vendor layer calls this function for MAD receives. * * SYNOPSIS */ typedef void (*osm_vend_mad_recv_callback_t) (IN osm_madw_t * p_madw, IN void *bind_context, IN osm_madw_t * p_req_madw); /* * PARAMETERS * p_madw * [in] The received MAD wrapper. * * bind_context * [in] User context supplied during the bind call. * * p_req_madw * [in] Pointer to the request mad wrapper that generated this response. * If the inbound MAD is not a response, this field is NULL. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****s* OpenSM Vendor API/osm_vend_mad_send_err_callback_t * NAME * osm_vend_mad_send_err_callback_t * * DESCRIPTION * Function prototype for the vendor send failure callback. * The vendor layer calls this function when MADs expecting * a response are completed in error, most likely due to a * timeout. * * SYNOPSIS */ typedef void (*osm_vend_mad_send_err_callback_t) (IN void *bind_context, IN osm_madw_t * p_madw); /* * PARAMETERS * bind_context * [in] User context supplied during the bind call. * * p_madw * [in] Pointer to the request mad that failed. * * RETURN VALUES * None. * * NOTES * The vendor layer does not call this function (or any other) * for MADs that were not expecting a response. * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_new * NAME * osm_vendor_new * * DESCRIPTION * Allocates and initializes a new osm_vendor_t object. * OpenSM calls this function before any other in the vendor API. * This object is passed as a parameter to all other vendor functions. * * SYNOPSIS */ osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log, IN const uint32_t timeout); /* * PARAMETERS * p_log * [in] Pointer to the log object to use. * * timeout * [in] transaction timeout * * RETURN VALUES * Returns a pointer to the vendor object. * * NOTES * * SEE ALSO *********/ /****s* OpenSM Vendor API/osm_vendor_delete * NAME * osm_vendor_delete * * DESCRIPTION * Dealocate the vendor object. * * SYNOPSIS */ void osm_vendor_delete(IN osm_vendor_t ** const pp_vend); /* * PARAMETERS * pp_vend * [in/out] pointer to pointer to vendor objcet to be deleted * * RETURN VALUES * None * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_get_all_port_attr * NAME * osm_vendor_get_all_port_attr * * DESCRIPTION * Returns an array of available port attribute structures. * * SYNOPSIS */ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports); /* * PARAMETERS * p_vend * [in] Pointer to the vendor object to initialize. * * p_attr_array * [in/out] Pointer to pre-allocated array of port attributes. * If it is NULL - then the command only updates the p_num_ports, * and return IB_INSUFFICIENT_MEMORY. * * p_num_ports * [in/out] Pointer to a variable to hold the total number of ports * available on the local machine. * * RETURN VALUES * IB_SUCCESS on success. * IB_INSUFFICIENT_MEMORY if the attribute array was not large enough. * The number of attributes needed is returned in num_guids. * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_init * NAME * osm_vendor_init * * DESCRIPTION * The osm_vendor_init function initializes the vendor transport layer. * * SYNOPSIS */ ib_api_status_t osm_vendor_init(IN osm_vendor_t * const p_vend, IN osm_log_t * const p_log, IN const uint32_t timeout); /* * PARAMETERS * p_vend * [in] Pointer to the vendor object to initialize. * * p_log * [in] Pointer to OpenSM's log object. Vendor code may * use the log object to send messages to OpenSM's log. * * timeout * [in] Transaction timeout value in milliseconds. * A value of 0 disables timeouts. * * RETURN VALUE * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_bind * NAME * osm_vendor_bind * * DESCRIPTION * The osm_vendor_bind function registers with the vendor transport layer * per Mad Class per PortGuid for mad transport capability. * * SYNOPSIS */ osm_bind_handle_t osm_vendor_bind(IN osm_vendor_t * const p_vend, IN osm_bind_info_t * const p_bind_info, IN osm_mad_pool_t * const p_mad_pool, IN osm_vend_mad_recv_callback_t mad_recv_callback, IN osm_vend_mad_send_err_callback_t send_err_callback, IN void *context); /* * PARAMETERS * p_vend * [in] pointer to the vendor object * * p_osm_bind_info * [in] pointer to a struct defining the type of bind to perform. * * p_mad_pool * [in] pointer to a mad wrappers pool to be used for allocating * mad wrappers on send and receive. * * mad_recv_callback * [in] the callback function to be invoked on mad receive. * * send_err_callback * [in] the callback function to be invoked on mad transaction errors. * * context * [in] the context to be provided to the callbacks as bind_ctx. * * RETURN VALUE * On success, a valid bind handle. * OSM_BIND_INVALID_HANDLE otherwise. * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_unbind * NAME * osm_vendor_unbind * * DESCRIPTION * Unbind the given bind handle (obtained by osm_vendor_bind). * * SYNOPSIS */ void osm_vendor_unbind(IN osm_bind_handle_t h_bind); /* * PARAMETERS * h_bind * [in] the bind handle to release. * * RETURN VALUE * NONE. * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_get * NAME * osm_vendor_get * * DESCRIPTION * Obtain a mad wrapper holding actual mad buffer to be sent via * the transport. * * SYNOPSIS */ ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind, IN const uint32_t mad_size, IN osm_vend_wrap_t * const p_vend_wrap); /* * PARAMETERS * h_bind * [in] the bind handle obtained by calling osm_vendor_bind * * mad_size * [in] the actual mad size required * * p_vend_wrap * [out] the returned mad vendor wrapper * * RETURN VALUE * IB_SUCCESS on succesful completion. * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_send * NAME * osm_vendor_send * * DESCRIPTION * * SYNOPSIS */ ib_api_status_t osm_vendor_send(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t const resp_expected); /* * PARAMETERS * h_bind * [in] the bind handle obtained by calling osm_vendor_bind * * p_madw * [in] pointer to the Mad Wrapper structure for the MAD to be sent. * * resp_expected * [in] boolean value declaring the mad as a request (expecting a response). * * RETURN VALUE * IB_SUCCESS on succesful completion. * * NOTES * 1. Only mads that expect a response are tracked for transaction competion. * 2. A mad that does not expect a response is being put back immediately * after being sent. * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_put * NAME * osm_vendor_put * * DESCRIPTION * Return a mad vendor wrapper to the mad pool. It also means that the * mad buffer is returned to the transport. * * SYNOPSIS */ void osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vend_wrap); /* * PARAMETERS * h_bind * [in] the bind handle obtained by calling osm_vendor_bind * * p_vend_wrap * [in] pointer to the mad vendor wrapper to put back into the pool. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****i* OpenSM Vendor API/osm_vendor_local_lid_change * NAME * osm_vendor_local_lid_change * * DESCRIPTION * Notifies the vendor transport layer that the local address * has changed. This allows the vendor layer to perform housekeeping * functions such as address vector updates. * * SYNOPSIS */ ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind); /* * PARAMETERS * h_bind * [in] the bind handle obtained by calling osm_vendor_bind * * RETURN VALUE * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_set_sm * NAME * osm_vendor_set_sm * * DESCRIPTION * Modifies the port info for the bound port to set the "IS_SM" bit * according to the value given (TRUE or FALSE). * * SYNOPSIS */ void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val); /* * PARAMETERS * h_bind * [in] bind handle for this port. * * is_sm_val * [in] If TRUE - will set the is_sm to TRUE, if FALSE - will set the * the is_sm to FALSE. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ /****f* OpenSM Vendor API/osm_vendor_set_debug * NAME * osm_vendor_set_debug * * DESCRIPTION * Modifies the vendor specific debug level. * * SYNOPSIS */ void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level); /* * PARAMETERS * p_vend * [in] vendor handle. * * level * [in] vendor specific debug level. * * RETURN VALUE * None. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_API_H_ */ opensm-3.3.20/include/vendor/osm_vendor.h0000644000205000001450000000504412104655724015265 00000000000000/* * Copyright (c) 2004-2008 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: * Include file used by OpenSM to pull in the correct vendor file. */ /* this is the generic include file which includes the proper vendor specific file */ #include #if defined( OSM_VENDOR_INTF_TEST ) #include #elif defined( OSM_VENDOR_INTF_UMADT ) #include #elif defined( OSM_VENDOR_INTF_MTL ) /* HACK - I do not know how to prevent complib from loading kernel H files */ #undef __init #include #elif defined( OSM_VENDOR_INTF_TS ) #undef __init #include #elif defined( OSM_VENDOR_INTF_ANAFA ) #undef __init #include #elif defined( OSM_VENDOR_INTF_SIM ) #undef __init #include #elif defined( OSM_VENDOR_INTF_OPENIB ) #include #elif defined( OSM_VENDOR_INTF_AL ) #include #else #error No MAD Interface selected! #error Choose an interface in osm_config.h #endif opensm-3.3.20/include/vendor/osm_vendor_sa_api.h0000644000205000001450000005415612557741775016627 00000000000000/* * 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: * Specification of the OpenSM SA Client API. This API uses the basic osm * vendor API to provide SA Client interface. */ #ifndef _OSM_VENDOR_SA_API_H_ #define _OSM_VENDOR_SA_API_H_ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****d* OpenSM Vendor SA Client/osmv_flags_t * NAME * osmv_flags_t * * DESCRIPTION * Access layer flags used to direct the operation of various calls. * * SYNOPSIS */ typedef uint32_t osmv_flags_t; #define OSM_SA_FLAGS_SYNC 0x00000001 /* * VALUES * OSM_SA_FLAGS_SYNC * Indicates that the given operation should be performed synchronously. * The call will block until it completes. Callbacks will still be * invoked. * * SEE ALSO * osmv_query_sa *****/ /****d* OpenSM Vendor SA Client/osmv_query_type_t * NAME * osmv_query_type_t * * DESCRIPTION * Abstracted queries supported by the access layer. * * SYNOPSIS */ typedef enum _osmv_query_type { OSMV_QUERY_USER_DEFINED, OSMV_QUERY_ALL_SVC_RECS, OSMV_QUERY_SVC_REC_BY_NAME, OSMV_QUERY_SVC_REC_BY_ID, OSMV_QUERY_CLASS_PORT_INFO, OSMV_QUERY_NODE_REC_BY_NODE_GUID, OSMV_QUERY_PORT_REC_BY_LID, OSMV_QUERY_PORT_REC_BY_LID_AND_NUM, OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK, OSMV_QUERY_SLVL_BY_LID_AND_PORTS, OSMV_QUERY_PATH_REC_BY_PORT_GUIDS, OSMV_QUERY_PATH_REC_BY_GIDS, OSMV_QUERY_PATH_REC_BY_LIDS, OSMV_QUERY_UD_MULTICAST_SET, OSMV_QUERY_UD_MULTICAST_DELETE, OSMV_QUERY_MULTIPATH_REC, } osmv_query_type_t; /* * VALUES * OSMV_QUERY_USER_DEFINED * Query the SA based on user-defined input. Queries of this type * should reference an osmv_user_query_t structure as input to the * query. * * OSMV_QUERY_SVC_REC_BY_NAME * Query for service records based on the service name. Queries of * this type should reference an ib_svc_name_t structure as input * to the query. * * OSMV_QUERY_SVC_REC_BY_ID * Query for service records based on the service ID. Queries of * this type should reference an ib_net64_t value that indicates * the ID of the service being requested. * * OSMV_QUERY_NODE_REC_BY_NODE_GUID * Query for node information based on the node's GUID. Queries of * this type should reference an ib_net64_t value that indicates * the GUID of the node being requested. * * OSMV_QUERY_PORT_REC_BY_LID * Query for port information based on the port's base LID. Queries * of this type should reference an ib_net16_t value that indicates * the base LID of the port being requested. * * OSMV_QUERY_PORT_REC_BY_LID_AND_NUM * Query for port information based on the port's LID and port num. * Queries of this type should reference an osmv_user_query_t * structure as input to the query. The port num and lid should * be provided by it. * * OSMV_QUERY_PATH_REC_BY_PORT_GUIDS * Query for path records between the specified pair of port GUIDs. * Queries of this type should reference an osmv_guid_pair_t * structure that indicates the GUIDs of the path being requested. * * OSMV_QUERY_PATH_REC_BY_GIDS * Query for path records between the specified pair of port GIDs. * Queries of this type should reference an osmv_gid_pair_t * structure that indicates the GIDs of the path being requested. * * OSMV_QUERY_PATH_REC_BY_LIDS * Query for path records between the specified pair of port LIDs. * Queries of this type should reference an osmv_lid_pair_t * structure that indicates the LIDs of the path being requested. * * NOTES * This enum is used to define abstracted queries provided by the access * layer. Users may issue queries not listed here by sending MADs directly * to subnet administration or a class manager. These queries are * intended to represent those most often used by clients. * * SEE ALSO * osmv_query, osmv_query_req_t, osmv_user_query_t, osmv_gid_pair_t, * osmv_lid_pair_t osmv_guid_pair_t *****/ /****s* OpenSM Vendor SA Client/osmv_user_query_t * NAME * osmv_user_query_t * * DESCRIPTION * User-defined query information. * * SYNOPSIS */ typedef struct _osmv_user_query { uint8_t method; ib_net16_t attr_id; ib_net16_t attr_offset; ib_net32_t attr_mod; ib_net64_t comp_mask; void *p_attr; } osmv_user_query_t; /* * FIELDS * * method * Method to be used * * attr_id * Attribute identifier of query data. * * attr_offset * Size of the query attribute, in 8-byte words. Users can set * this value by passing in the sizeof( attribute ) into the * ib_get_attr_offset() routine. * * attr_mod * Attribute modifier for query request. * * comp_mask * Indicates the attribute components that are specified for the * query. * * p_attr * References the attribute structure used as input into the query. * This field is ignored if comp_mask is set to 0. * * NOTES * This structure is used to describe a user-defined query. The attribute * ID, attribute offset, component mask, and attribute structure must match * those defined by the IBA specification. Users should refer to chapter * 15 of the IBA specification for additional details. * * SEE ALSO * osmv_query_type_t, ib_get_attr_offset, ib_get_attr_size, osmv_query_sa *****/ /****s* OpenSM Vendor SA Client/osmv_gid_pair_t * NAME * osmv_gid_pair_t * * DESCRIPTION * Source and destination GIDs. * * SYNOPSIS */ typedef struct _osmv_gid_pair { ib_gid_t src_gid; ib_gid_t dest_gid; } osmv_gid_pair_t; /* * FIELDS * src_gid * Source GID of a path. * * dest_gid * Destination GID of a path. * * NOTES * This structure is used to describe the endpoints of a path. * * SEE ALSO * ib_gid_t *****/ /****s* OpenSM Vendor SA Client/osmv_lid_pair_t * NAME * osmv_lid_pair_t * * DESCRIPTION * Source and destination LIDs. * * SYNOPSIS */ typedef struct _osmv_lid_pair { ib_net16_t src_lid; ib_net16_t dest_lid; } osmv_lid_pair_t; /* * FIELDS * src_lid * Source LID of a path. * * dest_lid * Destination LID of a path. * * NOTES * This structure is used to describe the endpoints of a path. *****/ /****s* OpenSM Vendor SA Client/osmv_guid_pair_t * NAME * osmv_guid_pair_t * * DESCRIPTION * Source and destination GUIDs. These may be port or channel adapter * GUIDs, depending on the context in which this structure is used. * * SYNOPSIS */ typedef struct _osmv_guid_pair { ib_net64_t src_guid; ib_net64_t dest_guid; } osmv_guid_pair_t; /* * FIELDS * src_guid * Source GUID of a path. * * dest_guid * Destination GUID of a path. * * NOTES * This structure is used to describe the endpoints of a path. The given * GUID pair may belong to either ports or channel adapters. * * SEE ALSO * ib_guid_t *****/ /****s* OpenSM Vendor SA Client/osmv_multipath_req_t * NAME * osmv_multipath_req_t * * DESCRIPTION * Fields from which to generate a MultiPathRecord request. * * SYNOPSIS */ typedef struct _osmv_multipath_req_t { ib_net64_t comp_mask; uint16_t pkey; boolean_t reversible; uint8_t num_path; uint8_t sl; uint8_t independence; uint8_t sgid_count; uint8_t dgid_count; ib_gid_t gids[IB_MULTIPATH_MAX_GIDS]; } osmv_multipath_req_t; /* * FIELDS * * NOTES * This structure is used to describe a multipath request. * * SEE ALSO *****/ /****s* OpenSM Vendor SA Client/osmv_query_res_t * NAME * osmv_query_res_t * * DESCRIPTION * Contains the results of a subnet administration query. * * SYNOPSIS */ typedef struct _osmv_query_res { const void *query_context; ib_api_status_t status; osmv_query_type_t query_type; uint32_t result_cnt; osm_madw_t *p_result_madw; } osmv_query_res_t; /* * FIELDS * query_context * User-defined context information associated with the query * through the osm_vendor_query_sa call. * * status * Indicates the success of the query operation. * * query_type * Indicates the type of query for which the results are being * returned. This matches the query_type specified through the * osm_vendor_query_sa call. * * result_cnt * The number of result structures that were returned by the query. * * p_result_madw * For queries returning IB_SUCCESS or IB_REMOTE_ERROR, this * references the MAD wrapper returned by subnet administration * containing the list of results or the returned error code. * * NOTES * A query result structure is returned to a client through their * osmv_pfn_query_cb_t routine to notify them of the results of a subnet * administration query. If the query was successful or received an error * from subnet administration, p_result_madw will reference a MAD wrapper * containing the results. The MAD referenced by p_result_madw is owned by * the user and remains available even after their callback returns. Users * must call osm_mad_pool_put() to return the MAD wrapper back to the * mad pool when they are done accessing the results. * * To retrieve individual result structures from the p_result_madw, users * may call osmv_get_query_result(). * * SEE ALSO * osmv_query_sa, osmv_pfn_query_cb_t, ib_api_status_t, * osmv_query_status_t, osmv_query_type_t, * osmv_get_query_result *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_result * NAME * osmv_get_query_result * * DESCRIPTION * Retrieves a result structure from a MADW returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline void *osmv_get_query_result(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad); CL_ASSERT(ib_get_attr_size(p_sa_mad->attr_offset) * (result_index + 1) + IB_SA_MAD_HDR_SIZE <= p_result_madw->mad_size); return (p_sa_mad->data + (ib_get_attr_size(p_sa_mad->attr_offset) * result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a result structure from a * call to osmv_query_sa(). The type of result structure must be known to * the user either through the user's context or the query_type returned as * part of the osmv_query_res_t structure. * * SEE ALSO * osmv_query_res_t, osm_madw_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_path_rec * NAME * osmv_get_query_path_rec * * DESCRIPTION * Retrieves a path record result from a MAD returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline ib_path_rec_t *osmv_get_query_path_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD); return ((ib_path_rec_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a path record result from * a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_path_rec_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_portinfo_rec * NAME * osmv_get_query_portinfo_rec * * DESCRIPTION * Retrieves a port info record result from a MAD returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline ib_portinfo_record_t *osmv_get_query_portinfo_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD); return ((ib_portinfo_record_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a port info record result * from a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_portinfo_record_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_node_rec * NAME * osmv_get_query_node_rec * * DESCRIPTION * Retrieves a node record result from a MAD returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline ib_node_record_t *osmv_get_query_node_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_NODE_RECORD); return ((ib_node_record_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a node record result from * a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_node_record_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_svc_rec * NAME * osmv_get_query_svc_rec * * DESCRIPTION * Retrieves a service record result from a MAD returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline ib_service_record_t *osmv_get_query_svc_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD); return ((ib_service_record_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a service record result from * a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_service_record_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_mc_rec * NAME * osmv_get_query_mc_rec * * DESCRIPTION * Retrieves a multicast record result from a MAD returned by a call to * osmv_query_sa(). * * SYNOPSIS */ static inline ib_member_rec_t *osmv_get_query_mc_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD); return ((ib_member_rec_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a service record result from * a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_member_rec_t *****/ /****f* OpenSM Vendor SA Client/osmv_get_query_inform_info_rec * NAME * osmv_get_query_inform_info_rec * * DESCRIPTION * Retrieves an InformInfo record result from a MAD returned by * a call to osmv_query_sa(). * * SYNOPSIS */ static inline ib_inform_info_record_t *osmv_get_query_inform_info_rec(IN osm_madw_t * p_result_madw, IN uint32_t result_index) { ib_sa_mad_t __attribute__((__unused__)) *p_sa_mad; CL_ASSERT(p_result_madw); p_sa_mad = (ib_sa_mad_t *) osm_madw_get_mad_ptr(p_result_madw); CL_ASSERT(p_sa_mad && p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD); return ((ib_inform_info_record_t *) osmv_get_query_result(p_result_madw, result_index)); } /* * PARAMETERS * p_result_madw * [in] This is a reference to the MAD returned as a result of the * query. * * result_index * [in] A zero-based index indicating which result to return. * * NOTES * This call returns a pointer to the start of a service record result from * a call to osmv_query_sa(). * * SEE ALSO * osmv_query_res_t, osm_madw_t, osmv_get_query_result, ib_inform_info_record_t *****/ /****f* OpenSM Vendor SA Client/osmv_pfn_query_cb_t * NAME * osmv_pfn_query_cb_t * * DESCRIPTION * User-defined callback invoked on completion of subnet administration * query. * * SYNOPSIS */ typedef void (*osmv_pfn_query_cb_t) (IN osmv_query_res_t * p_query_res); /* * PARAMETERS * p_query_res * [in] This is a reference to a structure containing the result of * the query. * * NOTES * This routine is invoked to notify a client of the result of a subnet * administration query. The p_query_rec parameter references the result * of the query and, in the case of a successful query, any information * returned by subnet administration. * * In the kernel, this callback is usually invoked using a tasklet, * dependent on the implementation of the underlying verbs provider driver. * * SEE ALSO * osmv_query_res_t *****/ /****s* OpenSM Vendor SA Client/osmv_query_req_t * NAME * osmv_query_req_t * * DESCRIPTION * Information used to request an access layer provided query of subnet * administration. * * SYNOPSIS */ typedef struct _osmv_query_req { osmv_query_type_t query_type; const void *p_query_input; ib_net64_t sm_key; uint32_t timeout_ms; uint32_t retry_cnt; osmv_flags_t flags; const void *query_context; osmv_pfn_query_cb_t pfn_query_cb; int with_grh; ib_gid_t gid; } osmv_query_req_t; /* * FIELDS * query_type * Indicates the type of query that the access layer should * perform. * * p_query_input * A pointer to the input for the query. The data referenced by * this structure is dependent on the type of query being requested * and is determined by the specified query_type. * * sm_key * The SM_Key to be provided with the SA MAD for authentication. * Normally 0 is used. * * timeout_ms * Specifies the number of milliseconds to wait for a response for * this query until retrying or timing out the request. * * retry_cnt * Specifies the number of times that the query will be retried * before failing the request. * * flags * Used to describe the mode of operation. Set to IB_FLAGS_SYNC to * process the called routine synchronously. * * query_context * User-defined context information associated with this query. * The context data is returned to the user as a part of their * query callback. * * pfn_query_cb * A user-defined callback that is invoked upon completion of the * query. * * with_grh * Indicates that SA queries should be sent with GRH. * * gid * Used to store the SM/SA GID. * * NOTES * This structure is used when requesting an osm vendor provided query * of subnet administration. Clients specify the type of query through * the query_type field. Based on the type of query, the p_query_input * field is set to reference the appropriate data structure. * * The information referenced by the p_query_input field is one of the * following: * * -- a NULL terminated service name * -- a service id * -- a single GUID * -- a pair of GUIDs specified through an osmv_guid_pair_t structure * -- a pair of GIDs specified through an osmv_gid_pair_t structure * * SEE ALSO * osmv_query_type_t, osmv_pfn_query_cb_t, osmv_guid_pair_t, * osmv_gid_pair_t *****/ /****f* OpenSM Vendor SA Client/osmv_bind_sa * NAME * osmv_bind_sa * * DESCRIPTION * Bind to the SA service and return a handle to be used for later * queries. * * * SYNOPSIS */ osm_bind_handle_t osmv_bind_sa(IN osm_vendor_t * const p_vend, IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid); /* * PARAMETERS * p_vend * [in] an osm_vendor object to work with * * p_mad_pool * [in] mad pool to obtain madw from * * port_guid * [in] the port guid to attach to. * * RETURN VALUE * Bind handle to be used for later SA queries or OSM_BIND_INVALID_HANDLE * * NOTES * * SEE ALSO * osmv_query_sa *********/ /****f* OpenSM Vendor SA Client/osmv_query_sa * NAME * osmv_query_sa * * DESCRIPTION * Query the SA given an SA query request (similar to IBAL ib_query). * * SYNOPSIS */ ib_api_status_t osmv_query_sa(IN osm_bind_handle_t h_bind, IN const osmv_query_req_t * const p_query_req); /* * PARAMETERS * h_bind * [in] bind handle for this port. Should be previously * obtained by calling osmv_bind_sa * * p_query_req * [in] an SA query request structure. * * RETURN VALUE * IB_SUCCESS if completed successfuly (or in ASYNC mode * if the request was sent). * * NOTES * * SEE ALSO * osmv_bind_sa *********/ END_C_DECLS #endif /* _OSM_VENDOR_SA_API_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx.h0000644000205000001450000000550012104655724016142 00000000000000/* * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007,2009 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. * */ #ifndef _OSMV_H_ #define _OSMV_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* Forward reference */ struct _osm_pkt_randomizer; /* The structure behind the OSM Vendor handle */ typedef struct _osm_vendor { /* for holding common transport info - useful at ibmgt transport */ void *p_transport_info; osm_log_t *p_log; /* Uniform timeout for every ACK/single MAD */ uint32_t resp_timeout; /* Uniform timeout for every rmpp transaction */ uint32_t ttime_timeout; /* All the bind handles associated with the vendor */ cl_qlist_t bind_handles; /* run randomizer flag */ boolean_t run_randomizer; /* Packet Randomizer object */ struct _osm_pkt_randomizer *p_pkt_randomizer; } osm_vendor_t; /* Repeating the definitions in osm_vendor_api.h */ typedef void *osm_bind_handle_t; typedef struct _osm_vend_wrap { ib_mad_t *p_mad; } osm_vend_wrap_t; #ifndef OSM_BIND_INVALID_HANDLE #define OSM_BIND_INVALID_HANDLE NULL #endif /* The maximum number of retransmissions of the same MAD */ #define OSM_DEFAULT_RETRY_COUNT 3 END_C_DECLS #endif opensm-3.3.20/include/vendor/osm_pkt_randomizer.h0000644000205000001450000001350112104655724017015 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of osm_subn_t. * This object represents an IBA subnet. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_PKT_RANDOMIZER_H_ #define _OSM_PKT_RANDOMIZER_H_ #include #include #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Packet Randomizer * NAME * Packet Randomizer * * DESCRIPTION * The Packet Randomizer object encapsulates the information needed for * randomly dropping packets for debug. * * The Packet Randomizer object is not thread safe, thus callers must * provide serialization. * * AUTHOR * Yael Kalka, Mellanox * *********/ /****d* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_t * NAME * osm_pkt_randomizer_t * * DESCRIPTION * Packet randomizer structure. This structure contains the various * parameters needed by the packet randomizer. * * SYNOPSIS */ typedef struct _osm_pkt_randomizer { uint8_t osm_pkt_drop_rate; uint8_t osm_pkt_num_unstable_links; uint8_t osm_pkt_unstable_link_rate; osm_dr_path_t *fault_dr_paths; uint8_t num_paths_initialized; } osm_pkt_randomizer_t; /* * FIELDS * * osm_pkt_drop_rate * Used by the randomizer whether to drop a packet or not. * Taken from the global variable OSM_PKT_DROP_RATE. If not given or * if set to zero, the randomizer will not run. * * osm_pkt_num_unstable_links * The number of unstable links to be drawn. * Taken from the global variable OSM_PKT_NUM_UNSTABLE_LINKS. default = 1. * * osm_pkt_unstable_link_rate * Used by the randomizer whether to add a packet to the unstable links * list or not. Taken from the global variable OSM_PKT_UNSTABLE_LINK_RATE. * default = 20. * * fault_dr_path * Array of osm_dr_path_t objects, that includes all the dr_paths * that are marked as errored. * * num_paths_initialized * Describes the number of paths from the fault_dr_paths array that * have already been initialized. * * SEE ALSO * Packet Randomizer object *********/ /****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_init * NAME * osm_pkt_randomizer_init * * DESCRIPTION * The osm_pkt_randomizer_init function initializes the Packet Randomizer object. * * SYNOPSIS */ ib_api_status_t osm_pkt_randomizer_init(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer, IN osm_log_t * p_log); /* * PARAMETERS * p_pkt_randomizer * [in] Pointer to the Packet Randomizer object to be initialized. * * p_log * [in] Pointer to the log object. * * RETURN VALUE * None * * NOTES * * SEE ALSO * *********/ /****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_destroy * NAME * osm_pkt_randomizer_destroy * * DESCRIPTION * The osm_pkt_randomizer_destroy function destroys the Packet Randomizer object. * * SYNOPSIS */ void osm_pkt_randomizer_destroy(IN osm_pkt_randomizer_t ** pp_pkt_randomizer, IN osm_log_t * p_log); /* * PARAMETERS * p_pkt_randomizer * [in] Pointer to the Packet Randomizer object to be destroyed. * * p_log * [in] Pointer to the log object. * * RETURN VALUE * None * * NOTES * * SEE ALSO * *********/ /****f* OpenSM: Pkt_Randomizer/osm_pkt_randomizer_madw_drop * NAME * osm_pkt_randomizer_madw_drop * * DESCRIPTION * The osm_pkt_randomizer_madw_drop is base function of the packet * randomizer. * It decides according to different random criteria whether or not * the packet received should be dropped (according to its dr_path). * This function is relevant both for mads sent by the SM and mads * received by the SM. * It returns TRUE if the mad should be dropped, and FALSE otherwise. * * SYNOPSIS */ boolean_t osm_pkt_randomizer_mad_drop(IN osm_log_t * p_log, IN osm_pkt_randomizer_t * p_pkt_randomizer, IN const ib_mad_t * p_mad); /* * PARAMETERS * p_subn * [in] Pointer to the Subnet object for this subnet. * * p_log * [in] Pointer to the log object. * * p_mad * [in] Pointer to the ib_mad_t mad to be checked. * * RETURN VALUE * TRUE if the mad should be dropped. FALSE otherwise. * * NOTES * * SEE ALSO * *********/ END_C_DECLS #endif /* _OSM_PKT_RANDOMIZER_H */ opensm-3.3.20/include/vendor/osm_vendor_ibumad.h0000644000205000001450000001037712424443362016611 00000000000000/* * Copyright (c) 2004-2008 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. * */ #ifndef _OSM_VENDOR_UMAD_H_ #define _OSM_VENDOR_UMAD_H_ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Vendor Access Layer (UMAD) * NAME * Vendor UMAD * * DESCRIPTION * This file is the vendor specific file for the UMAD Infiniband API. * * AUTHOR * * *********/ #define OSM_DEFAULT_RETRY_COUNT 3 #define OSM_UMAD_MAX_CAS UMAD_MAX_DEVICES #define OSM_UMAD_MAX_PORTS_PER_CA 2 #define OSM_UMAD_MAX_AGENTS 32 /****s* OpenSM: Vendor UMAD/osm_ca_info_t * NAME * osm_ca_info_t * * DESCRIPTION * Structure containing information about local Channel Adapters. * * SYNOPSIS */ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /* * FIELDS * guid * Node GUID of the local CA. * * attr_size * Size of the CA attributes for this CA. * * p_attr * Pointer to dynamicly allocated CA Attribute structure. * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_num_ports * NAME * osm_ca_info_get_num_ports * * DESCRIPTION * Returns the number of ports owned by this CA. * * SYNOPSIS */ static inline uint8_t osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info) { return (p_ca_info->p_attr->num_ports); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * RETURN VUMADUE * Returns the number of ports owned by this CA. * * NOTES * * SEE ALSO *********/ /****s* OpenSM: Vendor UMAD/osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef void *osm_bind_handle_t; /***********/ typedef struct _umad_match { ib_net64_t tid; void *v; uint32_t version; uint8_t mgmt_class; } umad_match_t; #define DEFAULT_OSM_UMAD_MAX_PENDING 1000 typedef struct vendor_match_tbl { uint32_t last_version; int max; umad_match_t *tbl; } vendor_match_tbl_t; typedef struct _osm_vendor { osm_log_t *p_log; uint32_t ca_count; osm_ca_info_t *p_ca_info; uint32_t timeout; int max_retries; osm_bind_handle_t agents[OSM_UMAD_MAX_AGENTS]; char ca_names[OSM_UMAD_MAX_CAS][UMAD_CA_NAME_LEN]; vendor_match_tbl_t mtbl; umad_port_t umad_port; pthread_mutex_t cb_mutex; pthread_mutex_t match_tbl_mutex; int umad_port_id; void *receiver; int issmfd; char issm_path[256]; } osm_vendor_t; #define OSM_BIND_INVALID_HANDLE 0 typedef struct _osm_vend_wrap { int agent; int size; int retries; void *umad; osm_bind_handle_t h_bind; } osm_vend_wrap_t; END_C_DECLS #endif /* _OSM_VENDOR_UMAD_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_transport_anafa.h0000644000205000001450000000460312104655724021407 00000000000000/* * Copyright (c) 2004, 2005 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. * */ /** * FILE osmv_transport.h * AUTHOR Edward Bortnikov * * DESCRIPTION * The lower-level MAD transport interface implementation * that allows sending a single MAD/receiving a callback * when a single MAD is received. */ #ifndef _OSMV_TRANSPORT_ANAFA_H_ #define _OSMV_TRANSPORT_ANAFA_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #define OSMV_ANAFA_ID 0 typedef struct _osmv_TOPSPIN_ANAFA_transport_mgr_ { int device_fd; cl_thread_t receiver; } osmv_TOPSPIN_ANAFA_transport_mgr_t; typedef struct _osmv_TOPSPIN_ANAFA_transport_info_ { int device_fd; } osmv_TOPSPIN_ANAFA_transport_info_t; END_C_DECLS #endif /* _OSMV_TRANSPORT_ANAFA_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_sender.h0000644000205000001450000000745512104655724017515 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_RMPP_SENDER_H_ #define _OSMV_RMPP_SENDER_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****d* OSM Vendor/osmv_simple_send_madw * NAME * osmv_simple_send_madw * * DESCRIPTION * Send a single MAD (256 bytes). * * If this MAD requires a response, set the timeout event. * The function call returns when the MAD's send completion is received. * */ ib_api_status_t osmv_simple_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry); /****d* OSM Vendor/osmv_rmpp_send_madw * NAME * osmv_rmpp_send_madw * * DESCRIPTION * Send a single MAD wrapper (of arbitrary length). * Follow the RMPP semantics * (segmentation, send window, timeouts etc). * * The function call returns either when the whole MAD * has been acknowledged, or upon error. */ ib_api_status_t osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds); /* * NAME osmv_rmpp_send_ack * * DESCRIPTION */ ib_api_status_t osmv_rmpp_send_ack(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN uint32_t seg_num, IN uint32_t nwl, IN const osm_mad_addr_t * p_mad_addr); /* * NAME osmv_rmpp_send_nak * * DESCRIPTION Send the RMPP ABORT or STOP packet */ ib_api_status_t osmv_rmpp_send_nak(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN const osm_mad_addr_t * p_mad_addr, IN uint8_t nak_type, IN uint8_t status); /* * NAME osmv_rmpp_snd_error * * DESCRIPTION Mark an error status and signal the sender thread to handle it */ static inline void osmv_rmpp_snd_error(IN osmv_rmpp_send_ctx_t * p_send_ctx, IN ib_api_status_t status) { p_send_ctx->status = status; /* Release the thread waiting on send() * It will release the transaction's context */ cl_event_signal(&p_send_ctx->event); } END_C_DECLS #endif /* _OSMV_RMPP_SENDER_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_defs.h0000644000205000001450000000612212104655724017144 00000000000000/* * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2009 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. * */ #ifndef _OSMV_DEFS_H_ #define _OSMV_DEFS_H_ #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* The maximum number of outstanding MADs an RMPP sender can transmit */ #define OSMV_RMPP_RECV_WIN 16 /* Transaction Timeout = OSMV_TXN_TIMEOUT_FACTOR * Response Timeout */ #define OSMV_TXN_TIMEOUT_FACTOR 128 /************/ /****s* OSM Vendor: Types/osmv_bind_obj_t * NAME * osmv_bind_obj_t * * DESCRIPTION * The object managing a single bind context. * The bind handle is a direct pointer to it. * * SYNOPSIS */ typedef struct _osmv_bind_obj { /* Used to signal when the struct is being destroyed */ struct _osmv_bind_obj *magic_ptr; osm_vendor_t /*const */ * p_vendor; uint32_t hca_hndl; uint32_t port_num; /* Atomic access protector */ cl_spinlock_t lock; /* is_closing == TRUE --> the handle is being unbound */ boolean_t is_closing; /* Event callbacks */ osm_vend_mad_recv_callback_t recv_cb; osm_vend_mad_send_err_callback_t send_err_cb; /* ... and their context */ void *cb_context; /* A pool to manage MAD wrappers */ osm_mad_pool_t *p_osm_pool; /* each subvendor implements its own transport mgr */ void *p_transp_mgr; /* The transaction DB */ osmv_txn_mgr_t txn_mgr; } osmv_bind_obj_t; END_C_DECLS #endif /* _OSMV_DEFS_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mtl_transaction_mgr.h0000644000205000001450000001765312104655724021424 00000000000000/* * Copyright (c) 2004, 2005 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: * Definition of interface for the MTL Vendor * This object is part of the OpenSM family of objects. */ #ifndef _OSM_TRANSACTION_MGR_H_ #define _OSM_TRANSACTION_MGR_H_ /* #include #include */ #include #include #include #include #include #include #include #include #include #include #include #ifdef OSM_VENDOR_INTF_MTL #include #include #endif #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: Transaction Manager/osm_madw_req_t * NAME * osm_madw_req_t * * DESCRIPTION * The structure defining each object in the transaction_mgr. * For every request mad sent, we will save such an object for it. * * SYNOPSIS */ typedef struct _osm_madw_req { cl_list_item_t list_item; cl_map_item_t map_item; osm_madw_t *p_madw; uint64_t waking_time; uint8_t retry_cnt; osm_bind_handle_t *p_bind; } osm_madw_req_t; /* * FIELDS * list_item * List item for qlist linkage. Must be first element!! * * map_item * Map item for qmap linkage. * * p_madw * pointer to mad wrapper that is expecting to get a response. * * waking_time * Time stamp (in microseconds) when the p_madw needs to wake up. * This value is * cl_get_time_stamp() + timeout during the sending of the mad. * where timeout should be given in microseconds. * * retry_cnt * The number of outstanding retries to be called. *********/ /****s* OpenSM: Transaction Manager/osm_transaction_mgr_t * NAME * osm_transaction_mgr_t * * DESCRIPTION * This structure defines the transaction manager. * It holds a qlist and a qmap, a lock on the transaction manager, and * a timer used for the list. * The manager is responsible for keeping track of every request mad that was * sent. It is used for finding mads according to their transaction id, and for * acting as an event wheel - reporting as error each packet was supposed to get * a response and didn't get one by the timeout time expected. * * Both the list and the map hold the osm_madw_req_t objects - one for every madw. * * Managing of the list: * The timer wakes on the timeout of the first madw. If the waking_time is greater than * the current time - then the mad received a response. If not - the mad didn't get * its response. * * SYNOPSIS */ typedef struct _osm_transaction_mgr { cl_qmap_t *madw_by_tid_map_p; cl_qlist_t *madw_reqs_list_p; cl_spinlock_t transaction_mgr_lock; cl_timer_t madw_list_timer; } osm_transaction_mgr_t; /* * FIELDS * madw_by_tid_map_p * A qmap with key = transaction id. and value of osm_madw_req_t. * * madw_reqs_list_p * A qlist of all the madw with their waking time. * * transaction_mgr_lock * Lock used on the transaction manager - make sure changes on it are serial. * * madw_list_timer * Timer on the list. *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_init * NAME * osm_transaction_mgr_init * * DESCRIPTION * Initialize the transaction manager. * Will update the p_transaction_mgr in the vendor object with * the new Transaction Manager created.* * * SYNOPSIS */ void osm_transaction_mgr_init(IN osm_vendor_t * const p_vend); /* * PARAMETERS * p_vend * [in] Pointer to a Osm Vendor object. * *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_destroy * NAME * osm_transaction_mgr_destroy * * DESCRIPTION * Destroy the transaction manager. * Will de-allocate all memory allocated by the Transaction * Manager up to now. * * SYNOPSIS */ void osm_transaction_mgr_destroy(IN osm_vendor_t * const p_vend); /* * PARAMETERS * p_vend * [in] Pointer to a Osm Vendor object. * *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_insert_madw * NAME * osm_transaction_mgr_insert_madw * * DESCRIPTION * Insert a new madw to the manager. The madw is added with a waking_time, * Which is equal to the current_time + timeout. This is the maximum time * that the madw can leave without being handled (e.g - get a response). * If there are no madw saved in the manager - start the timer for vendor * timeout period. * * SYNOPSIS */ ib_api_status_t osm_transaction_mgr_insert_madw(IN osm_bind_handle_t * p_bind, IN osm_madw_t * p_madw); /* * PARAMETERS * p_vend * [in] Pointer to a mtl bind object. * * p_madw * [in] Pointer to the Mad Wrapper to be added. * *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_erase_madw * NAME * osm_transaction_mgr_erase_madw * * DESCRIPTION * Erase a madw object from the manager. * The removal is done using the transaction id of the mad - using * it the madw_p is allocated (in the qmap) and removed from the * qmap and qlist. * * SYNOPSIS */ ib_api_status_t osm_transaction_mgr_erase_madw(IN osm_vendor_t * const p_vend, IN ib_mad_t * p_mad); /* * PARAMETERS * p_vend * [in] Pointer to a Osm Vendor object. * * p_mad * [in] Pointer to the Mad to be removed. * *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_get_madw_for_tid * NAME * osm_transaction_mgr_get_madw_for_tid * * DESCRIPTION * Return the mad wrapper, given the p_mad (and in it the transaction id) * * SYNOPSIS */ ib_api_status_t osm_transaction_mgr_get_madw_for_tid(IN osm_vendor_t * const p_vend, IN ib_mad_t * const p_mad, OUT osm_madw_t ** req_madw_p); /* * PARAMETERS * p_vend * [in] Pointer to a Osm Vendor object. * * p_mad * [in] Pointer to the Mad to be located. * * req_madw_p * [out] Pointer to the mad Wrapper to be found. * *********/ /****f* OpenSM: Transaction Manager/osm_transaction_mgr_callback * NAME * osm_transaction_mgr_callback * * DESCRIPTION * This callback is called on timeout of the timer. * It checks the time of the head madw in the qlist, and compares it to * the current time. * Will send an error callback if the time of the madw is less than the * current time - this means that the madw wasn't removed in the timeout * it was supposed to be handled. * * SYNOPSIS */ void osm_transaction_mgr_callback(IN void *context); /* * PARAMETERS * context * [in] void* context * *********/ END_C_DECLS #endif /* _OSM_TRANSACTION_MGR_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_sar.h0000644000205000001450000000610712104655724017013 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_SAR_H_ #define _OSMV_SAR_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct _osmv_rmpp_sar { void *p_arbt_mad; uint32_t data_len; /* total data len in all the mads */ /* these data members contain only constants */ uint32_t hdr_sz; uint32_t data_sz; /*typical data sz for this kind of mad (sa or regular */ } osmv_rmpp_sar_t; /* * NAME * osmv_rmpp_sar_alloc * * DESCRIPTION * c'tor for rmpp_sar object * * SEE ALSO * */ ib_api_status_t osmv_rmpp_sar_init(osmv_rmpp_sar_t * p_sar, void *p_arbt_mad, uint32_t mad_size, boolean_t is_sa_mad); /* * NAME * osmv_rmpp_sar_dealloc * * DESCRIPTION * d'tor for rmpp_sar object * * SEE ALSO * */ void osmv_rmpp_sar_done(osmv_rmpp_sar_t * p_sar); /* * NAME * osmv_rmpp_sar_get_mad_seg * * DESCRIPTION * segments the original mad buffer . returnes a mad with the data of the i-th segment * * SEE ALSO * */ ib_api_status_t osmv_rmpp_sar_get_mad_seg(osmv_rmpp_sar_t * p_sar, uint32_t seg_idx, void *p_buf); /* * NAME * osmv_rmpp_sar_reassemble_arbt_mad * * DESCRIPTION * gets a qlist of mads and reassmbles to one big mad buffer * ALSO - deallocates the mad list * * SEE ALSO * */ ib_api_status_t osmv_rmpp_sar_reassemble_arbt_mad(osmv_rmpp_sar_t * p_sar, cl_qlist_t * p_bufs); END_C_DECLS #endif /* _OSMV_SAR_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_dispatcher.h0000644000205000001450000000462412104655724020356 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_MAD_DISPATCHER_H_ #define _OSMV_MAD_DISPATCHER_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * NAME * osmv_dispatch_mad * * DESCRIPTION * Lower-level MAD dispatcher. * Implements a switch between the following MAD consumers: * (1) Non-RMPP consumer (DATA) * (2) RMPP receiver (DATA/ABORT/STOP) * (3) RMPP sender (ACK/ABORT/STOP) * * PARAMETERS * h_bind The bind handle * p_mad_buf The 256 byte buffer of individual MAD * p_mad_addr The MAD originator's address */ ib_api_status_t osmv_dispatch_mad(IN osm_bind_handle_t h_bind, IN const void *p_mad_buf, IN const osm_mad_addr_t * p_mad_addr); END_C_DECLS #endif opensm-3.3.20/include/vendor/osm_vendor_umadt.h0000644000205000001450000000650712104655724016464 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of osm_mad_wrapper_t. * This object represents the context wrapper for OpenSM MAD processing. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_VENDOR_UMADT_h_ #define _OSM_VENDOR_UMADT_h_ #include "iba/ib_types.h" #include "complib/cl_qlist.h" #include "complib/cl_thread.h" #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/ Vendor Umadt * NAME * MAD Wrapper * * DESCRIPTION * * * AUTHOR * Ranjit Pandit, Intel * *********/ typedef void *osm_vendor_t; #define OSM_BIND_INVALID_HANDLE 0 /****s* OpenSM: Vendor Umadt /osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef void *osm_bind_handle_t; /****s* OpenSM: Vendor Umadt /mad_direction_t * NAME * mad_direction_t * * DESCRIPTION * Tags for mad wrapper to indicate the direction of mads. * Umadt vendor transport layer uses this tag to call the appropriate * Umadt APIs. * * SYNOPSIS */ typedef enum _mad_direction_t { SEND = 0, RECEIVE, } mad_direction_t; /****s* OpenSM/ osm_vend_wrap_t * NAME * Umadt Vendor MAD Wrapper * * DESCRIPTION * Umadt specific MAD wrapper. Umadt transport layer sets this for * housekeeping. * * SYNOPSIS *********/ typedef struct _osm_vend_wrap_t { MadtStruct *p_madt_struct; mad_direction_t direction; // send or receive uint32_t size; } osm_vend_wrap_t; /* * FIELDS * p_madt_struct * Umadt mad structure to identify a mad. * * direction * Used to identify a mad with it's direction. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_UMADT_h_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_svc.h0000644000205000001450000001235412104655724017022 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_SVC_H_ #define _OSMV_SVC_H_ #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS inline static uint8_t osmv_invert_method(IN uint8_t req_method) { switch (req_method) { case IB_MAD_METHOD_GET_RESP: /* Not a 1-1 mapping! */ return IB_MAD_METHOD_GET; case IB_MAD_METHOD_GET: return IB_MAD_METHOD_GET_RESP; case IB_MAD_METHOD_SET: return IB_MAD_METHOD_GET_RESP; case IB_MAD_METHOD_GETTABLE_RESP: return IB_MAD_METHOD_GETTABLE; case IB_MAD_METHOD_GETTABLE: return IB_MAD_METHOD_GETTABLE_RESP; case IB_MAD_METHOD_GETMULTI_RESP: /* Not a 1-1 mapping! */ return IB_MAD_METHOD_GETMULTI; case IB_MAD_METHOD_GETTRACETABLE: case IB_MAD_METHOD_GETMULTI: return IB_MAD_METHOD_GETMULTI_RESP; case IB_MAD_METHOD_TRAP: return IB_MAD_METHOD_TRAP_REPRESS; case IB_MAD_METHOD_TRAP_REPRESS: return IB_MAD_METHOD_TRAP; case IB_MAD_METHOD_REPORT: return IB_MAD_METHOD_REPORT_RESP; case IB_MAD_METHOD_REPORT_RESP: return IB_MAD_METHOD_REPORT; /* IB_MAD_METHOD_SEND does not have a response */ case IB_MAD_METHOD_SEND: return IB_MAD_METHOD_SEND; default: CL_ASSERT(FALSE); } return 0; /* Just make the compiler happy */ } inline static boolean_t osmv_mad_is_rmpp(IN const ib_mad_t * p_mad) { uint8_t rmpp_flags; CL_ASSERT(NULL != p_mad); rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags; /* HACK - JUST SA and DevMgt for now - need to add BIS and DevAdm */ if ((p_mad->mgmt_class != IB_MCLASS_SUBN_ADM) && (p_mad->mgmt_class != IB_MCLASS_DEV_MGMT)) return (0); return (0 != (rmpp_flags & IB_RMPP_FLAG_ACTIVE)); } inline static boolean_t osmv_mad_is_multi_resp(IN const ib_mad_t * p_mad) { CL_ASSERT(NULL != p_mad); return (IB_MAD_METHOD_GETMULTI == p_mad->method || IB_MAD_METHOD_GETTRACETABLE == p_mad->method); } inline static boolean_t osmv_mad_is_sa(IN const ib_mad_t * p_mad) { CL_ASSERT(NULL != p_mad); return (IB_MCLASS_SUBN_ADM == p_mad->mgmt_class); } inline static boolean_t osmv_rmpp_is_abort_stop(IN const ib_mad_t * p_mad) { uint8_t rmpp_type; CL_ASSERT(p_mad); rmpp_type = ((ib_rmpp_mad_t *) p_mad)->rmpp_type; return (IB_RMPP_TYPE_STOP == rmpp_type || IB_RMPP_TYPE_ABORT == rmpp_type); } inline static boolean_t osmv_rmpp_is_data(IN const ib_mad_t * p_mad) { CL_ASSERT(p_mad); return (IB_RMPP_TYPE_DATA == ((ib_rmpp_mad_t *) p_mad)->rmpp_type); } inline static boolean_t osmv_rmpp_is_ack(IN const ib_mad_t * p_mad) { CL_ASSERT(p_mad); return (IB_RMPP_TYPE_ACK == ((ib_rmpp_mad_t *) p_mad)->rmpp_type); } inline static boolean_t osmv_rmpp_is_first(IN const ib_mad_t * p_mad) { uint8_t rmpp_flags; CL_ASSERT(NULL != p_mad); rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags; return (0 != (IB_RMPP_FLAG_FIRST & rmpp_flags)); } inline static boolean_t osmv_rmpp_is_last(IN const ib_mad_t * p_mad) { uint8_t rmpp_flags; CL_ASSERT(NULL != p_mad); rmpp_flags = ((ib_rmpp_mad_t *) p_mad)->rmpp_flags; return (0 != (IB_RMPP_FLAG_LAST & rmpp_flags)); } inline static uint8_t *osmv_mad_copy(IN const ib_mad_t * p_mad) { uint8_t *p_copy; CL_ASSERT(p_mad); p_copy = malloc(MAD_BLOCK_SIZE); if (NULL != p_copy) { memset(p_copy, 0, MAD_BLOCK_SIZE); memcpy(p_copy, p_mad, MAD_BLOCK_SIZE); } return p_copy; } /* Should be passed externally from the Makefile */ /* #define OSMV_RANDOM_DROP 1 */ #define OSMV_DROP_RATE 0.3 inline static boolean_t osmv_random_drop(void) { srand(1); /* Pick a new base */ return (rand() / (double)RAND_MAX < OSMV_DROP_RATE); } END_C_DECLS #endif /* _OSMV_SVC_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_hca.h0000644000205000001450000000437712104655724016770 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_HCA_H_ #define _OSMV_HCA_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #if defined( OSM_VENDOR_INTF_TS_NO_VAPI ) || defined( OSM_VENDOR_INTF_SIM ) #define VAPI_hca_hndl_t uint32_t #define VAPI_hca_id_t char* #endif ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t const *p_vend, IN ib_net64_t const guid, OUT uint32_t * p_hca_hndl, OUT char *p_hca_id, OUT uint8_t * p_hca_idx, OUT uint32_t * p_port_num); END_C_DECLS #endif /* _OSMV_HCA_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_rmpp_ctx.h0000644000205000001450000001415312104655724020062 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_RMPP_CTX_H #define _OSMV_RMPP_CTX_H #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct _osmv_rmpp_send_ctx { uint8_t status; uint32_t window_first; uint32_t window_last; uint32_t mad_sz; boolean_t is_sa_mad; cl_event_t event; /* Segmentation engine */ osmv_rmpp_sar_t sar; osm_log_t *p_log; } osmv_rmpp_send_ctx_t; typedef struct _osmv_rmpp_recv_ctx { boolean_t is_sa_mad; uint32_t expected_seg; /* Reassembly buffer */ cl_qlist_t *p_rbuf; /* Reassembly engine */ osmv_rmpp_sar_t sar; osm_log_t *p_log; } osmv_rmpp_recv_ctx_t; /* * NAME * osmv_rmpp_send_ctx_init * * DESCRIPTION * c'tor for rmpp_send_ctx obj * * SEE ALSO * */ ib_api_status_t osmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *arbt_mad, uint32_t mad_sz, osm_log_t * p_log); /* * NAME * osmv_rmpp_send_ctx_done * * DESCRIPTION * d'tor for rmpp_send_ctx obj * * SEE ALSO * */ void osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * ctx); /* * NAME * osmv_rmpp_send_ctx_get_wf * * DESCRIPTION * returns number of first segment in current window * SEE ALSO * */ static inline uint32_t osmv_rmpp_send_ctx_get_wf(IN const osmv_rmpp_send_ctx_t * p_ctx) { CL_ASSERT(p_ctx); return p_ctx->window_first; } /* * NAME * osmv_rmpp_send_ctx_set_wf * * DESCRIPTION * sets number of first segment in current window * SEE ALSO * */ static inline void osmv_rmpp_send_ctx_set_wf(IN osmv_rmpp_send_ctx_t * p_ctx, IN uint32_t val) { CL_ASSERT(p_ctx); p_ctx->window_first = val; } /* * NAME * osmv_rmpp_send_ctx_get_wl * * DESCRIPTION * returns number of last segment in current window * SEE ALSO * */ static inline uint32_t osmv_rmpp_send_ctx_get_wl(IN const osmv_rmpp_send_ctx_t * p_send_ctx) { CL_ASSERT(p_send_ctx); return p_send_ctx->window_last; } /* * NAME * osmv_rmpp_send_ctx_set_wl * * DESCRIPTION * sets number of last segment in current window * SEE ALSO * */ static inline void osmv_rmpp_send_ctx_set_wl(IN osmv_rmpp_send_ctx_t * p_ctx, IN uint32_t val) { CL_ASSERT(p_ctx); p_ctx->window_last = val; } /* * NAME * osmv_rmpp_send_ctx_get_num_segs * * DESCRIPTION * returns the total number of mad segments to send * SEE ALSO * */ uint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx); /* * NAME * osmv_rmpp_send_ctx_get_seg * * DESCRIPTION * Retrieves the mad segment by seg number (including setting the mad relevant bits & hdrs) * SEE ALSO * */ ib_api_status_t osmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx, IN uint32_t seg_idx, IN uint32_t resp_timeout, OUT void *p_mad); /* * NAME * osmv_rmpp_recv_ctx_init * * DESCRIPTION * c'tor for rmpp_recv_ctx obj * SEE ALSO * */ ib_api_status_t osmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log); /* * NAME * osmv_rmpp_recv_ctx_done * * DESCRIPTION * d'tor for rmpp_recv_ctx obj * SEE ALSO * */ void osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx); /* * NAME * osmv_rmpp_recv_ctx_get_es * * DESCRIPTION * retrunes index of expected segement in the curr window * */ static inline uint32_t osmv_rmpp_recv_ctx_get_es(IN const osmv_rmpp_recv_ctx_t * p_recv_ctx) { CL_ASSERT(p_recv_ctx); return p_recv_ctx->expected_seg; } /* * NAME * osmv_rmpp_recv_ctx_set_es * * DESCRIPTION * sets index of expected segement in the curr window * */ static inline void osmv_rmpp_recv_ctx_set_es(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN uint32_t val) { CL_ASSERT(p_recv_ctx); p_recv_ctx->expected_seg = val; } /* * NAME * osmv_rmpp_recv_ctx_store_madw_seg * * DESCRIPTION * stores rmpp mad in the list * */ ib_api_status_t osmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN void *p_mad); uint32_t osmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx); uint32_t osmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t * p_recv_ctx); uint32_t osmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx); /* * NAME * osmv_rmpp_recv_ctx_reassemble_arbt_mad * * DESCRIPTION * reassembles all rmpp buffs to one big arbitrary mad */ ib_api_status_t osmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN uint32_t size, IN void *p_arbt_mad); END_C_DECLS #endif opensm-3.3.20/include/vendor/osm_vendor_mlx_transport.h0000644000205000001450000000561012104655724020260 00000000000000/* * Copyright (c) 2004, 2005 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. * */ /** * FILE osmv_transport.h * AUTHOR Edward Bortnikov * * DESCRIPTION * The lower-level MAD transport interface implementation * that allows sending a single MAD/receiving a callback * when a single MAD is received. */ #ifndef _OSMV_TRANSPORT_H_ #define _OSMV_TRANSPORT_H_ #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * NAME * osmv_transport_init * * DESCRIPTION * Setup the MAD transport infrastructure (filters, callbacks etc). */ #define VENDOR_HCA_MAXNAMES 32 ib_api_status_t osmv_transport_init(IN osm_bind_info_t * p_info, IN char hca_id[VENDOR_HCA_MAXNAMES], IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo); /* * NAME * osmv_transport_send_mad * * DESCRIPTION * Send a single MAD (256 byte) */ ib_api_status_t osmv_transport_mad_send(IN const osm_bind_handle_t h_bind, IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr); /* * NAME * osmv_transport_done * * DESCRIPTION * deallocator of transportation infrastructure */ void osmv_transport_done(IN const osm_bind_handle_t h_bind); END_C_DECLS #endif /* _OSMV_TRANSPORT_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_inout.h0000644000205000001450000000434512104655724017366 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_INOUT_H_ #define _OSMV_INOUT_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #ifdef IN #undef IN #endif #ifdef OUT #undef OUT #endif #ifndef OSM_VENDOR_INTF_ANAFA #ifndef OSM_VENDOR_INTF_TS_NO_VAPI #ifndef OSM_VENDOR_INTF_SIM #include #endif #endif #endif #ifndef IN #define IN #endif #ifndef OUT #define OUT #endif #ifndef OSM_VENDOR_INTF_TS_NO_VAPI #ifndef OSM_VENDOR_INTF_ANAFA #ifndef OSM_VENDOR_INTF_SIM #include #include #endif #endif #endif END_C_DECLS #endif /* _OSMV_INOUT_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mtl_hca_guid.h0000644000205000001450000001147112104655724017765 00000000000000/* * Copyright (c) 2004, 2005 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: * Provides interface over VAPI for obtaining the local ports guids or from guid * obtaining the HCA and port number. */ #ifndef _OSM_VENDOR_HCA_GUID_H_ #define _OSM_VENDOR_HCA_GUID_H_ #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: Vendor AL/osm_ca_info_t * NAME * osm_ca_info_t * * DESCRIPTION * Structure containing information about local Channle Adapters. * * SYNOPSIS */ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /* * FIELDS * guid * Node GUID of the local CA. * * attr_size * Size of the CA attributes for this CA. * * p_attr * Pointer to dynamicly allocated CA Attribute structure. * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_port_guid * NAME * osm_ca_info_get_port_guid * * DESCRIPTION * Returns the port GUID of the specified port owned by this CA. * * SYNOPSIS */ static inline ib_net64_t osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (p_ca_info->p_attr->p_port_attr[index].port_guid); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * index * [in] Port "index" for which to retrieve the port GUID. * The index is the offset into the ca's internal array * of port attributes. * * RETURN VALUE * Returns the port GUID of the specified port owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port * NAME * osm_vendor_get_guid_ca_and_port * * DESCRIPTION * Given the vendor obj and a guid * return the ca id and port number that have that guid * * SYNOPSIS */ ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend, IN ib_net64_t const guid, OUT VAPI_hca_id_t * p_hca_id, OUT uint32_t * p_port_num); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * guid * [in] The guid to search for. * * p_hca_id * [out] The HCA Id (VAPI_hca_id_t *) that the port is found on. * * p_port_num * [out] Pointer to a port number arg to be filled with the port number with the given guid. * * RETURN VALUES * IB_SUCCESS on SUCCESS * IB_INVALID_GUID if the guid is notfound on any Local HCA Port * * NOTES * * SEE ALSO *********/ /****f* OpenSM: SM Vendor/osm_vendor_get_all_port_attr * NAME * osm_vendor_get_all_port_attr * * DESCRIPTION * Fill in the array of port_attr with all available ports on ALL the * avilable CAs on this machine. * ALSO - * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS * * SYNOPSIS */ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * p_attr_array * [out] Pre-allocated array of port attributes to be filled in * * p_num_ports * [out] The size of the given array. Filled in by the actual numberof ports found. * * RETURN VALUES * IB_SUCCESS if OK * IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided. * * NOTES * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_HCA_GUID_H_ */ opensm-3.3.20/include/vendor/osm_vendor_test.h0000644000205000001450000000645212104655724016330 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSM_VENDOR_TEST_H_ #define _OSM_VENDOR_TEST_H_ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* This value must be zero for the TEST transport. */ #define OSM_BIND_INVALID_HANDLE 0 /* * Abstract: * Declaration of vendor specific transport interface. * This is the "Test" vendor which allows compilation and some * testing without a real vendor interface. * These objects are part of the OpenSM family of objects. */ /****h* OpenSM/Vendor Test * NAME * Vendor Test * * DESCRIPTION * The Vendor Test structure encapsulates an artificial transport layer * interface for testing. * * AUTHOR * Steve King, Intel * *********/ /****s* OpenSM: Vendor Test/osm_vend_wrap_t * NAME * osm_vend_wrap_t * * DESCRIPTION * Vendor specific MAD wrapper context. * * This structure allows direct access to member variables. * * SYNOPSIS */ typedef struct _osm_vend_wrap { uint32_t dummy; } osm_vend_wrap_t; /*********/ /****s* OpenSM: Vendor Test/osm_vendor_t * NAME * osm_vendor_t * * DESCRIPTION * Vendor specific MAD interface. * * This interface defines access to the vendor specific MAD * transport layer. * * SYNOPSIS */ typedef struct _osm_vendor { osm_log_t *p_log; uint32_t timeout; } osm_vendor_t; /*********/ typedef struct _osm_bind_handle { osm_vendor_t *p_vend; ib_net64_t port_guid; uint8_t mad_class; uint8_t class_version; boolean_t is_responder; boolean_t is_trap_processor; boolean_t is_report_processor; uint32_t send_q_size; uint32_t recv_q_size; } *osm_bind_handle_t; END_C_DECLS #endif /* _OSM_VENDOR_TEST_H_ */ opensm-3.3.20/include/vendor/osm_vendor_ts.h0000644000205000001450000002164112104655724015774 00000000000000/* * Copyright (c) 2004, 2005 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: * Definition of interface for the TS Vendor * This object is part of the OpenSM family of objects. */ #ifndef _OSM_VENDOR_TS_H_ #define _OSM_VENDOR_TS_H_ #undef IN #undef OUT #include #include #include #define IN #define OUT #include "iba/ib_types.h" #include "iba/ib_al.h" #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: Vendor TS/osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef void *osm_bind_handle_t; /* **********/ #define OSM_DEFAULT_RETRY_COUNT 3 /****s* OpenSM: Vendor osm_ts_bind_info_t * NAME * osm_ts_bind_info_t * * DESCRIPTION * Handle to the result of binding a class callbacks . * * SYNOPSIS */ typedef struct _osm_ts_bind_info { int ul_dev_fd; VAPI_hca_hndl_t hca_hndl; struct _osm_vendor *p_vend; void *client_context; uint8_t port_num; void *rcv_callback; void *send_err_callback; struct _osm_mad_pool *p_osm_pool; cl_thread_t poller; } osm_ts_bind_info_t; /* * FIELDS * ul_dev_file_hdl * the file handle to be used for sending the MADs * * hca_hndl * Handle to the HCA provided by the underlying VAPI * * p_vend * Pointer to the vendor object. * * client_context * User's context passed during osm_bind * * hca_id * HCA Id we bind to. * * port_num * Port number (within the HCA) of the bound port. * * rcv_callback * OSM Callback function to be called on receive of MAD. * * send_err_callback * OSM Callback to be called on send error. * * p_osm_pool * Points to the MAD pool used by OSM * * poller * A thread reading from the device file handle * * SEE ALSO *********/ /****h* OpenSM/Vendor TS * NAME * Vendor TS * * DESCRIPTION * * The Vendor TS object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * * AUTHOR * * *********/ /****s* OpenSM: Vendor TS/osm_ca_info_t * NAME * osm_ca_info_t * * DESCRIPTION * Structure containing information about local Channle Adapters. * * SYNOPSIS */ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /* * FIELDS * guid * Node GUID of the local CA. * * attr_size * Size of the CA attributes for this CA. * * p_attr * Pointer to dynamicly allocated CA Attribute structure. * * SEE ALSO *********/ /***** OpenSM: Vendor TS/osm_vendor_t * NAME * osm_vendor_t * * DESCRIPTION * The structure defining a TS vendor * * SYNOPSIS */ typedef struct _osm_vendor { osm_log_t *p_log; uint32_t ca_count; osm_ca_info_t *p_ca_info; uint32_t timeout; struct _osm_transaction_mgr *p_transaction_mgr; osm_ts_bind_info_t smi_bind; osm_ts_bind_info_t gsi_bind; } osm_vendor_t; /* * FIELDS * h_al * Handle returned by TS open call . * * p_log * Pointer to the log object. * * ca_count * Number of CA's in the array pointed to by p_ca_info. * * p_ca_info * Pointer to dynamically allocated array of CA info objects. * * timeout * Transaction timeout time in milliseconds. * * p_transaction_mgr * Pointer to Transaction Manager. * * smi_bind * Bind information for handling SMI MADs * * gsi_bind * Bind information for GSI MADs * * SEE ALSO *********/ /****f* OpenSM: Vendor TS/CA Info/osm_ca_info_get_port_guid * NAME * osm_ca_info_get_port_guid * * DESCRIPTION * Returns the port GUID of the specified port owned by this CA. * * SYNOPSIS */ static inline ib_net64_t osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (p_ca_info->p_attr->p_port_attr[index].port_guid); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * index * [in] Port "index" for which to retrieve the port GUID. * The index is the offset into the ca's internal array * of port attributes. * * RETURN VALUE * Returns the port GUID of the specified port owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Vendor TS/CA Info/osm_ca_info_get_num_ports * NAME * osm_ca_info_get_num_ports * * DESCRIPTION * Returns the number of ports of the given ca_info * * SYNOPSIS */ static inline uint8_t osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info) { return (p_ca_info->p_attr->num_ports); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * RETURN VALUE * Returns the number of CA ports * * NOTES * * SEE ALSO *********/ /****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port * NAME * osm_vendor_get_guid_ca_and_port * * DESCRIPTION * Given the vendor obj and a guid * return the ca id and port number that have that guid * * SYNOPSIS */ ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend, IN ib_net64_t const guid, OUT VAPI_hca_hndl_t * p_hca_hndl, OUT VAPI_hca_id_t * p_hca_id, OUT uint32_t * p_port_num); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * guid * [in] The guid to search for. * * p_hca_id * [out] The HCA Id (VAPI_hca_id_t *) that the port is found on. * * p_port_num * [out] Pointer to a port number arg to be filled with the port number with the given guid. * * RETURN VALUES * IB_SUCCESS on SUCCESS * IB_INVALID_GUID if the guid is notfound on any Local HCA Port * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Vendor TS/osm_vendor_get_all_port_attr * NAME * osm_vendor_get_all_port_attr * * DESCRIPTION * Fill in the array of port_attr with all available ports on ALL the * avilable CAs on this machine. * ALSO - * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS * * SYNOPSIS */ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * p_attr_array * [out] Pre-allocated array of port attributes to be filled in * * p_num_ports * [out] The size of the given array. Filled in by the actual numberof ports found. * * RETURN VALUES * IB_SUCCESS if OK * IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided. * * NOTES * * SEE ALSO *********/ #define OSM_BIND_INVALID_HANDLE 0 /****s* OpenSM: Vendor TS/osm_vend_wrap_t * NAME * TS Vendor MAD Wrapper * * DESCRIPTION * TS specific MAD wrapper. TS transport layer uses this for * housekeeping. * * SYNOPSIS *********/ typedef struct _osm_vend_wrap_t { uint32_t size; osm_bind_handle_t h_bind; ib_mad_t *p_mad_buf; void *p_resp_madw; } osm_vend_wrap_t; /* * FIELDS * size * Size of the allocated MAD * * h_bind * Bind handle used on this transaction * * h_av * Address vector handle used for this transaction. * * p_resp_madw * Pointer to the mad wrapper structure used to hold the pending * reponse to the mad, if any. If a response is expected, the * wrapper for the reponse is allocated during the send call. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_TS_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mlx_txn.h0000644000205000001450000001734412104655724017044 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSMV_TXN_H_ #define _OSMV_TXN_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef enum _osmv_txn_rmpp_state { OSMV_TXN_RMPP_NONE = 0, /* Not part of RMPP transaction */ OSMV_TXN_RMPP_SENDER, OSMV_TXN_RMPP_RECEIVER } osmv_txn_rmpp_state_t; typedef struct _osmv_rmpp_txfr { osmv_txn_rmpp_state_t rmpp_state; boolean_t is_rmpp_init_by_peer; osmv_rmpp_send_ctx_t *p_rmpp_send_ctx; osmv_rmpp_recv_ctx_t *p_rmpp_recv_ctx; } osmv_rmpp_txfr_t; typedef struct _osmv_txn_ctx { /* The original Transaction ID */ uint64_t tid; /* The key by which the Transaction is stored */ uint64_t key; /* RMPP Send/Receive contexts, if applicable */ osmv_rmpp_txfr_t rmpp_txfr; /* A MAD that was sent during the transaction (request or response) */ osm_madw_t *p_madw; /* Reference to a log to enable tracing */ osm_log_t *p_log; } osmv_txn_ctx_t; typedef struct _osmv_txn_mgr { /* Container of all the transactions */ cl_qmap_t *p_txn_map; /* The timeouts DB */ cl_event_wheel_t *p_event_wheel; /* Reference to a log to enable tracing */ osm_log_t *p_log; } osmv_txn_mgr_t; /* * * * * * * osmv_txn_ctx_t functions * * * * * * * * */ /* * NAME * osmv_txn_init * * DESCRIPTION * allocs & inits the osmv_txn_ctx obj and insert it into the db * SEE ALSO * */ ib_api_status_t osmv_txn_init(IN osm_bind_handle_t h_bind, IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); /* * NAME * osmv_rmpp_txfr_init_sender * * DESCRIPTION * init the rmpp send ctx in the transaction * * SEE ALSO * */ ib_api_status_t osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw); /* * NAME * osmv_rmpp_txfr_init_receiver * * DESCRIPTION * init the rmpp recv ctx in the transaction * * SEE ALSO * */ ib_api_status_t osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_init_by_peer); /* * NAME * osmv_txn_done * * DESCRIPTION * destroys txn object and removes it from the db * * SEE ALSO * */ void osmv_txn_done(IN osm_bind_handle_t h_bind, IN uint64_t key, IN boolean_t is_in_cb); /* * NAME * osmv_txn_get_tid * * DESCRIPTION * returns tid of the transaction * SEE ALSO * */ static inline uint64_t osmv_txn_get_tid(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->tid; } /* * NAME * osmv_txn_get_key * * DESCRIPTION * returns key of the transaction * SEE ALSO * */ static inline uint64_t osmv_txn_get_key(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->key; } /* * NAME * osmv_txn_is_rmpp_init_by_peer * * DESCRIPTION * returns whether the rmpp txfr was init by the peer * * SEE ALSO * */ static inline boolean_t osmv_txn_is_rmpp_init_by_peer(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->rmpp_txfr.is_rmpp_init_by_peer; } /* * NAME * osmv_txn_get_rmpp_send_ctx * * DESCRIPTION * returns osmv_rmpp_send_ctx obj * SEE ALSO * */ static inline osmv_rmpp_send_ctx_t *osmv_txn_get_rmpp_send_ctx(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->rmpp_txfr.p_rmpp_send_ctx; } /* * NAME * osmv_txn_get_rmpp_recv_ctx * * DESCRIPTION * returns osmv_rmpp_recv_ctx obj * SEE ALSO * */ static inline osmv_rmpp_recv_ctx_t *osmv_txn_get_rmpp_recv_ctx(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->rmpp_txfr.p_rmpp_recv_ctx; } /* * NAME * osmv_txn_get_rmpp_state * * DESCRIPTION * returns the rmpp role of the transactino ( send/ recv) * SEE ALSO * */ static inline osmv_txn_rmpp_state_t osmv_txn_get_rmpp_state(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->rmpp_txfr.rmpp_state; } /* * NAME * osmv_txn_set_rmpp_state * * DESCRIPTION * sets the rmpp role of the transaction (send/ recv) * SEE ALSO * */ static inline void osmv_txn_set_rmpp_state(IN osmv_txn_ctx_t * p_txn, IN osmv_txn_rmpp_state_t state) { CL_ASSERT(NULL != p_txn); p_txn->rmpp_txfr.rmpp_state = state; } /* * NAME * osmv_txn_get_madw * * DESCRIPTION * returns the requester madw * SEE ALSO * */ static inline osm_madw_t *osmv_txn_get_madw(IN osmv_txn_ctx_t * p_txn) { CL_ASSERT(NULL != p_txn); return p_txn->p_madw; } /* * NAME * osmv_txn_set_madw * * DESCRIPTION * sets the requester madw * SEE ALSO * */ static inline void osmv_txn_set_madw(IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw) { CL_ASSERT(NULL != p_txn); p_txn->p_madw = p_madw; } /* * NAME * osmv_txn_set_timeout_ev * * DESCRIPTION * * SEE ALSO * */ ib_api_status_t osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key, IN uint64_t msec); /* * NAME * osmv_txn_remove_timeout_ev * * DESCRIPTION * SEE ALSO * */ void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key); /* * NAME * osmv_txn_lookup * * DESCRIPTION * get a transaction by its key * * SEE ALSO * */ ib_api_status_t osmv_txn_lookup(IN osm_bind_handle_t h_bind, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); void osmv_txn_abort_rmpp_txns(IN osm_bind_handle_t h_bind); /* * * * * * * * * * * * */ /* * NAME * osmv_txnmgr_init * * DESCRIPTION * c'tor for txn mgr obj * SEE ALSO * */ ib_api_status_t osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr, IN osm_log_t * p_log, IN cl_spinlock_t * p_lock); /* * NAME * osmv_txnmgr_done * * DESCRIPTION * c'tor for txn mgr obj * SEE ALSO * */ void osmv_txnmgr_done(IN osm_bind_handle_t h_bind); void osmv_txn_lock(IN osm_bind_handle_t h_bind); void osmv_txn_unlock(IN osm_bind_handle_t h_bind); inline static uint64_t osmv_txn_uniq_key(IN uint64_t tid) { uint64_t pid = getpid(); return ((pid << 32) | (tid & 0xFFFFFFFF)); } END_C_DECLS #endif /* _OSMV_TXN_H_ */ opensm-3.3.20/include/vendor/osm_vendor_al.h0000644000205000001450000001650112104655724015741 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of osm_mad_wrapper_t. * This object represents the context wrapper for OpenSM MAD processing. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_VENDOR_AL_H_ #define _OSM_VENDOR_AL_H_ #include #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Vendor AL * NAME * Vendor AL * * DESCRIPTION * * The Vendor AL object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * Enable various hacks to compensate for bugs in external code... * * * AUTHOR * * *********/ /****h* OpenSM/Vendor Access Layer (AL) * NAME * Vendor AL * * DESCRIPTION * This file is the vendor specific file for the AL Infiniband API. * * AUTHOR * Steve King, Intel * *********/ #define OSM_AL_SQ_SGE 256 #define OSM_AL_RQ_SGE 256 #define OSM_DEFAULT_RETRY_COUNT 3 /* AL supports RMPP */ #define VENDOR_RMPP_SUPPORT 1 /****s* OpenSM: Vendor AL/osm_ca_info_t * NAME * osm_ca_info_t * * DESCRIPTION * Structure containing information about local Channle Adapters. * * SYNOPSIS */ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /* * FIELDS * guid * Node GUID of the local CA. * * attr_size * Size of the CA attributes for this CA. * * p_attr * Pointer to dynamicly allocated CA Attribute structure. * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_num_ports * NAME * osm_ca_info_get_num_ports * * DESCRIPTION * Returns the number of ports owned by this CA. * * SYNOPSIS */ static inline uint8_t osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info) { return (p_ca_info->p_attr->num_ports); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * RETURN VALUE * Returns the number of ports owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_port_guid * NAME * osm_ca_info_get_port_guid * * DESCRIPTION * Returns the port GUID of the specified port owned by this CA. * * SYNOPSIS */ static inline ib_net64_t osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (p_ca_info->p_attr->p_port_attr[index].port_guid); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * index * [in] Port "index" for which to retrieve the port GUID. * The index is the offset into the ca's internal array * of port attributes. * * RETURN VALUE * Returns the port GUID of the specified port owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_port_num * NAME * osm_ca_info_get_port_num * * DESCRIPTION * Returns the port number of the specified port owned by this CA. * Port numbers start with 1 for HCA's. * * SYNOPSIS */ static inline uint8_t osm_ca_info_get_port_num(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (p_ca_info->p_attr->p_port_attr[index].port_num); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * index * [in] Port "index" for which to retrieve the port GUID. * The index is the offset into the ca's internal array * of port attributes. * * RETURN VALUE * Returns the port GUID of the specified port owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: CA Info/osm_ca_info_get_ca_guid * NAME * osm_ca_info_get_ca_guid * * DESCRIPTION * Returns the GUID of the specified CA. * * SYNOPSIS */ static inline ib_net64_t osm_ca_info_get_ca_guid(IN const osm_ca_info_t * const p_ca_info) { return (p_ca_info->p_attr->ca_guid); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * RETURN VALUE * Returns the GUID of the specified CA. * * NOTES * * SEE ALSO *********/ /****s* OpenSM: Vendor AL/osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef struct _osm_vendor { ib_al_handle_t h_al; osm_log_t *p_log; uint32_t ca_count; osm_ca_info_t *p_ca_info; uint32_t timeout; ib_ca_handle_t h_ca; ib_pd_handle_t h_pd; } osm_vendor_t; /* * FIELDS * h_al * Handle returned by AL open call (ib_open_al). * * p_log * Pointer to the log object. * * ca_count * Number of CA's in the array pointed to by p_ca_info. * * p_ca_info * Pointer to dynamically allocated array of CA info objects. * * h_pool * MAD Pool handle returned by ib_create_mad_pool at init time. * * timeout * Transaction timeout time in milliseconds. * * SEE ALSO *********/ #define OSM_BIND_INVALID_HANDLE 0 /****s* OpenSM: Vendor AL/osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef void *osm_bind_handle_t; /***********/ /****s* OpenSM/osm_vend_wrap_t * NAME * AL Vendor MAD Wrapper * * DESCRIPTION * AL specific MAD wrapper. AL transport layer uses this for * housekeeping. * * SYNOPSIS *********/ typedef struct _osm_vend_wrap_t { uint32_t size; osm_bind_handle_t h_bind; ib_mad_element_t *p_elem; ib_av_handle_t h_av; void *p_resp_madw; } osm_vend_wrap_t; /* * FIELDS * size * Size of the allocated MAD * * h_bind * Bind handle used on this transaction * * p_elem * Pointer to the mad element structure associated with * this mad. * * h_av * Address vector handle used for this transaction. * * p_resp_madw * Pointer to the mad wrapper structure used to hold the pending * reponse to the mad, if any. If a response is expected, the * wrapper for the reponse is allocated during the send call. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_AL_H_ */ opensm-3.3.20/include/vendor/osm_vendor_mtl.h0000644000205000001450000001675512104655724016154 00000000000000/* * Copyright (c) 2004, 2005 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: * Definition of interface for the MTL Vendor * This object is part of the OpenSM family of objects. */ #ifndef _OSM_VENDOR_MTL_H_ #define _OSM_VENDOR_MTL_H_ #undef IN #undef OUT #include #include #include #define IN #define OUT #include "iba/ib_types.h" #include "iba/ib_al.h" #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****h* OpenSM/Vendor MTL * NAME * Vendor MTL * * DESCRIPTION * * The Vendor MTL object is thread safe. * * This object should be treated as opaque and should be * manipulated only through the provided functions. * * * AUTHOR * * *********/ /****s* OpenSM: Vendor MTL/osm_ca_info_t * NAME * osm_ca_info_t * * DESCRIPTION * Structure containing information about local Channle Adapters. * * SYNOPSIS */ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /* * FIELDS * guid * Node GUID of the local CA. * * attr_size * Size of the CA attributes for this CA. * * p_attr * Pointer to dynamicly allocated CA Attribute structure. * * SEE ALSO *********/ #define OSM_DEFAULT_RETRY_COUNT 3 /***** OpenSM: Vendor MTL/osm_vendor_t * NAME * osm_vendor_t * * DESCRIPTION * The structure defining a vendor * * SYNOPSIS */ typedef struct _osm_vendor { ib_al_handle_t h_al; osm_log_t *p_log; uint32_t ca_count; osm_ca_info_t *p_ca_info; uint32_t timeout; struct osm_transaction_mgr_t *p_transaction_mgr; } osm_vendor_t; /* * FIELDS * h_al * Handle returned by MTL open call (ib_open_al). * * p_log * Pointer to the log object. * * ca_count * Number of CA's in the array pointed to by p_ca_info. * * p_ca_info * Pointer to dynamically allocated array of CA info objects. * * timeout * Transaction timeout time in milliseconds. * * p_transaction_mgr * Pointer to Transaction Manager. * * SEE ALSO *********/ /****f* OpenSM: Vendor MTL/CA Info/osm_ca_info_get_port_guid * NAME * osm_ca_info_get_port_guid * * DESCRIPTION * Returns the port GUID of the specified port owned by this CA. * * SYNOPSIS */ static inline ib_net64_t osm_ca_info_get_port_guid(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (p_ca_info->p_attr->p_port_attr[index].port_guid); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * index * [in] Port "index" for which to retrieve the port GUID. * The index is the offset into the ca's internal array * of port attributes. * * RETURN VALUE * Returns the port GUID of the specified port owned by this CA. * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Vendor MTL/CA Info/osm_ca_info_get_num_ports * NAME * osm_ca_info_get_num_ports * * DESCRIPTION * Returns the number of ports of the given ca_info * * SYNOPSIS */ static inline uint8_t osm_ca_info_get_num_ports(IN const osm_ca_info_t * const p_ca_info) { return (p_ca_info->p_attr->num_ports); } /* * PARAMETERS * p_ca_info * [in] Pointer to a CA Info object. * * RETURN VALUE * Returns the number of CA ports * * NOTES * * SEE ALSO *********/ /****f* OpenSM: SM Vendor/osm_vendor_get_guid_ca_and_port * NAME * osm_vendor_get_guid_ca_and_port * * DESCRIPTION * Given the vendor obj and a guid * return the ca id and port number that have that guid * * SYNOPSIS */ ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend, IN ib_net64_t const guid, OUT VAPI_hca_hndl_t * p_hca_hndl, OUT VAPI_hca_id_t * p_hca_id, OUT uint32_t * p_port_num); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * guid * [in] The guid to search for. * * p_hca_id * [out] The HCA Id (VAPI_hca_id_t *) that the port is found on. * * p_port_num * [out] Pointer to a port number arg to be filled with the port number with the given guid. * * RETURN VALUES * IB_SUCCESS on SUCCESS * IB_INVALID_GUID if the guid is notfound on any Local HCA Port * * NOTES * * SEE ALSO *********/ /****f* OpenSM: Vendor MTL/osm_vendor_get_all_port_attr * NAME * osm_vendor_get_all_port_attr * * DESCRIPTION * Fill in the array of port_attr with all available ports on ALL the * avilable CAs on this machine. * ALSO - * UPDATE THE VENDOR OBJECT LIST OF CA_INFO STRUCTS * * SYNOPSIS */ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports); /* * PARAMETERS * p_vend * [in] Pointer to an osm_vendor_t object. * * p_attr_array * [out] Pre-allocated array of port attributes to be filled in * * p_num_ports * [out] The size of the given array. Filled in by the actual numberof ports found. * * RETURN VALUES * IB_SUCCESS if OK * IB_INSUFFICIENT_MEMORY if not enough place for all ports was provided. * * NOTES * * SEE ALSO *********/ #define OSM_BIND_INVALID_HANDLE 0 /****s* OpenSM: Vendor MTL/osm_bind_handle_t * NAME * osm_bind_handle_t * * DESCRIPTION * handle returned by the vendor transport bind call. * * SYNOPSIS */ typedef void *osm_bind_handle_t; /***********/ /****s* OpenSM: Vendor MTL/osm_vend_wrap_t * NAME * MTL Vendor MAD Wrapper * * DESCRIPTION * MTL specific MAD wrapper. MTL transport layer uses this for * housekeeping. * * SYNOPSIS *********/ typedef struct _osm_vend_wrap_t { uint32_t size; osm_bind_handle_t h_bind; // ib_av_handle_t h_av; ib_mad_t *mad_buf_p; void *p_resp_madw; } osm_vend_wrap_t; /* * FIELDS * size * Size of the allocated MAD * * h_bind * Bind handle used on this transaction * * h_av * Address vector handle used for this transaction. * * p_resp_madw * Pointer to the mad wrapper structure used to hold the pending * reponse to the mad, if any. If a response is expected, the * wrapper for the reponse is allocated during the send call. * * SEE ALSO *********/ END_C_DECLS #endif /* _OSM_VENDOR_MTL_H_ */ opensm-3.3.20/include/vendor/osm_ts_useraccess.h0000644000205000001450000000402412104655724016633 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #include "ts_ib_useraccess.h" #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct ib_user_mad_filter osm_ts_user_mad_filter; typedef struct ib_set_port_info_ioctl osm_ts_set_port_info_ioctl; typedef struct ib_get_port_info_ioctl osm_ts_get_port_info_ioctl; typedef struct ib_gid_entry_ioctl osm_ts_gid_entry_ioctl; END_C_DECLS opensm-3.3.20/include/vendor/osm_umadt.h0000644000205000001450000000740512104655724015105 00000000000000/* * Copyright (c) 2004, 2005 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: * Declaration of osm_mad_wrapper_t. * This object represents the context wrapper for OpenSM MAD processing. * This object is part of the OpenSM family of objects. */ #ifndef _OSM_UMADT_h_ #define _OSM_UMADT_h_ #include "iba/ib_types.h" #include #include #include "umadt.h" #include "ibt.h" #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS typedef struct _umadt_obj_t { void *umadt_handle; UMADT_INTERFACE uMadtInterface; IBT_INTERFACE IbtInterface; boolean init_done; cl_spinlock_t register_lock; cl_qlist_t register_list; osm_log_t *p_log; uint32_t timeout; } umadt_obj_t; /*********/ /****s* OpenSM: Umadt MAD Wrapper/osm_bind_info * NAME * osm_bind_info * * DESCRIPTION * Context needed for processing individual MADs * * SYNOPSIS */ typedef struct _mad_bind_info_t { cl_list_item_t list_item; umadt_obj_t *p_umadt_obj; osm_mad_pool_t *p_mad_pool; osm_vend_mad_recv_callback_t mad_recv_callback; void *client_context; cl_thread_t recv_processor_thread; cl_spinlock_t trans_ctxt_lock; cl_qlist_t trans_ctxt_list; cl_timer_t timeout_timer; cl_spinlock_t timeout_list_lock; cl_qlist_t timeout_list; RegisterClassStruct umadt_reg_class; MADT_HANDLE umadt_handle; /* Umadt type */ } mad_bind_info_t; typedef struct _trans_context_t { cl_list_item_t list_item; uint64_t trans_id; uint64_t sent_time; /* micro secs */ void *context; } trans_context_t; /* * FIELDS * list_item * List linkage for pools and lists. MUST BE FIRST MEMBER! * * p_mad_pool * Pointer to the MAD pool to be used by mads with this bind handle. * * mad_recv_callback * Callback function called by the mad receive processor. * * client_context * context to be passed to the receive callback. * * recv_processor_thread * Thread structure for the receive processor thread. * * umadt_reg_class * Umadt register class struct used to register with Umadt. * * umadt_handle * Umadt returns this handle from a registration call. The transport layer * uses this handle to talk to Umadt. * * SEE ALSO *********/ END_C_DECLS #endif /*_OSM_UMADT_h_ */ opensm-3.3.20/include/vendor/osm_mtl_bind.h0000644000205000001450000000724112104655724015561 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifndef _OSM_BIND_H_ #define _OSM_BIND_H_ #include #include #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /****s* OpenSM: Vendor/osm_vendor_mgt_bind * NAME * osm_vendor_mgt_bind_t * * DESCRIPTION * Tracks the handles returned by IB_MGT to the SMI and GSI * Nulled on init of the vendor obj. Populated on first bind. * * SYNOPSIS */ typedef struct _osm_vendor_mgt_bind { boolean_t smi_init, gsi_init; IB_MGT_mad_hndl_t smi_mads_hdl; IB_MGT_mad_hndl_t gsi_mads_hdl; struct _osm_mtl_bind_info *smi_p_bind; } osm_vendor_mgt_bind_t; /* * FIELDS * smi_mads_hdl * Handle returned by IB_MGT_get_handle to the IB_MGT_SMI * * gsi_mads_hdl * Handle returned by IB_MGT_get_handle to the IB_MGT_GSI * * SEE ALSO *********/ /****s* OpenSM: Vendor osm_mtl_bind_info_t * NAME * osm_mtl_bind_info_t * * DESCRIPTION * Handle to the result of binding a class callbacks to IB_MGT. * * SYNOPSIS */ typedef struct _osm_mtl_bind_info { IB_MGT_mad_hndl_t mad_hndl; osm_vendor_t *p_vend; void *client_context; VAPI_hca_hndl_t hca_hndl; VAPI_hca_id_t hca_id; uint8_t port_num; osm_vend_mad_recv_callback_t rcv_callback; osm_vend_mad_send_err_callback_t send_err_callback; osm_mad_pool_t *p_osm_pool; } osm_mtl_bind_info_t; /* * FIELDS * mad_hndl * the handle returned from the registration in IB_MGT * * p_vend * Pointer to the vendor object. * * client_context * User's context passed during osm_bind * * hca_id * HCA Id we bind to. * * port_num * Port number (within the HCA) of the bound port. * * rcv_callback * OSM Callback function to be called on receive of MAD. * * send_err_callback * OSM Callback to be called on send error. * * p_osm_pool * Points to the MAD pool used by OSM * * * SEE ALSO *********/ ib_api_status_t osm_mtl_send_mad(IN osm_mtl_bind_info_t * p_bind, IN osm_madw_t * const p_madw); END_C_DECLS #endif // _OSM_BIND_H_ opensm-3.3.20/include/iba/0000755000205000001450000000000012726324777012267 500000000000000opensm-3.3.20/include/iba/ib_types.h0000644000205000001450000100223012665361573014171 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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. * */ #if !defined(__IB_TYPES_H__) #define __IB_TYPES_H__ #include #include #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS #if defined( __WIN__ ) #if defined( EXPORT_AL_SYMBOLS ) #define OSM_EXPORT __declspec(dllexport) #else #define OSM_EXPORT __declspec(dllimport) #endif #define OSM_API __stdcall #define OSM_CDECL __cdecl #else #define OSM_EXPORT extern #define OSM_API #define OSM_CDECL #define __ptr64 #endif /****h* IBA Base/Constants * NAME * Constants * * DESCRIPTION * The following constants are used throughout the IBA code base. * * Definitions are from the InfiniBand Architecture Specification v1.3.1 * *********/ /****d* IBA Base: Constants/MAD_BLOCK_SIZE * NAME * MAD_BLOCK_SIZE * * DESCRIPTION * Size of a non-RMPP MAD datagram. * * SOURCE */ #define MAD_BLOCK_SIZE 256 /**********/ /****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE * NAME * MAD_RMPP_HDR_SIZE * * DESCRIPTION * Size of an RMPP header, including the common MAD header. * * SOURCE */ #define MAD_RMPP_HDR_SIZE 36 /**********/ /****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE * NAME * MAD_RMPP_DATA_SIZE * * DESCRIPTION * Size of an RMPP transaction data section. * * SOURCE */ #define MAD_RMPP_DATA_SIZE (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE) /**********/ /****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE * NAME * MAD_BLOCK_GRH_SIZE * * DESCRIPTION * Size of a MAD datagram, including the GRH. * * SOURCE */ #define MAD_BLOCK_GRH_SIZE 296 /**********/ /****d* IBA Base: Constants/IB_LID_PERMISSIVE * NAME * IB_LID_PERMISSIVE * * DESCRIPTION * Permissive LID * * SOURCE */ #define IB_LID_PERMISSIVE 0xFFFF /**********/ /****d* IBA Base: Constants/IB_DEFAULT_PKEY * NAME * IB_DEFAULT_PKEY * * DESCRIPTION * P_Key value for the default partition. * * SOURCE */ #define IB_DEFAULT_PKEY 0xFFFF /**********/ /****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY * NAME * IB_QP1_WELL_KNOWN_Q_KEY * * DESCRIPTION * Well-known Q_Key for QP1 privileged mode access (15.4.2). * * SOURCE */ #define IB_QP1_WELL_KNOWN_Q_KEY CL_HTON32(0x80010000) /*********/ #define IB_QP0 0 #define IB_QP1 CL_HTON32(1) #define IB_QP_PRIVILEGED_Q_KEY CL_HTON32(0x80000000) /****d* IBA Base: Constants/IB_LID_UCAST_START * NAME * IB_LID_UCAST_START * * DESCRIPTION * Lowest valid unicast LID value. * * SOURCE */ #define IB_LID_UCAST_START_HO 0x0001 #define IB_LID_UCAST_START (CL_HTON16(IB_LID_UCAST_START_HO)) /**********/ /****d* IBA Base: Constants/IB_LID_UCAST_END * NAME * IB_LID_UCAST_END * * DESCRIPTION * Highest valid unicast LID value. * * SOURCE */ #define IB_LID_UCAST_END_HO 0xBFFF #define IB_LID_UCAST_END (CL_HTON16(IB_LID_UCAST_END_HO)) /**********/ /****d* IBA Base: Constants/IB_LID_MCAST_START * NAME * IB_LID_MCAST_START * * DESCRIPTION * Lowest valid multicast LID value. * * SOURCE */ #define IB_LID_MCAST_START_HO 0xC000 #define IB_LID_MCAST_START (CL_HTON16(IB_LID_MCAST_START_HO)) /**********/ /****d* IBA Base: Constants/IB_LID_MCAST_END * NAME * IB_LID_MCAST_END * * DESCRIPTION * Highest valid multicast LID value. * * SOURCE */ #define IB_LID_MCAST_END_HO 0xFFFE #define IB_LID_MCAST_END (CL_HTON16(IB_LID_MCAST_END_HO)) /**********/ /****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX * NAME * IB_DEFAULT_SUBNET_PREFIX * * DESCRIPTION * Default subnet GID prefix. * * SOURCE */ #define IB_DEFAULT_SUBNET_PREFIX (CL_HTON64(0xFE80000000000000ULL)) #define IB_DEFAULT_SUBNET_PREFIX_HO (0xFE80000000000000ULL) /**********/ /****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX * NAME * IB_NODE_NUM_PORTS_MAX * * DESCRIPTION * Maximum number of ports in a single node (14.2.5.7). * SOURCE */ #define IB_NODE_NUM_PORTS_MAX 0xFE /**********/ /****d* IBA Base: Constants/IB_INVALID_PORT_NUM * NAME * IB_INVALID_PORT_NUM * * DESCRIPTION * Value used to indicate an invalid port number (14.2.5.10). * * SOURCE */ #define IB_INVALID_PORT_NUM 0xFF /*********/ /****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX * NAME * IB_SUBNET_PATH_HOPS_MAX * * DESCRIPTION * Maximum number of directed route switch hops in a subnet (14.2.1.2). * * SOURCE */ #define IB_SUBNET_PATH_HOPS_MAX 64 /*********/ /****d* IBA Base: Constants/IB_HOPLIMIT_MAX * NAME * IB_HOPLIMIT_MAX * * DESCRIPTION * Maximum number of router hops allowed. * * SOURCE */ #define IB_HOPLIMIT_MAX 255 /*********/ /****d* IBA Base: Constants/IB_MC_SCOPE_* * NAME * IB_MC_SCOPE_* * * DESCRIPTION * Scope component definitions from IBA 1.2.1 (Table 3 p. 148) */ #define IB_MC_SCOPE_LINK_LOCAL 0x2 #define IB_MC_SCOPE_SITE_LOCAL 0x5 #define IB_MC_SCOPE_ORG_LOCAL 0x8 #define IB_MC_SCOPE_GLOBAL 0xE /*********/ /****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS * NAME * IB_PKEY_MAX_BLOCKS * * DESCRIPTION * Maximum number of PKEY blocks (14.2.5.7). * * SOURCE */ #define IB_PKEY_MAX_BLOCKS 2048 /*********/ /****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID * NAME * IB_MCAST_MAX_BLOCK_ID * * DESCRIPTION * Maximum number of Multicast port mask blocks * * SOURCE */ #define IB_MCAST_MAX_BLOCK_ID 511 /*********/ /****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO * NAME * IB_MCAST_BLOCK_ID_MASK_HO * * DESCRIPTION * Mask (host order) to recover the Multicast block ID. * * SOURCE */ #define IB_MCAST_BLOCK_ID_MASK_HO 0x000001FF /*********/ /****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE * NAME * IB_MCAST_BLOCK_SIZE * * DESCRIPTION * Number of port mask entries in a multicast forwarding table block. * * SOURCE */ #define IB_MCAST_BLOCK_SIZE 32 /*********/ /****d* IBA Base: Constants/IB_MCAST_MASK_SIZE * NAME * IB_MCAST_MASK_SIZE * * DESCRIPTION * Number of port mask bits in each entry in the multicast forwarding table. * * SOURCE */ #define IB_MCAST_MASK_SIZE 16 /*********/ /****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO * NAME * IB_MCAST_POSITION_MASK_HO * * DESCRIPTION * Mask (host order) to recover the multicast block position. * * SOURCE */ #define IB_MCAST_POSITION_MASK_HO 0xF0000000 /*********/ /****d* IBA Base: Constants/IB_MCAST_POSITION_MAX * NAME * IB_MCAST_POSITION_MAX * * DESCRIPTION * Maximum value for the multicast block position. * * SOURCE */ #define IB_MCAST_POSITION_MAX 0xF /*********/ /****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT * NAME * IB_MCAST_POSITION_SHIFT * * DESCRIPTION * Shift value to normalize the multicast block position value. * * SOURCE */ #define IB_MCAST_POSITION_SHIFT 28 /*********/ /****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX * NAME * IB_PKEY_ENTRIES_MAX * * DESCRIPTION * Maximum number of PKEY entries per port (14.2.5.7). * * SOURCE */ #define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK) /*********/ /****d* IBA Base: Constants/IB_PKEY_BASE_MASK * NAME * IB_PKEY_BASE_MASK * * DESCRIPTION * Masks for the base P_Key value given a P_Key Entry. * * SOURCE */ #define IB_PKEY_BASE_MASK (CL_HTON16(0x7FFF)) /*********/ /****d* IBA Base: Constants/IB_PKEY_TYPE_MASK * NAME * IB_PKEY_TYPE_MASK * * DESCRIPTION * Masks for the P_Key membership type given a P_Key Entry. * * SOURCE */ #define IB_PKEY_TYPE_MASK (CL_HTON16(0x8000)) /*********/ /****d* IBA Base: Constants/IB_DEFAULT_PARTIAL_PKEY * NAME * IB_DEFAULT_PARTIAL_PKEY * * DESCRIPTION * 0x7FFF in network order * * SOURCE */ #define IB_DEFAULT_PARTIAL_PKEY (CL_HTON16(0x7FFF)) /**********/ /****d* IBA Base: Constants/IB_MCLASS_SUBN_LID * NAME * IB_MCLASS_SUBN_LID * * DESCRIPTION * Subnet Management Class, Subnet Manager LID routed (13.4.4) * * SOURCE */ #define IB_MCLASS_SUBN_LID 0x01 /**********/ /****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR * NAME * IB_MCLASS_SUBN_DIR * * DESCRIPTION * Subnet Management Class, Subnet Manager directed route (13.4.4) * * SOURCE */ #define IB_MCLASS_SUBN_DIR 0x81 /**********/ /****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM * NAME * IB_MCLASS_SUBN_ADM * * DESCRIPTION * Management Class, Subnet Administration (13.4.4) * * SOURCE */ #define IB_MCLASS_SUBN_ADM 0x03 /**********/ /****d* IBA Base: Constants/IB_MCLASS_PERF * NAME * IB_MCLASS_PERF * * DESCRIPTION * Management Class, Performance Management (13.4.4) * * SOURCE */ #define IB_MCLASS_PERF 0x04 /**********/ /****d* IBA Base: Constants/IB_MCLASS_BM * NAME * IB_MCLASS_BM * * DESCRIPTION * Management Class, Baseboard Management (13.4.4) * * SOURCE */ #define IB_MCLASS_BM 0x05 /**********/ /****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT * NAME * IB_MCLASS_DEV_MGMT * * DESCRIPTION * Management Class, Device Management (13.4.4) * * SOURCE */ #define IB_MCLASS_DEV_MGMT 0x06 /**********/ /****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT * NAME * IB_MCLASS_COMM_MGMT * * DESCRIPTION * Management Class, Communication Management (13.4.4) * * SOURCE */ #define IB_MCLASS_COMM_MGMT 0x07 /**********/ /****d* IBA Base: Constants/IB_MCLASS_SNMP * NAME * IB_MCLASS_SNMP * * DESCRIPTION * Management Class, SNMP Tunneling (13.4.4) * * SOURCE */ #define IB_MCLASS_SNMP 0x08 /**********/ /****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN * NAME * IB_MCLASS_VENDOR_LOW_RANGE_MIN * * DESCRIPTION * Management Class, Vendor Specific Low Range Start * * SOURCE */ #define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09 /**********/ /****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX * NAME * IB_MCLASS_VENDOR_LOW_RANGE_MAX * * DESCRIPTION * Management Class, Vendor Specific Low Range End * * SOURCE */ #define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0F /**********/ /****d* IBA Base: Constants/IB_MCLASS_DEV_ADM * NAME * IB_MCLASS_DEV_ADM * * DESCRIPTION * Management Class, Device Administration * * SOURCE */ #define IB_MCLASS_DEV_ADM 0x10 /**********/ /****d* IBA Base: Constants/IB_MCLASS_BIS * NAME * IB_MCLASS_BIS * * DESCRIPTION * Management Class, BIS * * SOURCE */ #define IB_MCLASS_BIS 0x12 /**********/ /****d* IBA Base: Constants/IB_MCLASS_CC * NAME * IB_MCLASS_CC * * DESCRIPTION * Management Class, Congestion Control (A10.4.1) * * SOURCE */ #define IB_MCLASS_CC 0x21 /**********/ /****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN * NAME * IB_MCLASS_VENDOR_HIGH_RANGE_MIN * * DESCRIPTION * Management Class, Vendor Specific High Range Start * * SOURCE */ #define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30 /**********/ /****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX * NAME * IB_MCLASS_VENDOR_HIGH_RANGE_MAX * * DESCRIPTION * Management Class, Vendor Specific High Range End * * SOURCE */ #define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4F /**********/ /****f* IBA Base: Types/ib_class_is_vendor_specific_low * NAME * ib_class_is_vendor_specific_low * * DESCRIPTION * Indicates if the Class Code if a vendor specific class from * the low range * * SYNOPSIS */ static inline boolean_t OSM_API ib_class_is_vendor_specific_low(IN const uint8_t class_code) { return ((class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) && (class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX)); } /* * PARAMETERS * class_code * [in] The Management Datagram Class Code * * RETURN VALUE * TRUE if the class is in the Low range of Vendor Specific MADs * FALSE otherwise. * * NOTES * * SEE ALSO * IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX *********/ /****f* IBA Base: Types/ib_class_is_vendor_specific_high * NAME * ib_class_is_vendor_specific_high * * DESCRIPTION * Indicates if the Class Code if a vendor specific class from * the high range * * SYNOPSIS */ static inline boolean_t OSM_API ib_class_is_vendor_specific_high(IN const uint8_t class_code) { return ((class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) && (class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX)); } /* * PARAMETERS * class_code * [in] The Management Datagram Class Code * * RETURN VALUE * TRUE if the class is in the High range of Vendor Specific MADs * FALSE otherwise. * * NOTES * * SEE ALSO * IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX *********/ /****f* IBA Base: Types/ib_class_is_vendor_specific * NAME * ib_class_is_vendor_specific * * DESCRIPTION * Indicates if the Class Code if a vendor specific class * * SYNOPSIS */ static inline boolean_t OSM_API ib_class_is_vendor_specific(IN const uint8_t class_code) { return (ib_class_is_vendor_specific_low(class_code) || ib_class_is_vendor_specific_high(class_code)); } /* * PARAMETERS * class_code * [in] The Management Datagram Class Code * * RETURN VALUE * TRUE if the class is a Vendor Specific MAD * FALSE otherwise. * * NOTES * * SEE ALSO * ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high *********/ /****f* IBA Base: Types/ib_class_is_rmpp * NAME * ib_class_is_rmpp * * DESCRIPTION * Indicates if the Class Code supports RMPP * * SYNOPSIS */ static inline boolean_t OSM_API ib_class_is_rmpp(IN const uint8_t class_code) { return ((class_code == IB_MCLASS_SUBN_ADM) || (class_code == IB_MCLASS_DEV_MGMT) || (class_code == IB_MCLASS_DEV_ADM) || (class_code == IB_MCLASS_BIS) || ib_class_is_vendor_specific_high(class_code)); } /* * PARAMETERS * class_code * [in] The Management Datagram Class Code * * RETURN VALUE * TRUE if the class supports RMPP * FALSE otherwise. * * NOTES * *********/ /* * MAD methods */ /****d* IBA Base: Constants/IB_MAX_METHOD * NAME * IB_MAX_METHOD * * DESCRIPTION * Total number of methods available to a class, not including the R-bit. * * SOURCE */ #define IB_MAX_METHODS 128 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK * NAME * IB_MAD_METHOD_RESP_MASK * * DESCRIPTION * Response mask to extract 'R' bit from the method field. (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_RESP_MASK 0x80 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_GET * NAME * IB_MAD_METHOD_GET * * DESCRIPTION * Get() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_GET 0x01 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_SET * NAME * IB_MAD_METHOD_SET * * DESCRIPTION * Set() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_SET 0x02 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP * NAME * IB_MAD_METHOD_GET_RESP * * DESCRIPTION * GetResp() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_GET_RESP 0x81 /**********/ #define IB_MAD_METHOD_DELETE 0x15 /****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE * NAME * IB_MAD_METHOD_GETTABLE * * DESCRIPTION * SubnAdmGetTable() Method (15.2.2) * * SOURCE */ #define IB_MAD_METHOD_GETTABLE 0x12 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP * NAME * IB_MAD_METHOD_GETTABLE_RESP * * DESCRIPTION * SubnAdmGetTableResp() Method (15.2.2) * * SOURCE */ #define IB_MAD_METHOD_GETTABLE_RESP 0x92 /**********/ #define IB_MAD_METHOD_GETTRACETABLE 0x13 #define IB_MAD_METHOD_GETMULTI 0x14 #define IB_MAD_METHOD_GETMULTI_RESP 0x94 /****d* IBA Base: Constants/IB_MAD_METHOD_SEND * NAME * IB_MAD_METHOD_SEND * * DESCRIPTION * Send() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_SEND 0x03 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_TRAP * NAME * IB_MAD_METHOD_TRAP * * DESCRIPTION * Trap() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_TRAP 0x05 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_REPORT * NAME * IB_MAD_METHOD_REPORT * * DESCRIPTION * Report() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_REPORT 0x06 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP * NAME * IB_MAD_METHOD_REPORT_RESP * * DESCRIPTION * ReportResp() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_REPORT_RESP 0x86 /**********/ /****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS * NAME * IB_MAD_METHOD_TRAP_REPRESS * * DESCRIPTION * TrapRepress() Method (13.4.5) * * SOURCE */ #define IB_MAD_METHOD_TRAP_REPRESS 0x07 /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_BUSY * NAME * IB_MAD_STATUS_BUSY * * DESCRIPTION * Temporarily busy, MAD discarded (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_BUSY (CL_HTON16(0x0001)) /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT * NAME * IB_MAD_STATUS_REDIRECT * * DESCRIPTION * QP Redirection required (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_REDIRECT (CL_HTON16(0x0002)) /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER * NAME * IB_MAD_STATUS_UNSUP_CLASS_VER * * DESCRIPTION * Unsupported class version (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_UNSUP_CLASS_VER (CL_HTON16(0x0004)) /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD * NAME * IB_MAD_STATUS_UNSUP_METHOD * * DESCRIPTION * Unsupported method (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_UNSUP_METHOD (CL_HTON16(0x0008)) /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR * NAME * IB_MAD_STATUS_UNSUP_METHOD_ATTR * * DESCRIPTION * Unsupported method/attribute combination (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_UNSUP_METHOD_ATTR (CL_HTON16(0x000C)) /**********/ /****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD * NAME * IB_MAD_STATUS_INVALID_FIELD * * DESCRIPTION * Attribute contains one or more invalid fields (13.4.7) * * SOURCE */ #define IB_MAD_STATUS_INVALID_FIELD (CL_HTON16(0x001C)) /**********/ #define IB_MAD_STATUS_CLASS_MASK (CL_HTON16(0xFF00)) #define IB_SA_MAD_STATUS_SUCCESS (CL_HTON16(0x0000)) #define IB_SA_MAD_STATUS_NO_RESOURCES (CL_HTON16(0x0100)) #define IB_SA_MAD_STATUS_REQ_INVALID (CL_HTON16(0x0200)) #define IB_SA_MAD_STATUS_NO_RECORDS (CL_HTON16(0x0300)) #define IB_SA_MAD_STATUS_TOO_MANY_RECORDS (CL_HTON16(0x0400)) #define IB_SA_MAD_STATUS_INVALID_GID (CL_HTON16(0x0500)) #define IB_SA_MAD_STATUS_INSUF_COMPS (CL_HTON16(0x0600)) #define IB_SA_MAD_STATUS_DENIED (CL_HTON16(0x0700)) #define IB_SA_MAD_STATUS_PRIO_SUGGESTED (CL_HTON16(0x0800)) #define IB_DM_MAD_STATUS_NO_IOC_RESP (CL_HTON16(0x0100)) #define IB_DM_MAD_STATUS_NO_SVC_ENTRIES (CL_HTON16(0x0200)) #define IB_DM_MAD_STATUS_IOC_FAILURE (CL_HTON16(0x8000)) /****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO * NAME * IB_MAD_ATTR_CLASS_PORT_INFO * * DESCRIPTION * ClassPortInfo attribute (13.4.8) * * SOURCE */ #define IB_MAD_ATTR_CLASS_PORT_INFO (CL_HTON16(0x0001)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE * NAME * IB_MAD_ATTR_NOTICE * * DESCRIPTION * Notice attribute (13.4.8) * * SOURCE */ #define IB_MAD_ATTR_NOTICE (CL_HTON16(0x0002)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO * NAME * IB_MAD_ATTR_INFORM_INFO * * DESCRIPTION * InformInfo attribute (13.4.8) * * SOURCE */ #define IB_MAD_ATTR_INFORM_INFO (CL_HTON16(0x0003)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC * NAME * IB_MAD_ATTR_NODE_DESC * * DESCRIPTION * NodeDescription attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_NODE_DESC (CL_HTON16(0x0010)) /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL * NAME * IB_MAD_ATTR_PORT_SMPL_CTRL * * DESCRIPTION * PortSamplesControl attribute (16.1.3) * * SOURCE */ #define IB_MAD_ATTR_PORT_SMPL_CTRL (CL_HTON16(0x0010)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO * NAME * IB_MAD_ATTR_NODE_INFO * * DESCRIPTION * NodeInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_NODE_INFO (CL_HTON16(0x0011)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT * NAME * IB_MAD_ATTR_PORT_SMPL_RSLT * * DESCRIPTION * PortSamplesResult attribute (16.1.3) * * SOURCE */ #define IB_MAD_ATTR_PORT_SMPL_RSLT (CL_HTON16(0x0011)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO * NAME * IB_MAD_ATTR_SWITCH_INFO * * DESCRIPTION * SwitchInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_SWITCH_INFO (CL_HTON16(0x0012)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS * NAME * IB_MAD_ATTR_PORT_CNTRS * * DESCRIPTION * PortCounters attribute (16.1.3) * * SOURCE */ #define IB_MAD_ATTR_PORT_CNTRS (CL_HTON16(0x0012)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS_EXT * NAME * IB_MAD_ATTR_PORT_CNTRS_EXT * * DESCRIPTION * PortCountersExtended attribute (16.1.4) * * SOURCE */ #define IB_MAD_ATTR_PORT_CNTRS_EXT (CL_HTON16(0x001D)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_XMIT_DATA_SL * NAME * IB_MAD_ATTR_PORT_XMIT_DATA_SL * * DESCRIPTION * PortXmitDataSL attribute (A13.6.4) * * SOURCE */ #define IB_MAD_ATTR_PORT_XMIT_DATA_SL (CL_HTON16(0x0036)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_RCV_DATA_SL * NAME * IB_MAD_ATTR_PORT_RCV_DATA_SL * * DESCRIPTION * PortRcvDataSL attribute (A13.6.4) * * SOURCE */ #define IB_MAD_ATTR_PORT_RCV_DATA_SL (CL_HTON16(0x0037)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO * NAME * IB_MAD_ATTR_GUID_INFO * * DESCRIPTION * GUIDInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_GUID_INFO (CL_HTON16(0x0014)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO * NAME * IB_MAD_ATTR_PORT_INFO * * DESCRIPTION * PortInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_PORT_INFO (CL_HTON16(0x0015)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE * NAME * IB_MAD_ATTR_P_KEY_TABLE * * DESCRIPTION * PartitionTable attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_P_KEY_TABLE (CL_HTON16(0x0016)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE * NAME * IB_MAD_ATTR_SLVL_TABLE * * DESCRIPTION * SL VL Mapping Table attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_SLVL_TABLE (CL_HTON16(0x0017)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION * NAME * IB_MAD_ATTR_VL_ARBITRATION * * DESCRIPTION * VL Arbitration Table attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_VL_ARBITRATION (CL_HTON16(0x0018)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL * NAME * IB_MAD_ATTR_LIN_FWD_TBL * * DESCRIPTION * Switch linear forwarding table * * SOURCE */ #define IB_MAD_ATTR_LIN_FWD_TBL (CL_HTON16(0x0019)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL * NAME * IB_MAD_ATTR_RND_FWD_TBL * * DESCRIPTION * Switch random forwarding table * * SOURCE */ #define IB_MAD_ATTR_RND_FWD_TBL (CL_HTON16(0x001A)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL * NAME * IB_MAD_ATTR_MCAST_FWD_TBL * * DESCRIPTION * Switch multicast forwarding table * * SOURCE */ #define IB_MAD_ATTR_MCAST_FWD_TBL (CL_HTON16(0x001B)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD * NAME * IB_MAD_ATTR_NODE_RECORD * * DESCRIPTION * NodeRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_NODE_RECORD (CL_HTON16(0x0011)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD * NAME * IB_MAD_ATTR_PORTINFO_RECORD * * DESCRIPTION * PortInfoRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_PORTINFO_RECORD (CL_HTON16(0x0012)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO_RECORD * NAME * IB_MAD_ATTR_SWITCH_INFO_RECORD * * DESCRIPTION * SwitchInfoRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SWITCH_INFO_RECORD (CL_HTON16(0x0014)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD * NAME * IB_MAD_ATTR_LINK_RECORD * * DESCRIPTION * LinkRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_LINK_RECORD (CL_HTON16(0x0020)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO * NAME * IB_MAD_ATTR_SM_INFO * * DESCRIPTION * SMInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_SM_INFO (CL_HTON16(0x0020)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD * NAME * IB_MAD_ATTR_SMINFO_RECORD * * DESCRIPTION * SMInfoRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SMINFO_RECORD (CL_HTON16(0x0018)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_GUIDINFO_RECORD * NAME * IB_MAD_ATTR_GUIDINFO_RECORD * * DESCRIPTION * GuidInfoRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_GUIDINFO_RECORD (CL_HTON16(0x0030)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG * NAME * IB_MAD_ATTR_VENDOR_DIAG * * DESCRIPTION * VendorDiag attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_VENDOR_DIAG (CL_HTON16(0x0030)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO * NAME * IB_MAD_ATTR_LED_INFO * * DESCRIPTION * LedInfo attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_LED_INFO (CL_HTON16(0x0031)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO * NAME * IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO * * DESCRIPTION * Vendor specific SM attribute (14.2.5) * * SOURCE */ #define IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO (CL_HTON16(0xFF90)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD * NAME * IB_MAD_ATTR_SERVICE_RECORD * * DESCRIPTION * ServiceRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SERVICE_RECORD (CL_HTON16(0x0031)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD * NAME * IB_MAD_ATTR_LFT_RECORD * * DESCRIPTION * LinearForwardingTableRecord attribute (15.2.5.6) * * SOURCE */ #define IB_MAD_ATTR_LFT_RECORD (CL_HTON16(0x0015)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_MFT_RECORD * NAME * IB_MAD_ATTR_MFT_RECORD * * DESCRIPTION * MulticastForwardingTableRecord attribute (15.2.5.8) * * SOURCE */ #define IB_MAD_ATTR_MFT_RECORD (CL_HTON16(0x0017)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD * NAME * IB_MAD_ATTR_PKEYTBL_RECORD * * DESCRIPTION * PKEY Table Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_PKEY_TBL_RECORD (CL_HTON16(0x0033)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD * NAME * IB_MAD_ATTR_PATH_RECORD * * DESCRIPTION * PathRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_PATH_RECORD (CL_HTON16(0x0035)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD * NAME * IB_MAD_ATTR_VLARB_RECORD * * DESCRIPTION * VL Arbitration Table Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_VLARB_RECORD (CL_HTON16(0x0036)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD * NAME * IB_MAD_ATTR_SLVL_RECORD * * DESCRIPTION * SLtoVL Mapping Table Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SLVL_RECORD (CL_HTON16(0x0013)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD * NAME * IB_MAD_ATTR_MCMEMBER_RECORD * * DESCRIPTION * MCMemberRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_MCMEMBER_RECORD (CL_HTON16(0x0038)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD * NAME * IB_MAD_ATTR_TRACE_RECORD * * DESCRIPTION * TraceRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_TRACE_RECORD (CL_HTON16(0x0039)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD * NAME * IB_MAD_ATTR_MULTIPATH_RECORD * * DESCRIPTION * MultiPathRecord attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_MULTIPATH_RECORD (CL_HTON16(0x003A)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD * NAME * IB_MAD_ATTR_SVC_ASSOCIATION_RECORD * * DESCRIPTION * Service Association Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_HTON16(0x003B)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO_RECORD * NAME * IB_MAD_ATTR_INFORM_INFO_RECORD * * DESCRIPTION * InformInfo Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_INFORM_INFO_RECORD (CL_HTON16(0x00F3)) /****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO * NAME * IB_MAD_ATTR_IO_UNIT_INFO * * DESCRIPTION * IOUnitInfo attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_IO_UNIT_INFO (CL_HTON16(0x0010)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE * NAME * IB_MAD_ATTR_IO_CONTROLLER_PROFILE * * DESCRIPTION * IOControllerProfile attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_IO_CONTROLLER_PROFILE (CL_HTON16(0x0011)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES * NAME * IB_MAD_ATTR_SERVICE_ENTRIES * * DESCRIPTION * ServiceEntries attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_SERVICE_ENTRIES (CL_HTON16(0x0012)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT * NAME * IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT * * DESCRIPTION * DiagnosticTimeout attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT (CL_HTON16(0x0020)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST * NAME * IB_MAD_ATTR_PREPARE_TO_TEST * * DESCRIPTION * PrepareToTest attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_PREPARE_TO_TEST (CL_HTON16(0x0021)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE * NAME * IB_MAD_ATTR_TEST_DEVICE_ONCE * * DESCRIPTION * TestDeviceOnce attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_TEST_DEVICE_ONCE (CL_HTON16(0x0022)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP * NAME * IB_MAD_ATTR_TEST_DEVICE_LOOP * * DESCRIPTION * TestDeviceLoop attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_TEST_DEVICE_LOOP (CL_HTON16(0x0023)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE * NAME * IB_MAD_ATTR_DIAG_CODE * * DESCRIPTION * DiagCode attribute (16.3.3) * * SOURCE */ #define IB_MAD_ATTR_DIAG_CODE (CL_HTON16(0x0024)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD * NAME * IB_MAD_ATTR_SVC_ASSOCIATION_RECORD * * DESCRIPTION * Service Association Record attribute (15.2.5) * * SOURCE */ #define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_HTON16(0x003B)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_CONG_INFO * NAME * IB_MAD_ATTR_CONG_INFO * * DESCRIPTION * CongestionInfo attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_CONG_INFO (CL_HTON16(0x0011)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_CONG_KEY_INFO * NAME * IB_MAD_ATTR_CONG_KEY_INFO * * DESCRIPTION * CongestionKeyInfo attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_CONG_KEY_INFO (CL_HTON16(0x0012)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_CONG_LOG * NAME * IB_MAD_ATTR_CONG_LOG * * DESCRIPTION * CongestionLog attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_CONG_LOG (CL_HTON16(0x0013)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SW_CONG_SETTING * NAME * IB_MAD_ATTR_SW_CONG_SETTING * * DESCRIPTION * SwitchCongestionSetting attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_SW_CONG_SETTING (CL_HTON16(0x0014)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_SW_PORT_CONG_SETTING * NAME * IB_MAD_ATTR_SW_PORT_CONG_SETTING * * DESCRIPTION * SwitchPortCongestionSetting attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_SW_PORT_CONG_SETTING (CL_HTON16(0x0015)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_CA_CONG_SETTING * NAME * IB_MAD_ATTR_CA_CONG_SETTING * * DESCRIPTION * CACongestionSetting attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_CA_CONG_SETTING (CL_HTON16(0x0016)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_CC_TBL * NAME * IB_MAD_ATTR_CC_TBL * * DESCRIPTION * CongestionControlTable attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_CC_TBL (CL_HTON16(0x0017)) /**********/ /****d* IBA Base: Constants/IB_MAD_ATTR_TIME_STAMP * NAME * IB_MAD_ATTR_TIME_STAMP * * DESCRIPTION * TimeStamp attribute (A10.4.3) * * SOURCE */ #define IB_MAD_ATTR_TIME_STAMP (CL_HTON16(0x0018)) /**********/ /****d* IBA Base: Constants/IB_NODE_TYPE_CA * NAME * IB_NODE_TYPE_CA * * DESCRIPTION * Encoded generic node type used in MAD attributes (13.4.8.2) * * SOURCE */ #define IB_NODE_TYPE_CA 0x01 /**********/ /****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH * NAME * IB_NODE_TYPE_SWITCH * * DESCRIPTION * Encoded generic node type used in MAD attributes (13.4.8.2) * * SOURCE */ #define IB_NODE_TYPE_SWITCH 0x02 /**********/ /****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER * NAME * IB_NODE_TYPE_ROUTER * * DESCRIPTION * Encoded generic node type used in MAD attributes (13.4.8.2) * * SOURCE */ #define IB_NODE_TYPE_ROUTER 0x03 /**********/ /****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_CA * NAME * IB_NOTICE_PRODUCER_TYPE_CA * * DESCRIPTION * Encoded generic producer type used in Notice attribute (13.4.8.2) * * SOURCE */ #define IB_NOTICE_PRODUCER_TYPE_CA (CL_HTON32(0x000001)) /**********/ /****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_SWITCH * NAME * IB_NOTICE_PRODUCER_TYPE_SWITCH * * DESCRIPTION * Encoded generic producer type used in Notice attribute (13.4.8.2) * * SOURCE */ #define IB_NOTICE_PRODUCER_TYPE_SWITCH (CL_HTON32(0x000002)) /**********/ /****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_ROUTER * NAME * IB_NOTICE_PRODUCER_TYPE_ROUTER * * DESCRIPTION * Encoded generic producer type used in Notice attribute (13.4.8.2) * * SOURCE */ #define IB_NOTICE_PRODUCER_TYPE_ROUTER (CL_HTON32(0x000003)) /**********/ /****d* IBA Base: Constants/IB_NOTICE_PRODUCER_TYPE_CLASS_MGR * NAME * IB_NOTICE_PRODUCER_TYPE_CLASS_MGR * * DESCRIPTION * Encoded generic producer type used in Notice attribute (13.4.8.2) * * SOURCE */ #define IB_NOTICE_PRODUCER_TYPE_CLASS_MGR (CL_HTON32(0x000004)) /**********/ /****d* IBA Base: Constants/IB_MTU_LEN_TYPE * NAME * IB_MTU_LEN_TYPE * * DESCRIPTION * Encoded path MTU. * 1: 256 * 2: 512 * 3: 1024 * 4: 2048 * 5: 4096 * others: reserved * * SOURCE */ #define IB_MTU_LEN_256 1 #define IB_MTU_LEN_512 2 #define IB_MTU_LEN_1024 3 #define IB_MTU_LEN_2048 4 #define IB_MTU_LEN_4096 5 #define IB_MIN_MTU IB_MTU_LEN_256 #define IB_MAX_MTU IB_MTU_LEN_4096 /**********/ /****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE * NAME * IB_PATH_SELECTOR_TYPE * * DESCRIPTION * Path selector. * 0: greater than specified * 1: less than specified * 2: exactly the specified * 3: largest available * * SOURCE */ #define IB_PATH_SELECTOR_GREATER_THAN 0 #define IB_PATH_SELECTOR_LESS_THAN 1 #define IB_PATH_SELECTOR_EXACTLY 2 #define IB_PATH_SELECTOR_LARGEST 3 /**********/ /****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE * NAME * IB_SMINFO_STATE_NOTACTIVE * * DESCRIPTION * Encoded state value used in the SMInfo attribute. * * SOURCE */ #define IB_SMINFO_STATE_NOTACTIVE 0 /**********/ /****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING * NAME * IB_SMINFO_STATE_DISCOVERING * * DESCRIPTION * Encoded state value used in the SMInfo attribute. * * SOURCE */ #define IB_SMINFO_STATE_DISCOVERING 1 /**********/ /****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY * NAME * IB_SMINFO_STATE_STANDBY * * DESCRIPTION * Encoded state value used in the SMInfo attribute. * * SOURCE */ #define IB_SMINFO_STATE_STANDBY 2 /**********/ /****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER * NAME * IB_SMINFO_STATE_MASTER * * DESCRIPTION * Encoded state value used in the SMInfo attribute. * * SOURCE */ #define IB_SMINFO_STATE_MASTER 3 /**********/ /****d* IBA Base: Constants/IB_PATH_REC_SL_MASK * NAME * IB_PATH_REC_SL_MASK * * DESCRIPTION * Mask for the sl field for path record * * SOURCE */ #define IB_PATH_REC_SL_MASK 0x000F /****d* IBA Base: Constants/IB_MULTIPATH_REC_SL_MASK * NAME * IB_MULTIPATH_REC_SL_MASK * * DESCRIPTION * Mask for the sl field for MultiPath record * * SOURCE */ #define IB_MULTIPATH_REC_SL_MASK 0x000F /****d* IBA Base: Constants/IB_PATH_REC_QOS_CLASS_MASK * NAME * IB_PATH_REC_QOS_CLASS_MASK * * DESCRIPTION * Mask for the QoS class field for path record * * SOURCE */ #define IB_PATH_REC_QOS_CLASS_MASK 0xFFF0 /****d* IBA Base: Constants/IB_MULTIPATH_REC_QOS_CLASS_MASK * NAME * IB_MULTIPATH_REC_QOS_CLASS_MASK * * DESCRIPTION * Mask for the QoS class field for MultiPath record * * SOURCE */ #define IB_MULTIPATH_REC_QOS_CLASS_MASK 0xFFF0 /****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK * NAME * IB_PATH_REC_SELECTOR_MASK * * DESCRIPTION * Mask for the selector field for path record MTU, rate, * and packet lifetime. * * SOURCE */ #define IB_PATH_REC_SELECTOR_MASK 0xC0 /****d* IBA Base: Constants/IB_MULTIPATH_REC_SELECTOR_MASK * NAME * IB_MULTIPATH_REC_SELECTOR_MASK * * DESCRIPTION * Mask for the selector field for multipath record MTU, rate, * and packet lifetime. * * SOURCE */ #define IB_MULTIPATH_REC_SELECTOR_MASK 0xC0 /**********/ /****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK * NAME * IB_PATH_REC_BASE_MASK * * DESCRIPTION * Mask for the base value field for path record MTU, rate, * and packet lifetime. * * SOURCE */ #define IB_PATH_REC_BASE_MASK 0x3F /**********/ /****d* IBA Base: Constants/IB_MULTIPATH_REC_BASE_MASK * NAME * IB_MULTIPATH_REC_BASE_MASK * * DESCRIPTION * Mask for the base value field for multipath record MTU, rate, * and packet lifetime. * * SOURCE */ #define IB_MULTIPATH_REC_BASE_MASK 0x3F /**********/ /****h* IBA Base/Type Definitions * NAME * Type Definitions * * DESCRIPTION * Definitions are from the InfiniBand Architecture Specification v1.2 * *********/ /****d* IBA Base: Types/ib_net16_t * NAME * ib_net16_t * * DESCRIPTION * Defines the network ordered type for 16-bit values. * * SOURCE */ typedef uint16_t ib_net16_t; /**********/ /****d* IBA Base: Types/ib_net32_t * NAME * ib_net32_t * * DESCRIPTION * Defines the network ordered type for 32-bit values. * * SOURCE */ typedef uint32_t ib_net32_t; /**********/ /****d* IBA Base: Types/ib_net64_t * NAME * ib_net64_t * * DESCRIPTION * Defines the network ordered type for 64-bit values. * * SOURCE */ typedef uint64_t ib_net64_t; /**********/ /****d* IBA Base: Types/ib_gid_prefix_t * NAME * ib_gid_prefix_t * * DESCRIPTION * * SOURCE */ typedef ib_net64_t ib_gid_prefix_t; /**********/ /****d* IBA Base: Constants/ib_link_states_t * NAME * ib_link_states_t * * DESCRIPTION * Defines the link states of a port. * * SOURCE */ #define IB_LINK_NO_CHANGE 0 #define IB_LINK_DOWN 1 #define IB_LINK_INIT 2 #define IB_LINK_ARMED 3 #define IB_LINK_ACTIVE 4 #define IB_LINK_ACT_DEFER 5 /**********/ static const char *const __ib_node_type_str[] = { "UNKNOWN", "Channel Adapter", "Switch", "Router" }; /****f* IBA Base: Types/ib_get_node_type_str * NAME * ib_get_node_type_str * * DESCRIPTION * Returns a string for the specified node type. * 14.2.5.3 NodeInfo * * SYNOPSIS */ static inline const char *OSM_API ib_get_node_type_str(IN uint8_t node_type) { if (node_type > IB_NODE_TYPE_ROUTER) node_type = 0; return (__ib_node_type_str[node_type]); } /* * PARAMETERS * node_type * [in] Encoded node type as returned in the NodeInfo attribute. * RETURN VALUES * Pointer to the node type string. * * NOTES * * SEE ALSO * ib_node_info_t *********/ static const char *const __ib_producer_type_str[] = { "UNKNOWN", "Channel Adapter", "Switch", "Router", "Class Manager" }; /****f* IBA Base: Types/ib_get_producer_type_str * NAME * ib_get_producer_type_str * * DESCRIPTION * Returns a string for the specified producer type * 13.4.8.2 Notice * 13.4.8.3 InformInfo * * SYNOPSIS */ static inline const char *OSM_API ib_get_producer_type_str(IN ib_net32_t producer_type) { if (cl_ntoh32(producer_type) > CL_NTOH32(IB_NOTICE_PRODUCER_TYPE_CLASS_MGR)) producer_type = 0; return (__ib_producer_type_str[cl_ntoh32(producer_type)]); } /* * PARAMETERS * producer_type * [in] Encoded producer type from the Notice attribute * RETURN VALUES * Pointer to the producer type string. * * NOTES * * SEE ALSO * ib_notice_get_prod_type *********/ static const char *const __ib_port_state_str[] = { "No State Change (NOP)", "DOWN", "INIT", "ARMED", "ACTIVE", "ACTDEFER", "UNKNOWN" }; /****f* IBA Base: Types/ib_get_port_state_str * NAME * ib_get_port_state_str * * DESCRIPTION * Returns a string for the specified port state. * * SYNOPSIS */ static inline const char *OSM_API ib_get_port_state_str(IN uint8_t port_state) { if (port_state > IB_LINK_ACTIVE) port_state = IB_LINK_ACTIVE + 1; return (__ib_port_state_str[port_state]); } /* * PARAMETERS * port_state * [in] Encoded port state as returned in the PortInfo attribute. * RETURN VALUES * Pointer to the port state string. * * NOTES * * SEE ALSO * ib_port_info_t *********/ /****f* IBA Base: Types/ib_get_port_state_from_str * NAME * ib_get_port_state_from_str * * DESCRIPTION * Returns a string for the specified port state. * * SYNOPSIS */ static inline uint8_t OSM_API ib_get_port_state_from_str(IN char *p_port_state_str) { if (!strncmp(p_port_state_str, "No State Change (NOP)", 12)) return (0); else if (!strncmp(p_port_state_str, "DOWN", 4)) return (1); else if (!strncmp(p_port_state_str, "INIT", 4)) return (2); else if (!strncmp(p_port_state_str, "ARMED", 5)) return (3); else if (!strncmp(p_port_state_str, "ACTIVE", 6)) return (4); else if (!strncmp(p_port_state_str, "ACTDEFER", 8)) return (5); return (6); } /* * PARAMETERS * p_port_state_str * [in] A string matching one returned by ib_get_port_state_str * * RETURN VALUES * The appropriate code. * * NOTES * * SEE ALSO * ib_port_info_t *********/ /****d* IBA Base: Constants/Join States * NAME * Join States * * DESCRIPTION * Defines the join state flags for multicast group management. * * SOURCE */ #define IB_JOIN_STATE_FULL 1 #define IB_JOIN_STATE_NON 2 #define IB_JOIN_STATE_SEND_ONLY 4 /**********/ /****f* IBA Base: Types/ib_pkey_get_base * NAME * ib_pkey_get_base * * DESCRIPTION * Returns the base P_Key value with the membership bit stripped. * * SYNOPSIS */ static inline ib_net16_t OSM_API ib_pkey_get_base(IN const ib_net16_t pkey) { return ((ib_net16_t) (pkey & IB_PKEY_BASE_MASK)); } /* * PARAMETERS * pkey * [in] P_Key value * * RETURN VALUE * Returns the base P_Key value with the membership bit stripped. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_pkey_is_full_member * NAME * ib_pkey_is_full_member * * DESCRIPTION * Indicates if the port is a full member of the partition. * * SYNOPSIS */ static inline boolean_t OSM_API ib_pkey_is_full_member(IN const ib_net16_t pkey) { return ((pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK); } /* * PARAMETERS * pkey * [in] P_Key value * * RETURN VALUE * TRUE if the port is a full member of the partition. * FALSE otherwise. * * NOTES * * SEE ALSO * ib_pkey_get_base, ib_net16_t *********/ /****f* IBA Base: Types/ib_pkey_is_invalid * NAME * ib_pkey_is_invalid * * DESCRIPTION * Returns TRUE if the given P_Key is an invalid P_Key * C10-116: the CI shall regard a P_Key as invalid if its low-order * 15 bits are all zero... * * SYNOPSIS */ static inline boolean_t OSM_API ib_pkey_is_invalid(IN const ib_net16_t pkey) { return ib_pkey_get_base(pkey) == 0x0000 ? TRUE : FALSE; } /* * PARAMETERS * pkey * [in] P_Key value * * RETURN VALUE * Returns the base P_Key value with the membership bit stripped. * * NOTES * * SEE ALSO *********/ /****d* IBA Base: Types/ib_gid_t * NAME * ib_gid_t * * DESCRIPTION * * SYNOPSIS */ #include typedef union _ib_gid { uint8_t raw[16]; struct _ib_gid_unicast { ib_gid_prefix_t prefix; ib_net64_t interface_id; } PACK_SUFFIX unicast; struct _ib_gid_multicast { uint8_t header[2]; uint8_t raw_group_id[14]; } PACK_SUFFIX multicast; } PACK_SUFFIX ib_gid_t; #include /* * FIELDS * raw * GID represented as an unformated byte array. * * unicast * Typical unicast representation with subnet prefix and * port GUID. * * multicast * Representation for multicast use. * * SEE ALSO *********/ /****f* IBA Base: Types/ib_gid_is_multicast * NAME * ib_gid_is_multicast * * DESCRIPTION * Returns a boolean indicating whether a GID is a multicast GID. * * SYNOPSIS */ static inline boolean_t OSM_API ib_gid_is_multicast(IN const ib_gid_t * p_gid) { return (p_gid->raw[0] == 0xFF); } /****f* IBA Base: Types/ib_gid_get_scope * NAME * ib_gid_get_scope * * DESCRIPTION * Returns scope of (assumed) multicast GID. * * SYNOPSIS */ static inline uint8_t OSM_API ib_mgid_get_scope(IN const ib_gid_t * p_gid) { return (p_gid->raw[1] & 0x0F); } /****f* IBA Base: Types/ib_gid_set_scope * NAME * ib_gid_set_scope * * DESCRIPTION * Sets scope of (assumed) multicast GID. * * SYNOPSIS */ static inline void OSM_API ib_mgid_set_scope(IN ib_gid_t * const p_gid, IN const uint8_t scope) { p_gid->raw[1] &= 0xF0; p_gid->raw[1] |= scope & 0x0F; } /****f* IBA Base: Types/ib_gid_set_default * NAME * ib_gid_set_default * * DESCRIPTION * Sets a GID to the default value. * * SYNOPSIS */ static inline void OSM_API ib_gid_set_default(IN ib_gid_t * const p_gid, IN const ib_net64_t interface_id) { p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX; p_gid->unicast.interface_id = interface_id; } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * interface_id * [in] Manufacturer assigned EUI64 value of a port. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* IBA Base: Types/ib_gid_get_subnet_prefix * NAME * ib_gid_get_subnet_prefix * * DESCRIPTION * Gets the subnet prefix from a GID. * * SYNOPSIS */ static inline ib_net64_t OSM_API ib_gid_get_subnet_prefix(IN const ib_gid_t * const p_gid) { return (p_gid->unicast.prefix); } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * RETURN VALUES * 64-bit subnet prefix value. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* IBA Base: Types/ib_gid_is_link_local * NAME * ib_gid_is_link_local * * DESCRIPTION * Returns TRUE if the unicast GID scoping indicates link local, * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t OSM_API ib_gid_is_link_local(IN const ib_gid_t * const p_gid) { return ((ib_gid_get_subnet_prefix(p_gid) & CL_HTON64(0xFFC0000000000000ULL)) == IB_DEFAULT_SUBNET_PREFIX); } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * RETURN VALUES * Returns TRUE if the unicast GID scoping indicates link local, * FALSE otherwise. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* IBA Base: Types/ib_gid_is_site_local * NAME * ib_gid_is_site_local * * DESCRIPTION * Returns TRUE if the unicast GID scoping indicates site local, * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t OSM_API ib_gid_is_site_local(IN const ib_gid_t * const p_gid) { return ((ib_gid_get_subnet_prefix(p_gid) & CL_HTON64(0xFFFFFFFFFFFF0000ULL)) == CL_HTON64(0xFEC0000000000000ULL)); } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * RETURN VALUES * Returns TRUE if the unicast GID scoping indicates site local, * FALSE otherwise. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* IBA Base: Types/ib_gid_get_guid * NAME * ib_gid_get_guid * * DESCRIPTION * Gets the guid from a GID. * * SYNOPSIS */ static inline ib_net64_t OSM_API ib_gid_get_guid(IN const ib_gid_t * const p_gid) { return (p_gid->unicast.interface_id); } /* * PARAMETERS * p_gid * [in] Pointer to the GID object. * * RETURN VALUES * 64-bit GUID value. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****s* IBA Base: Types/ib_path_rec_t * NAME * ib_path_rec_t * * DESCRIPTION * Path records encapsulate the properties of a given * route between two end-points on a subnet. * * SYNOPSIS */ #include typedef struct _ib_path_rec { ib_net64_t service_id; ib_gid_t dgid; ib_gid_t sgid; ib_net16_t dlid; ib_net16_t slid; ib_net32_t hop_flow_raw; uint8_t tclass; uint8_t num_path; ib_net16_t pkey; ib_net16_t qos_class_sl; uint8_t mtu; uint8_t rate; uint8_t pkt_life; uint8_t preference; uint8_t resv2[6]; } PACK_SUFFIX ib_path_rec_t; #include /* * FIELDS * service_id * Service ID for QoS. * * dgid * GID of destination port. * * sgid * GID of source port. * * dlid * LID of destination port. * * slid * LID of source port. * * hop_flow_raw * Global routing parameters: hop count, flow label and raw bit. * * tclass * Another global routing parameter. * * num_path * Reversible path - 1 bit to say if path is reversible. * num_path [6:0] In queries, maximum number of paths to return. * In responses, undefined. * * pkey * Partition key (P_Key) to use on this path. * * qos_class_sl * QoS class and service level to use on this path. * * mtu * MTU and MTU selector fields to use on this path * * rate * Rate and rate selector fields to use on this path. * * pkt_life * Packet lifetime * * preference * Indicates the relative merit of this path versus other path * records returned from the SA. Lower numbers are better. * * resv2 * Reserved bytes. * SEE ALSO *********/ /* Path Record Component Masks */ #define IB_PR_COMPMASK_SERVICEID_MSB (CL_HTON64(((uint64_t)1)<<0)) #define IB_PR_COMPMASK_SERVICEID_LSB (CL_HTON64(((uint64_t)1)<<1)) #define IB_PR_COMPMASK_DGID (CL_HTON64(((uint64_t)1)<<2)) #define IB_PR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<3)) #define IB_PR_COMPMASK_DLID (CL_HTON64(((uint64_t)1)<<4)) #define IB_PR_COMPMASK_SLID (CL_HTON64(((uint64_t)1)<<5)) #define IB_PR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<6)) #define IB_PR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<7)) #define IB_PR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<8)) #define IB_PR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<9)) #define IB_PR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<10)) #define IB_PR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<11)) #define IB_PR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<12)) #define IB_PR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<13)) #define IB_PR_COMPMASK_QOS_CLASS (CL_HTON64(((uint64_t)1)<<14)) #define IB_PR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<15)) #define IB_PR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<16)) #define IB_PR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<17)) #define IB_PR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<18)) #define IB_PR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<19)) #define IB_PR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<20)) #define IB_PR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<21)) #define IB_PR_COMPMASK_SERVICEID (IB_PR_COMPMASK_SERVICEID_MSB | \ IB_PR_COMPMASK_SERVICEID_LSB) /* Link Record Component Masks */ #define IB_LR_COMPMASK_FROM_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_LR_COMPMASK_FROM_PORT (CL_HTON64(((uint64_t)1)<<1)) #define IB_LR_COMPMASK_TO_PORT (CL_HTON64(((uint64_t)1)<<2)) #define IB_LR_COMPMASK_TO_LID (CL_HTON64(((uint64_t)1)<<3)) /* VL Arbitration Record Masks */ #define IB_VLA_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_VLA_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<1)) #define IB_VLA_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<2)) /* SLtoVL Mapping Record Masks */ #define IB_SLVL_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_SLVL_COMPMASK_IN_PORT (CL_HTON64(((uint64_t)1)<<1)) #define IB_SLVL_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<2)) /* P_Key Table Record Masks */ #define IB_PKEY_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_PKEY_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1)) #define IB_PKEY_COMPMASK_PORT (CL_HTON64(((uint64_t)1)<<2)) /* Switch Info Record Masks */ #define IB_SWIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_SWIR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1)) /* LFT Record Masks */ #define IB_LFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_LFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1)) /* MFT Record Masks */ #define IB_MFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_MFTR_COMPMASK_POSITION (CL_HTON64(((uint64_t)1)<<1)) #define IB_MFTR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<2)) #define IB_MFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<3)) #define IB_MFTR_COMPMASK_RESERVED2 (CL_HTON64(((uint64_t)1)<<4)) /* NodeInfo Record Masks */ #define IB_NR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_NR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1)) #define IB_NR_COMPMASK_BASEVERSION (CL_HTON64(((uint64_t)1)<<2)) #define IB_NR_COMPMASK_CLASSVERSION (CL_HTON64(((uint64_t)1)<<3)) #define IB_NR_COMPMASK_NODETYPE (CL_HTON64(((uint64_t)1)<<4)) #define IB_NR_COMPMASK_NUMPORTS (CL_HTON64(((uint64_t)1)<<5)) #define IB_NR_COMPMASK_SYSIMAGEGUID (CL_HTON64(((uint64_t)1)<<6)) #define IB_NR_COMPMASK_NODEGUID (CL_HTON64(((uint64_t)1)<<7)) #define IB_NR_COMPMASK_PORTGUID (CL_HTON64(((uint64_t)1)<<8)) #define IB_NR_COMPMASK_PARTCAP (CL_HTON64(((uint64_t)1)<<9)) #define IB_NR_COMPMASK_DEVID (CL_HTON64(((uint64_t)1)<<10)) #define IB_NR_COMPMASK_REV (CL_HTON64(((uint64_t)1)<<11)) #define IB_NR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<12)) #define IB_NR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<13)) #define IB_NR_COMPMASK_NODEDESC (CL_HTON64(((uint64_t)1)<<14)) /* Service Record Component Masks Sec 15.2.5.14 Ver 1.1*/ #define IB_SR_COMPMASK_SID (CL_HTON64(((uint64_t)1)<<0)) #define IB_SR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<1)) #define IB_SR_COMPMASK_SPKEY (CL_HTON64(((uint64_t)1)<<2)) #define IB_SR_COMPMASK_RES1 (CL_HTON64(((uint64_t)1)<<3)) #define IB_SR_COMPMASK_SLEASE (CL_HTON64(((uint64_t)1)<<4)) #define IB_SR_COMPMASK_SKEY (CL_HTON64(((uint64_t)1)<<5)) #define IB_SR_COMPMASK_SNAME (CL_HTON64(((uint64_t)1)<<6)) #define IB_SR_COMPMASK_SDATA8_0 (CL_HTON64(((uint64_t)1)<<7)) #define IB_SR_COMPMASK_SDATA8_1 (CL_HTON64(((uint64_t)1)<<8)) #define IB_SR_COMPMASK_SDATA8_2 (CL_HTON64(((uint64_t)1)<<9)) #define IB_SR_COMPMASK_SDATA8_3 (CL_HTON64(((uint64_t)1)<<10)) #define IB_SR_COMPMASK_SDATA8_4 (CL_HTON64(((uint64_t)1)<<11)) #define IB_SR_COMPMASK_SDATA8_5 (CL_HTON64(((uint64_t)1)<<12)) #define IB_SR_COMPMASK_SDATA8_6 (CL_HTON64(((uint64_t)1)<<13)) #define IB_SR_COMPMASK_SDATA8_7 (CL_HTON64(((uint64_t)1)<<14)) #define IB_SR_COMPMASK_SDATA8_8 (CL_HTON64(((uint64_t)1)<<15)) #define IB_SR_COMPMASK_SDATA8_9 (CL_HTON64(((uint64_t)1)<<16)) #define IB_SR_COMPMASK_SDATA8_10 (CL_HTON64(((uint64_t)1)<<17)) #define IB_SR_COMPMASK_SDATA8_11 (CL_HTON64(((uint64_t)1)<<18)) #define IB_SR_COMPMASK_SDATA8_12 (CL_HTON64(((uint64_t)1)<<19)) #define IB_SR_COMPMASK_SDATA8_13 (CL_HTON64(((uint64_t)1)<<20)) #define IB_SR_COMPMASK_SDATA8_14 (CL_HTON64(((uint64_t)1)<<21)) #define IB_SR_COMPMASK_SDATA8_15 (CL_HTON64(((uint64_t)1)<<22)) #define IB_SR_COMPMASK_SDATA16_0 (CL_HTON64(((uint64_t)1)<<23)) #define IB_SR_COMPMASK_SDATA16_1 (CL_HTON64(((uint64_t)1)<<24)) #define IB_SR_COMPMASK_SDATA16_2 (CL_HTON64(((uint64_t)1)<<25)) #define IB_SR_COMPMASK_SDATA16_3 (CL_HTON64(((uint64_t)1)<<26)) #define IB_SR_COMPMASK_SDATA16_4 (CL_HTON64(((uint64_t)1)<<27)) #define IB_SR_COMPMASK_SDATA16_5 (CL_HTON64(((uint64_t)1)<<28)) #define IB_SR_COMPMASK_SDATA16_6 (CL_HTON64(((uint64_t)1)<<29)) #define IB_SR_COMPMASK_SDATA16_7 (CL_HTON64(((uint64_t)1)<<30)) #define IB_SR_COMPMASK_SDATA32_0 (CL_HTON64(((uint64_t)1)<<31)) #define IB_SR_COMPMASK_SDATA32_1 (CL_HTON64(((uint64_t)1)<<32)) #define IB_SR_COMPMASK_SDATA32_2 (CL_HTON64(((uint64_t)1)<<33)) #define IB_SR_COMPMASK_SDATA32_3 (CL_HTON64(((uint64_t)1)<<34)) #define IB_SR_COMPMASK_SDATA64_0 (CL_HTON64(((uint64_t)1)<<35)) #define IB_SR_COMPMASK_SDATA64_1 (CL_HTON64(((uint64_t)1)<<36)) /* Port Info Record Component Masks */ #define IB_PIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_PIR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<1)) #define IB_PIR_COMPMASK_OPTIONS (CL_HTON64(((uint64_t)1)<<2)) #define IB_PIR_COMPMASK_MKEY (CL_HTON64(((uint64_t)1)<<3)) #define IB_PIR_COMPMASK_GIDPRE (CL_HTON64(((uint64_t)1)<<4)) #define IB_PIR_COMPMASK_BASELID (CL_HTON64(((uint64_t)1)<<5)) #define IB_PIR_COMPMASK_SMLID (CL_HTON64(((uint64_t)1)<<6)) #define IB_PIR_COMPMASK_CAPMASK (CL_HTON64(((uint64_t)1)<<7)) #define IB_PIR_COMPMASK_DIAGCODE (CL_HTON64(((uint64_t)1)<<8)) #define IB_PIR_COMPMASK_MKEYLEASEPRD (CL_HTON64(((uint64_t)1)<<9)) #define IB_PIR_COMPMASK_LOCALPORTNUM (CL_HTON64(((uint64_t)1)<<10)) #define IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11)) #define IB_PIR_COMPMASK_LNKWIDTHSUPPORT (CL_HTON64(((uint64_t)1)<<12)) #define IB_PIR_COMPMASK_LNKWIDTHACTIVE (CL_HTON64(((uint64_t)1)<<13)) #define IB_PIR_COMPMASK_LNKSPEEDSUPPORT (CL_HTON64(((uint64_t)1)<<14)) #define IB_PIR_COMPMASK_PORTSTATE (CL_HTON64(((uint64_t)1)<<15)) #define IB_PIR_COMPMASK_PORTPHYSTATE (CL_HTON64(((uint64_t)1)<<16)) #define IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17)) #define IB_PIR_COMPMASK_MKEYPROTBITS (CL_HTON64(((uint64_t)1)<<18)) #define IB_PIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<19)) #define IB_PIR_COMPMASK_LMC (CL_HTON64(((uint64_t)1)<<20)) #define IB_PIR_COMPMASK_LINKSPEEDACTIVE (CL_HTON64(((uint64_t)1)<<21)) #define IB_PIR_COMPMASK_LINKSPEEDENABLE (CL_HTON64(((uint64_t)1)<<22)) #define IB_PIR_COMPMASK_NEIGHBORMTU (CL_HTON64(((uint64_t)1)<<23)) #define IB_PIR_COMPMASK_MASTERSMSL (CL_HTON64(((uint64_t)1)<<24)) #define IB_PIR_COMPMASK_VLCAP (CL_HTON64(((uint64_t)1)<<25)) #define IB_PIR_COMPMASK_INITTYPE (CL_HTON64(((uint64_t)1)<<26)) #define IB_PIR_COMPMASK_VLHIGHLIMIT (CL_HTON64(((uint64_t)1)<<27)) #define IB_PIR_COMPMASK_VLARBHIGHCAP (CL_HTON64(((uint64_t)1)<<28)) #define IB_PIR_COMPMASK_VLARBLOWCAP (CL_HTON64(((uint64_t)1)<<29)) #define IB_PIR_COMPMASK_INITTYPEREPLY (CL_HTON64(((uint64_t)1)<<30)) #define IB_PIR_COMPMASK_MTUCAP (CL_HTON64(((uint64_t)1)<<31)) #define IB_PIR_COMPMASK_VLSTALLCNT (CL_HTON64(((uint64_t)1)<<32)) #define IB_PIR_COMPMASK_HOQLIFE (CL_HTON64(((uint64_t)1)<<33)) #define IB_PIR_COMPMASK_OPVLS (CL_HTON64(((uint64_t)1)<<34)) #define IB_PIR_COMPMASK_PARENFIN (CL_HTON64(((uint64_t)1)<<35)) #define IB_PIR_COMPMASK_PARENFOUT (CL_HTON64(((uint64_t)1)<<36)) #define IB_PIR_COMPMASK_FILTERRAWIN (CL_HTON64(((uint64_t)1)<<37)) #define IB_PIR_COMPMASK_FILTERRAWOUT (CL_HTON64(((uint64_t)1)<<38)) #define IB_PIR_COMPMASK_MKEYVIO (CL_HTON64(((uint64_t)1)<<39)) #define IB_PIR_COMPMASK_PKEYVIO (CL_HTON64(((uint64_t)1)<<40)) #define IB_PIR_COMPMASK_QKEYVIO (CL_HTON64(((uint64_t)1)<<41)) #define IB_PIR_COMPMASK_GUIDCAP (CL_HTON64(((uint64_t)1)<<42)) #define IB_PIR_COMPMASK_CLIENTREREG (CL_HTON64(((uint64_t)1)<<43)) #define IB_PIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<44)) #define IB_PIR_COMPMASK_SUBNTO (CL_HTON64(((uint64_t)1)<<45)) #define IB_PIR_COMPMASK_RESV4 (CL_HTON64(((uint64_t)1)<<46)) #define IB_PIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<47)) #define IB_PIR_COMPMASK_LOCALPHYERR (CL_HTON64(((uint64_t)1)<<48)) #define IB_PIR_COMPMASK_OVERRUNERR (CL_HTON64(((uint64_t)1)<<49)) #define IB_PIR_COMPMASK_MAXCREDHINT (CL_HTON64(((uint64_t)1)<<50)) #define IB_PIR_COMPMASK_RESV5 (CL_HTON64(((uint64_t)1)<<51)) #define IB_PIR_COMPMASK_LINKRTLAT (CL_HTON64(((uint64_t)1)<<52)) #define IB_PIR_COMPMASK_CAPMASK2 (CL_HTON64(((uint64_t)1)<<53)) #define IB_PIR_COMPMASK_LINKSPDEXTACT (CL_HTON64(((uint64_t)1)<<54)) #define IB_PIR_COMPMASK_LINKSPDEXTSUPP (CL_HTON64(((uint64_t)1)<<55)) #define IB_PIR_COMPMASK_RESV7 (CL_HTON64(((uint64_t)1)<<56)) #define IB_PIR_COMPMASK_LINKSPDEXTENAB (CL_HTON64(((uint64_t)1)<<57)) /* Multicast Member Record Component Masks */ #define IB_MCR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<0)) #define IB_MCR_COMPMASK_MGID (CL_HTON64(((uint64_t)1)<<0)) #define IB_MCR_COMPMASK_PORT_GID (CL_HTON64(((uint64_t)1)<<1)) #define IB_MCR_COMPMASK_QKEY (CL_HTON64(((uint64_t)1)<<2)) #define IB_MCR_COMPMASK_MLID (CL_HTON64(((uint64_t)1)<<3)) #define IB_MCR_COMPMASK_MTU_SEL (CL_HTON64(((uint64_t)1)<<4)) #define IB_MCR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<5)) #define IB_MCR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<6)) #define IB_MCR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7)) #define IB_MCR_COMPMASK_RATE_SEL (CL_HTON64(((uint64_t)1)<<8)) #define IB_MCR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<9)) #define IB_MCR_COMPMASK_LIFE_SEL (CL_HTON64(((uint64_t)1)<<10)) #define IB_MCR_COMPMASK_LIFE (CL_HTON64(((uint64_t)1)<<11)) #define IB_MCR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<12)) #define IB_MCR_COMPMASK_FLOW (CL_HTON64(((uint64_t)1)<<13)) #define IB_MCR_COMPMASK_HOP (CL_HTON64(((uint64_t)1)<<14)) #define IB_MCR_COMPMASK_SCOPE (CL_HTON64(((uint64_t)1)<<15)) #define IB_MCR_COMPMASK_JOIN_STATE (CL_HTON64(((uint64_t)1)<<16)) #define IB_MCR_COMPMASK_PROXY (CL_HTON64(((uint64_t)1)<<17)) /* GUID Info Record Component Masks */ #define IB_GIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_GIR_COMPMASK_BLOCKNUM (CL_HTON64(((uint64_t)1)<<1)) #define IB_GIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<2)) #define IB_GIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<3)) #define IB_GIR_COMPMASK_GID0 (CL_HTON64(((uint64_t)1)<<4)) #define IB_GIR_COMPMASK_GID1 (CL_HTON64(((uint64_t)1)<<5)) #define IB_GIR_COMPMASK_GID2 (CL_HTON64(((uint64_t)1)<<6)) #define IB_GIR_COMPMASK_GID3 (CL_HTON64(((uint64_t)1)<<7)) #define IB_GIR_COMPMASK_GID4 (CL_HTON64(((uint64_t)1)<<8)) #define IB_GIR_COMPMASK_GID5 (CL_HTON64(((uint64_t)1)<<9)) #define IB_GIR_COMPMASK_GID6 (CL_HTON64(((uint64_t)1)<<10)) #define IB_GIR_COMPMASK_GID7 (CL_HTON64(((uint64_t)1)<<11)) /* MultiPath Record Component Masks */ #define IB_MPR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<0)) #define IB_MPR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1)) #define IB_MPR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<2)) #define IB_MPR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<3)) #define IB_MPR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<4)) #define IB_MPR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<5)) #define IB_MPR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<6)) #define IB_MPR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7)) #define IB_MPR_COMPMASK_QOS_CLASS (CL_HTON64(((uint64_t)1)<<8)) #define IB_MPR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<9)) #define IB_MPR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<10)) #define IB_MPR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<11)) #define IB_MPR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<12)) #define IB_MPR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<13)) #define IB_MPR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<14)) #define IB_MPR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<15)) #define IB_MPR_COMPMASK_SERVICEID_MSB (CL_HTON64(((uint64_t)1)<<16)) #define IB_MPR_COMPMASK_INDEPSELEC (CL_HTON64(((uint64_t)1)<<17)) #define IB_MPR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<18)) #define IB_MPR_COMPMASK_SGIDCOUNT (CL_HTON64(((uint64_t)1)<<19)) #define IB_MPR_COMPMASK_DGIDCOUNT (CL_HTON64(((uint64_t)1)<<20)) #define IB_MPR_COMPMASK_SERVICEID_LSB (CL_HTON64(((uint64_t)1)<<21)) #define IB_MPR_COMPMASK_SERVICEID (IB_MPR_COMPMASK_SERVICEID_MSB | \ IB_MPR_COMPMASK_SERVICEID_LSB) /* SMInfo Record Component Masks */ #define IB_SMIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0)) #define IB_SMIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1)) #define IB_SMIR_COMPMASK_GUID (CL_HTON64(((uint64_t)1)<<2)) #define IB_SMIR_COMPMASK_SMKEY (CL_HTON64(((uint64_t)1)<<3)) #define IB_SMIR_COMPMASK_ACTCOUNT (CL_HTON64(((uint64_t)1)<<4)) #define IB_SMIR_COMPMASK_PRIORITY (CL_HTON64(((uint64_t)1)<<5)) #define IB_SMIR_COMPMASK_SMSTATE (CL_HTON64(((uint64_t)1)<<6)) /* InformInfo Record Component Masks */ #define IB_IIR_COMPMASK_SUBSCRIBERGID (CL_HTON64(((uint64_t)1)<<0)) #define IB_IIR_COMPMASK_ENUM (CL_HTON64(((uint64_t)1)<<1)) #define IB_IIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<2)) #define IB_IIR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<3)) #define IB_IIR_COMPMASK_LIDRANGEBEGIN (CL_HTON64(((uint64_t)1)<<4)) #define IB_IIR_COMPMASK_LIDRANGEEND (CL_HTON64(((uint64_t)1)<<5)) #define IB_IIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<6)) #define IB_IIR_COMPMASK_ISGENERIC (CL_HTON64(((uint64_t)1)<<7)) #define IB_IIR_COMPMASK_SUBSCRIBE (CL_HTON64(((uint64_t)1)<<8)) #define IB_IIR_COMPMASK_TYPE (CL_HTON64(((uint64_t)1)<<9)) #define IB_IIR_COMPMASK_TRAPNUMB (CL_HTON64(((uint64_t)1)<<10)) #define IB_IIR_COMPMASK_DEVICEID (CL_HTON64(((uint64_t)1)<<10)) #define IB_IIR_COMPMASK_QPN (CL_HTON64(((uint64_t)1)<<11)) #define IB_IIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<12)) #define IB_IIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<13)) #define IB_IIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<14)) #define IB_IIR_COMPMASK_PRODTYPE (CL_HTON64(((uint64_t)1)<<15)) #define IB_IIR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<15)) /****f* IBA Base: Types/ib_path_rec_init_local * NAME * ib_path_rec_init_local * * DESCRIPTION * Initializes a subnet local path record. * * SYNOPSIS */ static inline void OSM_API ib_path_rec_init_local(IN ib_path_rec_t * const p_rec, IN ib_gid_t * const p_dgid, IN ib_gid_t * const p_sgid, IN ib_net16_t dlid, IN ib_net16_t slid, IN uint8_t num_path, IN ib_net16_t pkey, IN uint8_t sl, IN uint16_t qos_class, IN uint8_t mtu_selector, IN uint8_t mtu, IN uint8_t rate_selector, IN uint8_t rate, IN uint8_t pkt_life_selector, IN uint8_t pkt_life, IN uint8_t preference) { p_rec->dgid = *p_dgid; p_rec->sgid = *p_sgid; p_rec->dlid = dlid; p_rec->slid = slid; p_rec->num_path = num_path; p_rec->pkey = pkey; p_rec->qos_class_sl = cl_hton16((sl & IB_PATH_REC_SL_MASK) | (qos_class << 4)); p_rec->mtu = (uint8_t) ((mtu & IB_PATH_REC_BASE_MASK) | (uint8_t) (mtu_selector << 6)); p_rec->rate = (uint8_t) ((rate & IB_PATH_REC_BASE_MASK) | (uint8_t) (rate_selector << 6)); p_rec->pkt_life = (uint8_t) ((pkt_life & IB_PATH_REC_BASE_MASK) | (uint8_t) (pkt_life_selector << 6)); p_rec->preference = preference; /* Clear global routing fields for local path records */ p_rec->hop_flow_raw = 0; p_rec->tclass = 0; p_rec->service_id = 0; memset(p_rec->resv2, 0, sizeof(p_rec->resv2)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * dgid * [in] GID of destination port. * * sgid * [in] GID of source port. * * dlid * [in] LID of destination port. * * slid * [in] LID of source port. * * num_path * [in] Reversible path - 1 bit to say if path is reversible. * num_path [6:0] In queries, maximum number of paths to return. * In responses, undefined. * * pkey * [in] Partition key (P_Key) to use on this path. * * qos_class * [in] QoS class to use on this path. Lower 12-bits are valid. * * sl * [in] Service level to use on this path. Lower 4-bits are valid. * * mtu_selector * [in] Encoded MTU selector value to use on this path * * mtu * [in] Encoded MTU to use on this path * * rate_selector * [in] Encoded rate selector value to use on this path. * * rate * [in] Encoded rate to use on this path. * * pkt_life_selector * [in] Encoded Packet selector value lifetime for this path. * * pkt_life * [in] Encoded Packet lifetime for this path. * * preference * [in] Indicates the relative merit of this path versus other path * records returned from the SA. Lower numbers are better. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * ib_gid_t *********/ /****f* IBA Base: Types/ib_path_rec_num_path * NAME * ib_path_rec_num_path * * DESCRIPTION * Get max number of paths to return. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_num_path(IN const ib_path_rec_t * const p_rec) { return (p_rec->num_path & 0x7F); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Maximum number of paths to return for each unique SGID_DGID combination. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_set_sl * NAME * ib_path_rec_set_sl * * DESCRIPTION * Set path service level. * * SYNOPSIS */ static inline void OSM_API ib_path_rec_set_sl(IN ib_path_rec_t * const p_rec, IN const uint8_t sl) { p_rec->qos_class_sl = (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_QOS_CLASS_MASK)) | cl_hton16(sl & IB_PATH_REC_SL_MASK); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * sl * [in] Service level to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_sl * NAME * ib_path_rec_sl * * DESCRIPTION * Get path service level. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_sl(IN const ib_path_rec_t * const p_rec) { return (uint8_t)(cl_ntoh16(p_rec->qos_class_sl) & IB_PATH_REC_SL_MASK); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * SL. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_set_qos_class * NAME * ib_path_rec_set_qos_class * * DESCRIPTION * Set path QoS class. * * SYNOPSIS */ static inline void OSM_API ib_path_rec_set_qos_class(IN ib_path_rec_t * const p_rec, IN const uint16_t qos_class) { p_rec->qos_class_sl = (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) | cl_hton16(qos_class << 4); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * qos_class * [in] QoS class to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_qos_class * NAME * ib_path_rec_qos_class * * DESCRIPTION * Get QoS class. * * SYNOPSIS */ static inline uint16_t OSM_API ib_path_rec_qos_class(IN const ib_path_rec_t * const p_rec) { return (cl_ntoh16(p_rec->qos_class_sl) >> 4); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * QoS class of the path record. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_mtu * NAME * ib_path_rec_mtu * * DESCRIPTION * Get encoded path MTU. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_mtu(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) (p_rec->mtu & IB_PATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path MTU. * 1: 256 * 2: 512 * 3: 1024 * 4: 2048 * 5: 4096 * others: reserved * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_mtu_sel * NAME * ib_path_rec_mtu_sel * * DESCRIPTION * Get encoded path MTU selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_mtu_sel(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) ((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path MTU selector value (for queries). * 0: greater than MTU specified * 1: less than MTU specified * 2: exactly the MTU specified * 3: largest MTU available * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_rate * NAME * ib_path_rec_rate * * DESCRIPTION * Get encoded path rate. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_rate(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) (p_rec->rate & IB_PATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path rate. * 2: 2.5 Gb/sec. * 3: 10 Gb/sec. * 4: 30 Gb/sec. * 5: 5 Gb/sec. * 6: 20 Gb/sec. * 7: 40 Gb/sec. * 8: 60 Gb/sec. * 9: 80 Gb/sec. * 10: 120 Gb/sec. * 11: 14 Gb/sec. * 12: 56 Gb/sec. * 13: 112 Gb/sec. * 14: 168 Gb/sec. * 15: 25 Gb/sec. * 16: 100 Gb/sec. * 17: 200 Gb/sec. * 18: 300 Gb/sec. * others: reserved * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_rate_sel * NAME * ib_path_rec_rate_sel * * DESCRIPTION * Get encoded path rate selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_rate_sel(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) ((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path rate selector value (for queries). * 0: greater than rate specified * 1: less than rate specified * 2: exactly the rate specified * 3: largest rate available * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_pkt_life * NAME * ib_path_rec_pkt_life * * DESCRIPTION * Get encoded path pkt_life. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_pkt_life(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) (p_rec->pkt_life & IB_PATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path pkt_life = 4.096 usec * 2 ** PacketLifeTime. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_pkt_life_sel * NAME * ib_path_rec_pkt_life_sel * * DESCRIPTION * Get encoded path pkt_lifetime selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_pkt_life_sel(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) ((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Encoded path pkt_lifetime selector value (for queries). * 0: greater than rate specified * 1: less than rate specified * 2: exactly the rate specified * 3: smallest packet lifetime available * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_flow_lbl * NAME * ib_path_rec_flow_lbl * * DESCRIPTION * Get flow label. * * SYNOPSIS */ static inline uint32_t OSM_API ib_path_rec_flow_lbl(IN const ib_path_rec_t * const p_rec) { return (((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Flow label of the path record. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****f* IBA Base: Types/ib_path_rec_hop_limit * NAME * ib_path_rec_hop_limit * * DESCRIPTION * Get hop limit. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_rec_hop_limit(IN const ib_path_rec_t * const p_rec) { return ((uint8_t) (cl_ntoh32(p_rec->hop_flow_raw) & 0x000000FF)); } /* * PARAMETERS * p_rec * [in] Pointer to the path record object. * * RETURN VALUES * Hop limit of the path record. * * NOTES * * SEE ALSO * ib_path_rec_t *********/ /****s* IBA Base: Constants/IB_CLASS_CAP_TRAP * NAME * IB_CLASS_CAP_TRAP * * DESCRIPTION * ClassPortInfo CapabilityMask bits. This bit will be set * if the class supports Trap() MADs (13.4.8.1). * * SEE ALSO * ib_class_port_info_t, IB_CLASS_CAP_GETSET * * SOURCE */ #define IB_CLASS_CAP_TRAP 0x0001 /*********/ /****s* IBA Base: Constants/IB_CLASS_CAP_GETSET * NAME * IB_CLASS_CAP_GETSET * * DESCRIPTION * ClassPortInfo CapabilityMask bits. This bit will be set * if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1). * * SEE ALSO * ib_class_port_info_t, IB_CLASS_CAP_TRAP * * SOURCE */ #define IB_CLASS_CAP_GETSET 0x0002 /*********/ /****s* IBA Base: Constants/IB_CLASS_ENH_PORT0_CC_MASK * NAME * IB_CLASS_ENH_PORT0_CC_MASK * * DESCRIPTION * ClassPortInfo CapabilityMask bits. * Switch only: This bit will be set if the EnhancedPort0 * supports CA Congestion Control (A10.4.3.1). * * SEE ALSO * ib_class_port_info_t * * SOURCE */ #define IB_CLASS_ENH_PORT0_CC_MASK 0x0100 /*********/ /****s* IBA Base: Constants/IB_CLASS_RESP_TIME_MASK * NAME * IB_CLASS_RESP_TIME_MASK * * DESCRIPTION * Mask bits to extract the reponse time value from the * resp_time_val field of ib_class_port_info_t. * * SEE ALSO * ib_class_port_info_t * * SOURCE */ #define IB_CLASS_RESP_TIME_MASK 0x1F /*********/ /****s* IBA Base: Types/ib_class_port_info_t * NAME * ib_class_port_info_t * * DESCRIPTION * IBA defined ClassPortInfo attribute (13.4.8.1) * * SYNOPSIS */ #include typedef struct _ib_class_port_info { uint8_t base_ver; uint8_t class_ver; ib_net16_t cap_mask; ib_net32_t cap_mask2_resp_time; ib_gid_t redir_gid; ib_net32_t redir_tc_sl_fl; ib_net16_t redir_lid; ib_net16_t redir_pkey; ib_net32_t redir_qp; ib_net32_t redir_qkey; ib_gid_t trap_gid; ib_net32_t trap_tc_sl_fl; ib_net16_t trap_lid; ib_net16_t trap_pkey; ib_net32_t trap_hop_qp; ib_net32_t trap_qkey; } PACK_SUFFIX ib_class_port_info_t; #include /* * FIELDS * base_ver * Maximum supported MAD Base Version. * * class_ver * Maximum supported management class version. * * cap_mask * Supported capabilities of this management class. * * cap_mask2_resp_time * Maximum expected response time and additional * supported capabilities of this management class. * * redir_gid * GID to use for redirection, or zero * * redir_tc_sl_fl * Traffic class, service level and flow label the requester * should use if the service is redirected. * * redir_lid * LID used for redirection, or zero * * redir_pkey * P_Key used for redirection * * redir_qp * QP number used for redirection * * redir_qkey * Q_Key associated with the redirected QP. This shall be the * well known Q_Key value. * * trap_gid * GID value used for trap messages from this service. * * trap_tc_sl_fl * Traffic class, service level and flow label used for * trap messages originated by this service. * * trap_lid * LID used for trap messages, or zero * * trap_pkey * P_Key used for trap messages * * trap_hop_qp * Hop limit (upper 8 bits) and QP number used for trap messages * * trap_qkey * Q_Key associated with the trap messages QP. * * SEE ALSO * IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP * *********/ #define IB_PM_ALL_PORT_SELECT (CL_HTON16(((uint16_t)1)<<8)) #define IB_PM_EXT_WIDTH_SUPPORTED (CL_HTON16(((uint16_t)1)<<9)) #define IB_PM_EXT_WIDTH_NOIETF_SUP (CL_HTON16(((uint16_t)1)<<10)) #define IB_PM_SAMPLES_ONLY_SUP (CL_HTON16(((uint16_t)1)<<11)) #define IB_PM_PC_XMIT_WAIT_SUP (CL_HTON16(((uint16_t)1)<<12)) #define IS_PM_INH_LMTD_PKEY_MC_CONSTR_ERR (CL_HTON16(((uint16_t)1)<<13)) #define IS_PM_RSFEC_COUNTERS_SUP (CL_HTON16(((uint16_t)1)<<14)) #define IB_PM_IS_QP1_DROP_SUP (CL_HTON16(((uint16_t)1)<<15)) /****f* IBA Base: Types/ib_class_set_resp_time_val * NAME * ib_class_set_resp_time_val * * DESCRIPTION * Set maximum expected response time. * * SYNOPSIS */ static inline void OSM_API ib_class_set_resp_time_val(IN ib_class_port_info_t * const p_cpi, IN const uint8_t val) { p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time & CL_HTON32(~IB_CLASS_RESP_TIME_MASK)) | cl_hton32(val & IB_CLASS_RESP_TIME_MASK); } /* * PARAMETERS * p_cpi * [in] Pointer to the class port info object. * * val * [in] Response time value to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_class_port_info_t *********/ /****f* IBA Base: Types/ib_class_resp_time_val * NAME * ib_class_resp_time_val * * DESCRIPTION * Get response time value. * * SYNOPSIS */ static inline uint8_t OSM_API ib_class_resp_time_val(IN ib_class_port_info_t * const p_cpi) { return (uint8_t)(cl_ntoh32(p_cpi->cap_mask2_resp_time) & IB_CLASS_RESP_TIME_MASK); } /* * PARAMETERS * p_cpi * [in] Pointer to the class port info object. * * RETURN VALUES * Response time value. * * NOTES * * SEE ALSO * ib_class_port_info_t *********/ /****f* IBA Base: Types/ib_class_set_cap_mask2 * NAME * ib_class_set_cap_mask2 * * DESCRIPTION * Set ClassPortInfo:CapabilityMask2. * * SYNOPSIS */ static inline void OSM_API ib_class_set_cap_mask2(IN ib_class_port_info_t * const p_cpi, IN const uint32_t cap_mask2) { p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time & CL_HTON32(IB_CLASS_RESP_TIME_MASK)) | cl_hton32(cap_mask2 << 5); } /* * PARAMETERS * p_cpi * [in] Pointer to the class port info object. * * cap_mask2 * [in] CapabilityMask2 value to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_class_port_info_t *********/ /****f* IBA Base: Types/ib_class_cap_mask2 * NAME * ib_class_cap_mask2 * * DESCRIPTION * Get ClassPortInfo:CapabilityMask2. * * SYNOPSIS */ static inline uint32_t OSM_API ib_class_cap_mask2(IN const ib_class_port_info_t * const p_cpi) { return (cl_ntoh32(p_cpi->cap_mask2_resp_time) >> 5); } /* * PARAMETERS * p_cpi * [in] Pointer to the class port info object. * * RETURN VALUES * CapabilityMask2 of the ClassPortInfo. * * NOTES * * SEE ALSO * ib_class_port_info_t *********/ /****s* IBA Base: Types/ib_sm_info_t * NAME * ib_sm_info_t * * DESCRIPTION * SMInfo structure (14.2.5.13). * * SYNOPSIS */ #include typedef struct _ib_sm_info { ib_net64_t guid; ib_net64_t sm_key; ib_net32_t act_count; uint8_t pri_state; } PACK_SUFFIX ib_sm_info_t; #include /* * FIELDS * guid * Port GUID for this SM. * * sm_key * SM_Key of this SM. * * act_count * Activity counter used as a heartbeat. * * pri_state * Priority and State information * * SEE ALSO *********/ /****f* IBA Base: Types/ib_sminfo_get_priority * NAME * ib_sminfo_get_priority * * DESCRIPTION * Returns the priority value. * * SYNOPSIS */ static inline uint8_t OSM_API ib_sminfo_get_priority(IN const ib_sm_info_t * const p_smi) { return ((uint8_t) ((p_smi->pri_state & 0xF0) >> 4)); } /* * PARAMETERS * p_smi * [in] Pointer to the SMInfo Attribute. * * RETURN VALUES * Returns the priority value. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_sminfo_get_state * NAME * ib_sminfo_get_state * * DESCRIPTION * Returns the state value. * * SYNOPSIS */ static inline uint8_t OSM_API ib_sminfo_get_state(IN const ib_sm_info_t * const p_smi) { return ((uint8_t) (p_smi->pri_state & 0x0F)); } /* * PARAMETERS * p_smi * [in] Pointer to the SMInfo Attribute. * * RETURN VALUES * Returns the state value. * * NOTES * * SEE ALSO *********/ /****s* IBA Base: Types/ib_mad_t * NAME * ib_mad_t * * DESCRIPTION * IBA defined MAD header (13.4.3) * * SYNOPSIS */ #include typedef struct _ib_mad { uint8_t base_ver; uint8_t mgmt_class; uint8_t class_ver; uint8_t method; ib_net16_t status; ib_net16_t class_spec; ib_net64_t trans_id; ib_net16_t attr_id; ib_net16_t resv; ib_net32_t attr_mod; } PACK_SUFFIX ib_mad_t; #include /* * FIELDS * base_ver * MAD base format. * * mgmt_class * Class of operation. * * class_ver * Version of MAD class-specific format. * * method * Method to perform, including 'R' bit. * * status * Status of operation. * * class_spec * Reserved for subnet management. * * trans_id * Transaction ID. * * attr_id * Attribute ID. * * resv * Reserved field. * * attr_mod * Attribute modifier. * * SEE ALSO *********/ /****s* IBA Base: Types/ib_rmpp_mad_t * NAME * ib_rmpp_mad_t * * DESCRIPTION * IBA defined MAD RMPP header (13.6.2.1) * * SYNOPSIS */ #include typedef struct _ib_rmpp_mad { ib_mad_t common_hdr; uint8_t rmpp_version; uint8_t rmpp_type; uint8_t rmpp_flags; uint8_t rmpp_status; ib_net32_t seg_num; ib_net32_t paylen_newwin; } PACK_SUFFIX ib_rmpp_mad_t; #include /* * SEE ALSO * ib_mad_t *********/ /****f* IBA Base: Types/ib_mad_init_new * NAME * ib_mad_init_new * * DESCRIPTION * Initializes a MAD common header. * * SYNOPSIS */ static inline void OSM_API ib_mad_init_new(IN ib_mad_t * const p_mad, IN const uint8_t mgmt_class, IN const uint8_t class_ver, IN const uint8_t method, IN const ib_net64_t trans_id, IN const ib_net16_t attr_id, IN const ib_net32_t attr_mod) { CL_ASSERT(p_mad); p_mad->base_ver = 1; p_mad->mgmt_class = mgmt_class; p_mad->class_ver = class_ver; p_mad->method = method; p_mad->status = 0; p_mad->class_spec = 0; p_mad->trans_id = trans_id; p_mad->attr_id = attr_id; p_mad->resv = 0; p_mad->attr_mod = attr_mod; } /* * PARAMETERS * p_mad * [in] Pointer to the MAD common header. * * mgmt_class * [in] Class of operation. * * class_ver * [in] Version of MAD class-specific format. * * method * [in] Method to perform, including 'R' bit. * * trans_Id * [in] Transaction ID. * * attr_id * [in] Attribute ID. * * attr_mod * [in] Attribute modifier. * * RETURN VALUES * None. * * NOTES * * SEE ALSO * ib_mad_t *********/ /****f* IBA Base: Types/ib_mad_init_response * NAME * ib_mad_init_response * * DESCRIPTION * Initializes a MAD common header as a response. * * SYNOPSIS */ static inline void OSM_API ib_mad_init_response(IN const ib_mad_t * const p_req_mad, IN ib_mad_t * const p_mad, IN const ib_net16_t status) { CL_ASSERT(p_req_mad); CL_ASSERT(p_mad); *p_mad = *p_req_mad; p_mad->status = status; if (p_mad->method == IB_MAD_METHOD_SET) p_mad->method = IB_MAD_METHOD_GET; p_mad->method |= IB_MAD_METHOD_RESP_MASK; } /* * PARAMETERS * p_req_mad * [in] Pointer to the MAD common header in the original request MAD. * * p_mad * [in] Pointer to the MAD common header to initialize. * * status * [in] MAD Status value to return; * * RETURN VALUES * None. * * NOTES * p_req_mad and p_mad may point to the same MAD. * * SEE ALSO * ib_mad_t *********/ /****f* IBA Base: Types/ib_mad_is_response * NAME * ib_mad_is_response * * DESCRIPTION * Returns TRUE if the MAD is a response ('R' bit set) * or if the MAD is a TRAP REPRESS, * FALSE otherwise. * * SYNOPSIS */ static inline boolean_t OSM_API ib_mad_is_response(IN const ib_mad_t * const p_mad) { CL_ASSERT(p_mad); return (p_mad->method & IB_MAD_METHOD_RESP_MASK || p_mad->method == IB_MAD_METHOD_TRAP_REPRESS); } /* * PARAMETERS * p_mad * [in] Pointer to the MAD. * * RETURN VALUES * Returns TRUE if the MAD is a response ('R' bit set), * FALSE otherwise. * * NOTES * * SEE ALSO * ib_mad_t *********/ #define IB_RMPP_TYPE_DATA 1 #define IB_RMPP_TYPE_ACK 2 #define IB_RMPP_TYPE_STOP 3 #define IB_RMPP_TYPE_ABORT 4 #define IB_RMPP_NO_RESP_TIME 0x1F #define IB_RMPP_FLAG_ACTIVE 0x01 #define IB_RMPP_FLAG_FIRST 0x02 #define IB_RMPP_FLAG_LAST 0x04 #define IB_RMPP_STATUS_SUCCESS 0 #define IB_RMPP_STATUS_RESX 1 /* resources exhausted */ #define IB_RMPP_STATUS_T2L 118 /* time too long */ #define IB_RMPP_STATUS_BAD_LEN 119 /* incon. last and payload len */ #define IB_RMPP_STATUS_BAD_SEG 120 /* incon. first and segment no */ #define IB_RMPP_STATUS_BADT 121 /* bad rmpp type */ #define IB_RMPP_STATUS_W2S 122 /* newwindowlast too small */ #define IB_RMPP_STATUS_S2B 123 /* segment no too big */ #define IB_RMPP_STATUS_BAD_STATUS 124 /* illegal status */ #define IB_RMPP_STATUS_UNV 125 /* unsupported version */ #define IB_RMPP_STATUS_TMR 126 /* too many retries */ #define IB_RMPP_STATUS_UNSPEC 127 /* unspecified */ /****f* IBA Base: Types/ib_rmpp_is_flag_set * NAME * ib_rmpp_is_flag_set * * DESCRIPTION * Returns TRUE if the MAD has the given RMPP flag set. * * SYNOPSIS */ static inline boolean_t OSM_API ib_rmpp_is_flag_set(IN const ib_rmpp_mad_t * const p_rmpp_mad, IN const uint8_t flag) { CL_ASSERT(p_rmpp_mad); return ((p_rmpp_mad->rmpp_flags & flag) == flag); } /* * PARAMETERS * ib_rmpp_mad_t * [in] Pointer to a MAD with an RMPP header. * * flag * [in] The RMPP flag being examined. * * RETURN VALUES * Returns TRUE if the MAD has the given RMPP flag set. * * NOTES * * SEE ALSO * ib_mad_t, ib_rmpp_mad_t *********/ static inline void OSM_API ib_rmpp_set_resp_time(IN ib_rmpp_mad_t * const p_rmpp_mad, IN const uint8_t resp_time) { CL_ASSERT(p_rmpp_mad); p_rmpp_mad->rmpp_flags |= (resp_time << 3); } static inline uint8_t OSM_API ib_rmpp_get_resp_time(IN const ib_rmpp_mad_t * const p_rmpp_mad) { CL_ASSERT(p_rmpp_mad); return ((uint8_t) (p_rmpp_mad->rmpp_flags >> 3)); } /****d* IBA Base: Constants/IB_SMP_DIRECTION * NAME * IB_SMP_DIRECTION * * DESCRIPTION * The Direction bit for directed route SMPs. * * SOURCE */ #define IB_SMP_DIRECTION_HO 0x8000 #define IB_SMP_DIRECTION (CL_HTON16(IB_SMP_DIRECTION_HO)) /**********/ /****d* IBA Base: Constants/IB_SMP_STATUS_MASK * NAME * IB_SMP_STATUS_MASK * * DESCRIPTION * Mask value for extracting status from a directed route SMP. * * SOURCE */ #define IB_SMP_STATUS_MASK_HO 0x7FFF #define IB_SMP_STATUS_MASK (CL_HTON16(IB_SMP_STATUS_MASK_HO)) /**********/ /****s* IBA Base: Types/ib_smp_t * NAME * ib_smp_t * * DESCRIPTION * IBA defined SMP. (14.2.1.2) * * SYNOPSIS */ #define IB_SMP_DATA_SIZE 64 #include typedef struct _ib_smp { uint8_t base_ver; uint8_t mgmt_class; uint8_t class_ver; uint8_t method; ib_net16_t status; uint8_t hop_ptr; uint8_t hop_count; ib_net64_t trans_id; ib_net16_t attr_id; ib_net16_t resv; ib_net32_t attr_mod; ib_net64_t m_key; ib_net16_t dr_slid; ib_net16_t dr_dlid; uint32_t resv1[7]; uint8_t data[IB_SMP_DATA_SIZE]; uint8_t initial_path[IB_SUBNET_PATH_HOPS_MAX]; uint8_t return_path[IB_SUBNET_PATH_HOPS_MAX]; } PACK_SUFFIX ib_smp_t; #include /* * FIELDS * base_ver * MAD base format. * * mgmt_class * Class of operation. * * class_ver * Version of MAD class-specific format. * * method * Method to perform, including 'R' bit. * * status * Status of operation. * * hop_ptr * Hop pointer for directed route MADs. * * hop_count * Hop count for directed route MADs. * * trans_Id * Transaction ID. * * attr_id * Attribute ID. * * resv * Reserved field. * * attr_mod * Attribute modifier. * * m_key * Management key value. * * dr_slid * Directed route source LID. * * dr_dlid * Directed route destination LID. * * resv0 * Reserved for 64 byte alignment. * * data * MAD data payload. * * initial_path * Outbound port list. * * return_path * Inbound port list. * * SEE ALSO *********/ /****f* IBA Base: Types/ib_smp_get_status * NAME * ib_smp_get_status * * DESCRIPTION * Returns the SMP status value in network order. * * SYNOPSIS */ static inline ib_net16_t OSM_API ib_smp_get_status(IN const ib_smp_t * const p_smp) { return ((ib_net16_t) (p_smp->status & IB_SMP_STATUS_MASK)); } /* * PARAMETERS * p_smp * [in] Pointer to the SMP packet. * * RETURN VALUES * Returns the SMP status value in network order. * * NOTES * * SEE ALSO * ib_smp_t *********/ /****f* IBA Base: Types/ib_smp_is_response * NAME * ib_smp_is_response * * DESCRIPTION * Returns TRUE if the SMP is a response MAD, FALSE otherwise. * * SYNOPSIS */ static inline boolean_t OSM_API ib_smp_is_response(IN const ib_smp_t * const p_smp) { return (ib_mad_is_response((const ib_mad_t *)p_smp)); } /* * PARAMETERS * p_smp * [in] Pointer to the SMP packet. * * RETURN VALUES * Returns TRUE if the SMP is a response MAD, FALSE otherwise. * * NOTES * * SEE ALSO * ib_smp_t *********/ /****f* IBA Base: Types/ib_smp_is_d * NAME * ib_smp_is_d * * DESCRIPTION * Returns TRUE if the SMP 'D' (direction) bit is set. * * SYNOPSIS */ static inline boolean_t OSM_API ib_smp_is_d(IN const ib_smp_t * const p_smp) { return ((p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION); } /* * PARAMETERS * p_smp * [in] Pointer to the SMP packet. * * RETURN VALUES * Returns TRUE if the SMP 'D' (direction) bit is set. * * NOTES * * SEE ALSO * ib_smp_t *********/ /****f* IBA Base: Types/ib_smp_init_new * NAME * ib_smp_init_new * * DESCRIPTION * Initializes a MAD common header. * * TODO * This is too big for inlining, but leave it here for now * since there is not yet another convenient spot. * * SYNOPSIS */ static inline void OSM_API ib_smp_init_new(IN ib_smp_t * const p_smp, IN const uint8_t method, IN const ib_net64_t trans_id, IN const ib_net16_t attr_id, IN const ib_net32_t attr_mod, IN const uint8_t hop_count, IN const ib_net64_t m_key, IN const uint8_t * path_out, IN const ib_net16_t dr_slid, IN const ib_net16_t dr_dlid) { CL_ASSERT(p_smp); CL_ASSERT(hop_count < IB_SUBNET_PATH_HOPS_MAX); p_smp->base_ver = 1; p_smp->mgmt_class = IB_MCLASS_SUBN_DIR; p_smp->class_ver = 1; p_smp->method = method; p_smp->status = 0; p_smp->hop_ptr = 0; p_smp->hop_count = hop_count; p_smp->trans_id = trans_id; p_smp->attr_id = attr_id; p_smp->resv = 0; p_smp->attr_mod = attr_mod; p_smp->m_key = m_key; p_smp->dr_slid = dr_slid; p_smp->dr_dlid = dr_dlid; memset(p_smp->resv1, 0, sizeof(p_smp->resv1) + sizeof(p_smp->data) + sizeof(p_smp->initial_path) + sizeof(p_smp->return_path)); /* copy the path */ memcpy(&p_smp->initial_path, path_out, sizeof(p_smp->initial_path)); } /* * PARAMETERS * p_smp * [in] Pointer to the SMP packet. * * method * [in] Method to perform, including 'R' bit. * * trans_Id * [in] Transaction ID. * * attr_id * [in] Attribute ID. * * attr_mod * [in] Attribute modifier. * * hop_count * [in] Number of hops in the path. * * m_key * [in] Management key for this SMP. * * path_out * [in] Port array for outbound path. * * * RETURN VALUES * None. * * NOTES * Payload area is initialized to zero. * * * SEE ALSO * ib_mad_t *********/ /****f* IBA Base: Types/ib_smp_get_payload_ptr * NAME * ib_smp_get_payload_ptr * * DESCRIPTION * Gets a pointer to the SMP payload area. * * SYNOPSIS */ static inline void *OSM_API ib_smp_get_payload_ptr(IN const ib_smp_t * const p_smp) { return ((void *)p_smp->data); } /* * PARAMETERS * p_smp * [in] Pointer to the SMP packet. * * RETURN VALUES * Pointer to SMP payload area. * * NOTES * * SEE ALSO * ib_mad_t *********/ /****s* IBA Base: Types/ib_node_info_t * NAME * ib_node_info_t * * DESCRIPTION * IBA defined NodeInfo. (14.2.5.3) * * SYNOPSIS */ #include typedef struct _ib_node_info { uint8_t base_version; uint8_t class_version; uint8_t node_type; uint8_t num_ports; ib_net64_t sys_guid; ib_net64_t node_guid; ib_net64_t port_guid; ib_net16_t partition_cap; ib_net16_t device_id; ib_net32_t revision; ib_net32_t port_num_vendor_id; } PACK_SUFFIX ib_node_info_t; #include /************/ /****s* IBA Base: Types/ib_sa_mad_t * NAME * ib_sa_mad_t * * DESCRIPTION * IBA defined SA MAD format. (15.2.1) * * SYNOPSIS */ #define IB_SA_DATA_SIZE 200 #include typedef struct _ib_sa_mad { uint8_t base_ver; uint8_t mgmt_class; uint8_t class_ver; uint8_t method; ib_net16_t status; ib_net16_t resv; ib_net64_t trans_id; ib_net16_t attr_id; ib_net16_t resv1; ib_net32_t attr_mod; uint8_t rmpp_version; uint8_t rmpp_type; uint8_t rmpp_flags; uint8_t rmpp_status; ib_net32_t seg_num; ib_net32_t paylen_newwin; ib_net64_t sm_key; ib_net16_t attr_offset; ib_net16_t resv3; ib_net64_t comp_mask; uint8_t data[IB_SA_DATA_SIZE]; } PACK_SUFFIX ib_sa_mad_t; #include /**********/ #define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE) static inline uint32_t OSM_API ib_get_attr_size(IN const ib_net16_t attr_offset) { return (((uint32_t) cl_ntoh16(attr_offset)) << 3); } static inline ib_net16_t OSM_API ib_get_attr_offset(IN const uint32_t attr_size) { return (cl_hton16((uint16_t) (attr_size >> 3))); } /****f* IBA Base: Types/ib_sa_mad_get_payload_ptr * NAME * ib_sa_mad_get_payload_ptr * * DESCRIPTION * Gets a pointer to the SA MAD's payload area. * * SYNOPSIS */ static inline void *OSM_API ib_sa_mad_get_payload_ptr(IN const ib_sa_mad_t * const p_sa_mad) { return ((void *)p_sa_mad->data); } /* * PARAMETERS * p_sa_mad * [in] Pointer to the SA MAD packet. * * RETURN VALUES * Pointer to SA MAD payload area. * * NOTES * * SEE ALSO * ib_mad_t *********/ #define IB_NODE_INFO_PORT_NUM_MASK (CL_HTON32(0xFF000000)) #define IB_NODE_INFO_VEND_ID_MASK (CL_HTON32(0x00FFFFFF)) #if CPU_LE #define IB_NODE_INFO_PORT_NUM_SHIFT 0 #else #define IB_NODE_INFO_PORT_NUM_SHIFT 24 #endif /****f* IBA Base: Types/ib_node_info_get_local_port_num * NAME * ib_node_info_get_local_port_num * * DESCRIPTION * Gets the local port number from the NodeInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_node_info_get_local_port_num(IN const ib_node_info_t * const p_ni) { return ((uint8_t) ((p_ni->port_num_vendor_id & IB_NODE_INFO_PORT_NUM_MASK) >> IB_NODE_INFO_PORT_NUM_SHIFT)); } /* * PARAMETERS * p_ni * [in] Pointer to a NodeInfo attribute. * * RETURN VALUES * Local port number that returned the attribute. * * NOTES * * SEE ALSO * ib_node_info_t *********/ /****f* IBA Base: Types/ib_node_info_get_vendor_id * NAME * ib_node_info_get_vendor_id * * DESCRIPTION * Gets the VendorID from the NodeInfo attribute. * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_node_info_get_vendor_id(IN const ib_node_info_t * const p_ni) { return ((ib_net32_t) (p_ni->port_num_vendor_id & IB_NODE_INFO_VEND_ID_MASK)); } /* * PARAMETERS * p_ni * [in] Pointer to a NodeInfo attribute. * * RETURN VALUES * VendorID that returned the attribute. * * NOTES * * SEE ALSO * ib_node_info_t *********/ #define IB_NODE_DESCRIPTION_SIZE 64 #include typedef struct _ib_node_desc { // Node String is an array of UTF-8 characters // that describe the node in text format // Note that this string is NOT NULL TERMINATED! uint8_t description[IB_NODE_DESCRIPTION_SIZE]; } PACK_SUFFIX ib_node_desc_t; #include #include typedef struct _ib_node_record_t { ib_net16_t lid; ib_net16_t resv; ib_node_info_t node_info; ib_node_desc_t node_desc; uint8_t pad[4]; } PACK_SUFFIX ib_node_record_t; #include /****s* IBA Base: Types/ib_port_info_t * NAME * ib_port_info_t * * DESCRIPTION * IBA defined PortInfo. (14.2.5.6) * * SYNOPSIS */ #include typedef struct _ib_port_info { ib_net64_t m_key; ib_net64_t subnet_prefix; ib_net16_t base_lid; ib_net16_t master_sm_base_lid; ib_net32_t capability_mask; ib_net16_t diag_code; ib_net16_t m_key_lease_period; uint8_t local_port_num; uint8_t link_width_enabled; uint8_t link_width_supported; uint8_t link_width_active; uint8_t state_info1; /* LinkSpeedSupported and PortState */ uint8_t state_info2; /* PortPhysState and LinkDownDefaultState */ uint8_t mkey_lmc; /* M_KeyProtectBits and LMC */ uint8_t link_speed; /* LinkSpeedEnabled and LinkSpeedActive */ uint8_t mtu_smsl; uint8_t vl_cap; /* VLCap and InitType */ uint8_t vl_high_limit; uint8_t vl_arb_high_cap; uint8_t vl_arb_low_cap; uint8_t mtu_cap; uint8_t vl_stall_life; uint8_t vl_enforce; ib_net16_t m_key_violations; ib_net16_t p_key_violations; ib_net16_t q_key_violations; uint8_t guid_cap; uint8_t subnet_timeout; /* cli_rereg(1b), mcast_pkey_trap_suppr(1b), reserv(1b), timeout(5b) */ uint8_t resp_time_value; /* reserv(3b), rtv(5b) */ uint8_t error_threshold; /* local phy errors(4b), overrun errors(4b) */ ib_net16_t max_credit_hint; ib_net32_t link_rt_latency; /* reserv(8b), link round trip lat(24b) */ ib_net16_t capability_mask2; uint8_t link_speed_ext; /* LinkSpeedExtActive and LinkSpeedExtSupported */ uint8_t link_speed_ext_enabled; /* reserv(3b), LinkSpeedExtEnabled(5b) */ } PACK_SUFFIX ib_port_info_t; #include /************/ #define IB_PORT_STATE_MASK 0x0F #define IB_PORT_LMC_MASK 0x07 #define IB_PORT_LMC_MAX 0x07 #define IB_PORT_MPB_MASK 0xC0 #define IB_PORT_MPB_SHIFT 6 #define IB_PORT_LINK_SPEED_SHIFT 4 #define IB_PORT_LINK_SPEED_SUPPORTED_MASK 0xF0 #define IB_PORT_LINK_SPEED_ACTIVE_MASK 0xF0 #define IB_PORT_LINK_SPEED_ENABLED_MASK 0x0F #define IB_PORT_PHYS_STATE_MASK 0xF0 #define IB_PORT_PHYS_STATE_SHIFT 4 #define IB_PORT_PHYS_STATE_NO_CHANGE 0 #define IB_PORT_PHYS_STATE_SLEEP 1 #define IB_PORT_PHYS_STATE_POLLING 2 #define IB_PORT_PHYS_STATE_DISABLED 3 #define IB_PORT_PHYS_STATE_PORTCONFTRAIN 4 #define IB_PORT_PHYS_STATE_LINKUP 5 #define IB_PORT_PHYS_STATE_LINKERRRECOVER 6 #define IB_PORT_PHYS_STATE_PHYTEST 7 #define IB_PORT_LNKDWNDFTSTATE_MASK 0x0F #define IB_PORT_CAP_RESV0 (CL_HTON32(0x00000001)) #define IB_PORT_CAP_IS_SM (CL_HTON32(0x00000002)) #define IB_PORT_CAP_HAS_NOTICE (CL_HTON32(0x00000004)) #define IB_PORT_CAP_HAS_TRAP (CL_HTON32(0x00000008)) #define IB_PORT_CAP_HAS_IPD (CL_HTON32(0x00000010)) #define IB_PORT_CAP_HAS_AUTO_MIG (CL_HTON32(0x00000020)) #define IB_PORT_CAP_HAS_SL_MAP (CL_HTON32(0x00000040)) #define IB_PORT_CAP_HAS_NV_MKEY (CL_HTON32(0x00000080)) #define IB_PORT_CAP_HAS_NV_PKEY (CL_HTON32(0x00000100)) #define IB_PORT_CAP_HAS_LED_INFO (CL_HTON32(0x00000200)) #define IB_PORT_CAP_SM_DISAB (CL_HTON32(0x00000400)) #define IB_PORT_CAP_HAS_SYS_IMG_GUID (CL_HTON32(0x00000800)) #define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_HTON32(0x00001000)) #define IB_PORT_CAP_RESV13 (CL_HTON32(0x00002000)) #define IB_PORT_CAP_HAS_EXT_SPEEDS (CL_HTON32(0x00004000)) #define IB_PORT_CAP_HAS_CAP_MASK2 (CL_HTON32(0x00008000)) #define IB_PORT_CAP_HAS_COM_MGT (CL_HTON32(0x00010000)) #define IB_PORT_CAP_HAS_SNMP (CL_HTON32(0x00020000)) #define IB_PORT_CAP_REINIT (CL_HTON32(0x00040000)) #define IB_PORT_CAP_HAS_DEV_MGT (CL_HTON32(0x00080000)) #define IB_PORT_CAP_HAS_VEND_CLS (CL_HTON32(0x00100000)) #define IB_PORT_CAP_HAS_DR_NTC (CL_HTON32(0x00200000)) #define IB_PORT_CAP_HAS_CAP_NTC (CL_HTON32(0x00400000)) #define IB_PORT_CAP_HAS_BM (CL_HTON32(0x00800000)) #define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_HTON32(0x01000000)) #define IB_PORT_CAP_HAS_CLIENT_REREG (CL_HTON32(0x02000000)) #define IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC (CL_HTON32(0x04000000)) #define IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL (CL_HTON32(0x08000000)) #define IB_PORT_CAP_HAS_VEND_MADS (CL_HTON32(0x10000000)) #define IB_PORT_CAP_HAS_MCAST_PKEY_TRAP_SUPPRESS (CL_HTON32(0x20000000)) #define IB_PORT_CAP_HAS_MCAST_FDB_TOP (CL_HTON32(0x40000000)) #define IB_PORT_CAP_HAS_HIER_INFO (CL_HTON32(0x80000000)) #define IB_PORT_CAP2_IS_SET_NODE_DESC_SUPPORTED (CL_HTON16(0x0001)) #define IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED (CL_HTON16(0x0002)) /****s* IBA Base: Types/ib_port_info_ext_t * NAME * ib_port_info_ext_t * * DESCRIPTION * IBA defined PortInfoExtended. (14.2.5.19) * * SYNOPSIS */ #include typedef struct _ib_port_info_ext { ib_net32_t cap_mask; ib_net16_t fec_mode_active; ib_net16_t fdr_fec_mode_sup; ib_net16_t fdr_fec_mode_enable; ib_net16_t edr_fec_mode_sup; ib_net16_t edr_fec_mode_enable; uint8_t reserved[50]; } PACK_SUFFIX ib_port_info_ext_t; #include /************/ #define IB_PORT_EXT_NO_FEC_MODE_ACTIVE 0 #define IB_PORT_EXT_FIRE_CODE_FEC_MODE_ACTIVE (CL_HTON16(0x0001)) #define IB_PORT_EXT_RS_FEC_MODE_ACTIVE (CL_HTON16(0x0002)) #define IB_PORT_EXT_LOW_LATENCY_RS_FEC_MODE_ACTIVE (CL_HTON16(0x0003)) #define IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED (CL_HTON32(0x00000001)) /****f* IBA Base: Types/ib_port_info_get_port_state * NAME * ib_port_info_get_port_state * * DESCRIPTION * Returns the port state. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_port_state(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->state_info1 & IB_PORT_STATE_MASK)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Port state. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_port_state * NAME * ib_port_info_set_port_state * * DESCRIPTION * Sets the port state. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_port_state(IN ib_port_info_t * const p_pi, IN const uint8_t port_state) { p_pi->state_info1 = (uint8_t) ((p_pi->state_info1 & 0xF0) | port_state); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * port_state * [in] Port state value to set. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_vl_cap * NAME * ib_port_info_get_vl_cap * * DESCRIPTION * Gets the VL Capability of a port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_vl_cap(IN const ib_port_info_t * const p_pi) { return ((p_pi->vl_cap >> 4) & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * VL_CAP field * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_init_type * NAME * ib_port_info_get_init_type * * DESCRIPTION * Gets the init type of a port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_init_type(IN const ib_port_info_t * const p_pi) { return (uint8_t) (p_pi->vl_cap & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * InitType field * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_op_vls * NAME * ib_port_info_get_op_vls * * DESCRIPTION * Gets the operational VLs on a port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_op_vls(IN const ib_port_info_t * const p_pi) { return ((p_pi->vl_enforce >> 4) & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * OP_VLS field * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_op_vls * NAME * ib_port_info_set_op_vls * * DESCRIPTION * Sets the operational VLs on a port. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_op_vls(IN ib_port_info_t * const p_pi, IN const uint8_t op_vls) { p_pi->vl_enforce = (uint8_t) ((p_pi->vl_enforce & 0x0F) | (op_vls << 4)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * op_vls * [in] Encoded operation VLs value. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_state_no_change * NAME * ib_port_info_set_state_no_change * * DESCRIPTION * Sets the port state fields to the value for "no change". * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_state_no_change(IN ib_port_info_t * const p_pi) { ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE); p_pi->state_info2 = 0; } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_sup * NAME * ib_port_info_get_link_speed_sup * * DESCRIPTION * Returns the encoded value for the link speed supported. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_sup(IN const ib_port_info_t * const p_pi) { return ((uint8_t) ((p_pi->state_info1 & IB_PORT_LINK_SPEED_SUPPORTED_MASK) >> IB_PORT_LINK_SPEED_SHIFT)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the encoded value for the link speed supported. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_link_speed_sup * NAME * ib_port_info_set_link_speed_sup * * DESCRIPTION * Given an integer of the supported link speed supported. * Set the appropriate bits in state_info1 * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_link_speed_sup(IN uint8_t const speed, IN ib_port_info_t * p_pi) { p_pi->state_info1 = (~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1) | (IB_PORT_LINK_SPEED_SUPPORTED_MASK & (speed << IB_PORT_LINK_SPEED_SHIFT)); } /* * PARAMETERS * speed * [in] Supported Speeds Code. * * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_port_phys_state * NAME * ib_port_info_get_port_phys_state * * DESCRIPTION * Returns the encoded value for the port physical state. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_port_phys_state(IN const ib_port_info_t * const p_pi) { return ((uint8_t) ((p_pi->state_info2 & IB_PORT_PHYS_STATE_MASK) >> IB_PORT_PHYS_STATE_SHIFT)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the encoded value for the port physical state. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_port_phys_state * NAME * ib_port_info_set_port_phys_state * * DESCRIPTION * Given an integer of the port physical state, * Set the appropriate bits in state_info2 * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_port_phys_state(IN uint8_t const phys_state, IN ib_port_info_t * p_pi) { p_pi->state_info2 = (~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2) | (IB_PORT_PHYS_STATE_MASK & (phys_state << IB_PORT_PHYS_STATE_SHIFT)); } /* * PARAMETERS * phys_state * [in] port physical state. * * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * This function does not return a value. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_down_def_state * NAME * ib_port_info_get_link_down_def_state * * DESCRIPTION * Returns the link down default state. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_down_def_state(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * link down default state of the port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_link_down_def_state * NAME * ib_port_info_set_link_down_def_state * * DESCRIPTION * Sets the link down default state of the port. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_link_down_def_state(IN ib_port_info_t * const p_pi, IN const uint8_t link_dwn_state) { p_pi->state_info2 = (uint8_t) ((p_pi->state_info2 & 0xF0) | link_dwn_state); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * link_dwn_state * [in] Link down default state of the port. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_active * NAME * ib_port_info_get_link_speed_active * * DESCRIPTION * Returns the Link Speed Active value assigned to this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_active(IN const ib_port_info_t * const p_pi) { return ((uint8_t) ((p_pi->link_speed & IB_PORT_LINK_SPEED_ACTIVE_MASK) >> IB_PORT_LINK_SPEED_SHIFT)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the link speed active value assigned to this port. * * NOTES * * SEE ALSO *********/ #define IB_LINK_WIDTH_ACTIVE_1X 1 #define IB_LINK_WIDTH_ACTIVE_4X 2 #define IB_LINK_WIDTH_ACTIVE_8X 4 #define IB_LINK_WIDTH_ACTIVE_12X 8 #define IB_LINK_SPEED_ACTIVE_EXTENDED 0 #define IB_LINK_SPEED_ACTIVE_2_5 1 #define IB_LINK_SPEED_ACTIVE_5 2 #define IB_LINK_SPEED_ACTIVE_10 4 #define IB_LINK_SPEED_EXT_ACTIVE_NONE 0 #define IB_LINK_SPEED_EXT_ACTIVE_14 1 #define IB_LINK_SPEED_EXT_ACTIVE_25 2 #define IB_LINK_SPEED_EXT_DISABLE 30 #define IB_LINK_SPEED_EXT_SET_LSES 31 /* following v1 ver1.2 p901 */ #define IB_PATH_RECORD_RATE_2_5_GBS 2 #define IB_PATH_RECORD_RATE_10_GBS 3 #define IB_PATH_RECORD_RATE_30_GBS 4 #define IB_PATH_RECORD_RATE_5_GBS 5 #define IB_PATH_RECORD_RATE_20_GBS 6 #define IB_PATH_RECORD_RATE_40_GBS 7 #define IB_PATH_RECORD_RATE_60_GBS 8 #define IB_PATH_RECORD_RATE_80_GBS 9 #define IB_PATH_RECORD_RATE_120_GBS 10 #define IB_PATH_RECORD_RATE_14_GBS 11 #define IB_PATH_RECORD_RATE_56_GBS 12 #define IB_PATH_RECORD_RATE_112_GBS 13 #define IB_PATH_RECORD_RATE_168_GBS 14 #define IB_PATH_RECORD_RATE_25_GBS 15 #define IB_PATH_RECORD_RATE_100_GBS 16 #define IB_PATH_RECORD_RATE_200_GBS 17 #define IB_PATH_RECORD_RATE_300_GBS 18 #define IB_MIN_RATE IB_PATH_RECORD_RATE_2_5_GBS #define IB_MAX_RATE IB_PATH_RECORD_RATE_300_GBS static inline uint8_t OSM_API ib_port_info_get_link_speed_ext_active(IN const ib_port_info_t * const p_pi); /****f* IBA Base: Types/ib_port_info_compute_rate * NAME * ib_port_info_compute_rate * * DESCRIPTION * Returns the encoded value for the path rate. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_compute_rate(IN const ib_port_info_t * const p_pi, IN const int extended) { uint8_t rate = 0; if (extended) { switch (ib_port_info_get_link_speed_ext_active(p_pi)) { case IB_LINK_SPEED_EXT_ACTIVE_14: switch (p_pi->link_width_active) { case IB_LINK_WIDTH_ACTIVE_1X: rate = IB_PATH_RECORD_RATE_14_GBS; break; case IB_LINK_WIDTH_ACTIVE_4X: rate = IB_PATH_RECORD_RATE_56_GBS; break; case IB_LINK_WIDTH_ACTIVE_8X: rate = IB_PATH_RECORD_RATE_112_GBS; break; case IB_LINK_WIDTH_ACTIVE_12X: rate = IB_PATH_RECORD_RATE_168_GBS; break; default: rate = IB_PATH_RECORD_RATE_14_GBS; break; } break; case IB_LINK_SPEED_EXT_ACTIVE_25: switch (p_pi->link_width_active) { case IB_LINK_WIDTH_ACTIVE_1X: rate = IB_PATH_RECORD_RATE_25_GBS; break; case IB_LINK_WIDTH_ACTIVE_4X: rate = IB_PATH_RECORD_RATE_100_GBS; break; case IB_LINK_WIDTH_ACTIVE_8X: rate = IB_PATH_RECORD_RATE_200_GBS; break; case IB_LINK_WIDTH_ACTIVE_12X: rate = IB_PATH_RECORD_RATE_300_GBS; break; default: rate = IB_PATH_RECORD_RATE_25_GBS; break; } break; /* IB_LINK_SPEED_EXT_ACTIVE_NONE and any others */ default: break; } if (rate) return rate; } switch (ib_port_info_get_link_speed_active(p_pi)) { case IB_LINK_SPEED_ACTIVE_2_5: switch (p_pi->link_width_active) { case IB_LINK_WIDTH_ACTIVE_1X: rate = IB_PATH_RECORD_RATE_2_5_GBS; break; case IB_LINK_WIDTH_ACTIVE_4X: rate = IB_PATH_RECORD_RATE_10_GBS; break; case IB_LINK_WIDTH_ACTIVE_8X: rate = IB_PATH_RECORD_RATE_20_GBS; break; case IB_LINK_WIDTH_ACTIVE_12X: rate = IB_PATH_RECORD_RATE_30_GBS; break; default: rate = IB_PATH_RECORD_RATE_2_5_GBS; break; } break; case IB_LINK_SPEED_ACTIVE_5: switch (p_pi->link_width_active) { case IB_LINK_WIDTH_ACTIVE_1X: rate = IB_PATH_RECORD_RATE_5_GBS; break; case IB_LINK_WIDTH_ACTIVE_4X: rate = IB_PATH_RECORD_RATE_20_GBS; break; case IB_LINK_WIDTH_ACTIVE_8X: rate = IB_PATH_RECORD_RATE_40_GBS; break; case IB_LINK_WIDTH_ACTIVE_12X: rate = IB_PATH_RECORD_RATE_60_GBS; break; default: rate = IB_PATH_RECORD_RATE_5_GBS; break; } break; case IB_LINK_SPEED_ACTIVE_10: switch (p_pi->link_width_active) { case IB_LINK_WIDTH_ACTIVE_1X: rate = IB_PATH_RECORD_RATE_10_GBS; break; case IB_LINK_WIDTH_ACTIVE_4X: rate = IB_PATH_RECORD_RATE_40_GBS; break; case IB_LINK_WIDTH_ACTIVE_8X: rate = IB_PATH_RECORD_RATE_80_GBS; break; case IB_LINK_WIDTH_ACTIVE_12X: rate = IB_PATH_RECORD_RATE_120_GBS; break; default: rate = IB_PATH_RECORD_RATE_10_GBS; break; } break; default: rate = IB_PATH_RECORD_RATE_2_5_GBS; break; } return rate; } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * extended * [in] Indicates whether or not to use extended link speeds. * * RETURN VALUES * Returns the encoded value for the link speed supported. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_path_get_ipd * NAME * ib_path_get_ipd * * DESCRIPTION * Returns the encoded value for the inter packet delay. * * SYNOPSIS */ static inline uint8_t OSM_API ib_path_get_ipd(IN uint8_t local_link_width_supported, IN uint8_t path_rec_rate) { uint8_t ipd = 0; switch (local_link_width_supported) { /* link_width_supported = 1: 1x */ case 1: break; /* link_width_supported = 3: 1x or 4x */ case 3: switch (path_rec_rate & 0x3F) { case IB_PATH_RECORD_RATE_2_5_GBS: ipd = 3; break; default: break; } break; /* link_width_supported = 11: 1x or 4x or 12x */ case 11: switch (path_rec_rate & 0x3F) { case IB_PATH_RECORD_RATE_2_5_GBS: ipd = 11; break; case IB_PATH_RECORD_RATE_10_GBS: ipd = 2; break; default: break; } break; default: break; } return ipd; } /* * PARAMETERS * local_link_width_supported * [in] link with supported for this port * * path_rec_rate * [in] rate field of the path record * * RETURN VALUES * Returns the ipd * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_mtu_cap * NAME * ib_port_info_get_mtu_cap * * DESCRIPTION * Returns the encoded value for the maximum MTU supported by this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_mtu_cap(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->mtu_cap & 0x0F)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the encooded value for the maximum MTU supported by this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_neighbor_mtu * NAME * ib_port_info_get_neighbor_mtu * * DESCRIPTION * Returns the encoded value for the neighbor MTU supported by this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_neighbor_mtu(IN const ib_port_info_t * const p_pi) { return ((uint8_t) ((p_pi->mtu_smsl & 0xF0) >> 4)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the encoded value for the neighbor MTU at this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_neighbor_mtu * NAME * ib_port_info_set_neighbor_mtu * * DESCRIPTION * Sets the Neighbor MTU value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_neighbor_mtu(IN ib_port_info_t * const p_pi, IN const uint8_t mtu) { CL_ASSERT(mtu <= 5); CL_ASSERT(mtu != 0); p_pi->mtu_smsl = (uint8_t) ((p_pi->mtu_smsl & 0x0F) | (mtu << 4)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * mtu * [in] Encoded MTU value to set * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_master_smsl * NAME * ib_port_info_get_master_smsl * * DESCRIPTION * Returns the encoded value for the Master SMSL at this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_master_smsl(IN const ib_port_info_t * const p_pi) { return (uint8_t) (p_pi->mtu_smsl & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the encoded value for the Master SMSL at this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_master_smsl * NAME * ib_port_info_set_master_smsl * * DESCRIPTION * Sets the Master SMSL value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_master_smsl(IN ib_port_info_t * const p_pi, IN const uint8_t smsl) { p_pi->mtu_smsl = (uint8_t) ((p_pi->mtu_smsl & 0xF0) | smsl); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * mtu * [in] Encoded Master SMSL value to set * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_timeout * NAME * ib_port_info_set_timeout * * DESCRIPTION * Sets the encoded subnet timeout value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_timeout(IN ib_port_info_t * const p_pi, IN const uint8_t timeout) { CL_ASSERT(timeout <= 0x1F); p_pi->subnet_timeout = (uint8_t) ((p_pi->subnet_timeout & 0xE0) | (timeout & 0x1F)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * timeout * [in] Encoded timeout value to set * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_client_rereg * NAME * ib_port_info_set_client_rereg * * DESCRIPTION * Sets the encoded client reregistration bit value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_client_rereg(IN ib_port_info_t * const p_pi, IN const uint8_t client_rereg) { CL_ASSERT(client_rereg <= 0x1); p_pi->subnet_timeout = (uint8_t) ((p_pi->subnet_timeout & 0x7F) | (client_rereg << 7)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * client_rereg * [in] Client reregistration value to set (either 1 or 0). * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_mcast_pkey_trap_suppress * NAME * ib_port_info_set_mcast_pkey_trap_suppress * * DESCRIPTION * Sets the encoded multicast pkey trap suppression enabled bit value * in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_mcast_pkey_trap_suppress(IN ib_port_info_t * const p_pi, IN const uint8_t trap_suppress) { CL_ASSERT(trap_suppress <= 0x1); p_pi->subnet_timeout = (uint8_t) ((p_pi->subnet_timeout & 0xBF) | (trap_suppress << 6)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * trap_suppress * [in] Multicast pkey trap suppression enabled value to set * (either 1 or 0). * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_timeout * NAME * ib_port_info_get_timeout * * DESCRIPTION * Gets the encoded subnet timeout value in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_timeout(IN ib_port_info_t const *p_pi) { return (p_pi->subnet_timeout & 0x1F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * The encoded timeout value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_ext_active * NAME * ib_port_info_get_link_speed_ext_active * * DESCRIPTION * Gets the encoded LinkSpeedExtActive value in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_ext_active(IN const ib_port_info_t * const p_pi) { return ((p_pi->link_speed_ext & 0xF0) >> 4); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * The encoded LinkSpeedExtActive value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_ext_sup * NAME * ib_port_info_get_link_speed_ext_sup * * DESCRIPTION * Returns the encoded value for the link speed extended supported. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_ext_sup(IN const ib_port_info_t * const p_pi) { return (p_pi->link_speed_ext & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * The encoded LinkSpeedExtSupported value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_ext_enabled * NAME * ib_port_info_get_link_speed_ext_enabled * * DESCRIPTION * Gets the encoded LinkSpeedExtEnabled value in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_ext_enabled(IN const ib_port_info_t * const p_pi) { return (p_pi->link_speed_ext_enabled & 0x1F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * The encoded LinkSpeedExtEnabled value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_link_speed_ext_enabled * NAME * ib_port_info_set_link_speed_ext_enabled * * DESCRIPTION * Sets the link speed extended enabled value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_link_speed_ext_enabled(IN ib_port_info_t * const p_pi, IN const uint8_t link_speed_ext_enabled) { CL_ASSERT(link_speed_ext_enabled <= 0x1F); p_pi->link_speed_ext_enabled = link_speed_ext_enabled & 0x1F; } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * link_speed_ext_enabled * [in] link speed extehded enabled value to set. * * RETURN VALUES * The encoded LinkSpeedExtEnabled value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_resp_time_value * NAME * ib_port_info_get_resp_time_value * * DESCRIPTION * Gets the encoded resp time value in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_resp_time_value(IN const ib_port_info_t * const p_pi) { return (p_pi->resp_time_value & 0x1F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * The encoded resp time value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_client_rereg * NAME * ib_port_info_get_client_rereg * * DESCRIPTION * Gets the encoded client reregistration bit value in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_client_rereg(IN ib_port_info_t const *p_pi) { return ((p_pi->subnet_timeout & 0x80) >> 7); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Client reregistration value (either 1 or 0). * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_mcast_pkey_trap_suppress * NAME * ib_port_info_get_mcast_pkey_trap_suppress * * DESCRIPTION * Gets the encoded multicast pkey trap suppression enabled bit value * in the PortInfo attribute. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_mcast_pkey_trap_suppress(IN ib_port_info_t const *p_pi) { return ((p_pi->subnet_timeout & 0x40) >> 6); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Multicast PKey trap suppression enabled value (either 1 or 0). * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_hoq_lifetime * NAME * ib_port_info_set_hoq_lifetime * * DESCRIPTION * Sets the Head of Queue Lifetime for which a packet can live in the head * of VL queue * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_hoq_lifetime(IN ib_port_info_t * const p_pi, IN const uint8_t hoq_life) { p_pi->vl_stall_life = (uint8_t) ((hoq_life & 0x1f) | (p_pi->vl_stall_life & 0xe0)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * hoq_life * [in] Encoded lifetime value to set * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_hoq_lifetime * NAME * ib_port_info_get_hoq_lifetime * * DESCRIPTION * Gets the Head of Queue Lifetime for which a packet can live in the head * of VL queue * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_hoq_lifetime(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->vl_stall_life & 0x1f)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Encoded lifetime value * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_vl_stall_count * NAME * ib_port_info_set_vl_stall_count * * DESCRIPTION * Sets the VL Stall Count which define the number of contiguous * HLL (hoq) drops that will put the VL into stalled mode. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_vl_stall_count(IN ib_port_info_t * const p_pi, IN const uint8_t vl_stall_count) { p_pi->vl_stall_life = (uint8_t) ((p_pi->vl_stall_life & 0x1f) | ((vl_stall_count << 5) & 0xe0)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * vl_stall_count * [in] value to set * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_vl_stall_count * NAME * ib_port_info_get_vl_stall_count * * DESCRIPTION * Gets the VL Stall Count which define the number of contiguous * HLL (hoq) drops that will put the VL into stalled mode * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_vl_stall_count(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->vl_stall_life & 0xe0) >> 5); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * vl stall count * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_lmc * NAME * ib_port_info_get_lmc * * DESCRIPTION * Returns the LMC value assigned to this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_lmc(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->mkey_lmc & IB_PORT_LMC_MASK)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the LMC value assigned to this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_lmc * NAME * ib_port_info_set_lmc * * DESCRIPTION * Sets the LMC value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_lmc(IN ib_port_info_t * const p_pi, IN const uint8_t lmc) { CL_ASSERT(lmc <= IB_PORT_LMC_MAX); p_pi->mkey_lmc = (uint8_t) ((p_pi->mkey_lmc & 0xF8) | lmc); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * lmc * [in] LMC value to set, must be less than 7. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_link_speed_enabled * NAME * ib_port_info_get_link_speed_enabled * * DESCRIPTION * Returns the link speed enabled value assigned to this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_link_speed_enabled(IN const ib_port_info_t * const p_pi) { return ((uint8_t) (p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Port state. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_link_speed_enabled * NAME * ib_port_info_set_link_speed_enabled * * DESCRIPTION * Sets the link speed enabled value in the PortInfo attribute. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_link_speed_enabled(IN ib_port_info_t * const p_pi, IN const uint8_t link_speed_enabled) { p_pi->link_speed = (uint8_t) ((p_pi->link_speed & 0xF0) | link_speed_enabled); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * link_speed_enabled * [in] link speed enabled value to set. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_mpb * NAME * ib_port_info_get_mpb * * DESCRIPTION * Returns the M_Key protect bits assigned to this port. * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_mpb(IN const ib_port_info_t * const p_pi) { return ((uint8_t) ((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >> IB_PORT_MPB_SHIFT)); } /* * PARAMETERS * p_ni * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the M_Key protect bits assigned to this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_mpb * NAME * ib_port_info_set_mpb * * DESCRIPTION * Set the M_Key protect bits of this port. * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_mpb(IN ib_port_info_t * p_pi, IN uint8_t mpb) { p_pi->mkey_lmc = (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) | (IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT)); } /* * PARAMETERS * mpb * [in] M_Key protect bits * p_ni * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_local_phy_err_thd * NAME * ib_port_info_get_local_phy_err_thd * * DESCRIPTION * Returns the Phy Link Threshold * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_local_phy_err_thd(IN const ib_port_info_t * const p_pi) { return (uint8_t) ((p_pi->error_threshold & 0xF0) >> 4); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the Phy Link error threshold assigned to this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_overrun_err_thd * NAME * ib_port_info_get_local_overrun_err_thd * * DESCRIPTION * Returns the Credits Overrun Errors Threshold * * SYNOPSIS */ static inline uint8_t OSM_API ib_port_info_get_overrun_err_thd(IN const ib_port_info_t * const p_pi) { return (uint8_t) (p_pi->error_threshold & 0x0F); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * Returns the Credits Overrun errors threshold assigned to this port. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd * NAME * ib_port_info_set_phy_and_overrun_err_thd * * DESCRIPTION * Sets the Phy Link and Credits Overrun Errors Threshold * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_phy_and_overrun_err_thd(IN ib_port_info_t * const p_pi, IN uint8_t phy_threshold, IN uint8_t overrun_threshold) { p_pi->error_threshold = (uint8_t) (((phy_threshold & 0x0F) << 4) | (overrun_threshold & 0x0F)); } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * phy_threshold * [in] Physical Link Errors Threshold above which Trap 129 is generated * * overrun_threshold * [in] Credits overrun Errors Threshold above which Trap 129 is generated * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_get_m_key * NAME * ib_port_info_get_m_key * * DESCRIPTION * Gets the M_Key * * SYNOPSIS */ static inline ib_net64_t OSM_API ib_port_info_get_m_key(IN const ib_port_info_t * const p_pi) { return p_pi->m_key; } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * * RETURN VALUES * M_Key. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_port_info_set_m_key * NAME * ib_port_info_set_m_key * * DESCRIPTION * Sets the M_Key value * * SYNOPSIS */ static inline void OSM_API ib_port_info_set_m_key(IN ib_port_info_t * const p_pi, IN ib_net64_t m_key) { p_pi->m_key = m_key; } /* * PARAMETERS * p_pi * [in] Pointer to a PortInfo attribute. * m_key * [in] M_Key value. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****s* IBA Base: Types/ib_mlnx_ext_port_info_t * NAME * ib_mlnx_ext_port_info_t * * DESCRIPTION * Mellanox ExtendedPortInfo (Vendor specific SM class attribute). * * SYNOPSIS */ #include typedef struct _ib_mlnx_ext_port_info { uint8_t resvd1[3]; uint8_t state_change_enable; uint8_t resvd2[3]; uint8_t link_speed_supported; uint8_t resvd3[3]; uint8_t link_speed_enabled; uint8_t resvd4[3]; uint8_t link_speed_active; uint8_t resvd5[48]; } PACK_SUFFIX ib_mlnx_ext_port_info_t; #include /************/ #define FDR10 0x01 typedef uint8_t ib_svc_name_t[64]; #include typedef struct _ib_service_record { ib_net64_t service_id; ib_gid_t service_gid; ib_net16_t service_pkey; ib_net16_t resv; ib_net32_t service_lease; uint8_t service_key[16]; ib_svc_name_t service_name; uint8_t service_data8[16]; ib_net16_t service_data16[8]; ib_net32_t service_data32[4]; ib_net64_t service_data64[2]; } PACK_SUFFIX ib_service_record_t; #include #include typedef struct _ib_portinfo_record { ib_net16_t lid; uint8_t port_num; uint8_t options; ib_port_info_t port_info; uint8_t pad[4]; } PACK_SUFFIX ib_portinfo_record_t; #include #include typedef struct _ib_portinfoext_record { ib_net16_t lid; uint8_t port_num; uint8_t options; ib_port_info_ext_t port_info_ext; } PACK_SUFFIX ib_portinfoext_record_t; #include #include typedef struct _ib_link_record { ib_net16_t from_lid; uint8_t from_port_num; uint8_t to_port_num; ib_net16_t to_lid; uint8_t pad[2]; } PACK_SUFFIX ib_link_record_t; #include #include typedef struct _ib_sminfo_record { ib_net16_t lid; uint16_t resv0; ib_sm_info_t sm_info; uint8_t pad[7]; } PACK_SUFFIX ib_sminfo_record_t; #include /****s* IBA Base: Types/ib_lft_record_t * NAME * ib_lft_record_t * * DESCRIPTION * IBA defined LinearForwardingTableRecord (15.2.5.6) * * SYNOPSIS */ #include typedef struct _ib_lft_record { ib_net16_t lid; ib_net16_t block_num; uint32_t resv0; uint8_t lft[64]; } PACK_SUFFIX ib_lft_record_t; #include /************/ /****s* IBA Base: Types/ib_mft_record_t * NAME * ib_mft_record_t * * DESCRIPTION * IBA defined MulticastForwardingTableRecord (15.2.5.8) * * SYNOPSIS */ #include typedef struct _ib_mft_record { ib_net16_t lid; ib_net16_t position_block_num; uint32_t resv0; ib_net16_t mft[IB_MCAST_BLOCK_SIZE]; } PACK_SUFFIX ib_mft_record_t; #include /************/ /****s* IBA Base: Types/ib_switch_info_t * NAME * ib_switch_info_t * * DESCRIPTION * IBA defined SwitchInfo. (14.2.5.4) * * SYNOPSIS */ #include typedef struct _ib_switch_info { ib_net16_t lin_cap; ib_net16_t rand_cap; ib_net16_t mcast_cap; ib_net16_t lin_top; uint8_t def_port; uint8_t def_mcast_pri_port; uint8_t def_mcast_not_port; uint8_t life_state; ib_net16_t lids_per_port; ib_net16_t enforce_cap; uint8_t flags; uint8_t resvd; ib_net16_t mcast_top; } PACK_SUFFIX ib_switch_info_t; #include /************/ #include typedef struct _ib_switch_info_record { ib_net16_t lid; uint16_t resv0; ib_switch_info_t switch_info; } PACK_SUFFIX ib_switch_info_record_t; #include #define IB_SWITCH_PSC 0x04 /****f* IBA Base: Types/ib_switch_info_get_state_change * NAME * ib_switch_info_get_state_change * * DESCRIPTION * Returns the value of the state change flag. * * SYNOPSIS */ static inline boolean_t OSM_API ib_switch_info_get_state_change(IN const ib_switch_info_t * const p_si) { return ((p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * * RETURN VALUES * Returns the value of the state change flag. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_switch_info_clear_state_change * NAME * ib_switch_info_clear_state_change * * DESCRIPTION * Clears the switch's state change bit. * * SYNOPSIS */ static inline void OSM_API ib_switch_info_clear_state_change(IN ib_switch_info_t * const p_si) { p_si->life_state = (uint8_t) (p_si->life_state & 0xFB); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * * RETURN VALUES * None * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_switch_info_state_change_set * NAME * ib_switch_info_state_change_set * * DESCRIPTION * Clears the switch's state change bit. * * SYNOPSIS */ static inline void OSM_API ib_switch_info_state_change_set(IN ib_switch_info_t * const p_si) { p_si->life_state = (uint8_t) ((p_si->life_state & ~IB_SWITCH_PSC) | IB_SWITCH_PSC); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * * RETURN VALUES * None * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_switch_info_get_opt_sl2vlmapping * NAME * ib_switch_info_get_state_opt_sl2vlmapping * * DESCRIPTION * Returns the value of the optimized SLtoVLMapping programming flag. * * SYNOPSIS */ static inline boolean_t OSM_API ib_switch_info_get_opt_sl2vlmapping(IN const ib_switch_info_t * const p_si) { return ((p_si->life_state & 0x01) == 0x01); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * * RETURN VALUES * Returns the value of the optimized SLtoVLMapping programming flag. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_switch_info_set_life_time * NAME * ib_switch_info_set_life_time * * DESCRIPTION * Sets the value of LifeTimeValue. * * SYNOPSIS */ static inline void OSM_API ib_switch_info_set_life_time(IN ib_switch_info_t * const p_si, IN const uint8_t life_time_val) { p_si->life_state = (p_si->life_state & 0x1f) | (life_time_val << 3); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * life_time_val * [in] LiveTimeValue. * * RETURN VALUES * None. * * NOTES * * SEE ALSO *********/ /****f* IBA Base: Types/ib_switch_info_is_enhanced_port0 * NAME * ib_switch_info_is_enhanced_port0 * * DESCRIPTION * Returns TRUE if the enhancedPort0 bit is on (meaning the switch * port zero supports enhanced functions). * Returns FALSE otherwise. * * SYNOPSIS */ static inline boolean_t OSM_API ib_switch_info_is_enhanced_port0(IN const ib_switch_info_t * const p_si) { return ((p_si->flags & 0x08) == 0x08); } /* * PARAMETERS * p_si * [in] Pointer to a SwitchInfo attribute. * * RETURN VALUES * Returns TRUE if the switch supports enhanced port 0. FALSE otherwise. * * NOTES * * SEE ALSO *********/ /****s* IBA Base: Types/ib_guid_info_t * NAME * ib_guid_info_t * * DESCRIPTION * IBA defined GuidInfo. (14.2.5.5) * * SYNOPSIS */ #define GUID_TABLE_MAX_ENTRIES 8 #include typedef struct _ib_guid_info { ib_net64_t guid[GUID_TABLE_MAX_ENTRIES]; } PACK_SUFFIX ib_guid_info_t; #include /************/ #include typedef struct _ib_guidinfo_record { ib_net16_t lid; uint8_t block_num; uint8_t resv; uint32_t reserved; ib_guid_info_t guid_info; } PACK_SUFFIX ib_guidinfo_record_t; #include #define IB_MULTIPATH_MAX_GIDS 11 /* Support max that can fit into first MAD (for now) */ #include typedef struct _ib_multipath_rec_t { ib_net32_t hop_flow_raw; uint8_t tclass; uint8_t num_path; ib_net16_t pkey; ib_net16_t qos_class_sl; uint8_t mtu; uint8_t rate; uint8_t pkt_life; uint8_t service_id_8msb; uint8_t independence; /* formerly resv2 */ uint8_t sgid_count; uint8_t dgid_count; uint8_t service_id_56lsb[7]; ib_gid_t gids[IB_MULTIPATH_MAX_GIDS]; } PACK_SUFFIX ib_multipath_rec_t; #include /* * FIELDS * hop_flow_raw * Global routing parameters: hop count, flow label and raw bit. * * tclass * Another global routing parameter. * * num_path * Reversible path - 1 bit to say if path is reversible. * num_path [6:0] In queries, maximum number of paths to return. * In responses, undefined. * * pkey * Partition key (P_Key) to use on this path. * * qos_class_sl * QoS class and service level to use on this path. * * mtu * MTU and MTU selector fields to use on this path * rate * Rate and rate selector fields to use on this path. * * pkt_life * Packet lifetime * * service_id_8msb * 8 most significant bits of Service ID * * service_id_56lsb * 56 least significant bits of Service ID * * preference * Indicates the relative merit of this path versus other path * records returned from the SA. Lower numbers are better. * * SEE ALSO *********/ /****f* IBA Base: Types/ib_multipath_rec_num_path * NAME * ib_multipath_rec_num_path * * DESCRIPTION * Get max number of paths to return. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_num_path(IN const ib_multipath_rec_t * const p_rec) { return (p_rec->num_path & 0x7F); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Maximum number of paths to return for each unique SGID_DGID combination. * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_set_sl * NAME * ib_multipath_rec_set_sl * * DESCRIPTION * Set path service level. * * SYNOPSIS */ static inline void OSM_API ib_multipath_rec_set_sl( IN ib_multipath_rec_t* const p_rec, IN const uint8_t sl ) { p_rec->qos_class_sl = (p_rec->qos_class_sl & CL_HTON16(IB_MULTIPATH_REC_QOS_CLASS_MASK)) | cl_hton16(sl & IB_MULTIPATH_REC_SL_MASK); } /* * PARAMETERS * p_rec * [in] Pointer to the MultiPath record object. * * sl * [in] Service level to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_sl * NAME * ib_multipath_rec_sl * * DESCRIPTION * Get multipath service level. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_sl(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) ((cl_ntoh16(p_rec->qos_class_sl)) & IB_MULTIPATH_REC_SL_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * SL. * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_set_qos_class * NAME * ib_multipath_rec_set_qos_class * * DESCRIPTION * Set path QoS class. * * SYNOPSIS */ static inline void OSM_API ib_multipath_rec_set_qos_class( IN ib_multipath_rec_t* const p_rec, IN const uint16_t qos_class ) { p_rec->qos_class_sl = (p_rec->qos_class_sl & CL_HTON16(IB_MULTIPATH_REC_SL_MASK)) | cl_hton16(qos_class << 4); } /* * PARAMETERS * p_rec * [in] Pointer to the MultiPath record object. * * qos_class * [in] QoS class to set. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_qos_class * NAME * ib_multipath_rec_qos_class * * DESCRIPTION * Get QoS class. * * SYNOPSIS */ static inline uint16_t OSM_API ib_multipath_rec_qos_class( IN const ib_multipath_rec_t* const p_rec ) { return (cl_ntoh16( p_rec->qos_class_sl ) >> 4); } /* * PARAMETERS * p_rec * [in] Pointer to the MultiPath record object. * * RETURN VALUES * QoS class of the MultiPath record. * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_mtu * NAME * ib_multipath_rec_mtu * * DESCRIPTION * Get encoded path MTU. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_mtu(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) (p_rec->mtu & IB_MULTIPATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded path MTU. * 1: 256 * 2: 512 * 3: 1024 * 4: 2048 * 5: 4096 * others: reserved * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_mtu_sel * NAME * ib_multipath_rec_mtu_sel * * DESCRIPTION * Get encoded multipath MTU selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_mtu_sel(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) ((p_rec->mtu & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded path MTU selector value (for queries). * 0: greater than MTU specified * 1: less than MTU specified * 2: exactly the MTU specified * 3: largest MTU available * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_rate * NAME * ib_multipath_rec_rate * * DESCRIPTION * Get encoded multipath rate. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_rate(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) (p_rec->rate & IB_MULTIPATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded multipath rate. * 2: 2.5 Gb/sec. * 3: 10 Gb/sec. * 4: 30 Gb/sec. * 5: 5 Gb/sec. * 6: 20 Gb/sec. * 7: 40 Gb/sec. * 8: 60 Gb/sec. * 9: 80 Gb/sec. * 10: 120 Gb/sec. * 11: 14 Gb/sec. * 12: 56 Gb/sec. * 13: 112 Gb/sec. * 14: 168 Gb/sec. * 15: 25 Gb/sec. * 16: 100 Gb/sec. * 17: 200 Gb/sec. * 18: 300 Gb/sec. * others: reserved * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_rate_sel * NAME * ib_multipath_rec_rate_sel * * DESCRIPTION * Get encoded multipath rate selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_rate_sel(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) ((p_rec->rate & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded path rate selector value (for queries). * 0: greater than rate specified * 1: less than rate specified * 2: exactly the rate specified * 3: largest rate available * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_pkt_life * NAME * ib_multipath_rec_pkt_life * * DESCRIPTION * Get encoded multipath pkt_life. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_pkt_life(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) (p_rec->pkt_life & IB_MULTIPATH_REC_BASE_MASK)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded multipath pkt_life = 4.096 usec * 2 ** PacketLifeTime. * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_pkt_life_sel * NAME * ib_multipath_rec_pkt_life_sel * * DESCRIPTION * Get encoded multipath pkt_lifetime selector. * * SYNOPSIS */ static inline uint8_t OSM_API ib_multipath_rec_pkt_life_sel(IN const ib_multipath_rec_t * const p_rec) { return ((uint8_t) ((p_rec->pkt_life & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6)); } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Encoded path pkt_lifetime selector value (for queries). * 0: greater than rate specified * 1: less than rate specified * 2: exactly the rate specified * 3: smallest packet lifetime available * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ /****f* IBA Base: Types/ib_multipath_rec_service_id * NAME * ib_multipath_rec_service_id * * DESCRIPTION * Get multipath service id. * * SYNOPSIS */ static inline ib_net64_t OSM_API ib_multipath_rec_service_id(IN const ib_multipath_rec_t * const p_rec) { union { ib_net64_t sid; uint8_t sid_arr[8]; } sid_union; sid_union.sid_arr[0] = p_rec->service_id_8msb; memcpy(&sid_union.sid_arr[1], p_rec->service_id_56lsb, 7); return sid_union.sid; } /* * PARAMETERS * p_rec * [in] Pointer to the multipath record object. * * RETURN VALUES * Service ID * * NOTES * * SEE ALSO * ib_multipath_rec_t *********/ #define IB_NUM_PKEY_ELEMENTS_IN_BLOCK 32 /****s* IBA Base: Types/ib_pkey_table_t * NAME * ib_pkey_table_t * * DESCRIPTION * IBA defined PKey table. (14.2.5.7) * * SYNOPSIS */ #include typedef struct _ib_pkey_table { ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK]; } PACK_SUFFIX ib_pkey_table_t; #include /************/ /****s* IBA Base: Types/ib_pkey_table_record_t * NAME * ib_pkey_table_record_t * * DESCRIPTION * IBA defined P_Key Table Record for SA Query. (15.2.5.11) * * SYNOPSIS */ #include typedef struct _ib_pkey_table_record { ib_net16_t lid; // for CA: lid of port, for switch lid of port 0 ib_net16_t block_num; uint8_t port_num; // for switch: port number, for CA: reserved uint8_t reserved1; uint16_t reserved2; ib_pkey_table_t pkey_tbl; } PACK_SUFFIX ib_pkey_table_record_t; #include /************/ #define IB_DROP_VL 15 #define IB_MAX_NUM_VLS 16 /****s* IBA Base: Types/ib_slvl_table_t * NAME * ib_slvl_table_t * * DESCRIPTION * IBA defined SL2VL Mapping Table Attribute. (14.2.5.8) * * SYNOPSIS */ #include typedef struct _ib_slvl_table { uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS / 2]; } PACK_SUFFIX ib_slvl_table_t; #include /************/ /****s* IBA Base: Types/ib_slvl_table_record_t * NAME * ib_slvl_table_record_t * * DESCRIPTION * IBA defined SL to VL Mapping Table Record for SA Query. (15.2.5.4) * * SYNOPSIS */ #include typedef struct _ib_slvl_table_record { ib_net16_t lid; // for CA: lid of port, for switch lid of port 0 uint8_t in_port_num; // reserved for CAs uint8_t out_port_num; // reserved for CAs uint32_t resv; ib_slvl_table_t slvl_tbl; } PACK_SUFFIX ib_slvl_table_record_t; #include /************/ /****f* IBA Base: Types/ib_slvl_table_set * NAME * ib_slvl_table_set * * DESCRIPTION * Set slvl table entry. * * SYNOPSIS */ static inline void OSM_API ib_slvl_table_set(IN ib_slvl_table_t * p_slvl_tbl, IN uint8_t sl_index, IN uint8_t vl) { uint8_t idx = sl_index / 2; CL_ASSERT(vl <= 15); CL_ASSERT(sl_index <= 15); if (sl_index % 2) /* this is an odd sl. Need to update the ls bits */ p_slvl_tbl->raw_vl_by_sl[idx] = (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) | vl; else /* this is an even sl. Need to update the ms bits */ p_slvl_tbl->raw_vl_by_sl[idx] = (vl << 4) | (p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F); } /* * PARAMETERS * p_slvl_tbl * [in] pointer to ib_slvl_table_t object. * * sl_index * [in] the sl index in the table to be updated. * * vl * [in] the vl value to update for that sl. * * RETURN VALUES * None * * NOTES * * SEE ALSO * ib_slvl_table_t *********/ /****f* IBA Base: Types/ib_slvl_table_get * NAME * ib_slvl_table_get * * DESCRIPTION * Get slvl table entry. * * SYNOPSIS */ static inline uint8_t OSM_API ib_slvl_table_get(IN const ib_slvl_table_t * p_slvl_tbl, IN uint8_t sl_index) { uint8_t idx = sl_index / 2; CL_ASSERT(sl_index <= 15); if (sl_index % 2) /* this is an odd sl. Need to return the ls bits. */ return (p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F); else /* this is an even sl. Need to return the ms bits. */ return ((p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4); } /* * PARAMETERS * p_slvl_tbl * [in] pointer to ib_slvl_table_t object. * * sl_index * [in] the sl index in the table whose value should be returned. * * RETURN VALUES * vl for the requested sl_index. * * NOTES * * SEE ALSO * ib_slvl_table_t *********/ /****s* IBA Base: Types/ib_vl_arb_element_t * NAME * ib_vl_arb_element_t * * DESCRIPTION * IBA defined VL Arbitration Table Element. (14.2.5.9) * * SYNOPSIS */ #include typedef struct _ib_vl_arb_element { uint8_t vl; uint8_t weight; } PACK_SUFFIX ib_vl_arb_element_t; #include /************/ #define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32 /****s* IBA Base: Types/ib_vl_arb_table_t * NAME * ib_vl_arb_table_t * * DESCRIPTION * IBA defined VL Arbitration Table. (14.2.5.9) * * SYNOPSIS */ #include typedef struct _ib_vl_arb_table { ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]; } PACK_SUFFIX ib_vl_arb_table_t; #include /************/ /****s* IBA Base: Types/ib_vl_arb_table_record_t * NAME * ib_vl_arb_table_record_t * * DESCRIPTION * IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9) * * SYNOPSIS */ #include typedef struct _ib_vl_arb_table_record { ib_net16_t lid; // for CA: lid of port, for switch lid of port 0 uint8_t port_num; uint8_t block_num; uint32_t reserved; ib_vl_arb_table_t vl_arb_tbl; } PACK_SUFFIX ib_vl_arb_table_record_t; #include /************/ /* * Global route header information received with unreliable datagram messages */ #include typedef struct _ib_grh { ib_net32_t ver_class_flow; ib_net16_t resv1; uint8_t resv2; uint8_t hop_limit; ib_gid_t src_gid; ib_gid_t dest_gid; } PACK_SUFFIX ib_grh_t; #include /****f* IBA Base: Types/ib_grh_get_ver_class_flow * NAME * ib_grh_get_ver_class_flow * * DESCRIPTION * Get encoded version, traffic class and flow label in grh * * SYNOPSIS */ static inline void OSM_API ib_grh_get_ver_class_flow(IN const ib_net32_t ver_class_flow, OUT uint8_t * const p_ver, OUT uint8_t * const p_tclass, OUT uint32_t * const p_flow_lbl) { ib_net32_t tmp_ver_class_flow; if (p_ver) *p_ver = (uint8_t) (ver_class_flow & 0x0f); tmp_ver_class_flow = ver_class_flow >> 4; if (p_tclass) *p_tclass = (uint8_t) (tmp_ver_class_flow & 0xff); tmp_ver_class_flow = tmp_ver_class_flow >> 8; if (p_flow_lbl) *p_flow_lbl = tmp_ver_class_flow & 0xfffff; } /* * PARAMETERS * ver_class_flow * [in] the version, traffic class and flow label info. * * RETURN VALUES * p_ver * [out] pointer to the version info. * * p_tclass * [out] pointer to the traffic class info. * * p_flow_lbl * [out] pointer to the flow label info * * NOTES * * SEE ALSO * ib_grh_t *********/ /****f* IBA Base: Types/ib_grh_set_ver_class_flow * NAME * ib_grh_set_ver_class_flow * * DESCRIPTION * Set encoded version, traffic class and flow label in grh * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_grh_set_ver_class_flow(IN const uint8_t ver, IN const uint8_t tclass, IN const uint32_t flow_lbl) { ib_net32_t ver_class_flow; ver_class_flow = flow_lbl; ver_class_flow = ver_class_flow << 8; ver_class_flow = ver_class_flow | tclass; ver_class_flow = ver_class_flow << 4; ver_class_flow = ver_class_flow | ver; return (ver_class_flow); } /* * PARAMETERS * ver * [in] the version info. * * tclass * [in] the traffic class info. * * flow_lbl * [in] the flow label info * * RETURN VALUES * ver_class_flow * [out] the version, traffic class and flow label info. * * NOTES * * SEE ALSO * ib_grh_t *********/ /****s* IBA Base: Types/ib_member_rec_t * NAME * ib_member_rec_t * * DESCRIPTION * Multicast member record, used to create, join, and leave multicast * groups. * * SYNOPSIS */ #include typedef struct _ib_member_rec { ib_gid_t mgid; ib_gid_t port_gid; ib_net32_t qkey; ib_net16_t mlid; uint8_t mtu; uint8_t tclass; ib_net16_t pkey; uint8_t rate; uint8_t pkt_life; ib_net32_t sl_flow_hop; uint8_t scope_state; uint8_t proxy_join:1; uint8_t reserved[2]; uint8_t pad[4]; } PACK_SUFFIX ib_member_rec_t; #include /* * FIELDS * mgid * Multicast GID address for this multicast group. * * port_gid * Valid GID of the endpoint joining this multicast group. * * qkey * Q_Key to be sued by this multicast group. * * mlid * Multicast LID for this multicast group. * * mtu * MTU and MTU selector fields to use on this path * * tclass * Another global routing parameter. * * pkey * Partition key (P_Key) to use for this member. * * rate * Rate and rate selector fields to use on this path. * * pkt_life * Packet lifetime * * sl_flow_hop * Global routing parameters: service level, hop count, and flow label. * * scope_state * MGID scope and JoinState of multicast request. * * proxy_join * Enables others in the Partition to proxy add/remove from the group * * SEE ALSO *********/ /****f* IBA Base: Types/ib_member_get_sl_flow_hop * NAME * ib_member_get_sl_flow_hop * * DESCRIPTION * Get encoded sl, flow label, and hop limit * * SYNOPSIS */ static inline void OSM_API ib_member_get_sl_flow_hop(IN const ib_net32_t sl_flow_hop, OUT uint8_t * const p_sl, OUT uint32_t * const p_flow_lbl, OUT uint8_t * const p_hop) { uint32_t tmp; tmp = cl_ntoh32(sl_flow_hop); if (p_hop) *p_hop = (uint8_t) tmp; tmp >>= 8; if (p_flow_lbl) *p_flow_lbl = (uint32_t) (tmp & 0xfffff); tmp >>= 20; if (p_sl) *p_sl = (uint8_t) tmp; } /* * PARAMETERS * sl_flow_hop * [in] the sl, flow label, and hop limit of MC Group * * RETURN VALUES * p_sl * [out] pointer to the service level * * p_flow_lbl * [out] pointer to the flow label info * * p_hop * [out] pointer to the hop count limit. * * NOTES * * SEE ALSO * ib_member_rec_t *********/ /****f* IBA Base: Types/ib_member_set_sl_flow_hop * NAME * ib_member_set_sl_flow_hop * * DESCRIPTION * Set encoded sl, flow label, and hop limit * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_member_set_sl_flow_hop(IN const uint8_t sl, IN const uint32_t flow_label, IN const uint8_t hop_limit) { uint32_t tmp; tmp = (sl << 28) | ((flow_label & 0xfffff) << 8) | hop_limit; return cl_hton32(tmp); } /* * PARAMETERS * sl * [in] the service level. * * flow_lbl * [in] the flow label info * * hop_limit * [in] the hop limit. * * RETURN VALUES * sl_flow_hop * [out] the encoded sl, flow label, and hop limit * * NOTES * * SEE ALSO * ib_member_rec_t *********/ /****f* IBA Base: Types/ib_member_get_scope_state * NAME * ib_member_get_scope_state * * DESCRIPTION * Get encoded MGID scope and JoinState * * SYNOPSIS */ static inline void OSM_API ib_member_get_scope_state(IN const uint8_t scope_state, OUT uint8_t * const p_scope, OUT uint8_t * const p_state) { uint8_t tmp_scope_state; if (p_state) *p_state = (uint8_t) (scope_state & 0x0f); tmp_scope_state = scope_state >> 4; if (p_scope) *p_scope = (uint8_t) (tmp_scope_state & 0x0f); } /* * PARAMETERS * scope_state * [in] the scope and state * * RETURN VALUES * p_scope * [out] pointer to the MGID scope * * p_state * [out] pointer to the join state * * NOTES * * SEE ALSO * ib_member_rec_t *********/ /****f* IBA Base: Types/ib_member_set_scope_state * NAME * ib_member_set_scope_state * * DESCRIPTION * Set encoded version, MGID scope and JoinState * * SYNOPSIS */ static inline uint8_t OSM_API ib_member_set_scope_state(IN const uint8_t scope, IN const uint8_t state) { uint8_t scope_state; scope_state = scope; scope_state = scope_state << 4; scope_state = scope_state | state; return (scope_state); } /* * PARAMETERS * scope * [in] the MGID scope * * state * [in] the JoinState * * RETURN VALUES * scope_state * [out] the encoded one * * NOTES * * SEE ALSO * ib_member_rec_t *********/ /****f* IBA Base: Types/ib_member_set_join_state * NAME * ib_member_set_join_state * * DESCRIPTION * Set JoinState * * SYNOPSIS */ static inline void OSM_API ib_member_set_join_state(IN OUT ib_member_rec_t * p_mc_rec, IN const uint8_t state) { /* keep the scope as it is */ p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state); } /* * PARAMETERS * p_mc_rec * [in] pointer to the member record * * state * [in] the JoinState * * RETURN VALUES * NONE * * NOTES * * SEE ALSO * ib_member_rec_t *********/ /* * Join State Codes: */ #define IB_MC_REC_STATE_FULL_MEMBER 0x01 #define IB_MC_REC_STATE_NON_MEMBER 0x02 #define IB_MC_REC_STATE_SEND_ONLY_NON_MEMBER 0x04 /* * Generic MAD notice types */ #define IB_NOTICE_TYPE_FATAL 0x00 #define IB_NOTICE_TYPE_URGENT 0x01 #define IB_NOTICE_TYPE_SECURITY 0x02 #define IB_NOTICE_TYPE_SUBN_MGMT 0x03 #define IB_NOTICE_TYPE_INFO 0x04 #define IB_NOTICE_TYPE_EMPTY 0x7F #define SM_GID_IN_SERVICE_TRAP 64 #define SM_GID_OUT_OF_SERVICE_TRAP 65 #define SM_MGID_CREATED_TRAP 66 #define SM_MGID_DESTROYED_TRAP 67 #define SM_UNPATH_TRAP 68 #define SM_REPATH_TRAP 69 #define SM_LINK_STATE_CHANGED_TRAP 128 #define SM_LINK_INTEGRITY_THRESHOLD_TRAP 129 #define SM_BUFFER_OVERRUN_THRESHOLD_TRAP 130 #define SM_WATCHDOG_TIMER_EXPIRED_TRAP 131 #define SM_LOCAL_CHANGES_TRAP 144 #define SM_SYS_IMG_GUID_CHANGED_TRAP 145 #define SM_BAD_MKEY_TRAP 256 #define SM_BAD_PKEY_TRAP 257 #define SM_BAD_QKEY_TRAP 258 #define SM_BAD_SWITCH_PKEY_TRAP 259 #include typedef struct _ib_mad_notice_attr // Total Size calc Accumulated { uint8_t generic_type; // 1 1 union _notice_g_or_v { struct _notice_generic // 5 6 { uint8_t prod_type_msb; ib_net16_t prod_type_lsb; ib_net16_t trap_num; } PACK_SUFFIX generic; struct _notice_vend { uint8_t vend_id_msb; ib_net16_t vend_id_lsb; ib_net16_t dev_id; } PACK_SUFFIX vend; } g_or_v; ib_net16_t issuer_lid; // 2 8 ib_net16_t toggle_count; // 2 10 union _data_details // 54 64 { struct _raw_data { uint8_t details[54]; } PACK_SUFFIX raw_data; struct _ntc_64_67 { uint8_t res[6]; ib_gid_t gid; // the Node or Multicast Group that came in/out } PACK_SUFFIX ntc_64_67; struct _ntc_128 { ib_net16_t sw_lid; // the sw lid of which link state changed } PACK_SUFFIX ntc_128; struct _ntc_129_131 { ib_net16_t pad; ib_net16_t lid; // lid and port number of the violation uint8_t port_num; } PACK_SUFFIX ntc_129_131; struct _ntc_144 { ib_net16_t pad1; ib_net16_t lid; // lid where change occured uint8_t pad2; // reserved uint8_t local_changes; // 7b reserved 1b local changes ib_net32_t new_cap_mask; // new capability mask ib_net16_t change_flgs; // 10b reserved 6b change flags ib_net16_t cap_mask2; } PACK_SUFFIX ntc_144; struct _ntc_145 { ib_net16_t pad1; ib_net16_t lid; // lid where sys guid changed ib_net16_t pad2; ib_net64_t new_sys_guid; // new system image guid } PACK_SUFFIX ntc_145; struct _ntc_256 { // total: 54 ib_net16_t pad1; // 2 ib_net16_t lid; // 2 ib_net16_t dr_slid; // 2 uint8_t method; // 1 uint8_t pad2; // 1 ib_net16_t attr_id; // 2 ib_net32_t attr_mod; // 4 ib_net64_t mkey; // 8 uint8_t pad3; // 1 uint8_t dr_trunc_hop; // 1 uint8_t dr_rtn_path[30]; // 30 } PACK_SUFFIX ntc_256; struct _ntc_257_258 // violation of p/q_key // 49 { ib_net16_t pad1; // 2 ib_net16_t lid1; // 2 ib_net16_t lid2; // 2 ib_net32_t key; // 4 ib_net32_t qp1; // 4b sl, 4b pad, 24b qp1 ib_net32_t qp2; // 8b pad, 24b qp2 ib_gid_t gid1; // 16 ib_gid_t gid2; // 16 } PACK_SUFFIX ntc_257_258; struct _ntc_259 // pkey violation from switch 51 { ib_net16_t data_valid; // 2 ib_net16_t lid1; // 2 ib_net16_t lid2; // 2 ib_net16_t pkey; // 2 ib_net32_t sl_qp1; // 4b sl, 4b pad, 24b qp1 ib_net32_t qp2; // 8b pad, 24b qp2 ib_gid_t gid1; // 16 ib_gid_t gid2; // 16 ib_net16_t sw_lid; // 2 uint8_t port_no; // 1 } PACK_SUFFIX ntc_259; struct _ntc_bkey_259 // bkey violation { ib_net16_t lidaddr; uint8_t method; uint8_t reserved; ib_net16_t attribute_id; ib_net32_t attribute_modifier; ib_net32_t qp; // qp is low 24 bits ib_net64_t bkey; ib_gid_t gid; } PACK_SUFFIX ntc_bkey_259; struct _ntc_cckey_0 // CC key violation { ib_net16_t slid; // source LID from offending packet LRH uint8_t method; // method, from common MAD header uint8_t resv0; ib_net16_t attribute_id; // Attribute ID, from common MAD header ib_net16_t resv1; ib_net32_t attribute_modifier; // Attribute Modif, from common MAD header ib_net32_t qp; // 8b pad, 24b dest QP from BTH ib_net64_t cc_key; // CC key of the offending packet ib_gid_t source_gid; // GID from GRH of the offending packet uint8_t padding[14]; // Padding - ignored on read } PACK_SUFFIX ntc_cckey_0; } data_details; ib_gid_t issuer_gid; // 16 80 } PACK_SUFFIX ib_mad_notice_attr_t; #include /** * Trap 259 masks */ #define TRAP_259_MASK_SL (CL_HTON32(0xF0000000)) #define TRAP_259_MASK_QP (CL_HTON32(0x00FFFFFF)) /** * Trap 144 masks */ #define TRAP_144_MASK_OTHER_LOCAL_CHANGES 0x01 #define TRAP_144_MASK_CAPABILITY_MASK2_CHANGE (CL_HTON16(0x0020)) #define TRAP_144_MASK_HIERARCHY_INFO_CHANGE (CL_HTON16(0x0010)) #define TRAP_144_MASK_SM_PRIORITY_CHANGE (CL_HTON16(0x0008)) #define TRAP_144_MASK_LINK_SPEED_ENABLE_CHANGE (CL_HTON16(0x0004)) #define TRAP_144_MASK_LINK_WIDTH_ENABLE_CHANGE (CL_HTON16(0x0002)) #define TRAP_144_MASK_NODE_DESCRIPTION_CHANGE (CL_HTON16(0x0001)) /****f* IBA Base: Types/ib_notice_is_generic * NAME * ib_notice_is_generic * * DESCRIPTION * Check if the notice is generic * * SYNOPSIS */ static inline boolean_t OSM_API ib_notice_is_generic(IN const ib_mad_notice_attr_t * p_ntc) { return (p_ntc->generic_type & 0x80); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * RETURN VALUES * TRUE if notice MAD is generic * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_get_type * NAME * ib_notice_get_type * * DESCRIPTION * Get the notice type * * SYNOPSIS */ static inline uint8_t OSM_API ib_notice_get_type(IN const ib_mad_notice_attr_t * p_ntc) { return p_ntc->generic_type & 0x7f; } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * RETURN VALUES * TRUE if mad is generic * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_get_prod_type * NAME * ib_notice_get_prod_type * * DESCRIPTION * Get the notice Producer Type of Generic Notice * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_notice_get_prod_type(IN const ib_mad_notice_attr_t * p_ntc) { uint32_t pt; pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) | (p_ntc->g_or_v.generic.prod_type_msb << 16); return cl_hton32(pt); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * RETURN VALUES * The producer type * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_set_prod_type * NAME * ib_notice_set_prod_type * * DESCRIPTION * Set the notice Producer Type of Generic Notice * * SYNOPSIS */ static inline void OSM_API ib_notice_set_prod_type(IN ib_mad_notice_attr_t * p_ntc, IN ib_net32_t prod_type_val) { uint32_t ptv = cl_ntoh32(prod_type_val); p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16((uint16_t) (ptv & 0x0000ffff)); p_ntc->g_or_v.generic.prod_type_msb = (uint8_t) ((ptv & 0x00ff0000) >> 16); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * prod_type * [in] The producer Type code * * RETURN VALUES * None * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_set_prod_type_ho * NAME * ib_notice_set_prod_type_ho * * DESCRIPTION * Set the notice Producer Type of Generic Notice given Host Order * * SYNOPSIS */ static inline void OSM_API ib_notice_set_prod_type_ho(IN ib_mad_notice_attr_t * p_ntc, IN uint32_t prod_type_val_ho) { p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16((uint16_t) (prod_type_val_ho & 0x0000ffff)); p_ntc->g_or_v.generic.prod_type_msb = (uint8_t) ((prod_type_val_ho & 0x00ff0000) >> 16); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * prod_type * [in] The producer Type code in host order * * RETURN VALUES * None * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_get_vend_id * NAME * ib_notice_get_vend_id * * DESCRIPTION * Get the Vendor Id of Vendor type Notice * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_notice_get_vend_id(IN const ib_mad_notice_attr_t * p_ntc) { uint32_t vi; vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) | (p_ntc->g_or_v.vend.vend_id_msb << 16); return cl_hton32(vi); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * RETURN VALUES * The Vendor Id of Vendor type Notice * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_set_vend_id * NAME * ib_notice_set_vend_id * * DESCRIPTION * Set the notice Producer Type of Generic Notice * * SYNOPSIS */ static inline void OSM_API ib_notice_set_vend_id(IN ib_mad_notice_attr_t * p_ntc, IN ib_net32_t vend_id) { uint32_t vi = cl_ntoh32(vend_id); p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t) (vi & 0x0000ffff)); p_ntc->g_or_v.vend.vend_id_msb = (uint8_t) ((vi & 0x00ff0000) >> 16); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * vend_id * [in] The producer Type code * * RETURN VALUES * None * * SEE ALSO * ib_mad_notice_attr_t *********/ /****f* IBA Base: Types/ib_notice_set_vend_id_ho * NAME * ib_notice_set_vend_id_ho * * DESCRIPTION * Set the notice Producer Type of Generic Notice given a host order value * * SYNOPSIS */ static inline void OSM_API ib_notice_set_vend_id_ho(IN ib_mad_notice_attr_t * p_ntc, IN uint32_t vend_id_ho) { p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t) (vend_id_ho & 0x0000ffff)); p_ntc->g_or_v.vend.vend_id_msb = (uint8_t) ((vend_id_ho & 0x00ff0000) >> 16); } /* * PARAMETERS * p_ntc * [in] Pointer to the notice MAD attribute * * vend_id_ho * [in] The producer Type code in host order * * RETURN VALUES * None * * SEE ALSO * ib_mad_notice_attr_t *********/ #include typedef struct _ib_inform_info { ib_gid_t gid; ib_net16_t lid_range_begin; ib_net16_t lid_range_end; ib_net16_t reserved1; uint8_t is_generic; uint8_t subscribe; ib_net16_t trap_type; union _inform_g_or_v { struct _inform_generic { ib_net16_t trap_num; ib_net32_t qpn_resp_time_val; uint8_t reserved2; uint8_t node_type_msb; ib_net16_t node_type_lsb; } PACK_SUFFIX generic; struct _inform_vend { ib_net16_t dev_id; ib_net32_t qpn_resp_time_val; uint8_t reserved2; uint8_t vendor_id_msb; ib_net16_t vendor_id_lsb; } PACK_SUFFIX vend; } PACK_SUFFIX g_or_v; } PACK_SUFFIX ib_inform_info_t; #include /****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time * NAME * ib_inform_info_get_qpn_resp_time * * DESCRIPTION * Get QPN of the inform info * * SYNOPSIS */ static inline void OSM_API ib_inform_info_get_qpn_resp_time(IN const ib_net32_t qpn_resp_time_val, OUT ib_net32_t * const p_qpn, OUT uint8_t * const p_resp_time_val) { uint32_t tmp = cl_ntoh32(qpn_resp_time_val); if (p_qpn) *p_qpn = cl_hton32((tmp & 0xffffff00) >> 8); if (p_resp_time_val) *p_resp_time_val = (uint8_t) (tmp & 0x0000001f); } /* * PARAMETERS * qpn_resp_time_val * [in] the qpn and resp time val from the mad * * RETURN VALUES * p_qpn * [out] pointer to the qpn * * p_state * [out] pointer to the resp time val * * NOTES * * SEE ALSO * ib_inform_info_t *********/ /****f* IBA Base: Types/ib_inform_info_set_qpn * NAME * ib_inform_info_set_qpn * * DESCRIPTION * Set the QPN of the inform info * * SYNOPSIS */ static inline void OSM_API ib_inform_info_set_qpn(IN ib_inform_info_t * p_ii, IN ib_net32_t const qpn) { uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val); uint32_t qpn_h = cl_ntoh32(qpn); p_ii->g_or_v.generic.qpn_resp_time_val = cl_hton32((tmp & 0x000000ff) | ((qpn_h << 8) & 0xffffff00) ); } /* * PARAMETERS * * NOTES * * SEE ALSO * ib_inform_info_t *********/ /****f* IBA Base: Types/ib_inform_info_get_prod_type * NAME * ib_inform_info_get_prod_type * * DESCRIPTION * Get Producer Type of the Inform Info * 13.4.8.3 InformInfo * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_inform_info_get_prod_type(IN const ib_inform_info_t * p_inf) { uint32_t nt; nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) | (p_inf->g_or_v.generic.node_type_msb << 16); return cl_hton32(nt); } /* * PARAMETERS * p_inf * [in] pointer to an inform info * * RETURN VALUES * The producer type * * NOTES * * SEE ALSO * ib_inform_info_t *********/ /****f* IBA Base: Types/ib_inform_info_get_vend_id * NAME * ib_inform_info_get_vend_id * * DESCRIPTION * Get Node Type of the Inform Info * * SYNOPSIS */ static inline ib_net32_t OSM_API ib_inform_info_get_vend_id(IN const ib_inform_info_t * p_inf) { uint32_t vi; vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) | (p_inf->g_or_v.vend.vendor_id_msb << 16); return cl_hton32(vi); } /* * PARAMETERS * p_inf * [in] pointer to an inform info * * RETURN VALUES * The node type * * NOTES * * SEE ALSO * ib_inform_info_t *********/ /****s* IBA Base: Types/ib_inform_info_record_t * NAME * ib_inform_info_record_t * * DESCRIPTION * IBA defined InformInfo Record. (15.2.5.12) * * SYNOPSIS */ #include typedef struct _ib_inform_info_record { ib_gid_t subscriber_gid; ib_net16_t subscriber_enum; uint8_t reserved[6]; ib_inform_info_t inform_info; uint8_t pad[4]; } PACK_SUFFIX ib_inform_info_record_t; #include /****s* IBA Base: Types/ib_perfmgt_mad_t * NAME * ib_perfmgt_mad_t * * DESCRIPTION * IBA defined Perf Management MAD (16.3.1) * * SYNOPSIS */ #include typedef struct _ib_perfmgt_mad { ib_mad_t header; uint8_t resv[40]; #define IB_PM_DATA_SIZE 192 uint8_t data[IB_PM_DATA_SIZE]; } PACK_SUFFIX ib_perfmgt_mad_t; #include /* * FIELDS * header * Common MAD header. * * resv * Reserved. * * data * Performance Management payload. The structure and content of this field * depends upon the method, attr_id, and attr_mod fields in the header. * * SEE ALSO * ib_mad_t *********/ /****s* IBA Base: Types/ib_port_counters * NAME * ib_port_counters_t * * DESCRIPTION * IBA defined PortCounters Attribute. (16.1.3.5) * * SYNOPSIS */ #include typedef struct _ib_port_counters { uint8_t reserved; uint8_t port_select; ib_net16_t counter_select; ib_net16_t symbol_err_cnt; uint8_t link_err_recover; uint8_t link_downed; ib_net16_t rcv_err; ib_net16_t rcv_rem_phys_err; ib_net16_t rcv_switch_relay_err; ib_net16_t xmit_discards; uint8_t xmit_constraint_err; uint8_t rcv_constraint_err; uint8_t counter_select2; uint8_t link_int_buffer_overrun; ib_net16_t resv; ib_net16_t vl15_dropped; ib_net32_t xmit_data; ib_net32_t rcv_data; ib_net32_t xmit_pkts; ib_net32_t rcv_pkts; ib_net32_t xmit_wait; } PACK_SUFFIX ib_port_counters_t; #include #define PC_LINK_INT(integ_buf_over) ((integ_buf_over & 0xF0) >> 4) #define PC_BUF_OVERRUN(integ_buf_over) (integ_buf_over & 0x0F) /****s* IBA Base: Types/ib_port_counters_ext * NAME * ib_port_counters_ext_t * * DESCRIPTION * IBA defined PortCounters Extended Attribute. (16.1.4.11) * * SYNOPSIS */ #include typedef struct _ib_port_counters_ext { uint8_t reserved; uint8_t port_select; ib_net16_t counter_select; ib_net32_t reserved2; ib_net64_t xmit_data; ib_net64_t rcv_data; ib_net64_t xmit_pkts; ib_net64_t rcv_pkts; ib_net64_t unicast_xmit_pkts; ib_net64_t unicast_rcv_pkts; ib_net64_t multicast_xmit_pkts; ib_net64_t multicast_rcv_pkts; } PACK_SUFFIX ib_port_counters_ext_t; #include /****s* IBA Base: Types/ib_port_samples_control * NAME * ib_port_samples_control_t * * DESCRIPTION * IBA defined PortSamplesControl Attribute. (16.1.3.2) * * SYNOPSIS */ #include typedef struct _ib_port_samples_control { uint8_t op_code; uint8_t port_select; uint8_t tick; uint8_t counter_width; /* 5 bits res : 3bits counter_width */ ib_net32_t counter_mask; /* 2 bits res : 3 bits counter_mask : 27 bits counter_masks_1to9 */ ib_net16_t counter_mask_10to14; /* 1 bits res : 15 bits counter_masks_10to14 */ uint8_t sample_mech; uint8_t sample_status; /* 6 bits res : 2 bits sample_status */ ib_net64_t option_mask; ib_net64_t vendor_mask; ib_net32_t sample_start; ib_net32_t sample_interval; ib_net16_t tag; ib_net16_t counter_select0; ib_net16_t counter_select1; ib_net16_t counter_select2; ib_net16_t counter_select3; ib_net16_t counter_select4; ib_net16_t counter_select5; ib_net16_t counter_select6; ib_net16_t counter_select7; ib_net16_t counter_select8; ib_net16_t counter_select9; ib_net16_t counter_select10; ib_net16_t counter_select11; ib_net16_t counter_select12; ib_net16_t counter_select13; ib_net16_t counter_select14; } PACK_SUFFIX ib_port_samples_control_t; #include /****d* IBA Base: Types/CounterSelect values * NAME * Counter select values * * DESCRIPTION * Mandatory counter select values (16.1.3.3) * * SYNOPSIS */ #define IB_CS_PORT_XMIT_DATA (CL_HTON16(0x0001)) #define IB_CS_PORT_RCV_DATA (CL_HTON16(0x0002)) #define IB_CS_PORT_XMIT_PKTS (CL_HTON16(0x0003)) #define IB_CS_PORT_RCV_PKTS (CL_HTON16(0x0004)) #define IB_CS_PORT_XMIT_WAIT (CL_HTON16(0x0005)) /****s* IBA Base: Types/ib_port_samples_result * NAME * ib_port_samples_result_t * * DESCRIPTION * IBA defined PortSamplesControl Attribute. (16.1.3.2) * * SYNOPSIS */ #include typedef struct _ib_port_samples_result { ib_net16_t tag; ib_net16_t sample_status; /* 14 bits res : 2 bits sample_status */ ib_net32_t counter0; ib_net32_t counter1; ib_net32_t counter2; ib_net32_t counter3; ib_net32_t counter4; ib_net32_t counter5; ib_net32_t counter6; ib_net32_t counter7; ib_net32_t counter8; ib_net32_t counter9; ib_net32_t counter10; ib_net32_t counter11; ib_net32_t counter12; ib_net32_t counter13; ib_net32_t counter14; } PACK_SUFFIX ib_port_samples_result_t; #include /****s* IBA Base: Types/ib_port_xmit_data_sl * NAME * ib_port_xmit_data_sl_t * * DESCRIPTION * IBA defined PortXmitDataSL Attribute. (A13.6.4) * * SYNOPSIS */ #include typedef struct _ib_port_xmit_data_sl { uint8_t reserved; uint8_t port_select; ib_net16_t counter_select; ib_net32_t port_xmit_data_sl[16]; uint8_t resv[124]; } PACK_SUFFIX ib_port_xmit_data_sl_t; #include /****s* IBA Base: Types/ib_port_rcv_data_sl * NAME * ib_port_rcv_data_sl_t * * DESCRIPTION * IBA defined PortRcvDataSL Attribute. (A13.6.4) * * SYNOPSIS */ #include typedef struct _ib_port_rcv_data_sl { uint8_t reserved; uint8_t port_select; ib_net16_t counter_select; ib_net32_t port_rcv_data_sl[16]; uint8_t resv[124]; } PACK_SUFFIX ib_port_rcv_data_sl_t; #include /****d* IBA Base: Types/DM_SVC_NAME * NAME * DM_SVC_NAME * * DESCRIPTION * IBA defined Device Management service name (16.3) * * SYNOPSIS */ #define DM_SVC_NAME "DeviceManager.IBTA" /* * SEE ALSO *********/ /****s* IBA Base: Types/ib_dm_mad_t * NAME * ib_dm_mad_t * * DESCRIPTION * IBA defined Device Management MAD (16.3.1) * * SYNOPSIS */ #include typedef struct _ib_dm_mad { ib_mad_t header; uint8_t resv[40]; #define IB_DM_DATA_SIZE 192 uint8_t data[IB_DM_DATA_SIZE]; } PACK_SUFFIX ib_dm_mad_t; #include /* * FIELDS * header * Common MAD header. * * resv * Reserved. * * data * Device Management payload. The structure and content of this field * depend upon the method, attr_id, and attr_mod fields in the header. * * SEE ALSO * ib_mad_t *********/ /****s* IBA Base: Types/ib_iou_info_t * NAME * ib_iou_info_t * * DESCRIPTION * IBA defined IO Unit information structure (16.3.3.3) * * SYNOPSIS */ #include typedef struct _ib_iou_info { ib_net16_t change_id; uint8_t max_controllers; uint8_t diag_rom; #define IB_DM_CTRL_LIST_SIZE 128 uint8_t controller_list[IB_DM_CTRL_LIST_SIZE]; #define IOC_NOT_INSTALLED 0x0 #define IOC_INSTALLED 0x1 // Reserved values 0x02-0xE #define SLOT_DOES_NOT_EXIST 0xF } PACK_SUFFIX ib_iou_info_t; #include /* * FIELDS * change_id * Value incremented, with rollover, by any change to the controller_list. * * max_controllers * Number of slots in controller_list. * * diag_rom * A byte containing two fields: DiagDeviceID and OptionROM. * These fields may be read using the ib_iou_info_diag_dev_id * and ib_iou_info_option_rom functions. * * controller_list * A series of 4-bit nibbles, with each nibble representing a slot * in the IO Unit. Individual nibbles may be read using the * ioc_at_slot function. * * SEE ALSO * ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot *********/ /****f* IBA Base: Types/ib_iou_info_diag_dev_id * NAME * ib_iou_info_diag_dev_id * * DESCRIPTION * Returns the DiagDeviceID. * * SYNOPSIS */ static inline uint8_t OSM_API ib_iou_info_diag_dev_id(IN const ib_iou_info_t * const p_iou_info) { return ((uint8_t) (p_iou_info->diag_rom >> 6 & 1)); } /* * PARAMETERS * p_iou_info * [in] Pointer to the IO Unit information structure. * * RETURN VALUES * DiagDeviceID field of the IO Unit information. * * NOTES * * SEE ALSO * ib_iou_info_t *********/ /****f* IBA Base: Types/ib_iou_info_option_rom * NAME * ib_iou_info_option_rom * * DESCRIPTION * Returns the OptionROM. * * SYNOPSIS */ static inline uint8_t OSM_API ib_iou_info_option_rom(IN const ib_iou_info_t * const p_iou_info) { return ((uint8_t) (p_iou_info->diag_rom >> 7)); } /* * PARAMETERS * p_iou_info * [in] Pointer to the IO Unit information structure. * * RETURN VALUES * OptionROM field of the IO Unit information. * * NOTES * * SEE ALSO * ib_iou_info_t *********/ /****f* IBA Base: Types/ioc_at_slot * NAME * ioc_at_slot * * DESCRIPTION * Returns the IOC value at the specified slot. * * SYNOPSIS */ static inline uint8_t OSM_API ioc_at_slot(IN const ib_iou_info_t * const p_iou_info, IN uint8_t slot) { if (slot >= IB_DM_CTRL_LIST_SIZE) return SLOT_DOES_NOT_EXIST; else return (int8_t) ((slot % 2) ? ((p_iou_info->controller_list[slot / 2] & 0xf0) >> 4) : (p_iou_info->controller_list[slot / 2] & 0x0f)); } /* * PARAMETERS * p_iou_info * [in] Pointer to the IO Unit information structure. * * slot * [in] Pointer to the IO Unit information structure. * * RETURN VALUES * OptionROM field of the IO Unit information. * * NOTES * * SEE ALSO * ib_iou_info_t *********/ /****s* IBA Base: Types/ib_ioc_profile_t * NAME * ib_ioc_profile_t * * DESCRIPTION * IBA defined IO Controller profile structure (16.3.3.4) * * SYNOPSIS */ #include typedef struct _ib_ioc_profile { ib_net64_t ioc_guid; ib_net32_t vend_id; ib_net32_t dev_id; ib_net16_t dev_ver; ib_net16_t resv2; ib_net32_t subsys_vend_id; ib_net32_t subsys_id; ib_net16_t io_class; ib_net16_t io_subclass; ib_net16_t protocol; ib_net16_t protocol_ver; ib_net32_t resv3; ib_net16_t send_msg_depth; uint8_t resv4; uint8_t rdma_read_depth; ib_net32_t send_msg_size; ib_net32_t rdma_size; uint8_t ctrl_ops_cap; #define CTRL_OPS_CAP_ST 0x01 #define CTRL_OPS_CAP_SF 0x02 #define CTRL_OPS_CAP_RT 0x04 #define CTRL_OPS_CAP_RF 0x08 #define CTRL_OPS_CAP_WT 0x10 #define CTRL_OPS_CAP_WF 0x20 #define CTRL_OPS_CAP_AT 0x40 #define CTRL_OPS_CAP_AF 0x80 uint8_t resv5; uint8_t num_svc_entries; #define MAX_NUM_SVC_ENTRIES 0xff uint8_t resv6[9]; #define CTRL_ID_STRING_LEN 64 char id_string[CTRL_ID_STRING_LEN]; } PACK_SUFFIX ib_ioc_profile_t; #include /* * FIELDS * ioc_guid * An EUI-64 GUID used to uniquely identify the IO controller. * * vend_id * IO controller vendor ID, IEEE format. * * dev_id * A number assigned by the vendor to identify the type of controller. * * dev_ver * A number assigned by the vendor to identify the divice version. * * subsys_vend_id * ID of the vendor of the enclosure, if any, in which the IO controller * resides in IEEE format; otherwise zero. * * subsys_id * A number identifying the subsystem where the controller resides. * * io_class * 0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand * Architecture. 0xffff = Vendor specific. * * io_subclass * 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand * Architecture. 0xffff = Vendor specific. This shall be set to 0xfff * if the io_class component is 0xffff. * * protocol * 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand * Architecture. 0xffff = Vendor specific. This shall be set to 0xfff * if the io_class component is 0xffff. * * protocol_ver * Protocol specific. * * send_msg_depth * Maximum depth of the send message queue. * * rdma_read_depth * Maximum depth of the per-channel RDMA read queue. * * send_msg_size * Maximum size of send messages. * * ctrl_ops_cap * Supported operation types of this IO controller. A bit set to one * for affirmation of supported capability. * * num_svc_entries * Number of entries in the service entries table. * * id_string * UTF-8 encoded string for identifying the controller to an operator. * * SEE ALSO * ib_dm_mad_t *********/ static inline uint32_t OSM_API ib_ioc_profile_get_vend_id(IN const ib_ioc_profile_t * const p_ioc_profile) { return (cl_ntoh32(p_ioc_profile->vend_id) >> 8); } static inline void OSM_API ib_ioc_profile_set_vend_id(IN ib_ioc_profile_t * const p_ioc_profile, IN const uint32_t vend_id) { p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8); } /****s* IBA Base: Types/ib_svc_entry_t * NAME * ib_svc_entry_t * * DESCRIPTION * IBA defined IO Controller service entry structure (16.3.3.5) * * SYNOPSIS */ #include typedef struct _ib_svc_entry { #define MAX_SVC_ENTRY_NAME_LEN 40 char name[MAX_SVC_ENTRY_NAME_LEN]; ib_net64_t id; } PACK_SUFFIX ib_svc_entry_t; #include /* * FIELDS * name * UTF-8 encoded, null-terminated name of the service. * * id * An identifier of the associated Service. * * SEE ALSO * ib_svc_entries_t *********/ /****s* IBA Base: Types/ib_svc_entries_t * NAME * ib_svc_entries_t * * DESCRIPTION * IBA defined IO Controller service entry array (16.3.3.5) * * SYNOPSIS */ #include typedef struct _ib_svc_entries { #define SVC_ENTRY_COUNT 4 ib_svc_entry_t service_entry[SVC_ENTRY_COUNT]; } PACK_SUFFIX ib_svc_entries_t; #include /* * FIELDS * service_entry * An array of IO controller service entries. * * SEE ALSO * ib_dm_mad_t, ib_svc_entry_t *********/ static inline void OSM_API ib_dm_get_slot_lo_hi(IN const ib_net32_t slot_lo_hi, OUT uint8_t * const p_slot, OUT uint8_t * const p_lo, OUT uint8_t * const p_hi) { ib_net32_t tmp_slot_lo_hi = CL_NTOH32(slot_lo_hi); if (p_slot) *p_slot = (uint8_t) ((tmp_slot_lo_hi >> 16) & 0x0f); if (p_hi) *p_hi = (uint8_t) ((tmp_slot_lo_hi >> 8) & 0xff); if (p_lo) *p_lo = (uint8_t) ((tmp_slot_lo_hi >> 0) & 0xff); } /* * IBA defined information describing an I/O controller */ #include typedef struct _ib_ioc_info { ib_net64_t module_guid; ib_net64_t iou_guid; ib_ioc_profile_t ioc_profile; ib_net64_t access_key; uint16_t initiators_conf; uint8_t resv[38]; } PACK_SUFFIX ib_ioc_info_t; #include /* * The following definitions are shared between the Access Layer and VPD */ typedef struct _ib_ca *__ptr64 ib_ca_handle_t; typedef struct _ib_pd *__ptr64 ib_pd_handle_t; typedef struct _ib_rdd *__ptr64 ib_rdd_handle_t; typedef struct _ib_mr *__ptr64 ib_mr_handle_t; typedef struct _ib_mw *__ptr64 ib_mw_handle_t; typedef struct _ib_qp *__ptr64 ib_qp_handle_t; typedef struct _ib_eec *__ptr64 ib_eec_handle_t; typedef struct _ib_cq *__ptr64 ib_cq_handle_t; typedef struct _ib_av *__ptr64 ib_av_handle_t; typedef struct _ib_mcast *__ptr64 ib_mcast_handle_t; /* Currently for windows branch, use the extended version of ib special verbs struct in order to be compliant with Infinicon ib_types; later we'll change it to support OpenSM ib_types.h */ #ifndef __WIN__ /****d* Access Layer/ib_api_status_t * NAME * ib_api_status_t * * DESCRIPTION * Function return codes indicating the success or failure of an API call. * Note that success is indicated by the return value IB_SUCCESS, which * is always zero. * * NOTES * IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call * in the pre-ioctl step itself. * * SYNOPSIS */ typedef enum _ib_api_status_t { IB_SUCCESS, IB_INSUFFICIENT_RESOURCES, IB_INSUFFICIENT_MEMORY, IB_INVALID_PARAMETER, IB_INVALID_SETTING, IB_NOT_FOUND, IB_TIMEOUT, IB_CANCELED, IB_INTERRUPTED, IB_INVALID_PERMISSION, IB_UNSUPPORTED, IB_OVERFLOW, IB_MAX_MCAST_QPS_REACHED, IB_INVALID_QP_STATE, IB_INVALID_EEC_STATE, IB_INVALID_APM_STATE, IB_INVALID_PORT_STATE, IB_INVALID_STATE, IB_RESOURCE_BUSY, IB_INVALID_PKEY, IB_INVALID_LKEY, IB_INVALID_RKEY, IB_INVALID_MAX_WRS, IB_INVALID_MAX_SGE, IB_INVALID_CQ_SIZE, IB_INVALID_SERVICE_TYPE, IB_INVALID_GID, IB_INVALID_LID, IB_INVALID_GUID, IB_INVALID_CA_HANDLE, IB_INVALID_AV_HANDLE, IB_INVALID_CQ_HANDLE, IB_INVALID_EEC_HANDLE, IB_INVALID_QP_HANDLE, IB_INVALID_PD_HANDLE, IB_INVALID_MR_HANDLE, IB_INVALID_MW_HANDLE, IB_INVALID_RDD_HANDLE, IB_INVALID_MCAST_HANDLE, IB_INVALID_CALLBACK, IB_INVALID_AL_HANDLE, /* InfiniBand Access Layer */ IB_INVALID_HANDLE, /* InfiniBand Access Layer */ IB_ERROR, /* InfiniBand Access Layer */ IB_REMOTE_ERROR, /* Infiniband Access Layer */ IB_VERBS_PROCESSING_DONE, /* See Notes above */ IB_INVALID_WR_TYPE, IB_QP_IN_TIMEWAIT, IB_EE_IN_TIMEWAIT, IB_INVALID_PORT, IB_NOT_DONE, IB_UNKNOWN_ERROR /* ALWAYS LAST ENUM VALUE! */ } ib_api_status_t; /*****/ OSM_EXPORT const char *ib_error_str[]; /****f* IBA Base: Types/ib_get_err_str * NAME * ib_get_err_str * * DESCRIPTION * Returns a string for the specified status value. * * SYNOPSIS */ static inline const char *OSM_API ib_get_err_str(IN ib_api_status_t status) { if (status > IB_UNKNOWN_ERROR) status = IB_UNKNOWN_ERROR; return (ib_error_str[status]); } /* * PARAMETERS * status * [in] status value * * RETURN VALUES * Pointer to the status description string. * * NOTES * * SEE ALSO *********/ /****d* Verbs/ib_async_event_t * NAME * ib_async_event_t -- Async event types * * DESCRIPTION * This type indicates the reason the async callback was called. * The context in the ib_event_rec_t indicates the resource context * that associated with the callback. For example, for IB_AE_CQ_ERROR * the context provided during the ib_create_cq is returned in the event. * * SYNOPSIS */ typedef enum _ib_async_event_t { IB_AE_SQ_ERROR = 1, IB_AE_SQ_DRAINED, IB_AE_RQ_ERROR, IB_AE_CQ_ERROR, IB_AE_QP_FATAL, IB_AE_QP_COMM, IB_AE_QP_APM, IB_AE_EEC_FATAL, IB_AE_EEC_COMM, IB_AE_EEC_APM, IB_AE_LOCAL_FATAL, IB_AE_PKEY_TRAP, IB_AE_QKEY_TRAP, IB_AE_MKEY_TRAP, IB_AE_PORT_TRAP, IB_AE_SYSIMG_GUID_TRAP, IB_AE_BUF_OVERRUN, IB_AE_LINK_INTEGRITY, IB_AE_FLOW_CTRL_ERROR, IB_AE_BKEY_TRAP, IB_AE_QP_APM_ERROR, IB_AE_EEC_APM_ERROR, IB_AE_WQ_REQ_ERROR, IB_AE_WQ_ACCESS_ERROR, IB_AE_PORT_ACTIVE, IB_AE_PORT_DOWN, IB_AE_UNKNOWN /* ALWAYS LAST ENUM VALUE */ } ib_async_event_t; /* * VALUES * IB_AE_SQ_ERROR * An error occurred when accessing the send queue of the QP or EEC. * This event is optional. * * IB_AE_SQ_DRAINED * The send queue of the specified QP has completed the outstanding * messages in progress when the state change was requested and, if * applicable, has received all acknowledgements for those messages. * * IB_AE_RQ_ERROR * An error occurred when accessing the receive queue of the QP or EEC. * This event is optional. * * IB_AE_CQ_ERROR * An error occurred when writing an entry to the CQ. * * IB_AE_QP_FATAL * A catastrophic error occurred while accessing or processing the * work queue that prevents reporting of completions. * * IB_AE_QP_COMM * The first packet has arrived for the receive work queue where the * QP is still in the RTR state. * * IB_AE_QP_APM * If alternate path migration is supported, this event indicates that * the QP connection has migrated to the alternate path. * * IB_AE_EEC_FATAL * If reliable datagram service is supported, this event indicates that * a catastrophic error occurred while accessing or processing the EEC * that prevents reporting of completions. * * IB_AE_EEC_COMM * If reliable datagram service is supported, this event indicates that * the first packet has arrived for the receive work queue where the * EEC is still in the RTR state. * * IB_AE_EEC_APM * If reliable datagram service and alternate path migration is supported, * this event indicates that the EEC connection has migrated to the * alternate path. * * IB_AE_LOCAL_FATAL * A catastrophic HCA error occurred which cannot be attributed to * any resource; behavior is indeterminate. * * IB_AE_PKEY_TRAP * A PKEY violation was detected. This event is optional. * * IB_AE_QKEY_TRAP * A QKEY violation was detected. This event is optional. * * IB_AE_MKEY_TRAP * A MKEY violation was detected. This event is optional. * * IB_AE_PORT_TRAP * A port capability change was detected. This event is optional. * * IB_AE_SYSIMG_GUID_TRAP * If the system image GUID is supported, this event indicates that * the system image GUID of this HCA has been changed. This event * is optional. * * IB_AE_BUF_OVERRUN * The number of consecutive flow control update periods with at least * one overrun error in each period has exceeded the threshold specified * in the port info attributes. This event is optional. * * IB_AE_LINK_INTEGRITY * The detection of excessively frequent local physical errors has * exceeded the threshold specified in the port info attributes. This * event is optional. * * IB_AE_FLOW_CTRL_ERROR * An HCA watchdog timer monitoring the arrival of flow control updates * has expired without receiving an update. This event is optional. * * IB_AE_BKEY_TRAP * An BKEY violation was detected. This event is optional. * * IB_AE_QP_APM_ERROR * If alternate path migration is supported, this event indicates that * an incoming path migration request to this QP was not accepted. * * IB_AE_EEC_APM_ERROR * If reliable datagram service and alternate path migration is supported, * this event indicates that an incoming path migration request to this * EEC was not accepted. * * IB_AE_WQ_REQ_ERROR * An OpCode violation was detected at the responder. * * IB_AE_WQ_ACCESS_ERROR * An access violation was detected at the responder. * * IB_AE_PORT_ACTIVE * If the port active event is supported, this event is generated * when the link becomes active: IB_LINK_ACTIVE. * * IB_AE_PORT_DOWN * The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED, * IB_LINK_DOWN. * * IB_AE_UNKNOWN * An unknown error occurred which cannot be attributed to any * resource; behavior is indeterminate. * *****/ OSM_EXPORT const char *ib_async_event_str[]; /****f* IBA Base: Types/ib_get_async_event_str * NAME * ib_get_async_event_str * * DESCRIPTION * Returns a string for the specified asynchronous event. * * SYNOPSIS */ static inline const char *OSM_API ib_get_async_event_str(IN ib_async_event_t event) { if (event > IB_AE_UNKNOWN) event = IB_AE_UNKNOWN; return (ib_async_event_str[event]); } /* * PARAMETERS * event * [in] event value * * RETURN VALUES * Pointer to the asynchronous event description string. * * NOTES * * SEE ALSO *********/ /****s* Verbs/ib_event_rec_t * NAME * ib_event_rec_t -- Async event notification record * * DESCRIPTION * When an async event callback is made, this structure is passed to indicate * the type of event, the source of event that caused it, and the context * associated with this event. * * context -- Context of the resource that caused the event. * -- ca_context if this is a port/adapter event. * -- qp_context if the source is a QP event * -- cq_context if the source is a CQ event. * -- ee_context if the source is an EE event. * * SYNOPSIS */ typedef struct _ib_event_rec { void *context; ib_async_event_t type; /* HCA vendor specific event information. */ uint64_t vendor_specific; /* The following structures are valid only for trap types. */ union _trap { struct { uint16_t lid; ib_net64_t port_guid; uint8_t port_num; /* * The following structure is valid only for * P_KEY, Q_KEY, and M_KEY violation traps. */ struct { uint8_t sl; uint16_t src_lid; uint16_t dest_lid; union _key { uint16_t pkey; uint32_t qkey; uint64_t mkey; } key; uint32_t src_qp; uint32_t dest_qp; ib_gid_t src_gid; ib_gid_t dest_gid; } violation; } info; ib_net64_t sysimg_guid; } trap; } ib_event_rec_t; /*******/ /****d* Access Layer/ib_atomic_t * NAME * ib_atomic_t * * DESCRIPTION * Indicates atomicity levels supported by an adapter. * * SYNOPSIS */ typedef enum _ib_atomic_t { IB_ATOMIC_NONE, IB_ATOMIC_LOCAL, IB_ATOMIC_GLOBAL } ib_atomic_t; /* * VALUES * IB_ATOMIC_NONE * Atomic operations not supported. * * IB_ATOMIC_LOCAL * Atomic operations guaranteed between QPs of a single CA. * * IB_ATOMIC_GLOBAL * Atomic operations are guaranteed between CA and any other entity * in the system. *****/ /****s* Access Layer/ib_port_cap_t * NAME * ib_port_cap_t * * DESCRIPTION * Indicates which management agents are currently available on the specified * port. * * SYNOPSIS */ typedef struct _ib_port_cap { boolean_t cm; boolean_t snmp; boolean_t dev_mgmt; boolean_t vend; boolean_t sm; boolean_t sm_disable; boolean_t qkey_ctr; boolean_t pkey_ctr; boolean_t notice; boolean_t trap; boolean_t apm; boolean_t slmap; boolean_t pkey_nvram; boolean_t mkey_nvram; boolean_t sysguid; boolean_t dr_notice; boolean_t boot_mgmt; boolean_t capm_notice; boolean_t reinit; boolean_t ledinfo; boolean_t port_active; } ib_port_cap_t; /*****/ /****d* Access Layer/ib_init_type_t * NAME * ib_init_type_t * * DESCRIPTION * If supported by the HCA, the type of initialization requested by * this port before SM moves it to the active or armed state. If the * SM implements reinitialization, it shall set these bits to indicate * the type of initialization performed prior to activating the port. * Otherwise, these bits shall be set to 0. * * SYNOPSIS */ typedef uint8_t ib_init_type_t; #define IB_INIT_TYPE_NO_LOAD 0x01 #define IB_INIT_TYPE_PRESERVE_CONTENT 0x02 #define IB_INIT_TYPE_PRESERVE_PRESENCE 0x04 #define IB_INIT_TYPE_DO_NOT_RESUSCITATE 0x08 /*****/ /****s* Access Layer/ib_port_attr_mod_t * NAME * ib_port_attr_mod_t * * DESCRIPTION * Port attributes that may be modified. * * SYNOPSIS */ typedef struct _ib_port_attr_mod { ib_port_cap_t cap; uint16_t pkey_ctr; uint16_t qkey_ctr; ib_init_type_t init_type; ib_net64_t system_image_guid; } ib_port_attr_mod_t; /* * SEE ALSO * ib_port_cap_t *****/ /****s* Access Layer/ib_port_attr_t * NAME * ib_port_attr_t * * DESCRIPTION * Information about a port on a given channel adapter. * * SYNOPSIS */ typedef struct _ib_port_attr { ib_net64_t port_guid; uint8_t port_num; uint8_t mtu; uint64_t max_msg_size; ib_net16_t lid; uint8_t lmc; /* * LinkWidthSupported as defined in PortInfo. Required to calculate * inter-packet delay (a.k.a. static rate). */ uint8_t link_width_supported; uint16_t max_vls; ib_net16_t sm_lid; uint8_t sm_sl; uint8_t link_state; ib_init_type_t init_type_reply; /* Optional */ /* * subnet_timeout: * The maximum expected subnet propagation delay to reach any port on * the subnet. This value also determines the rate at which traps can * be generated from this node. * * timeout = 4.096 microseconds * 2^subnet_timeout */ uint8_t subnet_timeout; ib_port_cap_t cap; uint16_t pkey_ctr; uint16_t qkey_ctr; uint16_t num_gids; uint16_t num_pkeys; /* * Pointers at the end of the structure to allow doing a simple * memory comparison of contents up to the first pointer. */ ib_gid_t *p_gid_table; ib_net16_t *p_pkey_table; } ib_port_attr_t; /* * SEE ALSO * uint8_t, ib_port_cap_t, ib_link_states_t *****/ /****s* Access Layer/ib_ca_attr_t * NAME * ib_ca_attr_t * * DESCRIPTION * Information about a channel adapter. * * SYNOPSIS */ typedef struct _ib_ca_attr { ib_net64_t ca_guid; uint32_t vend_id; uint16_t dev_id; uint16_t revision; uint64_t fw_ver; /* * Total size of the ca attributes in bytes */ uint32_t size; uint32_t max_qps; uint32_t max_wrs; uint32_t max_sges; uint32_t max_rd_sges; uint32_t max_cqs; uint32_t max_cqes; uint32_t max_pds; uint32_t init_regions; uint64_t init_region_size; uint32_t init_windows; uint32_t max_addr_handles; uint32_t max_partitions; ib_atomic_t atomicity; uint8_t max_qp_resp_res; uint8_t max_eec_resp_res; uint8_t max_resp_res; uint8_t max_qp_init_depth; uint8_t max_eec_init_depth; uint32_t max_eecs; uint32_t max_rdds; uint32_t max_ipv6_qps; uint32_t max_ether_qps; uint32_t max_mcast_grps; uint32_t max_mcast_qps; uint32_t max_qps_per_mcast_grp; uint32_t max_fmr; uint32_t max_map_per_fmr; /* * local_ack_delay: * Specifies the maximum time interval between the local CA receiving * a message and the transmission of the associated ACK or NAK. * * timeout = 4.096 microseconds * 2^local_ack_delay */ uint8_t local_ack_delay; boolean_t bad_pkey_ctr_support; boolean_t bad_qkey_ctr_support; boolean_t raw_mcast_support; boolean_t apm_support; boolean_t av_port_check; boolean_t change_primary_port; boolean_t modify_wr_depth; boolean_t current_qp_state_support; boolean_t shutdown_port_capability; boolean_t init_type_support; boolean_t port_active_event_support; boolean_t system_image_guid_support; boolean_t hw_agents; ib_net64_t system_image_guid; uint32_t num_page_sizes; uint8_t num_ports; uint32_t *p_page_size; ib_port_attr_t *p_port_attr; } ib_ca_attr_t; /* * FIELDS * ca_guid * GUID for this adapter. * * vend_id * IEEE vendor ID for this adapter * * dev_id * Device ID of this adapter. (typically from PCI device ID) * * revision * Revision ID of this adapter * * fw_ver * Device Firmware version. * * size * Total size in bytes for the HCA attributes. This size includes total * size required for all the variable members of the structure. If a * vendor requires to pass vendor specific fields beyond this structure, * the HCA vendor can choose to report a larger size. If a vendor is * reporting extended vendor specific features, they should also provide * appropriate access functions to aid with the required interpretation. * * max_qps * Maximum number of QP's supported by this HCA. * * max_wrs * Maximum number of work requests supported by this HCA. * * max_sges * Maximum number of scatter gather elements supported per work request. * * max_rd_sges * Maximum number of scatter gather elements supported for READ work * requests for a Reliable Datagram QP. This value must be zero if RD * service is not supported. * * max_cqs * Maximum number of Completion Queues supported. * * max_cqes * Maximum number of CQ elements supported per CQ. * * max_pds * Maximum number of protection domains supported. * * init_regions * Initial number of memory regions supported. These are only informative * values. HCA vendors can extended and grow these limits on demand. * * init_region_size * Initial limit on the size of the registered memory region. * * init_windows * Initial number of window entries supported. * * max_addr_handles * Maximum number of address handles supported. * * max_partitions * Maximum number of partitions supported. * * atomicity * Indicates level of atomic operations supported by this HCA. * * max_qp_resp_res * max_eec_resp_res * Maximum limit on number of responder resources for incoming RDMA * operations, on QPs and EEC's respectively. * * max_resp_res * Maximum number of responder resources per HCA, with this HCA used as * the target. * * max_qp_init_depth * max_eec_init_depth * Maximimum initiator depth per QP or EEC for initiating RDMA reads and * atomic operations. * * max_eecs * Maximimum number of EEC's supported by the HCA. * * max_rdds * Maximum number of Reliable datagram domains supported. * * max_ipv6_qps * max_ether_qps * Maximum number of IPV6 and raw ether QP's supported by this HCA. * * max_mcast_grps * Maximum number of multicast groups supported. * * max_mcast_qps * Maximum number of QP's that can support multicast operations. * * max_qps_per_mcast_grp * Maximum number of multicast QP's per multicast group. * * local_ack_delay * Specifies the maximum time interval between the local CA receiving * a message and the transmission of the associated ACK or NAK. * timeout = 4.096 microseconds * 2^local_ack_delay * * bad_pkey_ctr_support * bad_qkey_ctr_support * Indicates support for the bad pkey and qkey counters. * * raw_mcast_support * Indicates support for raw packet multicast. * * apm_support * Indicates support for Automatic Path Migration. * * av_port_check * Indicates ability to check port number in address handles. * * change_primary_port * Indicates ability to change primary port for a QP or EEC during a * SQD->RTS transition. * * modify_wr_depth * Indicates ability to modify QP depth during a modify QP operation. * Check the verb specification for permitted states. * * current_qp_state_support * Indicates ability of the HCA to support the current QP state modifier * during a modify QP operation. * * shutdown_port_capability * Shutdown port capability support indicator. * * init_type_support * Indicates init_type_reply and ability to set init_type is supported. * * port_active_event_support * Port active event support indicator. * * system_image_guid_support * System image GUID support indicator. * * hw_agents * Indicates SMA is implemented in HW. * * system_image_guid * Optional system image GUID. This field is valid only if the * system_image_guid_support flag is set. * * num_page_sizes * Indicates support for different page sizes supported by the HCA. * The variable size array can be obtained from p_page_size. * * num_ports * Number of physical ports supported on this HCA. * * p_page_size * Array holding different page size supported. * * p_port_attr * Array holding port attributes. * * NOTES * This structure contains the attributes of a channel adapter. Users must * call ib_copy_ca_attr to copy the contents of this structure to a new * memory region. * * SEE ALSO * ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr *****/ /****f* Access layer/ib_copy_ca_attr * NAME * ib_copy_ca_attr * * DESCRIPTION * Copies CA attributes. * * SYNOPSIS */ ib_ca_attr_t *ib_copy_ca_attr(IN ib_ca_attr_t * const p_dest, IN const ib_ca_attr_t * const p_src); /* * PARAMETERS * p_dest * Pointer to the buffer that is the destination of the copy. * * p_src * Pointer to the CA attributes to copy. * * RETURN VALUE * Pointer to the copied CA attributes. * * NOTES * The buffer pointed to by the p_dest parameter must be at least the size * specified in the size field of the buffer pointed to by p_src. * * SEE ALSO * ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr *****/ /****s* Access Layer/ib_av_attr_t * NAME * ib_av_attr_t * * DESCRIPTION * IBA address vector. * * SYNOPSIS */ typedef struct _ib_av_attr { uint8_t port_num; uint8_t sl; ib_net16_t dlid; boolean_t grh_valid; ib_grh_t grh; uint8_t static_rate; uint8_t path_bits; struct _av_conn { uint8_t path_mtu; uint8_t local_ack_timeout; uint8_t seq_err_retry_cnt; uint8_t rnr_retry_cnt; } conn; } ib_av_attr_t; /* * SEE ALSO * ib_gid_t *****/ /****d* Access Layer/ib_qp_type_t * NAME * ib_qp_type_t * * DESCRIPTION * Indicates the type of queue pair being created. * * SYNOPSIS */ typedef enum _ib_qp_type { IB_QPT_RELIABLE_CONN = 0, /* Matches CM REQ transport type */ IB_QPT_UNRELIABLE_CONN = 1, /* Matches CM REQ transport type */ IB_QPT_RELIABLE_DGRM = 2, /* Matches CM REQ transport type */ IB_QPT_UNRELIABLE_DGRM, IB_QPT_QP0, IB_QPT_QP1, IB_QPT_RAW_IPV6, IB_QPT_RAW_ETHER, IB_QPT_MAD, /* InfiniBand Access Layer */ IB_QPT_QP0_ALIAS, /* InfiniBand Access Layer */ IB_QPT_QP1_ALIAS /* InfiniBand Access Layer */ } ib_qp_type_t; /* * VALUES * IB_QPT_RELIABLE_CONN * Reliable, connected queue pair. * * IB_QPT_UNRELIABLE_CONN * Unreliable, connected queue pair. * * IB_QPT_RELIABLE_DGRM * Reliable, datagram queue pair. * * IB_QPT_UNRELIABLE_DGRM * Unreliable, datagram queue pair. * * IB_QPT_QP0 * Queue pair 0. * * IB_QPT_QP1 * Queue pair 1. * * IB_QPT_RAW_DGRM * Raw datagram queue pair. * * IB_QPT_RAW_IPV6 * Raw IP version 6 queue pair. * * IB_QPT_RAW_ETHER * Raw Ethernet queue pair. * * IB_QPT_MAD * Unreliable, datagram queue pair that will send and receive management * datagrams with assistance from the access layer. * * IB_QPT_QP0_ALIAS * Alias to queue pair 0. Aliased QPs can only be created on an aliased * protection domain. * * IB_QPT_QP1_ALIAS * Alias to queue pair 1. Aliased QPs can only be created on an aliased * protection domain. *****/ /****d* Access Layer/ib_access_t * NAME * ib_access_t * * DESCRIPTION * Indicates the type of access is permitted on resources such as QPs, * memory regions and memory windows. * * SYNOPSIS */ typedef uint32_t ib_access_t; #define IB_AC_RDMA_READ 0x00000001 #define IB_AC_RDMA_WRITE 0x00000002 #define IB_AC_ATOMIC 0x00000004 #define IB_AC_LOCAL_WRITE 0x00000008 #define IB_AC_MW_BIND 0x00000010 /* * NOTES * Users may combine access rights using a bit-wise or operation to specify * additional access. For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants * RDMA read and write access. *****/ /****d* Access Layer/ib_qp_state_t * NAME * ib_qp_state_t * * DESCRIPTION * Indicates or sets the state of a queue pair. The current state of a queue * pair is returned through the ib_qp_query call and set via the * ib_qp_modify call. * * SYNOPSIS */ typedef uint32_t ib_qp_state_t; #define IB_QPS_RESET 0x00000001 #define IB_QPS_INIT 0x00000002 #define IB_QPS_RTR 0x00000004 #define IB_QPS_RTS 0x00000008 #define IB_QPS_SQD 0x00000010 #define IB_QPS_SQD_DRAINING 0x00000030 #define IB_QPS_SQD_DRAINED 0x00000050 #define IB_QPS_SQERR 0x00000080 #define IB_QPS_ERROR 0x00000100 #define IB_QPS_TIME_WAIT 0xDEAD0000 /* InfiniBand Access Layer */ /*****/ /****d* Access Layer/ib_apm_state_t * NAME * ib_apm_state_t * * DESCRIPTION * The current automatic path migration state of a queue pair * * SYNOPSIS */ typedef enum _ib_apm_state { IB_APM_MIGRATED = 1, IB_APM_REARM, IB_APM_ARMED } ib_apm_state_t; /*****/ /****s* Access Layer/ib_qp_create_t * NAME * ib_qp_create_t * * DESCRIPTION * Attributes used to initialize a queue pair at creation time. * * SYNOPSIS */ typedef struct _ib_qp_create { ib_qp_type_t qp_type; ib_rdd_handle_t h_rdd; uint32_t sq_depth; uint32_t rq_depth; uint32_t sq_sge; uint32_t rq_sge; ib_cq_handle_t h_sq_cq; ib_cq_handle_t h_rq_cq; boolean_t sq_signaled; } ib_qp_create_t; /* * FIELDS * type * Specifies the type of queue pair to create. * * h_rdd * A handle to a reliable datagram domain to associate with the queue * pair. This field is ignored if the queue pair is not a reliable * datagram type queue pair. * * sq_depth * Indicates the requested maximum number of work requests that may be * outstanding on the queue pair's send queue. This value must be less * than or equal to the maximum reported by the channel adapter associated * with the queue pair. * * rq_depth * Indicates the requested maximum number of work requests that may be * outstanding on the queue pair's receive queue. This value must be less * than or equal to the maximum reported by the channel adapter associated * with the queue pair. * * sq_sge * Indicates the maximum number scatter-gather elements that may be * given in a send work request. This value must be less * than or equal to the maximum reported by the channel adapter associated * with the queue pair. * * rq_sge * Indicates the maximum number scatter-gather elements that may be * given in a receive work request. This value must be less * than or equal to the maximum reported by the channel adapter associated * with the queue pair. * * h_sq_cq * A handle to the completion queue that will be used to report send work * request completions. This handle must be NULL if the type is * IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS. * * h_rq_cq * A handle to the completion queue that will be used to report receive * work request completions. This handle must be NULL if the type is * IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS. * * sq_signaled * A flag that is used to indicate whether the queue pair will signal * an event upon completion of a send work request. If set to * TRUE, send work requests will always generate a completion * event. If set to FALSE, a completion event will only be * generated if the send_opt field of the send work request has the * IB_SEND_OPT_SIGNALED flag set. * * SEE ALSO * ib_qp_type_t, ib_qp_attr_t *****/ /****s* Access Layer/ib_qp_attr_t * NAME * ib_qp_attr_t * * DESCRIPTION * Queue pair attributes returned through ib_query_qp. * * SYNOPSIS */ typedef struct _ib_qp_attr { ib_pd_handle_t h_pd; ib_qp_type_t qp_type; ib_access_t access_ctrl; uint16_t pkey_index; uint32_t sq_depth; uint32_t rq_depth; uint32_t sq_sge; uint32_t rq_sge; uint8_t init_depth; uint8_t resp_res; ib_cq_handle_t h_sq_cq; ib_cq_handle_t h_rq_cq; ib_rdd_handle_t h_rdd; boolean_t sq_signaled; ib_qp_state_t state; ib_net32_t num; ib_net32_t dest_num; ib_net32_t qkey; ib_net32_t sq_psn; ib_net32_t rq_psn; uint8_t primary_port; uint8_t alternate_port; ib_av_attr_t primary_av; ib_av_attr_t alternate_av; ib_apm_state_t apm_state; } ib_qp_attr_t; /* * FIELDS * h_pd * This is a handle to a protection domain associated with the queue * pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM. * * NOTES * Other fields are defined by the Infiniband specification. * * SEE ALSO * ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t *****/ /****d* Access Layer/ib_qp_opts_t * NAME * ib_qp_opts_t * * DESCRIPTION * Optional fields supplied in the modify QP operation. * * SYNOPSIS */ typedef uint32_t ib_qp_opts_t; #define IB_MOD_QP_ALTERNATE_AV 0x00000001 #define IB_MOD_QP_PKEY 0x00000002 #define IB_MOD_QP_APM_STATE 0x00000004 #define IB_MOD_QP_PRIMARY_AV 0x00000008 #define IB_MOD_QP_RNR_NAK_TIMEOUT 0x00000010 #define IB_MOD_QP_RESP_RES 0x00000020 #define IB_MOD_QP_INIT_DEPTH 0x00000040 #define IB_MOD_QP_PRIMARY_PORT 0x00000080 #define IB_MOD_QP_ACCESS_CTRL 0x00000100 #define IB_MOD_QP_QKEY 0x00000200 #define IB_MOD_QP_SQ_DEPTH 0x00000400 #define IB_MOD_QP_RQ_DEPTH 0x00000800 #define IB_MOD_QP_CURRENT_STATE 0x00001000 #define IB_MOD_QP_RETRY_CNT 0x00002000 #define IB_MOD_QP_LOCAL_ACK_TIMEOUT 0x00004000 #define IB_MOD_QP_RNR_RETRY_CNT 0x00008000 /* * SEE ALSO * ib_qp_mod_t *****/ /****s* Access Layer/ib_qp_mod_t * NAME * ib_qp_mod_t * * DESCRIPTION * Information needed to change the state of a queue pair through the * ib_modify_qp call. * * SYNOPSIS */ typedef struct _ib_qp_mod { ib_qp_state_t req_state; union _qp_state { struct _qp_reset { /* * Time, in milliseconds, that the QP needs to spend in * the time wait state before being reused. */ uint32_t timewait; } reset; struct _qp_init { ib_qp_opts_t opts; uint8_t primary_port; ib_net32_t qkey; uint16_t pkey_index; ib_access_t access_ctrl; } init; struct _qp_rtr { ib_net32_t rq_psn; ib_net32_t dest_qp; ib_av_attr_t primary_av; uint8_t resp_res; ib_qp_opts_t opts; ib_av_attr_t alternate_av; ib_net32_t qkey; uint16_t pkey_index; ib_access_t access_ctrl; uint32_t sq_depth; uint32_t rq_depth; uint8_t rnr_nak_timeout; } rtr; struct _qp_rts { ib_net32_t sq_psn; uint8_t retry_cnt; uint8_t rnr_retry_cnt; uint8_t rnr_nak_timeout; uint8_t local_ack_timeout; uint8_t init_depth; ib_qp_opts_t opts; ib_qp_state_t current_state; ib_net32_t qkey; ib_access_t access_ctrl; uint8_t resp_res; ib_av_attr_t primary_av; ib_av_attr_t alternate_av; uint32_t sq_depth; uint32_t rq_depth; ib_apm_state_t apm_state; uint8_t primary_port; uint16_t pkey_index; } rts; struct _qp_sqd { boolean_t sqd_event; } sqd; } state; } ib_qp_mod_t; /* * SEE ALSO * ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t *****/ /****s* Access Layer/ib_eec_attr_t * NAME * ib_eec_attr_t * * DESCRIPTION * Information about an end-to-end context. * * SYNOPSIS */ typedef struct _ib_eec_attr { ib_qp_state_t state; ib_rdd_handle_t h_rdd; ib_net32_t local_eecn; ib_net32_t sq_psn; ib_net32_t rq_psn; uint8_t primary_port; uint16_t pkey_index; uint32_t resp_res; ib_net32_t remote_eecn; uint32_t init_depth; uint32_t dest_num; // ??? What is this? ib_av_attr_t primary_av; ib_av_attr_t alternate_av; ib_apm_state_t apm_state; } ib_eec_attr_t; /* * SEE ALSO * ib_qp_state_t, ib_av_attr_t, ib_apm_state_t *****/ /****d* Access Layer/ib_eec_opts_t * NAME * ib_eec_opts_t * * DESCRIPTION * Optional fields supplied in the modify EEC operation. * * SYNOPSIS */ typedef uint32_t ib_eec_opts_t; #define IB_MOD_EEC_ALTERNATE_AV 0x00000001 #define IB_MOD_EEC_PKEY 0x00000002 #define IB_MOD_EEC_APM_STATE 0x00000004 #define IB_MOD_EEC_PRIMARY_AV 0x00000008 #define IB_MOD_EEC_RNR 0x00000010 #define IB_MOD_EEC_RESP_RES 0x00000020 #define IB_MOD_EEC_OUTSTANDING 0x00000040 #define IB_MOD_EEC_PRIMARY_PORT 0x00000080 /* * NOTES * * *****/ /****s* Access Layer/ib_eec_mod_t * NAME * ib_eec_mod_t * * DESCRIPTION * Information needed to change the state of an end-to-end context through * the ib_modify_eec function. * * SYNOPSIS */ typedef struct _ib_eec_mod { ib_qp_state_t req_state; union _eec_state { struct _eec_init { uint8_t primary_port; uint16_t pkey_index; } init; struct _eec_rtr { ib_net32_t rq_psn; ib_net32_t remote_eecn; ib_av_attr_t primary_av; uint8_t resp_res; ib_eec_opts_t opts; ib_av_attr_t alternate_av; uint16_t pkey_index; } rtr; struct _eec_rts { ib_net32_t sq_psn; uint8_t retry_cnt; uint8_t rnr_retry_cnt; uint8_t local_ack_timeout; uint8_t init_depth; ib_eec_opts_t opts; ib_av_attr_t alternate_av; ib_apm_state_t apm_state; ib_av_attr_t primary_av; uint16_t pkey_index; uint8_t primary_port; } rts; struct _eec_sqd { boolean_t sqd_event; } sqd; } state; } ib_eec_mod_t; /* * SEE ALSO * ib_qp_state_t, ib_av_attr_t, ib_apm_state_t *****/ /****d* Access Layer/ib_wr_type_t * NAME * ib_wr_type_t * * DESCRIPTION * Identifies the type of work request posted to a queue pair. * * SYNOPSIS */ typedef enum _ib_wr_type_t { WR_SEND = 1, WR_RDMA_WRITE, WR_RDMA_READ, WR_COMPARE_SWAP, WR_FETCH_ADD } ib_wr_type_t; /*****/ /****s* Access Layer/ib_local_ds_t * NAME * ib_local_ds_t * * DESCRIPTION * Local data segment information referenced by send and receive work * requests. This is used to specify local data buffers used as part of a * work request. * * SYNOPSIS */ typedef struct _ib_local_ds { void *vaddr; uint32_t length; uint32_t lkey; } ib_local_ds_t; /*****/ /****d* Access Layer/ib_send_opt_t * NAME * ib_send_opt_t * * DESCRIPTION * Optional flags used when posting send work requests. These flags * indicate specific processing for the send operation. * * SYNOPSIS */ typedef uint32_t ib_send_opt_t; #define IB_SEND_OPT_IMMEDIATE 0x00000001 #define IB_SEND_OPT_FENCE 0x00000002 #define IB_SEND_OPT_SIGNALED 0x00000004 #define IB_SEND_OPT_SOLICITED 0x00000008 #define IB_SEND_OPT_INLINE 0x00000010 #define IB_SEND_OPT_LOCAL 0x00000020 #define IB_SEND_OPT_VEND_MASK 0xFFFF0000 /* * VALUES * The following flags determine the behavior of a work request when * posted to the send side. * * IB_SEND_OPT_IMMEDIATE * Send immediate data with the given request. * * IB_SEND_OPT_FENCE * The operation is fenced. Complete all pending send operations * before processing this request. * * IB_SEND_OPT_SIGNALED * If the queue pair is configured for signaled completion, then * generate a completion queue entry when this request completes. * * IB_SEND_OPT_SOLICITED * Set the solicited bit on the last packet of this request. * * IB_SEND_OPT_INLINE * Indicates that the requested send data should be copied into a VPD * owned data buffer. This flag permits the user to issue send operations * without first needing to register the buffer(s) associated with the * send operation. Verb providers that support this operation may place * vendor specific restrictions on the size of send operation that may * be performed as inline. * * * IB_SEND_OPT_LOCAL * Indicates that a sent MAD request should be given to the local VPD for * processing. MADs sent using this option are not placed on the wire. * This send option is only valid for MAD send operations. * * * IB_SEND_OPT_VEND_MASK * This mask indicates bits reserved in the send options that may be used * by the verbs provider to indicate vendor specific options. Bits set * in this area of the send options are ignored by the Access Layer, but * may have specific meaning to the underlying VPD. * *****/ /****s* Access Layer/ib_send_wr_t * NAME * ib_send_wr_t * * DESCRIPTION * Information used to submit a work request to the send queue of a queue * pair. * * SYNOPSIS */ typedef struct _ib_send_wr { struct _ib_send_wr *p_next; uint64_t wr_id; ib_wr_type_t wr_type; ib_send_opt_t send_opt; uint32_t num_ds; ib_local_ds_t *ds_array; ib_net32_t immediate_data; union _send_dgrm { struct _send_ud { ib_net32_t remote_qp; ib_net32_t remote_qkey; ib_av_handle_t h_av; } ud; struct _send_rd { ib_net32_t remote_qp; ib_net32_t remote_qkey; ib_net32_t eecn; } rd; struct _send_raw_ether { ib_net16_t dest_lid; uint8_t path_bits; uint8_t sl; uint8_t max_static_rate; ib_net16_t ether_type; } raw_ether; struct _send_raw_ipv6 { ib_net16_t dest_lid; uint8_t path_bits; uint8_t sl; uint8_t max_static_rate; } raw_ipv6; } dgrm; struct _send_remote_ops { uint64_t vaddr; uint32_t rkey; ib_net64_t atomic1; ib_net64_t atomic2; } remote_ops; } ib_send_wr_t; /* * FIELDS * p_next * A pointer used to chain work requests together. This permits multiple * work requests to be posted to a queue pair through a single function * call. This value is set to NULL to mark the end of the chain. * * wr_id * A 64-bit work request identifier that is returned to the consumer * as part of the work completion. * * wr_type * The type of work request being submitted to the send queue. * * send_opt * Optional send control parameters. * * num_ds * Number of local data segments specified by this work request. * * ds_array * A reference to an array of local data segments used by the send * operation. * * immediate_data * 32-bit field sent as part of a message send or RDMA write operation. * This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE * has been set. * * dgrm.ud.remote_qp * Identifies the destination queue pair of an unreliable datagram send * operation. * * dgrm.ud.remote_qkey * The qkey for the destination queue pair. * * dgrm.ud.h_av * An address vector that specifies the path information used to route * the outbound datagram to the destination queue pair. * * dgrm.rd.remote_qp * Identifies the destination queue pair of a reliable datagram send * operation. * * dgrm.rd.remote_qkey * The qkey for the destination queue pair. * * dgrm.rd.eecn * The local end-to-end context number to use with the reliable datagram * send operation. * * dgrm.raw_ether.dest_lid * The destination LID that will receive this raw ether send. * * dgrm.raw_ether.path_bits * path bits... * * dgrm.raw_ether.sl * service level... * * dgrm.raw_ether.max_static_rate * static rate... * * dgrm.raw_ether.ether_type * ether type... * * dgrm.raw_ipv6.dest_lid * The destination LID that will receive this raw ether send. * * dgrm.raw_ipv6.path_bits * path bits... * * dgrm.raw_ipv6.sl * service level... * * dgrm.raw_ipv6.max_static_rate * static rate... * * remote_ops.vaddr * The registered virtual memory address of the remote memory to access * with an RDMA or atomic operation. * * remote_ops.rkey * The rkey associated with the specified remote vaddr. This data must * be presented exactly as obtained from the remote node. No swapping * of data must be performed. * * atomic1 * The first operand for an atomic operation. * * atomic2 * The second operand for an atomic operation. * * NOTES * The format of data sent over the fabric is user-defined and is considered * opaque to the access layer. The sole exception to this are MADs posted * to a MAD QP service. MADs are expected to match the format defined by * the Infiniband specification and must be in network-byte order when posted * to the MAD QP service. * * SEE ALSO * ib_wr_type_t, ib_local_ds_t, ib_send_opt_t *****/ /****s* Access Layer/ib_recv_wr_t * NAME * ib_recv_wr_t * * DESCRIPTION * Information used to submit a work request to the receive queue of a queue * pair. * * SYNOPSIS */ typedef struct _ib_recv_wr { struct _ib_recv_wr *p_next; uint64_t wr_id; uint32_t num_ds; ib_local_ds_t *ds_array; } ib_recv_wr_t; /* * FIELDS * p_next * A pointer used to chain work requests together. This permits multiple * work requests to be posted to a queue pair through a single function * call. This value is set to NULL to mark the end of the chain. * * wr_id * A 64-bit work request identifier that is returned to the consumer * as part of the work completion. * * num_ds * Number of local data segments specified by this work request. * * ds_array * A reference to an array of local data segments used by the send * operation. * * SEE ALSO * ib_local_ds_t *****/ /****s* Access Layer/ib_bind_wr_t * NAME * ib_bind_wr_t * * DESCRIPTION * Information used to submit a memory window bind work request to the send * queue of a queue pair. * * SYNOPSIS */ typedef struct _ib_bind_wr { uint64_t wr_id; ib_send_opt_t send_opt; ib_mr_handle_t h_mr; ib_access_t access_ctrl; uint32_t current_rkey; ib_local_ds_t local_ds; } ib_bind_wr_t; /* * FIELDS * wr_id * A 64-bit work request identifier that is returned to the consumer * as part of the work completion. * * send_opt * Optional send control parameters. * * h_mr * Handle to the memory region to which this window is being bound. * * access_ctrl * Access rights for this memory window. * * current_rkey * The current rkey assigned to this window for remote access. * * local_ds * A reference to a local data segment used by the bind operation. * * SEE ALSO * ib_send_opt_t, ib_access_t, ib_local_ds_t *****/ /****d* Access Layer/ib_wc_status_t * NAME * ib_wc_status_t * * DESCRIPTION * Indicates the status of a completed work request. These VALUES are * returned to the user when retrieving completions. Note that success is * identified as IB_WCS_SUCCESS, which is always zero. * * SYNOPSIS */ typedef enum _ib_wc_status_t { IB_WCS_SUCCESS, IB_WCS_LOCAL_LEN_ERR, IB_WCS_LOCAL_OP_ERR, IB_WCS_LOCAL_EEC_OP_ERR, IB_WCS_LOCAL_PROTECTION_ERR, IB_WCS_WR_FLUSHED_ERR, IB_WCS_MEM_WINDOW_BIND_ERR, IB_WCS_REM_ACCESS_ERR, IB_WCS_REM_OP_ERR, IB_WCS_RNR_RETRY_ERR, IB_WCS_TIMEOUT_RETRY_ERR, IB_WCS_REM_INVALID_REQ_ERR, IB_WCS_REM_INVALID_RD_REQ_ERR, IB_WCS_INVALID_EECN, IB_WCS_INVALID_EEC_STATE, IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */ IB_WCS_CANCELED, /* InfiniBand Access Layer */ IB_WCS_UNKNOWN /* Must be last. */ } ib_wc_status_t; /* * VALUES * IB_WCS_SUCCESS * Work request completed successfully. * * IB_WCS_MAD * The completed work request was associated with a managmenet datagram * that requires post processing. The MAD will be returned to the user * through a callback once all post processing has completed. * * IB_WCS_LOCAL_LEN_ERR * Generated for a work request posted to the send queue when the * total of the data segment lengths exceeds the message length of the * channel. Generated for a work request posted to the receive queue when * the total of the data segment lengths is too small for a * valid incoming message. * * IB_WCS_LOCAL_OP_ERR * An internal QP consistency error was generated while processing this * work request. This may indicate that the QP was in an incorrect state * for the requested operation. * * IB_WCS_LOCAL_EEC_OP_ERR * An internal EEC consistency error was generated while processing * this work request. This may indicate that the EEC was in an incorrect * state for the requested operation. * * IB_WCS_LOCAL_PROTECTION_ERR * The data segments of the locally posted work request did not refer to * a valid memory region. The memory may not have been properly * registered for the requested operation. * * IB_WCS_WR_FLUSHED_ERR * The work request was flushed from the QP before being completed. * * IB_WCS_MEM_WINDOW_BIND_ERR * A memory window bind operation failed due to insufficient access * rights. * * IB_WCS_REM_ACCESS_ERR, * A protection error was detected at the remote node for a RDMA or atomic * operation. * * IB_WCS_REM_OP_ERR, * The operation could not be successfully completed at the remote node. * This may indicate that the remote QP was in an invalid state or * contained an invalid work request. * * IB_WCS_RNR_RETRY_ERR, * The RNR retry count was exceeded while trying to send this message. * * IB_WCS_TIMEOUT_RETRY_ERR * The local transport timeout counter expired while trying to send this * message. * * IB_WCS_REM_INVALID_REQ_ERR, * The remote node detected an invalid message on the channel. This error * is usually a result of one of the following: * - The operation was not supported on receive queue. * - There was insufficient buffers to receive a new RDMA request. * - There was insufficient buffers to receive a new atomic operation. * - An RDMA request was larger than 2^31 bytes. * * IB_WCS_REM_INVALID_RD_REQ_ERR, * Responder detected an invalid RD message. This may be the result of an * invalid qkey or an RDD mismatch. * * IB_WCS_INVALID_EECN * An invalid EE context number was detected. * * IB_WCS_INVALID_EEC_STATE * The EEC was in an invalid state for the specified request. * * IB_WCS_UNMATCHED_RESPONSE * A response MAD was received for which there was no matching send. The * send operation may have been canceled by the user or may have timed * out. * * IB_WCS_CANCELED * The completed work request was canceled by the user. *****/ OSM_EXPORT const char *ib_wc_status_str[]; /****f* IBA Base: Types/ib_get_wc_status_str * NAME * ib_get_wc_status_str * * DESCRIPTION * Returns a string for the specified work completion status. * * SYNOPSIS */ static inline const char *OSM_API ib_get_wc_status_str(IN ib_wc_status_t wc_status) { if (wc_status > IB_WCS_UNKNOWN) wc_status = IB_WCS_UNKNOWN; return (ib_wc_status_str[wc_status]); } /* * PARAMETERS * wc_status * [in] work completion status value * * RETURN VALUES * Pointer to the work completion status description string. * * NOTES * * SEE ALSO *********/ /****d* Access Layer/ib_wc_type_t * NAME * ib_wc_type_t * * DESCRIPTION * Indicates the type of work completion. * * SYNOPSIS */ typedef enum _ib_wc_type_t { IB_WC_SEND, IB_WC_RDMA_WRITE, IB_WC_RECV, IB_WC_RDMA_READ, IB_WC_MW_BIND, IB_WC_FETCH_ADD, IB_WC_COMPARE_SWAP, IB_WC_RECV_RDMA_WRITE } ib_wc_type_t; /*****/ /****d* Access Layer/ib_recv_opt_t * NAME * ib_recv_opt_t * * DESCRIPTION * Indicates optional fields valid in a receive work completion. * * SYNOPSIS */ typedef uint32_t ib_recv_opt_t; #define IB_RECV_OPT_IMMEDIATE 0x00000001 #define IB_RECV_OPT_FORWARD 0x00000002 #define IB_RECV_OPT_GRH_VALID 0x00000004 #define IB_RECV_OPT_VEND_MASK 0xFFFF0000 /* * VALUES * IB_RECV_OPT_IMMEDIATE * Indicates that immediate data is valid for this work completion. * * IB_RECV_OPT_FORWARD * Indicates that the received trap should be forwarded to the SM. * * IB_RECV_OPT_GRH_VALID * Indicates presence of the global route header. When set, the * first 40 bytes received are the GRH. * * IB_RECV_OPT_VEND_MASK * This mask indicates bits reserved in the receive options that may be * used by the verbs provider to indicate vendor specific options. Bits * set in this area of the receive options are ignored by the Access Layer, * but may have specific meaning to the underlying VPD. *****/ /****s* Access Layer/ib_wc_t * NAME * ib_wc_t * * DESCRIPTION * Work completion information. * * SYNOPSIS */ typedef struct _ib_wc { struct _ib_wc *p_next; uint64_t wr_id; ib_wc_type_t wc_type; uint32_t length; ib_wc_status_t status; uint64_t vendor_specific; union _wc_recv { struct _wc_conn { ib_recv_opt_t recv_opt; ib_net32_t immediate_data; } conn; struct _wc_ud { ib_recv_opt_t recv_opt; ib_net32_t immediate_data; ib_net32_t remote_qp; uint16_t pkey_index; ib_net16_t remote_lid; uint8_t remote_sl; uint8_t path_bits; } ud; struct _wc_rd { ib_net32_t remote_eecn; ib_net32_t remote_qp; ib_net16_t remote_lid; uint8_t remote_sl; uint32_t free_cnt; } rd; struct _wc_raw_ipv6 { ib_net16_t remote_lid; uint8_t remote_sl; uint8_t path_bits; } raw_ipv6; struct _wc_raw_ether { ib_net16_t remote_lid; uint8_t remote_sl; uint8_t path_bits; ib_net16_t ether_type; } raw_ether; } recv; } ib_wc_t; /* * FIELDS * p_next * A pointer used to chain work completions. This permits multiple * work completions to be retrieved from a completion queue through a * single function call. This value is set to NULL to mark the end of * the chain. * * wr_id * The 64-bit work request identifier that was specified when posting the * work request. * * wc_type * Indicates the type of work completion. * * * length * The total length of the data sent or received with the work request. * * status * The result of the work request. * * vendor_specific * HCA vendor specific information returned as part of the completion. * * recv.conn.recv_opt * Indicates optional fields valid as part of a work request that * completed on a connected (reliable or unreliable) queue pair. * * recv.conn.immediate_data * 32-bit field received as part of an inbound message on a connected * queue pair. This field is only valid if the recv_opt flag * IB_RECV_OPT_IMMEDIATE has been set. * * recv.ud.recv_opt * Indicates optional fields valid as part of a work request that * completed on an unreliable datagram queue pair. * * recv.ud.immediate_data * 32-bit field received as part of an inbound message on a unreliable * datagram queue pair. This field is only valid if the recv_opt flag * IB_RECV_OPT_IMMEDIATE has been set. * * recv.ud.remote_qp * Identifies the source queue pair of a received datagram. * * recv.ud.pkey_index * The pkey index for the source queue pair. This is valid only for * GSI type QP's. * * recv.ud.remote_lid * The source LID of the received datagram. * * recv.ud.remote_sl * The service level used by the source of the received datagram. * * recv.ud.path_bits * path bits... * * recv.rd.remote_eecn * The remote end-to-end context number that sent the received message. * * recv.rd.remote_qp * Identifies the source queue pair of a received message. * * recv.rd.remote_lid * The source LID of the received message. * * recv.rd.remote_sl * The service level used by the source of the received message. * * recv.rd.free_cnt * The number of available entries in the completion queue. Reliable * datagrams may complete out of order, so this field may be used to * determine the number of additional completions that may occur. * * recv.raw_ipv6.remote_lid * The source LID of the received message. * * recv.raw_ipv6.remote_sl * The service level used by the source of the received message. * * recv.raw_ipv6.path_bits * path bits... * * recv.raw_ether.remote_lid * The source LID of the received message. * * recv.raw_ether.remote_sl * The service level used by the source of the received message. * * recv.raw_ether.path_bits * path bits... * * recv.raw_ether.ether_type * ether type... * NOTES * When the work request completes with error, the only values that the * consumer can depend on are the wr_id field, and the status of the * operation. * * If the consumer is using the same CQ for completions from more than * one type of QP (i.e Reliable Connected, Datagram etc), then the consumer * must have additional information to decide what fields of the union are * valid. * SEE ALSO * ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t *****/ /****s* Access Layer/ib_mr_create_t * NAME * ib_mr_create_t * * DESCRIPTION * Information required to create a registered memory region. * * SYNOPSIS */ typedef struct _ib_mr_create { void *vaddr; uint64_t length; ib_access_t access_ctrl; } ib_mr_create_t; /* * FIELDS * vaddr * Starting virtual address of the region being registered. * * length * Length of the buffer to register. * * access_ctrl * Access rights of the registered region. * * SEE ALSO * ib_access_t *****/ /****s* Access Layer/ib_phys_create_t * NAME * ib_phys_create_t * * DESCRIPTION * Information required to create a physical memory region. * * SYNOPSIS */ typedef struct _ib_phys_create { uint64_t length; uint32_t num_bufs; uint64_t *buf_array; uint32_t buf_offset; uint32_t page_size; ib_access_t access_ctrl; } ib_phys_create_t; /* * length * The length of the memory region in bytes. * * num_bufs * Number of buffers listed in the specified buffer array. * * buf_array * An array of physical buffers to be registered as a single memory * region. * * buf_offset * The offset into the first physical page of the specified memory * region to start the virtual address. * * page_size * The physical page size of the memory being registered. * * access_ctrl * Access rights of the registered region. * * SEE ALSO * ib_access_t *****/ /****s* Access Layer/ib_mr_attr_t * NAME * ib_mr_attr_t * * DESCRIPTION * Attributes of a registered memory region. * * SYNOPSIS */ typedef struct _ib_mr_attr { ib_pd_handle_t h_pd; void *local_lb; void *local_ub; void *remote_lb; void *remote_ub; ib_access_t access_ctrl; uint32_t lkey; uint32_t rkey; } ib_mr_attr_t; /* * DESCRIPTION * h_pd * Handle to the protection domain for this memory region. * * local_lb * The virtual address of the lower bound of protection for local * memory access. * * local_ub * The virtual address of the upper bound of protection for local * memory access. * * remote_lb * The virtual address of the lower bound of protection for remote * memory access. * * remote_ub * The virtual address of the upper bound of protection for remote * memory access. * * access_ctrl * Access rights for the specified memory region. * * lkey * The lkey associated with this memory region. * * rkey * The rkey associated with this memory region. * * NOTES * The remote_lb, remote_ub, and rkey are only valid if remote memory access * is enabled for this memory region. * * SEE ALSO * ib_access_t *****/ /****d* Access Layer/ib_ca_mod_t * NAME * ib_ca_mod_t -- Modify port attributes and error counters * * DESCRIPTION * Specifies modifications to the port attributes of a channel adapter. * * SYNOPSIS */ typedef uint32_t ib_ca_mod_t; #define IB_CA_MOD_IS_CM_SUPPORTED 0x00000001 #define IB_CA_MOD_IS_SNMP_SUPPORTED 0x00000002 #define IB_CA_MOD_IS_DEV_MGMT_SUPPORTED 0x00000004 #define IB_CA_MOD_IS_VEND_SUPPORTED 0x00000008 #define IB_CA_MOD_IS_SM 0x00000010 #define IB_CA_MOD_IS_SM_DISABLED 0x00000020 #define IB_CA_MOD_QKEY_CTR 0x00000040 #define IB_CA_MOD_PKEY_CTR 0x00000080 #define IB_CA_MOD_IS_NOTICE_SUPPORTED 0x00000100 #define IB_CA_MOD_IS_TRAP_SUPPORTED 0x00000200 #define IB_CA_MOD_IS_APM_SUPPORTED 0x00000400 #define IB_CA_MOD_IS_SLMAP_SUPPORTED 0x00000800 #define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED 0x00001000 #define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED 0x00002000 #define IB_CA_MOD_IS_SYSGUID_SUPPORTED 0x00004000 #define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED 0x00008000 #define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED 0x00010000 #define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED 0x00020000 #define IB_CA_MOD_IS_REINIT_SUPORTED 0x00040000 #define IB_CA_MOD_IS_LEDINFO_SUPPORTED 0x00080000 #define IB_CA_MOD_SHUTDOWN_PORT 0x00100000 #define IB_CA_MOD_INIT_TYPE_VALUE 0x00200000 #define IB_CA_MOD_SYSTEM_IMAGE_GUID 0x00400000 /* * VALUES * IB_CA_MOD_IS_CM_SUPPORTED * Indicates if there is a communication manager accessible through * the port. * * IB_CA_MOD_IS_SNMP_SUPPORTED * Indicates if there is an SNMP agent accessible through the port. * * IB_CA_MOD_IS_DEV_MGMT_SUPPORTED * Indicates if there is a device management agent accessible * through the port. * * IB_CA_MOD_IS_VEND_SUPPORTED * Indicates if there is a vendor supported agent accessible * through the port. * * IB_CA_MOD_IS_SM * Indicates if there is a subnet manager accessible through * the port. * * IB_CA_MOD_IS_SM_DISABLED * Indicates if the port has been disabled for configuration by the * subnet manager. * * IB_CA_MOD_QKEY_CTR * Used to reset the qkey violation counter associated with the * port. * * IB_CA_MOD_PKEY_CTR * Used to reset the pkey violation counter associated with the * port. * * IB_CA_MOD_IS_NOTICE_SUPPORTED * Indicates that this CA supports ability to generate Notices for * Port State changes. (only applicable to switches) * * IB_CA_MOD_IS_TRAP_SUPPORTED * Indicates that this management port supports ability to generate * trap messages. (only applicable to switches) * * IB_CA_MOD_IS_APM_SUPPORTED * Indicates that this port is capable of performing Automatic * Path Migration. * * IB_CA_MOD_IS_SLMAP_SUPPORTED * Indicates this port supports SLMAP capability. * * IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED * Indicates that PKEY is supported in NVRAM * * IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED * Indicates that MKEY is supported in NVRAM * * IB_CA_MOD_IS_SYSGUID_SUPPORTED * Indicates System Image GUID support. * * IB_CA_MOD_IS_DR_NOTICE_SUPPORTED * Indicate support for generating Direct Routed Notices * * IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED * Indicates support for Boot Management * * IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED * Indicates capability to generate notices for changes to CAPMASK * * IB_CA_MOD_IS_REINIT_SUPORTED * Indicates type of node init supported. Refer to Chapter 14 for * Initialization actions. * * IB_CA_MOD_IS_LEDINFO_SUPPORTED * Indicates support for LED info. * * IB_CA_MOD_SHUTDOWN_PORT * Used to modify the port active indicator. * * IB_CA_MOD_INIT_TYPE_VALUE * Used to modify the init_type value for the port. * * IB_CA_MOD_SYSTEM_IMAGE_GUID * Used to modify the system image GUID for the port. *****/ /****d* Access Layer/ib_mr_mod_t * NAME * ib_mr_mod_t * * DESCRIPTION * Mask used to specify which attributes of a registered memory region are * being modified. * * SYNOPSIS */ typedef uint32_t ib_mr_mod_t; #define IB_MR_MOD_ADDR 0x00000001 #define IB_MR_MOD_PD 0x00000002 #define IB_MR_MOD_ACCESS 0x00000004 /* * PARAMETERS * IB_MEM_MOD_ADDR * The address of the memory region is being modified. * * IB_MEM_MOD_PD * The protection domain associated with the memory region is being * modified. * * IB_MEM_MOD_ACCESS * The access rights the memory region are being modified. *****/ /****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER * NAME * IB_SMINFO_ATTR_MOD_HANDOVER * * DESCRIPTION * Encoded attribute modifier value used on SubnSet(SMInfo) SMPs. * * SOURCE */ #define IB_SMINFO_ATTR_MOD_HANDOVER (CL_HTON32(0x000001)) /**********/ /****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE * NAME * IB_SMINFO_ATTR_MOD_ACKNOWLEDGE * * DESCRIPTION * Encoded attribute modifier value used on SubnSet(SMInfo) SMPs. * * SOURCE */ #define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE (CL_HTON32(0x000002)) /**********/ /****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE * NAME * IB_SMINFO_ATTR_MOD_DISABLE * * DESCRIPTION * Encoded attribute modifier value used on SubnSet(SMInfo) SMPs. * * SOURCE */ #define IB_SMINFO_ATTR_MOD_DISABLE (CL_HTON32(0x000003)) /**********/ /****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY * NAME * IB_SMINFO_ATTR_MOD_STANDBY * * DESCRIPTION * Encoded attribute modifier value used on SubnSet(SMInfo) SMPs. * * SOURCE */ #define IB_SMINFO_ATTR_MOD_STANDBY (CL_HTON32(0x000004)) /**********/ /****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER * NAME * IB_SMINFO_ATTR_MOD_DISCOVER * * DESCRIPTION * Encoded attribute modifier value used on SubnSet(SMInfo) SMPs. * * SOURCE */ #define IB_SMINFO_ATTR_MOD_DISCOVER (CL_HTON32(0x000005)) /**********/ /****s* Access Layer/ib_ci_op_t * NAME * ib_ci_op_t * * DESCRIPTION * A structure used for vendor specific CA interface communication. * * SYNOPSIS */ typedef struct _ib_ci_op { IN uint32_t command; IN OUT void *p_buf OPTIONAL; IN uint32_t buf_size; IN OUT uint32_t num_bytes_ret; IN OUT int32_t status; } ib_ci_op_t; /* * FIELDS * command * A command code that is understood by the verbs provider. * * p_buf * A reference to a buffer containing vendor specific data. The verbs * provider must not access pointers in the p_buf between user-mode and * kernel-mode. Any pointers embedded in the p_buf are invalidated by * the user-mode/kernel-mode transition. * * buf_size * The size of the buffer in bytes. * * num_bytes_ret * The size in bytes of the vendor specific data returned in the buffer. * This field is set by the verbs provider. The verbs provider should * verify that the buffer size is sufficient to hold the data being * returned. * * status * The completion status from the verbs provider. This field should be * initialize to indicate an error to allow detection and cleanup in * case a communication error occurs between user-mode and kernel-mode. * * NOTES * This structure is provided to allow the exchange of vendor specific * data between the originator and the verbs provider. Users of this * structure are expected to know the format of data in the p_buf based * on the structure command field or the usage context. *****/ /****s* IBA Base: Types/ib_cc_mad_t * NAME * ib_cc_mad_t * * DESCRIPTION * IBA defined Congestion Control MAD format. (A10.4.1) * * SYNOPSIS */ #define IB_CC_LOG_DATA_SIZE 32 #define IB_CC_MGT_DATA_SIZE 192 #define IB_CC_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_CC_LOG_DATA_SIZE \ - IB_CC_MGT_DATA_SIZE) #include typedef struct _ib_cc_mad { ib_mad_t header; ib_net64_t cc_key; uint8_t log_data[IB_CC_LOG_DATA_SIZE]; uint8_t mgt_data[IB_CC_MGT_DATA_SIZE]; } PACK_SUFFIX ib_cc_mad_t; #include /* * FIELDS * header * Common MAD header. * * cc_key * CC_Key of the Congestion Control MAD. * * log_data * Congestion Control log data of the CC MAD. * * mgt_data * Congestion Control management data of the CC MAD. * * SEE ALSO * ib_mad_t *********/ /****f* IBA Base: Types/ib_cc_mad_get_cc_key * NAME * ib_cc_mad_get_cc_key * * DESCRIPTION * Gets a CC_Key of the CC MAD. * * SYNOPSIS */ static inline ib_net64_t OSM_API ib_cc_mad_get_cc_key(IN const ib_cc_mad_t * const p_cc_mad) { return p_cc_mad->cc_key; } /* * PARAMETERS * p_cc_mad * [in] Pointer to the CC MAD packet. * * RETURN VALUES * CC_Key of the provided CC MAD packet. * * NOTES * * SEE ALSO * ib_cc_mad_t *********/ /****f* IBA Base: Types/ib_cc_mad_get_log_data_ptr * NAME * ib_cc_mad_get_log_data_ptr * * DESCRIPTION * Gets a pointer to the CC MAD's log data area. * * SYNOPSIS */ static inline void * OSM_API ib_cc_mad_get_log_data_ptr(IN const ib_cc_mad_t * const p_cc_mad) { return ((void *)p_cc_mad->log_data); } /* * PARAMETERS * p_cc_mad * [in] Pointer to the CC MAD packet. * * RETURN VALUES * Pointer to CC MAD log data area. * * NOTES * * SEE ALSO * ib_cc_mad_t *********/ /****f* IBA Base: Types/ib_cc_mad_get_mgt_data_ptr * NAME * ib_cc_mad_get_mgt_data_ptr * * DESCRIPTION * Gets a pointer to the CC MAD's management data area. * * SYNOPSIS */ static inline void * OSM_API ib_cc_mad_get_mgt_data_ptr(IN const ib_cc_mad_t * const p_cc_mad) { return ((void *)p_cc_mad->mgt_data); } /* * PARAMETERS * p_cc_mad * [in] Pointer to the CC MAD packet. * * RETURN VALUES * Pointer to CC MAD management data area. * * NOTES * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_cong_info_t * NAME * ib_cong_info_t * * DESCRIPTION * IBA defined CongestionInfo attribute (A10.4.3.3) * * SYNOPSIS */ #include typedef struct _ib_cong_info { uint8_t cong_info; uint8_t resv; uint8_t ctrl_table_cap; } PACK_SUFFIX ib_cong_info_t; #include /* * FIELDS * cong_info * Congestion control capabilities of the node. * * ctrl_table_cap * Number of 64 entry blocks in the CongestionControlTable. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_cong_key_info_t * NAME * ib_cong_key_info_t * * DESCRIPTION * IBA defined CongestionKeyInfo attribute (A10.4.3.4) * * SYNOPSIS */ #include typedef struct _ib_cong_key_info { ib_net64_t cc_key; ib_net16_t protect_bit; ib_net16_t lease_period; ib_net16_t violations; } PACK_SUFFIX ib_cong_key_info_t; #include /* * FIELDS * cc_key * 8-byte CC Key. * * protect_bit * Bit 0 is a CC Key Protect Bit, other 15 bits are reserved. * * lease_period * How long the CC Key protect bit is to remain non-zero. * * violations * Number of received MADs that violated CC Key. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_cong_log_event_sw_t * NAME * ib_cong_log_event_sw_t * * DESCRIPTION * IBA defined CongestionLogEvent (SW) entry (A10.4.3.5) * * SYNOPSIS */ #include typedef struct _ib_cong_log_event_sw { ib_net16_t slid; ib_net16_t dlid; ib_net32_t sl; ib_net32_t time_stamp; } PACK_SUFFIX ib_cong_log_event_sw_t; #include /* * FIELDS * slid * Source LID of congestion event. * * dlid * Destination LID of congestion event. * * sl * 4 bits - SL of congestion event. * rest of the bits are reserved. * * time_stamp * Timestamp of congestion event. * * SEE ALSO * ib_cc_mad_t, ib_cong_log_t *********/ /****s* IBA Base: Types/ib_cong_log_event_ca_t * NAME * ib_cong_log_event_ca_t * * DESCRIPTION * IBA defined CongestionLogEvent (CA) entry (A10.4.3.5) * * SYNOPSIS */ #include typedef struct _ib_cong_log_event_ca { ib_net32_t local_qp_resv0; ib_net32_t remote_qp_sl_service_type; ib_net16_t remote_lid; ib_net16_t resv1; ib_net32_t time_stamp; } PACK_SUFFIX ib_cong_log_event_ca_t; #include /* * FIELDS * resv0_local_qp * bits [31:8] local QP that reached CN threshold. * bits [7:0] reserved. * * remote_qp_sl_service_type * bits [31:8] remote QP that is connected to local QP. * bits [7:4] SL of the local QP. * bits [3:0] Service Type of the local QP. * * remote_lid * LID of the remote port that is connected to local QP. * * time_stamp * Timestamp when threshold reached. * * SEE ALSO * ib_cc_mad_t, ib_cong_log_t *********/ /****s* IBA Base: Types/ib_cong_log_t * NAME * ib_cong_log_t * * DESCRIPTION * IBA defined CongestionLog attribute (A10.4.3.5) * * SYNOPSIS */ #include typedef struct _ib_cong_log { uint8_t log_type; union _log_details { struct _log_sw { uint8_t cong_flags; ib_net16_t event_counter; ib_net32_t time_stamp; uint8_t port_map[32]; ib_cong_log_event_sw_t entry_list[15]; } PACK_SUFFIX log_sw; struct _log_ca { uint8_t cong_flags; ib_net16_t event_counter; ib_net16_t event_map; ib_net16_t resv; ib_net32_t time_stamp; ib_cong_log_event_ca_t log_event[13]; } PACK_SUFFIX log_ca; } log_details; } PACK_SUFFIX ib_cong_log_t; #include /* * FIELDS * * log_{sw,ca}.log_type * Log type: 0x1 is for Switch, 0x2 is for CA * * log_{sw,ca}.cong_flags * Congestion Flags. * * log_{sw,ca}.event_counter * Number of events since log last sent. * * log_{sw,ca}.time_stamp * Timestamp when log sent. * * log_sw.port_map * If a bit set to 1, then the corresponding port * has marked packets with a FECN. * bits 0 and 255 - reserved * bits [254..1] - ports [254..1]. * * log_sw.entry_list * Array of 13 most recent congestion log events. * * log_ca.event_map * array 16 bits, one for each SL. * * log_ca.log_event * Array of 13 most recent congestion log events. * * SEE ALSO * ib_cc_mad_t, ib_cong_log_event_sw_t, ib_cong_log_event_ca_t *********/ /****s* IBA Base: Types/ib_sw_cong_setting_t * NAME * ib_sw_cong_setting_t * * DESCRIPTION * IBA defined SwitchCongestionSetting attribute (A10.4.3.6) * * SYNOPSIS */ #define IB_CC_PORT_MASK_DATA_SIZE 32 #include typedef struct _ib_sw_cong_setting { ib_net32_t control_map; uint8_t victim_mask[IB_CC_PORT_MASK_DATA_SIZE]; uint8_t credit_mask[IB_CC_PORT_MASK_DATA_SIZE]; uint8_t threshold_resv; uint8_t packet_size; ib_net16_t cs_threshold_resv; ib_net16_t cs_return_delay; ib_net16_t marking_rate; } PACK_SUFFIX ib_sw_cong_setting_t; #include /* * FIELDS * * control_map * Indicates which components of this attribute are valid * * victim_mask * If the bit set to 1, then the port corresponding to * that bit shall mark packets that encounter congestion * with a FECN, whether they are the source or victim * of congestion. (See A10.2.1.1.1) * bit 0: port 0 (enhanced port 0 only) * bits [254..1]: ports [254..1] * bit 255: reserved * * credit_mask * If the bit set to 1, then the port corresponding * to that bit shall apply Credit Starvation. * bit 0: port 0 (enhanced port 0 only) * bits [254..1]: ports [254..1] * bit 255: reserved * * threshold_resv * bits [7..4] Indicates how aggressive cong. marking should be * bits [3..0] Reserved * * packet_size * Any packet less than this size won't be marked with FECN * * cs_threshold_resv * bits [15..12] How aggressive Credit Starvation should be * bits [11..0] Reserved * * cs_return_delay * Value that controls credit return rate. * * marking_rate * The value that provides the mean number of packets * between marking eligible packets with FECN. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_sw_port_cong_setting_element_t * NAME * ib_sw_port_cong_setting_element_t * * DESCRIPTION * IBA defined SwitchPortCongestionSettingElement (A10.4.3.7) * * SYNOPSIS */ #include typedef struct _ib_sw_port_cong_setting_element { uint8_t valid_ctrl_type_res_threshold; uint8_t packet_size; ib_net16_t cong_param; } PACK_SUFFIX ib_sw_port_cong_setting_element_t; #include /* * FIELDS * * valid_ctrl_type_res_threshold * bit 7: "Valid" * when set to 1, indicates this switch * port congestion setting element is valid. * bit 6: "Control Type" * Indicates which type of attribute is being set: * 0b = Congestion Control parameters are being set. * 1b = Credit Starvation parameters are being set. * bits [5..4]: reserved * bits [3..0]: "Threshold" * When Control Type is 0, contains the congestion * threshold value (Threshold) for this port. * When Control Type is 1, contains the credit * starvation threshold (CS_Threshold) value for * this port. * * packet_size * When Control Type is 0, this field contains the minimum * size of packets that may be marked with a FECN. * When Control Type is 1, this field is reserved. * * cong_parm * When Control Type is 0, this field contains the port * marking_rate. * When Control Type is 1, this field is reserved. * * SEE ALSO * ib_cc_mad_t, ib_sw_port_cong_setting_t *********/ /****d* IBA Base: Types/ib_sw_port_cong_setting_block_t * NAME * ib_sw_port_cong_setting_block_t * * DESCRIPTION * Defines the SwitchPortCongestionSetting Block (A10.4.3.7). * * SOURCE */ #define IB_CC_SW_PORT_SETTING_ELEMENTS 32 typedef ib_sw_port_cong_setting_element_t ib_sw_port_cong_setting_block_t[IB_CC_SW_PORT_SETTING_ELEMENTS]; /**********/ /****s* IBA Base: Types/ib_sw_port_cong_setting_t * NAME * ib_sw_port_cong_setting_t * * DESCRIPTION * IBA defined SwitchPortCongestionSetting attribute (A10.4.3.7) * * SYNOPSIS */ #include typedef struct _ib_sw_port_cong_setting { ib_sw_port_cong_setting_block_t block; } PACK_SUFFIX ib_sw_port_cong_setting_t; #include /* * FIELDS * * block * SwitchPortCongestionSetting block. * * SEE ALSO * ib_cc_mad_t, ib_sw_port_cong_setting_element_t *********/ /****s* IBA Base: Types/ib_ca_cong_entry_t * NAME * ib_ca_cong_entry_t * * DESCRIPTION * IBA defined CACongestionEntry (A10.4.3.8) * * SYNOPSIS */ #include typedef struct _ib_ca_cong_entry { ib_net16_t ccti_timer; uint8_t ccti_increase; uint8_t trigger_threshold; uint8_t ccti_min; uint8_t resv0; ib_net16_t resv1; } PACK_SUFFIX ib_ca_cong_entry_t; #include /* * FIELDS * * ccti_timer * When the timer expires it will be reset to its specified * value, and 1 will be decremented from the CCTI. * * ccti_increase * The number to be added to the table Index (CCTI) * on the receipt of a BECN. * * trigger_threshold * When the CCTI is equal to this value, an event * is logged in the CAs cyclic event log. * * ccti_min * The minimum value permitted for the CCTI. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_ca_cong_setting_t * NAME * ib_ca_cong_setting_t * * DESCRIPTION * IBA defined CACongestionSetting attribute (A10.4.3.8) * * SYNOPSIS */ #define IB_CA_CONG_ENTRY_DATA_SIZE 16 #include typedef struct _ib_ca_cong_setting { ib_net16_t port_control; ib_net16_t control_map; ib_ca_cong_entry_t entry_list[IB_CA_CONG_ENTRY_DATA_SIZE]; } PACK_SUFFIX ib_ca_cong_setting_t; #include /* * FIELDS * * port_control * Congestion attributes for this port: * bit0 = 0: QP based CC * bit0 = 1: SL/Port based CC * All other bits are reserved * * control_map * An array of sixteen bits, one for each SL. Each bit indicates * whether or not the corresponding entry is to be modified. * * entry_list * List of 16 CACongestionEntries, one per SL. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_cc_tbl_entry_t * NAME * ib_cc_tbl_entry_t * * DESCRIPTION * IBA defined CongestionControlTableEntry (A10.4.3.9) * * SYNOPSIS */ #include typedef struct _ib_cc_tbl_entry { ib_net16_t shift_multiplier; } PACK_SUFFIX ib_cc_tbl_entry_t; #include /* * FIELDS * * shift_multiplier * bits [15..14] - CCT Shift * used when calculating the injection rate delay * bits [13..0] - CCT Multiplier * used when calculating the injection rate delay * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_cc_tbl_t * NAME * ib_cc_tbl_t * * DESCRIPTION * IBA defined CongestionControlTable attribute (A10.4.3.9) * * SYNOPSIS */ #define IB_CC_TBL_ENTRY_LIST_MAX 64 #include typedef struct _ib_cc_tbl { ib_net16_t ccti_limit; ib_net16_t resv; ib_cc_tbl_entry_t entry_list[IB_CC_TBL_ENTRY_LIST_MAX]; } PACK_SUFFIX ib_cc_tbl_t; #include /* * FIELDS * * ccti_limit * Maximum valid CCTI for this table. * * entry_list * List of up to 64 CongestionControlTableEntries. * * SEE ALSO * ib_cc_mad_t *********/ /****s* IBA Base: Types/ib_time_stamp_t * NAME * ib_time_stamp_t * * DESCRIPTION * IBA defined TimeStamp attribute (A10.4.3.10) * * SOURCE */ #include typedef struct _ib_time_stamp { ib_net32_t value; } PACK_SUFFIX ib_time_stamp_t; #include /* * FIELDS * * value * Free running clock that provides relative time info * for a device. Time is kept in 1.024 usec units. * * SEE ALSO * ib_cc_mad_t *********/ END_C_DECLS #else /* ndef __WIN__ */ #include #endif #endif /* __IB_TYPES_H__ */ opensm-3.3.20/include/iba/ib_cm_types.h0000644000205000001450000001422112104655724014642 00000000000000/* * Copyright (c) 2004-2007 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. * */ #if !defined(__IB_CM_TYPES_H__) #define __IB_CM_TYPES_H__ #ifndef __WIN__ #include #ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } #else /* !__cplusplus */ # define BEGIN_C_DECLS # define END_C_DECLS #endif /* __cplusplus */ BEGIN_C_DECLS /* * Defines known Communication management class versions */ #define IB_MCLASS_CM_VER_2 2 #define IB_MCLASS_CM_VER_1 1 /* * Defines the size of user available data in communication management MADs */ #define IB_REQ_PDATA_SIZE_VER2 92 #define IB_MRA_PDATA_SIZE_VER2 222 #define IB_REJ_PDATA_SIZE_VER2 148 #define IB_REP_PDATA_SIZE_VER2 196 #define IB_RTU_PDATA_SIZE_VER2 224 #define IB_LAP_PDATA_SIZE_VER2 168 #define IB_APR_PDATA_SIZE_VER2 148 #define IB_DREQ_PDATA_SIZE_VER2 220 #define IB_DREP_PDATA_SIZE_VER2 224 #define IB_SIDR_REQ_PDATA_SIZE_VER2 216 #define IB_SIDR_REP_PDATA_SIZE_VER2 136 #define IB_REQ_PDATA_SIZE_VER1 92 #define IB_MRA_PDATA_SIZE_VER1 222 #define IB_REJ_PDATA_SIZE_VER1 148 #define IB_REP_PDATA_SIZE_VER1 204 #define IB_RTU_PDATA_SIZE_VER1 224 #define IB_LAP_PDATA_SIZE_VER1 168 #define IB_APR_PDATA_SIZE_VER1 151 #define IB_DREQ_PDATA_SIZE_VER1 220 #define IB_DREP_PDATA_SIZE_VER1 224 #define IB_SIDR_REQ_PDATA_SIZE_VER1 216 #define IB_SIDR_REP_PDATA_SIZE_VER1 140 #define IB_ARI_SIZE 72 // redefine #define IB_APR_INFO_SIZE 72 /****d* Access Layer/ib_rej_status_t * NAME * ib_rej_status_t * * DESCRIPTION * Rejection reasons. * * SYNOPSIS */ typedef ib_net16_t ib_rej_status_t; /* * SEE ALSO * ib_cm_rej, ib_cm_rej_rec_t * * SOURCE */ #define IB_REJ_INSUF_QP CL_HTON16(1) #define IB_REJ_INSUF_EEC CL_HTON16(2) #define IB_REJ_INSUF_RESOURCES CL_HTON16(3) #define IB_REJ_TIMEOUT CL_HTON16(4) #define IB_REJ_UNSUPPORTED CL_HTON16(5) #define IB_REJ_INVALID_COMM_ID CL_HTON16(6) #define IB_REJ_INVALID_COMM_INSTANCE CL_HTON16(7) #define IB_REJ_INVALID_SID CL_HTON16(8) #define IB_REJ_INVALID_XPORT CL_HTON16(9) #define IB_REJ_STALE_CONN CL_HTON16(10) #define IB_REJ_RDC_NOT_EXIST CL_HTON16(11) #define IB_REJ_INVALID_GID CL_HTON16(12) #define IB_REJ_INVALID_LID CL_HTON16(13) #define IB_REJ_INVALID_SL CL_HTON16(14) #define IB_REJ_INVALID_TRAFFIC_CLASS CL_HTON16(15) #define IB_REJ_INVALID_HOP_LIMIT CL_HTON16(16) #define IB_REJ_INVALID_PKT_RATE CL_HTON16(17) #define IB_REJ_INVALID_ALT_GID CL_HTON16(18) #define IB_REJ_INVALID_ALT_LID CL_HTON16(19) #define IB_REJ_INVALID_ALT_SL CL_HTON16(20) #define IB_REJ_INVALID_ALT_TRAFFIC_CLASS CL_HTON16(21) #define IB_REJ_INVALID_ALT_HOP_LIMIT CL_HTON16(22) #define IB_REJ_INVALID_ALT_PKT_RATE CL_HTON16(23) #define IB_REJ_PORT_REDIRECT CL_HTON16(24) #define IB_REJ_INVALID_MTU CL_HTON16(26) #define IB_REJ_INSUFFICIENT_RESP_RES CL_HTON16(27) #define IB_REJ_USER_DEFINED CL_HTON16(28) #define IB_REJ_INVALID_RNR_RETRY CL_HTON16(29) #define IB_REJ_DUPLICATE_LOCAL_COMM_ID CL_HTON16(30) #define IB_REJ_INVALID_CLASS_VER CL_HTON16(31) #define IB_REJ_INVALID_FLOW_LBL CL_HTON16(32) #define IB_REJ_INVALID_ALT_FLOW_LBL CL_HTON16(33) #define IB_REJ_SERVICE_HANDOFF CL_HTON16(65535) /******/ /****d* Access Layer/ib_apr_status_t * NAME * ib_apr_status_t * * DESCRIPTION * Automatic path migration status information. * * SYNOPSIS */ typedef uint8_t ib_apr_status_t; /* * SEE ALSO * ib_cm_apr, ib_cm_apr_rec_t * * SOURCE */ #define IB_AP_SUCCESS 0 #define IB_AP_INVALID_COMM_ID 1 #define IB_AP_UNSUPPORTED 2 #define IB_AP_REJECT 3 #define IB_AP_REDIRECT 4 #define IB_AP_IS_CURRENT 5 #define IB_AP_INVALID_QPN_EECN 6 #define IB_AP_INVALID_LID 7 #define IB_AP_INVALID_GID 8 #define IB_AP_INVALID_FLOW_LBL 9 #define IB_AP_INVALID_TCLASS 10 #define IB_AP_INVALID_HOP_LIMIT 11 #define IB_AP_INVALID_PKT_RATE 12 #define IB_AP_INVALID_SL 13 /******/ /****d* Access Layer/ib_cm_cap_mask_t * NAME * ib_cm_cap_mask_t * * DESCRIPTION * Capability mask values in ClassPortInfo. * * SYNOPSIS */ #define IB_CM_RELIABLE_CONN_CAPABLE CL_HTON16(9) #define IB_CM_RELIABLE_DGRM_CAPABLE CL_HTON16(10) #define IB_CM_RDGRM_CAPABLE CL_HTON16(11) #define IB_CM_UNRELIABLE_CONN_CAPABLE CL_HTON16(12) #define IB_CM_SIDR_CAPABLE CL_HTON16(13) /* * SEE ALSO * ib_cm_rep, ib_class_port_info_t * * SOURCE * *******/ /* * Service ID resolution status */ typedef uint16_t ib_sidr_status_t; #define IB_SIDR_SUCCESS 0 #define IB_SIDR_UNSUPPORTED 1 #define IB_SIDR_REJECT 2 #define IB_SIDR_NO_QP 3 #define IB_SIDR_REDIRECT 4 #define IB_SIDR_UNSUPPORTED_VER 5 END_C_DECLS #endif /* ndef __WIN__ */ #endif /* __IB_CM_TYPES_H__ */ opensm-3.3.20/include/Makefile.am0000644000205000001450000000217212104655724013477 00000000000000 SUBDIRS = . nobase_pkginclude_HEADERS = iba/ib_types.h iba/ib_cm_types.h EXTRA_DIST = \ $(srcdir)/iba/ib_types.h \ $(srcdir)/iba/ib_cm_types.h \ $(srcdir)/vendor/osm_vendor_mlx_transport_anafa.h \ $(srcdir)/vendor/osm_vendor_mlx.h \ $(srcdir)/vendor/osm_vendor_mlx_sender.h \ $(srcdir)/vendor/osm_vendor_ibumad.h \ $(srcdir)/vendor/osm_vendor_mlx_defs.h \ $(srcdir)/vendor/osm_vendor_mtl_transaction_mgr.h \ $(srcdir)/vendor/osm_vendor_mlx_sar.h \ $(srcdir)/vendor/osm_vendor_mlx_dispatcher.h \ $(srcdir)/vendor/osm_vendor_umadt.h \ $(srcdir)/vendor/osm_vendor_mlx_svc.h \ $(srcdir)/vendor/osm_vendor_mlx_hca.h \ $(srcdir)/vendor/osm_vendor_mlx_rmpp_ctx.h \ $(srcdir)/vendor/osm_vendor_mlx_transport.h \ $(srcdir)/vendor/osm_vendor_mlx_inout.h \ $(srcdir)/vendor/osm_vendor_mtl_hca_guid.h \ $(srcdir)/vendor/osm_vendor_test.h \ $(srcdir)/vendor/osm_vendor_ts.h \ $(srcdir)/vendor/osm_vendor_mlx_txn.h \ $(srcdir)/vendor/osm_vendor_al.h \ $(srcdir)/vendor/osm_vendor_mtl.h \ $(srcdir)/vendor/osm_ts_useraccess.h \ $(srcdir)/vendor/osm_umadt.h \ $(srcdir)/vendor/osm_mtl_bind.h pkgincludedir = $(includedir)/infiniband opensm-3.3.20/include/Makefile.in0000644000205000001450000005220112726323425013506 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = include DIST_COMMON = $(nobase_pkginclude_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(pkgincludedir)" HEADERS = $(nobase_pkginclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" pkgincludedir = $(includedir)/infiniband ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . nobase_pkginclude_HEADERS = iba/ib_types.h iba/ib_cm_types.h EXTRA_DIST = \ $(srcdir)/iba/ib_types.h \ $(srcdir)/iba/ib_cm_types.h \ $(srcdir)/vendor/osm_vendor_mlx_transport_anafa.h \ $(srcdir)/vendor/osm_vendor_mlx.h \ $(srcdir)/vendor/osm_vendor_mlx_sender.h \ $(srcdir)/vendor/osm_vendor_ibumad.h \ $(srcdir)/vendor/osm_vendor_mlx_defs.h \ $(srcdir)/vendor/osm_vendor_mtl_transaction_mgr.h \ $(srcdir)/vendor/osm_vendor_mlx_sar.h \ $(srcdir)/vendor/osm_vendor_mlx_dispatcher.h \ $(srcdir)/vendor/osm_vendor_umadt.h \ $(srcdir)/vendor/osm_vendor_mlx_svc.h \ $(srcdir)/vendor/osm_vendor_mlx_hca.h \ $(srcdir)/vendor/osm_vendor_mlx_rmpp_ctx.h \ $(srcdir)/vendor/osm_vendor_mlx_transport.h \ $(srcdir)/vendor/osm_vendor_mlx_inout.h \ $(srcdir)/vendor/osm_vendor_mtl_hca_guid.h \ $(srcdir)/vendor/osm_vendor_test.h \ $(srcdir)/vendor/osm_vendor_ts.h \ $(srcdir)/vendor/osm_vendor_mlx_txn.h \ $(srcdir)/vendor/osm_vendor_al.h \ $(srcdir)/vendor/osm_vendor_mtl.h \ $(srcdir)/vendor/osm_ts_useraccess.h \ $(srcdir)/vendor/osm_umadt.h \ $(srcdir)/vendor/osm_mtl_bind.h all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status include/config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-nobase_pkgincludeHEADERS: $(nobase_pkginclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" @list='$(nobase_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo "$(MKDIR_P) '$(DESTDIR)$(pkgincludedir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)/$$dir"; }; \ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(pkgincludedir)/$$dir'"; \ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(pkgincludedir)/$$dir" || exit $$?; }; \ done uninstall-nobase_pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(nobase_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(HEADERS) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-nobase_pkgincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-nobase_pkgincludeHEADERS .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic clean-libtool \ ctags ctags-recursive distclean distclean-generic \ distclean-hdr distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man \ install-nobase_pkgincludeHEADERS install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am uninstall-nobase_pkgincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/include/config.h.in0000644000205000001450000001105012726323624013462 00000000000000/* include/config.h.in. Generated from configure.in by autoheader. */ /* Define as 1 if you want Dual Sided RMPP Support */ #undef DUAL_SIDED_RMPP /* Define as 1 if you want to enable a loopback console */ #undef ENABLE_OSM_CONSOLE_LOOPBACK /* Define as 1 if you want to enable a console on a socket connection */ #undef ENABLE_OSM_CONSOLE_SOCKET /* Define as 1 if you want to enable the event plugin */ #undef ENABLE_OSM_DEFAULT_EVENT_PLUGIN /* Define as 1 if you want to enable the performance manager */ #undef ENABLE_OSM_PERF_MGR /* Define as 1 if you want to enable the performance manager profiling code */ #undef ENABLE_OSM_PERF_MGR_PROFILE /* Define to 1 if the compiler supports __builtin_expect. */ #undef HAVE_BUILTIN_EXPECT /* Define a default node name map file */ #undef HAVE_DEFAULT_NODENAME_MAP /* Define a default OpenSM config file */ #undef HAVE_DEFAULT_OPENSM_CONFIG_FILE /* Define a Partition config file */ #undef HAVE_DEFAULT_PARTITION_CONFIG_FILE /* Define a Per Module Logging config file */ #undef HAVE_DEFAULT_PER_MOD_LOGGING_FILE /* Define a Prefix Routes config file */ #undef HAVE_DEFAULT_PREFIX_ROUTES_FILE /* Define a QOS policy config file */ #undef HAVE_DEFAULT_QOS_POLICY_FILE /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL /* Define to 1 if you have the `ibumad' library (-libumad). */ #undef HAVE_LIBIBUMAD /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `vapi' library (-lvapi). */ #undef HAVE_LIBVAPI /* Define to 1 if you have the `wrap' library (-lwrap). */ #undef HAVE_LIBWRAP /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define OpenSM config directory */ #undef OPENSM_CONFIG_DIR /* define 1 if OpenSM build is in a debug mode */ #undef OSM_DEBUG /* Define as 1 for vapi vendor */ #undef OSM_VENDOR_INTF_MTL /* Define as 1 for OpenIB vendor */ #undef OSM_VENDOR_INTF_OPENIB /* Define as 1 for sim vendor */ #undef OSM_VENDOR_INTF_SIM /* Define as 1 for ts vendor */ #undef OSM_VENDOR_INTF_TS /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 if your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Define as 1 if you want Vendor RMPP Support */ #undef VENDOR_RMPP_SUPPORT /* Version number of package */ #undef VERSION /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* define 1 if OpenSM build is in a debug mode */ #undef _DEBUG_ /* mark config.h inclusion */ #undef _OSM_CONFIG_H_ /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to `int' if does not define. */ #undef pid_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to empty if the keyword `volatile' does not work. Warning: valid code using `volatile' can become incorrect without. Disable with care. */ #undef volatile opensm-3.3.20/man/0000755000205000001450000000000012726324754010657 500000000000000opensm-3.3.20/man/opensm.8.in0000644000205000001450000017665212664021371012605 00000000000000.TH OPENSM 8 "Sept 15, 2014" "OpenIB" "OpenIB Management" .SH NAME opensm \- InfiniBand subnet manager and administration (SM/SA) .SH SYNOPSIS .B opensm [\-\-version]] [\-F | \-\-config ] [\-c(reate-config) ] [\-g(uid) ] [\-l(mc) ] [\-p(riority) ] [\-\-smkey ] [\-\-sm_sl ] [\-r(eassign_lids)] [\-R | \-\-routing_engine ] [\-\-do_mesh_analysis] [\-\-lash_start_vl ] [\-A | \-\-ucast_cache] [\-z | \-\-connect_roots] [\-M | \-\-lid_matrix_file ] [\-U | \-\-lfts_file ] [\-S | \-\-sadb_file ] [\-a | \-\-root_guid_file ] [\-u | \-\-cn_guid_file ] [\-G | \-\-io_guid_file ] [\-\-port\-shifting] [\-\-scatter\-ports ] [\-H | \-\-max_reverse_hops ] [\-X | \-\-guid_routing_order_file ] [\-m | \-\-ids_guid_file ] [\-o(nce)] [\-s(weep) ] [\-t(imeout) ] [\-\-retries ] [\-\-maxsmps ] [\-\-console [off | local | socket | loopback]] [\-\-console-port ] [\-i | \-\-ignore_guids ] [\-w | \-\-hop_weights_file ] [\-O | \-\-port_search_ordering_file ] [\-O | \-\-dimn_ports_file ] (DEPRECATED) [\-f | \-\-log_file ] [\-L | \-\-log_limit ] [\-e(rase_log_file)] [\-P(config) ] [\-N | \-\-no_part_enforce] (DEPRECATED) [\-Z | \-\-part_enforce [both | in | out | off]] [\-W | \-\-allow_both_pkeys] [\-Q | \-\-qos [\-Y | \-\-qos_policy_file ]] [\-\-congestion\-control] [\-\-cckey ] [\-y | \-\-stay_on_fatal] [\-B | \-\-daemon] [\-J | \-\-pidfile ] [\-I | \-\-inactive] [\-\-perfmgr] [\-\-perfmgr_sweep_time_s ] [\-\-prefix_routes_file ] [\-\-consolidate_ipv6_snm_req] [\-\-log_prefix ] [\-\-torus_config ] [\-v(erbose)] [\-V] [\-D ] [\-d(ebug) ] [\-h(elp)] [\-?] .SH DESCRIPTION .PP opensm is an InfiniBand compliant Subnet Manager and Administration, and runs on top of OpenIB. opensm provides an implementation of an InfiniBand Subnet Manager and Administration. Such a software entity is required to run for in order to initialize the InfiniBand hardware (at least one per each InfiniBand subnet). opensm also now contains an experimental version of a performance manager as well. opensm defaults were designed to meet the common case usage on clusters with up to a few hundred nodes. Thus, in this default mode, opensm will scan the IB fabric, initialize it, and sweep occasionally for changes. opensm attaches to a specific IB port on the local machine and configures only the fabric connected to it. (If the local machine has other IB ports, opensm will ignore the fabrics connected to those other ports). If no port is specified, it will select the first "best" available port. opensm can present the available ports and prompt for a port number to attach to. By default, the run is logged to two files: /var/log/messages and /var/log/opensm.log. The first file will register only general major events, whereas the second will include details of reported errors. All errors reported in this second file should be treated as indicators of IB fabric health issues. (Note that when a fatal and non-recoverable error occurs, opensm will exit.) Both log files should include the message "SUBNET UP" if opensm was able to setup the subnet correctly. .SH OPTIONS .PP .TP \fB\-\-version\fR Prints OpenSM version and exits. .TP \fB\-F\fR, \fB\-\-config\fR The name of the OpenSM config file. When not specified \fB\% @OPENSM_CONFIG_DIR@/@OPENSM_CONFIG_FILE@\fP will be used (if exists). .TP \fB\-c\fR, \fB\-\-create-config\fR OpenSM will dump its configuration to the specified file and exit. This is a way to generate OpenSM configuration file template. .TP \fB\-g\fR, \fB\-\-guid\fR This option specifies the local port GUID value with which OpenSM should bind. OpenSM may be bound to 1 port at a time. If GUID given is 0, OpenSM displays a list of possible port GUIDs and waits for user input. Without -g, OpenSM tries to use the default port. .TP \fB\-l\fR, \fB\-\-lmc\fR This option specifies the subnet's LMC value. The number of LIDs assigned to each port is 2^LMC. The LMC value must be in the range 0-7. LMC values > 0 allow multiple paths between ports. LMC values > 0 should only be used if the subnet topology actually provides multiple paths between ports, i.e. multiple interconnects between switches. Without -l, OpenSM defaults to LMC = 0, which allows one path between any two ports. .TP \fB\-p\fR, \fB\-\-priority\fR This option specifies the SM\'s PRIORITY. This will effect the handover cases, where master is chosen by priority and GUID. Range goes from 0 (default and lowest priority) to 15 (highest). .TP \fB\-\-smkey\fR This option specifies the SM\'s SM_Key (64 bits). This will effect SM authentication. Note that OpenSM version 3.2.1 and below used the default value '1' in a host byte order, it is fixed now but you may need this option to interoperate with old OpenSM running on a little endian machine. .TP \fB\-\-sm_sl\fR This option sets the SL to use for communication with the SM/SA. Defaults to 0. .TP \fB\-r\fR, \fB\-\-reassign_lids\fR This option causes OpenSM to reassign LIDs to all end nodes. Specifying -r on a running subnet may disrupt subnet traffic. Without -r, OpenSM attempts to preserve existing LID assignments resolving multiple use of same LID. .TP \fB\-R\fR, \fB\-\-routing_engine\fR This option chooses routing engine(s) to use instead of Min Hop algorithm (default). Multiple routing engines can be specified separated by commas so that specific ordering of routing algorithms will be tried if earlier routing engines fail. If all configured routing engines fail, OpenSM will always attempt to route with Min Hop unless 'no_fallback' is included in the list of routing engines. Supported engines: minhop, updn, dnup, file, ftree, lash, dor, torus-2QoS, dfsssp, sssp. .TP \fB\-\-do_mesh_analysis\fR This option enables additional analysis for the lash routing engine to precondition switch port assignments in regular cartesian meshes which may reduce the number of SLs required to give a deadlock free routing. .TP \fB\-\-lash_start_vl\fR This option sets the starting VL to use for the lash routing algorithm. Defaults to 0. .TP \fB\-A\fR, \fB\-\-ucast_cache\fR This option enables unicast routing cache and prevents routing recalculation (which is a heavy task in a large cluster) when there was no topology change detected during the heavy sweep, or when the topology change does not require new routing calculation, e.g. when one or more CAs/RTRs/leaf switches going down, or one or more of these nodes coming back after being down. A very common case that is handled by the unicast routing cache is host reboot, which otherwise would cause two full routing recalculations: one when the host goes down, and the other when the host comes back online. .TP \fB\-z\fR, \fB\-\-connect_roots\fR This option enforces routing engines (up/down and fat-tree) to make connectivity between root switches and in this way to be fully IBA compliant. In many cases this can violate "pure" deadlock free algorithm, so use it carefully. .TP \fB\-M\fR, \fB\-\-lid_matrix_file\fR This option specifies the name of the lid matrix dump file from where switch lid matrices (min hops tables) will be loaded. .TP \fB\-U\fR, \fB\-\-lfts_file\fR This option specifies the name of the LFTs file from where switch forwarding tables will be loaded when using "file" routing engine. .TP \fB\-S\fR, \fB\-\-sadb_file\fR This option specifies the name of the SA DB dump file from where SA database will be loaded. .TP \fB\-a\fR, \fB\-\-root_guid_file\fR Set the root nodes for the Up/Down or Fat-Tree routing algorithm to the guids provided in the given file (one to a line). .TP \fB\-u\fR, \fB\-\-cn_guid_file\fR Set the compute nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms to the port GUIDs provided in the given file (one to a line). .TP \fB\-G\fR, \fB\-\-io_guid_file\fR Set the I/O nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms to the port GUIDs provided in the given file (one to a line). .br In the case of Fat-Tree routing: .br I/O nodes are non-CN nodes allowed to use up to max_reverse_hops switches the wrong way around to improve connectivity. .br In the case of (DF)SSSP routing: .br Providing guids of compute and/or I/O nodes will ensure that paths towards those nodes are as much separated as possible within their node category, i.e., I/O traffic will not share the same link if multiple links are available. .TP \fB\-\-port\-shifting\fR This option enables a feature called \fBport shifting\fR. In some fabrics, particularly cluster environments, routes commonly align and congest with other routes due to algorithmically unchanging traffic patterns. This routing option will "shift" routing around in an attempt to alleviate this problem. .TP \fB\-\-scatter\-ports\fR This option is used to randomize port selection in routing rather than using a round-robin algorithm (which is the default). Value supplied with option is used as a random seed. If value is 0, which is the default, the scatter ports option is disabled. .TP \fB\-H\fR, \fB\-\-max_reverse_hops\fR Set the maximum number of reverse hops an I/O node is allowed to make. A reverse hop is the use of a switch the wrong way around. .TP \fB\-m\fR, \fB\-\-ids_guid_file\fR Name of the map file with set of the IDs which will be used by Up/Down routing algorithm instead of node GUIDs (format: per line). .TP \fB\-X\fR, \fB\-\-guid_routing_order_file\fR Set the order port guids will be routed for the MinHop and Up/Down routing algorithms to the guids provided in the given file (one to a line). .TP \fB\-o\fR, \fB\-\-once\fR This option causes OpenSM to configure the subnet once, then exit. Ports remain in the ACTIVE state. .TP \fB\-s\fR, \fB\-\-sweep\fR This option specifies the number of seconds between subnet sweeps. Specifying -s 0 disables sweeping. Without -s, OpenSM defaults to a sweep interval of 10 seconds. .TP \fB\-t\fR, \fB\-\-timeout\fR This option specifies the time in milliseconds used for transaction timeouts. Timeout values should be > 0. Without -t, OpenSM defaults to a timeout value of 200 milliseconds. .TP \fB\-\-retries\fR This option specifies the number of retries used for transactions. Without --retries, OpenSM defaults to 3 retries for transactions. .TP \fB\-\-maxsmps\fR This option specifies the number of VL15 SMP MADs allowed on the wire at any one time. Specifying \-\-maxsmps 0 allows unlimited outstanding SMPs. Without \-\-maxsmps, OpenSM defaults to a maximum of 4 outstanding SMPs. .TP \fB\-\-console [off | local | loopback | socket]\fR This option brings up the OpenSM console (default off). Note, loopback and socket open a socket which can be connected to WITHOUT CREDENTIALS. Loopback is safer if access to your SM host is controlled. tcp_wrappers (hosts.[allow|deny]) is used with loopback and socket. loopback and socket will only be available if OpenSM was built with --enable-console-loopback (default yes) and --enable-console-socket (default no) respectively. .TP \fB\-\-console-port\fR Specify an alternate telnet port for the socket console (default 10000). Note that this option only appears if OpenSM was built with --enable-console-socket. .TP \fB\-i\fR, \fB\-\-ignore_guids\fR This option provides the means to define a set of ports (by node guid and port number) that will be ignored by the link load equalization algorithm. .TP \fB\-w\fR, \fB\-\-hop_weights_file\fR This option provides weighting factors per port representing a hop cost in computing the lid matrix. The file consists of lines containing a switch port GUID (specified as a 64 bit hex number, with leading 0x), output port number, and weighting factor. Any port not listed in the file defaults to a weighting factor of 1. Lines starting with # are comments. Weights affect only the output route from the port, so many useful configurations will require weights to be specified in pairs. .TP \fB\-O\fR, \fB\-\-port_search_ordering_file\fR This option tweaks the routing. It suitable for two cases: 1. While using DOR routing algorithm. This option provides a mapping between hypercube dimensions and ports on a per switch basis for the DOR routing engine. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. The order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. 2. While using general routing algorithm. This option provides the order of the ports that would be chosen for routing, from each switch rather than searching for an appropriate port from port 1 to N. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. In case of DOR, the order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. .TP \fB\-O\fR, \fB\-\-dimn_ports_file\fR \fB(DEPRECATED)\fR This is a deprecated flag. Please use \fB\-\-port_search_ordering_file\fR instead. This option provides a mapping between hypercube dimensions and ports on a per switch basis for the DOR routing engine. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. The order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. .TP \fB\-x\fR, \fB\-\-honor_guid2lid\fR This option forces OpenSM to honor the guid2lid file, when it comes out of Standby state, if such file exists under OSM_CACHE_DIR, and is valid. By default, this is FALSE. .TP \fB\-f\fR, \fB\-\-log_file\fR This option defines the log to be the given file. By default, the log goes to /var/log/opensm.log. For the log to go to standard output use -f stdout. .TP \fB\-L\fR, \fB\-\-log_limit\fR This option defines maximal log file size in MB. When specified the log file will be truncated upon reaching this limit. .TP \fB\-e\fR, \fB\-\-erase_log_file\fR This option will cause deletion of the log file (if it previously exists). By default, the log file is accumulative. .TP \fB\-P\fR, \fB\-\-Pconfig\fR This option defines the optional partition configuration file. The default name is \fB\%@OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@\fP. .TP \fB\-\-prefix_routes_file\fR Prefix routes control how the SA responds to path record queries for off-subnet DGIDs. By default, the SA fails such queries. The .B PREFIX ROUTES section below describes the format of the configuration file. The default path is \fB\%@OPENSM_CONFIG_DIR@/prefix\-routes.conf\fP. .TP \fB\-Q\fR, \fB\-\-qos\fR This option enables QoS setup. It is disabled by default. .TP \fB\-Y\fR, \fB\-\-qos_policy_file\fR This option defines the optional QoS policy file. The default name is \fB\%@OPENSM_CONFIG_DIR@/@QOS_POLICY_FILE@\fP. See QoS_management_in_OpenSM.txt in opensm doc for more information on configuring QoS policy via this file. .TP \fB\-\-congestion_control\fR (EXPERIMENTAL) This option enables congestion control configuration. It is disabled by default. See config file for congestion control configuration options. \fB\-\-cc_key\fR (EXPERIMENTAL) This option configures the CCkey to use when configuring congestion control. Note that this option does not configure a new CCkey into switches and CAs. Defaults to 0. .TP \fB\-N\fR, \fB\-\-no_part_enforce\fR \fB(DEPRECATED)\fR This is a deprecated flag. Please use \fB\-\-part_enforce\fR instead. This option disables partition enforcement on switch external ports. .TP \fB\-Z\fR, \fB\-\-part_enforce\fR [both | in | out | off] This option indicates the partition enforcement type (for switches). Enforcement type can be inbound only (in), outbound only (out), both or disabled (off). Default is both. .TP \fB\-W\fR, \fB\-\-allow_both_pkeys\fR This option indicates whether both full and limited membership on the same partition can be configured in the PKeyTable. Default is not to allow both pkeys. .TP \fB\-y\fR, \fB\-\-stay_on_fatal\fR This option will cause SM not to exit on fatal initialization issues: if SM discovers duplicated guids or a 12x link with lane reversal badly configured. By default, the SM will exit on these errors. .TP \fB\-B\fR, \fB\-\-daemon\fR Run in daemon mode - OpenSM will run in the background. .TP \fB\-J\fR, \fB\-\-pidfile \fR Makes the SM write its own PID to the specified file when started in daemon mode. .TP \fB\-I\fR, \fB\-\-inactive\fR Start SM in inactive rather than init SM state. This option can be used in conjunction with the perfmgr so as to run a standalone performance manager without SM/SA. However, this is NOT currently implemented in the performance manager. .TP \fB\-\-perfmgr\fR Enable the perfmgr. Only takes effect if --enable-perfmgr was specified at configure time. See performance-manager-HOWTO.txt in opensm doc for more information on running perfmgr. .TP \fB\-\-perfmgr_sweep_time_s\fR Specify the sweep time for the performance manager in seconds (default is 180 seconds). Only takes effect if --enable-perfmgr was specified at configure time. .TP .BI --consolidate_ipv6_snm_req Use shared MLID for IPv6 Solicited Node Multicast groups per MGID scope and P_Key. .TP \fB\-\-log_prefix\fR This option specifies the prefix to the syslog messages from OpenSM. A suitable prefix can be used to identify the IB subnet in syslog messages when two or more instances of OpenSM run in a single node to manage multiple fabrics. For example, in a dual-fabric (or dual-rail) IB cluster, the prefix for the first fabric could be "mpi" and the other fabric could be "storage". .TP \fB\-\-torus_config\fR This option defines the file name for the extra configuration information needed for the torus-2QoS routing engine. The default name is \fB\%@OPENSM_CONFIG_DIR@/@TORUS2QOS_CONF_FILE@\fP .TP \fB\-v\fR, \fB\-\-verbose\fR This option increases the log verbosity level. The -v option may be specified multiple times to further increase the verbosity level. See the -D option for more information about log verbosity. .TP \fB\-V\fR This option sets the maximum verbosity level and forces log flushing. The -V option is equivalent to \'-D 0xFF -d 2\'. See the -D option for more information about log verbosity. .TP \fB\-D\fR This option sets the log verbosity level. A flags field must follow the -D option. A bit set/clear in the flags enables/disables a specific log level as follows: BIT LOG LEVEL ENABLED ---- ----------------- 0x01 - ERROR (error messages) 0x02 - INFO (basic messages, low volume) 0x04 - VERBOSE (interesting stuff, moderate volume) 0x08 - DEBUG (diagnostic, high volume) 0x10 - FUNCS (function entry/exit, very high volume) 0x20 - FRAMES (dumps all SMP and GMP frames) 0x40 - ROUTING (dump FDB routing information) 0x80 - SYS (syslog at LOG_INFO level in addition to OpenSM logging) Without -D, OpenSM defaults to ERROR + INFO (0x3). Specifying -D 0 disables all messages. Specifying -D 0xFF enables all messages (see -V). High verbosity levels may require increasing the transaction timeout with the -t option. .TP \fB\-d\fR, \fB\-\-debug\fR This option specifies a debug option. These options are not normally needed. The number following -d selects the debug option to enable as follows: OPT Description --- ----------------- -d0 - Ignore other SM nodes -d1 - Force single threaded dispatching -d2 - Force log flushing after each log message -d3 - Disable multicast support .TP \fB\-h\fR, \fB\-\-help\fR Display this usage info then exit. .TP \fB\-?\fR Display this usage info then exit. .SH ENVIRONMENT VARIABLES .PP The following environment variables control opensm behavior: OSM_TMP_DIR - controls the directory in which the temporary files generated by opensm are created. These files are: opensm-subnet.lst, opensm.fdbs, and opensm.mcfdbs. By default, this directory is /var/log. OSM_CACHE_DIR - opensm stores certain data to the disk such that subsequent runs are consistent. The default directory used is /var/cache/opensm. The following files are included in it: guid2lid - stores the LID range assigned to each GUID guid2mkey - stores the MKey previously assiged to each GUID neighbors - stores a map of the GUIDs at either end of each link in the fabric .SH NOTES .PP When opensm receives a HUP signal, it starts a new heavy sweep as if a trap was received or a topology change was found. .PP Also, SIGUSR1 can be used to trigger a reopen of /var/log/opensm.log for logrotate purposes. .SH PARTITION CONFIGURATION .PP The default name of OpenSM partitions configuration file is \fB\%@OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@\fP. The default may be changed by using the --Pconfig (-P) option with OpenSM. The default partition will be created by OpenSM unconditionally even when partition configuration file does not exist or cannot be accessed. The default partition has P_Key value 0x7fff. OpenSM\'s port will always have full membership in default partition. All other end ports will have full membership if the partition configuration file is not found or cannot be accessed, or limited membership if the file exists and can be accessed but there is no rule for the Default partition. Effectively, this amounts to the same as if one of the following rules below appear in the partition configuration file. In the case of no rule for the Default partition: Default=0x7fff : ALL=limited, SELF=full ; In the case of no partition configuration file or file cannot be accessed: Default=0x7fff : ALL=full ; File Format Comments: Line content followed after \'#\' character is comment and ignored by parser. General file format: :[]; Partition Definition: [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited] PartitionName - string, will be used with logging. When omitted, empty string will be used. PKey - P_Key value for this partition. Only low 15 bits will be used. When omitted will be autogenerated. indx0 - indicates that this pkey should be inserted in block 0 index 0. ipoib_bc_flags - used to indicate/specify IPoIB capability of this partition. defmember=full|limited|both - specifies default membership for port guid list. Default is limited. ipoib_bc_flags: ipoib_flag|[mgroup_flag]* ipoib_flag: ipoib - indicates that this partition may be used for IPoIB, as a result the IPoIB broadcast group will be created with the mgroup_flag flags given, if any. Partition Properties: [|]* | Port list: [,] Port Specifier: [=[full|limited|both]] PortGUID - GUID of partition member EndPort. Hexadecimal numbers should start from 0x, decimal numbers are accepted too. full, limited, - indicates full and/or limited membership for both this port. When omitted (or unrecognized) limited membership is assumed. Both indicates both full and limited membership for this port. MCast Group: mgid=gid[,mgroup_flag]* - gid specified is verified to be a Multicast address. IP groups are verified to match the rate and mtu of the broadcast group. The P_Key bits of the mgid for IP groups are verified to either match the P_Key specified in by "Partition Definition" or if they are 0x0000 the P_Key will be copied into those bits. mgroup_flag: rate= - specifies rate for this MC group (default is 3 (10GBps)) mtu= - specifies MTU for this MC group (default is 4 (2048)) sl= - specifies SL for this MC group (default is 0) scope= - specifies scope for this MC group (default is 2 (link local)). Multiple scope settings are permitted for a partition. NOTE: This overwrites the scope nibble of the specified mgid. Furthermore specifying multiple scope settings will result in multiple MC groups being created. Q_Key= - specifies the Q_Key for this MC group (default: 0x0b1b for IP groups, 0 for other groups) WARNING: changing this for the broadcast group may break IPoIB on client nodes!! TClass= - specifies tclass for this MC group (default is 0) FlowLabel= - specifies FlowLabel for this MC group (default is 0) Note that values for rate, mtu, and scope, for both partitions and multicast groups, should be specified as defined in the IBTA specification (for example, mtu=4 for 2048). There are several useful keywords for PortGUID definition: - 'ALL' means all end ports in this subnet. - 'ALL_CAS' means all Channel Adapter end ports in this subnet. - 'ALL_SWITCHES' means all Switch end ports in this subnet. - 'ALL_ROUTERS' means all Router end ports in this subnet. - 'SELF' means subnet manager's port. Empty list means no ports in this partition. Notes: White space is permitted between delimiters ('=', ',',':',';'). PartitionName does not need to be unique, PKey does need to be unique. If PKey is repeated then those partition configurations will be merged and first PartitionName will be used (see also next note). It is possible to split partition configuration in more than one definition, but then PKey should be explicitly specified (otherwise different PKey values will be generated for those definitions). Examples: Default=0x7fff : ALL, SELF=full ; Default=0x7fff : ALL, ALL_SWITCHES=full, SELF=full ; NewPartition , ipoib : 0x123456=full, 0x3456789034=limi, 0x2134af2306 ; YetAnotherOne = 0x300 : SELF=full ; YetAnotherOne = 0x300 : ALL=limited ; ShareIO = 0x80 , defmember=full : 0x123451, 0x123452; # 0x123453, 0x123454 will be limited ShareIO = 0x80 : 0x123453, 0x123454, 0x123455=full; # 0x123456, 0x123457 will be limited ShareIO = 0x80 : defmember=limited : 0x123456, 0x123457, 0x123458=full; ShareIO = 0x80 , defmember=full : 0x123459, 0x12345a; ShareIO = 0x80 , defmember=full : 0x12345b, 0x12345c=limited, 0x12345d; # multicast groups added to default Default=0x7fff,ipoib: mgid=ff12:401b::0707,sl=1 # random IPv4 group mgid=ff12:601b::16 # MLDv2-capable routers mgid=ff12:401b::16 # IGMP mgid=ff12:601b::2 # All routers mgid=ff12::1,sl=1,Q_Key=0xDEADBEEF,rate=3,mtu=2 # random group ALL=full; Note: The following rule is equivalent to how OpenSM used to run prior to the partition manager: Default=0x7fff,ipoib:ALL=full; .SH QOS CONFIGURATION .PP There are a set of QoS related low-level configuration parameters. All these parameter names are prefixed by "qos_" string. Here is a full list of these parameters: qos_max_vls - The maximum number of VLs that will be on the subnet qos_high_limit - The limit of High Priority component of VL Arbitration table (IBA 7.6.9) qos_vlarb_low - Low priority VL Arbitration table (IBA 7.6.9) template qos_vlarb_high - High priority VL Arbitration table (IBA 7.6.9) template Both VL arbitration templates are pairs of VL and weight qos_sl2vl - SL2VL Mapping table (IBA 7.6.6) template. It is a list of VLs corresponding to SLs 0-15 (Note that VL15 used here means drop this SL) Typical default values (hard-coded in OpenSM initialization) are: qos_max_vls 15 qos_high_limit 0 qos_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4 qos_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0 qos_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 The syntax is compatible with rest of OpenSM configuration options and values may be stored in OpenSM config file (cached options file). In addition to the above, we may define separate QoS configuration parameters sets for various target types. As targets, we currently support CAs, routers, switch external ports, and switch's enhanced port 0. The names of such specialized parameters are prefixed by "qos__" string. Here is a full list of the currently supported sets: qos_ca_ - QoS configuration parameters set for CAs. qos_rtr_ - parameters set for routers. qos_sw0_ - parameters set for switches' port 0. qos_swe_ - parameters set for switches' external ports. Examples: qos_sw0_max_vls=2 qos_ca_sl2vl=0,1,2,3,5,5,5,12,12,0, qos_swe_high_limit=0 .SH PREFIX ROUTES .PP Prefix routes control how the SA responds to path record queries for off-subnet DGIDs. By default, the SA fails such queries. Note that IBA does not specify how the SA should obtain off-subnet path record information. The prefix routes configuration is meant as a stop-gap until the specification is completed. .PP Each line in the configuration file is a 64-bit prefix followed by a 64-bit GUID, separated by white space. The GUID specifies the router port on the local subnet that will handle the prefix. Blank lines are ignored, as is anything between a \fB#\fP character and the end of the line. The prefix and GUID are both in hex, the leading 0x is optional. Either, or both, can be wild-carded by specifying an asterisk instead of an explicit prefix or GUID. .PP When responding to a path record query for an off-subnet DGID, opensm searches for the first prefix match in the configuration file. Therefore, the order of the lines in the configuration file is important: a wild-carded prefix at the beginning of the configuration file renders all subsequent lines useless. If there is no match, then opensm fails the query. It is legal to repeat prefixes in the configuration file, opensm will return the path to the first available matching router. A configuration file with a single line where both prefix and GUID are wild-carded means that a path record query specifying any off-subnet DGID should return a path to the first available router. This configuration yields the same behavior formerly achieved by compiling opensm with -DROUTER_EXP which has been obsoleted. .SH MKEY CONFIGURATION .PP OpenSM supports configuring a single management key (MKey) for use across the subnet. The following configuration options are available: m_key - the 64-bit MKey to be used on the subnet (IBA 14.2.4) m_key_protection_level - the numeric value of the MKey ProtectBits (IBA 14.2.4.1) m_key_lease_period - the number of seconds a CA will wait for a response from the SM before resetting the protection level to 0 (IBA 14.2.4.2). OpenSM will configure all ports with the MKey specified by m_key, defaulting to a value of 0. A m_key value of 0 disables MKey protection on the subnet. Switches and HCAs with a non-zero MKey will not accept requests to change their configuration unless the request includes the proper MKey. MKey Protection Levels MKey protection levels modify how switches and CAs respond to SMPs lacking a valid MKey. OpenSM will configure each port's ProtectBits to support the level defined by the m_key_protection_level parameter. If no parameter is specified, OpenSM defaults to operating at protection level 0. There are currently 4 protection levels defined by the IBA: 0 - Queries return valid data, including MKey. Configuration changes are not allowed unless the request contains a valid MKey. 1 - Like level 0, but the MKey is set to 0 (0x00000000) in queries, unless the request contains a valid MKey. 2 - Neither queries nor configuration changes are allowed, unless the request contains a valid MKey. 3 - Identical to 2. Maintained for backwards compatibility. MKey Lease Period InfiniBand supports a MKey lease timeout, which is intended to allow administrators or a new SM to recover/reset lost MKeys on a fabric. If MKeys are enabled on the subnet and a switch or CA receives a request that requires a valid MKey but does not contain one, it warns the SM by sending a trap (Bad M_Key, Trap 256). If the MKey lease period is non-zero, it also starts a countdown timer for the time specified by the lease period. If a SM (or other agent) responds with the correct MKey, the timer is stopped and reset. Should the timer reach zero, the switch or CA will reset its MKey protection level to 0, exposing the MKey and allowing recovery. OpenSM will initialize all ports to use a mkey lease period of the number of seconds specified in the config file. If no mkey_lease_period is specified, a default of 0 will be used. OpenSM normally quickly responds to all Bad_M_Key traps, resetting the lease timers. Additionally, OpenSM's subnet sweeps will also cancel any running timers. For maximum protection against accidentally-exposed MKeys, the MKey lease time should be a few multiples of the subnet sweep time. If OpenSM detects at startup that your sweep interval is greater than your MKey lease period, it will reset the lease period to be greater than the sweep interval. Similarly, if sweeping is disabled at startup, it will be re-enabled with an interval less than the Mkey lease period. If OpenSM is required to recover a subnet for which it is missing mkeys, it must do so one switch level at a time. As such, the total time to recover the subnet may be as long as the mkey lease period multiplied by the maximum number of hops between the SM and an endpoint, plus one. MKey Effects on Diagnostic Utilities Setting a MKey may have a detrimental effect on diagnostic software run on the subnet, unless your diagnostic software is able to retrieve MKeys from the SA or can be explicitly configured with the proper MKey. This is particularly true at protection level 2, where CAs will ignore queries for management information that do not contain the proper MKey. .SH ROUTING .PP OpenSM now offers nine routing engines: 1. Min Hop Algorithm - based on the minimum hops to each node where the path length is optimized. 2. UPDN Unicast routing algorithm - also based on the minimum hops to each node, but it is constrained to ranking rules. This algorithm should be chosen if the subnet is not a pure Fat Tree, and deadlock may occur due to a loop in the subnet. 3. DNUP Unicast routing algorithm - similar to UPDN but allows routing in fabrics which have some CA nodes attached closer to the roots than some switch nodes. 4. Fat Tree Unicast routing algorithm - this algorithm optimizes routing for congestion-free "shift" communication pattern. It should be chosen if a subnet is a symmetrical or almost symmetrical fat-tree of various types, not just K-ary-N-Trees: non-constant K, not fully staffed, any Constant Bisectional Bandwidth (CBB) ratio. Similar to UPDN, Fat Tree routing is constrained to ranking rules. 5. LASH unicast routing algorithm - uses Infiniband virtual layers (SL) to provide deadlock-free shortest-path routing while also distributing the paths between layers. LASH is an alternative deadlock-free topology-agnostic routing algorithm to the non-minimal UPDN algorithm avoiding the use of a potentially congested root node. 6. DOR Unicast routing algorithm - based on the Min Hop algorithm, but avoids port equalization except for redundant links between the same two switches. This provides deadlock free routes for hypercubes when the fabric is cabled as a hypercube and for meshes when cabled as a mesh (see details below). 7. Torus-2QoS unicast routing algorithm - a DOR-based routing algorithm specialized for 2D/3D torus topologies. Torus-2QoS provides deadlock-free routing while supporting two quality of service (QoS) levels. In addition it is able to route around multiple failed fabric links or a single failed fabric switch without introducing deadlocks, and without changing path SL values granted before the failure. 8. DFSSSP unicast routing algorithm - a deadlock-free single-source-shortest-path routing, which uses the SSSP algorithm (see algorithm 9.) as the base to optimize link utilization and uses Infiniband virtual lanes (SL) to provide deadlock-freedom. 9. SSSP unicast routing algorithm - a single-source-shortest-path routing algorithm, which globally balances the number of routes per link to optimize link utilization. This routing algorithm has no restrictions in terms of the underlying topology. OpenSM also supports a file method which can load routes from a table. See \'Modular Routing Engine\' for more information on this. The basic routing algorithm is comprised of two stages: 1. MinHop matrix calculation How many hops are required to get from each port to each LID ? The algorithm to fill these tables is different if you run standard (min hop) or Up/Down. For standard routing, a "relaxation" algorithm is used to propagate min hop from every destination LID through neighbor switches For Up/Down routing, a BFS from every target is used. The BFS tracks link direction (up or down) and avoid steps that will perform up after a down step was used. 2. Once MinHop matrices exist, each switch is visited and for each target LID a decision is made as to what port should be used to get to that LID. This step is common to standard and Up/Down routing. Each port has a counter counting the number of target LIDs going through it. When there are multiple alternative ports with same MinHop to a LID, the one with less previously assigned LIDs is selected. If LMC > 0, more checks are added: Within each group of LIDs assigned to same target port, a. use only ports which have same MinHop b. first prefer the ones that go to different systemImageGuid (then the previous LID of the same LMC group) c. if none - prefer those which go through another NodeGuid d. fall back to the number of paths method (if all go to same node). Effect of Topology Changes OpenSM will preserve existing routing in any case where there is no change in the fabric switches unless the -r (--reassign_lids) option is specified. -r .br --reassign_lids This option causes OpenSM to reassign LIDs to all end nodes. Specifying -r on a running subnet may disrupt subnet traffic. Without -r, OpenSM attempts to preserve existing LID assignments resolving multiple use of same LID. If a link is added or removed, OpenSM does not recalculate the routes that do not have to change. A route has to change if the port is no longer UP or no longer the MinHop. When routing changes are performed, the same algorithm for balancing the routes is invoked. In the case of using the file based routing, any topology changes are currently ignored The 'file' routing engine just loads the LFTs from the file specified, with no reaction to real topology. Obviously, this will not be able to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent switches will be skipped. Multicast is not affected by 'file' routing engine (this uses min hop tables). Min Hop Algorithm The Min Hop algorithm is invoked by default if no routing algorithm is specified. It can also be invoked by specifying '-R minhop'. The Min Hop algorithm is divided into two stages: computation of min-hop tables on every switch and LFT output port assignment. Link subscription is also equalized with the ability to override based on port GUID. The latter is supplied by: -i .br \-\-ignore_guids This option provides the means to define a set of ports (by guid) that will be ignored by the link load equalization algorithm. Note that only endports (CA, switch port 0, and router ports) and not switch external ports are supported. LMC awareness routes based on (remote) system or switch basis. Purpose of UPDN Algorithm The UPDN algorithm is designed to prevent deadlocks from occurring in loops of the subnet. A loop-deadlock is a situation in which it is no longer possible to send data between any two hosts connected through the loop. As such, the UPDN routing algorithm should be used if the subnet is not a pure Fat Tree, and one of its loops may experience a deadlock (due, for example, to high pressure). The UPDN algorithm is based on the following main stages: 1. Auto-detect root nodes - based on the CA hop length from any switch in the subnet, a statistical histogram is built for each switch (hop num vs number of occurrences). If the histogram reflects a specific column (higher than others) for a certain node, then it is marked as a root node. Since the algorithm is statistical, it may not find any root nodes. The list of the root nodes found by this auto-detect stage is used by the ranking process stage. Note 1: The user can override the node list manually. Note 2: If this stage cannot find any root nodes, and the user did not specify a guid list file, OpenSM defaults back to the Min Hop routing algorithm. 2. Ranking process - All root switch nodes (found in stage 1) are assigned a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the subnet are ranked incrementally. This ranking aids in the process of enforcing rules that ensure loop-free paths. 3. Min Hop Table setting - after ranking is done, a BFS algorithm is run from each (CA or switch) node in the subnet. During the BFS process, the FDB table of each switch node traversed by BFS is updated, in reference to the starting node, based on the ranking rules and guid values. At the end of the process, the updated FDB tables ensure loop-free paths through the subnet. Note: Up/Down routing does not allow LID routing communication between switches that are located inside spine "switch systems". The reason is that there is no way to allow a LID route between them that does not break the Up/Down rule. One ramification of this is that you cannot run SM on switches other than the leaf switches of the fabric. UPDN Algorithm Usage Activation through OpenSM Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm. Use '-a ' for adding an UPDN guid file that contains the root nodes for ranking. If the `-a' option is not used, OpenSM uses its auto-detect root nodes algorithm. Notes on the guid list file: 1. A valid guid file specifies one guid in each line. Lines with an invalid format will be discarded. .br 2. The user should specify the root switch guids. However, it is also possible to specify CA guids; OpenSM will use the guid of the switch (if it exists) that connects the CA to the subnet as a root node. Purpose of DNUP Algorithm The DNUP algorithm is designed to serve a similar purpose to UPDN. However it is intended to work in network topologies which are unsuited to UPDN due to nodes being connected closer to the roots than some of the switches. An example would be a fabric which contains nodes and uplinks connected to the same switch. The operation of DNUP is the same as UPDN with the exception of the ranking process. In DNUP all switch nodes are ranked based solely on their distance from CA Nodes, all switch nodes directly connected to at least one CA are assigned a value of 1 all other switch nodes are assigned a value of one more than the minimum rank of all neighbor switch nodes. Fat-tree Routing Algorithm The fat-tree algorithm optimizes routing for "shift" communication pattern. It should be chosen if a subnet is a symmetrical or almost symmetrical fat-tree of various types. It supports not just K-ary-N-Trees, by handling for non-constant K, cases where not all leafs (CAs) are present, any CBB ratio. As in UPDN, fat-tree also prevents credit-loop-deadlocks. If the root guid file is not provided ('-a' or '--root_guid_file' options), the topology has to be pure fat-tree that complies with the following rules: - Tree rank should be between two and eight (inclusively) - Switches of the same rank should have the same number of UP-going port groups*, unless they are root switches, in which case the shouldn't have UP-going ports at all. - Switches of the same rank should have the same number of DOWN-going port groups, unless they are leaf switches. - Switches of the same rank should have the same number of ports in each UP-going port group. - Switches of the same rank should have the same number of ports in each DOWN-going port group. - All the CAs have to be at the same tree level (rank). If the root guid file is provided, the topology doesn't have to be pure fat-tree, and it should only comply with the following rules: - Tree rank should be between two and eight (inclusively) - All the Compute Nodes** have to be at the same tree level (rank). Note that non-compute node CAs are allowed here to be at different tree ranks. * ports that are connected to the same remote switch are referenced as \'port group\'. ** list of compute nodes (CNs) can be specified by \'-u\' or \'--cn_guid_file\' OpenSM options. Topologies that do not comply cause a fallback to min hop routing. Note that this can also occur on link failures which cause the topology to no longer be "pure" fat-tree. Note that although fat-tree algorithm supports trees with non-integer CBB ratio, the routing will not be as balanced as in case of integer CBB ratio. In addition to this, although the algorithm allows leaf switches to have any number of CAs, the closer the tree is to be fully populated, the more effective the "shift" communication pattern will be. In general, even if the root list is provided, the closer the topology to a pure and symmetrical fat-tree, the more optimal the routing will be. The algorithm also dumps compute node ordering file (opensm-ftree-ca-order.dump) in the same directory where the OpenSM log resides. This ordering file provides the CN order that may be used to create efficient communication pattern, that will match the routing tables. Routing between non-CN nodes The use of the cn_guid_file option allows non-CN nodes to be located on different levels in the fat tree. In such case, it is not guaranteed that the Fat Tree algorithm will route between two non-CN nodes. To solve this problem, a list of non-CN nodes can be specified by \'-G\' or \'--io_guid_file\' option. Theses nodes will be allowed to use switches the wrong way round a specific number of times (specified by \'-H\' or \'--max_reverse_hops\'. With the proper max_reverse_hops and io_guid_file values, you can ensure full connectivity in the Fat Tree. Please note that using max_reverse_hops creates routes that use the switch in a counter-stream way. This option should never be used to connect nodes with high bandwidth traffic between them ! It should only be used to allow connectivity for HA purposes or similar. Also having routes the other way around can in theory cause credit loops. Use these options with extreme care ! Activation through OpenSM Use '-R ftree' option to activate the fat-tree algorithm. Use '-a ' to provide root nodes for ranking. If the `-a' option is not used, routing algorithm will detect roots automatically. Use '-u ' to provide the list of compute nodes. If the `-u' option is not used, all the CAs are considered as compute nodes. Note: LMC > 0 is not supported by fat-tree routing. If this is specified, the default routing algorithm is invoked instead. LASH Routing Algorithm LASH is an acronym for LAyered SHortest Path Routing. It is a deterministic shortest path routing algorithm that enables topology agnostic deadlock-free routing within communication networks. When computing the routing function, LASH analyzes the network topology for the shortest-path routes between all pairs of sources / destinations and groups these paths into virtual layers in such a way as to avoid deadlock. Note LASH analyzes routes and ensures deadlock freedom between switch pairs. The link from HCA between and switch does not need virtual layers as deadlock will not arise between switch and HCA. In more detail, the algorithm works as follows: 1) LASH determines the shortest-path between all pairs of source / destination switches. Note, LASH ensures the same SL is used for all SRC/DST - DST/SRC pairs and there is no guarantee that the return path for a given DST/SRC will be the reverse of the route SRC/DST. 2) LASH then begins an SL assignment process where a route is assigned to a layer (SL) if the addition of that route does not cause deadlock within that layer. This is achieved by maintaining and analysing a channel dependency graph for each layer. Once the potential addition of a path could lead to deadlock, LASH opens a new layer and continues the process. 3) Once this stage has been completed, it is highly likely that the first layers processed will contain more paths than the latter ones. To better balance the use of layers, LASH moves paths from one layer to another so that the number of paths in each layer averages out. Note, the implementation of LASH in opensm attempts to use as few layers as possible. This number can be less than the number of actual layers available. In general LASH is a very flexible algorithm. It can, for example, reduce to Dimension Order Routing in certain topologies, it is topology agnostic and fares well in the face of faults. It has been shown that for both regular and irregular topologies, LASH outperforms Up/Down. The reason for this is that LASH distributes the traffic more evenly through a network, avoiding the bottleneck issues related to a root node and always routes shortest-path. The algorithm was developed by Simula Research Laboratory. Use '-R lash -Q ' option to activate the LASH algorithm. Note: QoS support has to be turned on in order that SL/VL mappings are used. Note: LMC > 0 is not supported by the LASH routing. If this is specified, the default routing algorithm is invoked instead. For open regular cartesian meshes the DOR algorithm is the ideal routing algorithm. For toroidal meshes on the other hand there are routing loops that can cause deadlocks. LASH can be used to route these cases. The performance of LASH can be improved by preconditioning the mesh in cases where there are multiple links connecting switches and also in cases where the switches are not cabled consistently. An option exists for LASH to do this. To invoke this use '-R lash -Q --do_mesh_analysis'. This will add an additional phase that analyses the mesh to try to determine the dimension and size of a mesh. If it determines that the mesh looks like an open or closed cartesian mesh it reorders the ports in dimension order before the rest of the LASH algorithm runs. DOR Routing Algorithm The Dimension Order Routing algorithm is based on the Min Hop algorithm and so uses shortest paths. Instead of spreading traffic out across different paths with the same shortest distance, it chooses among the available shortest paths based on an ordering of dimensions. Each port must be consistently cabled to represent a hypercube dimension or a mesh dimension. Alternatively, the -O option can be used to assign a custom mapping between the ports on a given switch, and the associated dimension. Paths are grown from a destination back to a source using the lowest dimension (port) of available paths at each step. This provides the ordering necessary to avoid deadlock. When there are multiple links between any two switches, they still represent only one dimension and traffic is balanced across them unless port equalization is turned off. In the case of hypercubes, the same port must be used throughout the fabric to represent the hypercube dimension and match on both ends of the cable, or the -O option used to accomplish the alignment. In the case of meshes, the dimension should consistently use the same pair of ports, one port on one end of the cable, and the other port on the other end, continuing along the mesh dimension, or the -O option used as an override. Use '-R dor' option to activate the DOR algorithm. DFSSSP and SSSP Routing Algorithm The (Deadlock-Free) Single-Source-Shortest-Path routing algorithm is designed to optimize link utilization thru global balancing of routes, while supporting arbitrary topologies. The DFSSSP routing algorithm uses Infiniband virtual lanes (SL) to provide deadlock-freedom. The DFSSSP algorithm consists of five major steps: .br 1) It discovers the subnet and models the subnet as a directed multigraph in which each node represents a node of the physical network and each edge represents one direction of the full-duplex links used to connect the nodes. .br 2) A loop, which iterates over all CA and switches of the subnet, will perform three steps to generate the linear forwarding tables for each switch: .br 2.1) use Dijkstra's algorithm to find the shortest path from all nodes to the current selected destination; .br 2.2) update the egde weights in the graph, i.e. add the number of routes, which use a link to reach the destination, to the link/edge; .br 2.3) update the LFT of each switch with the outgoing port which was used in the current step to route the traffic to the destination node. .br 3) After the number of available virtual lanes or layers in the subnet is detected and a channel dependency graph is initialized for each layer, the algorithm will put each possible route of the subnet into the first layer. .br 4) A loop iterates over all channel dependency graphs (CDG) and performs the following substeps: .br 4.1) search for a cycle in the current CDG; .br 4.2) when a cycle is found, i.e. a possible deadlock is present, one edge is selected and all routes, which induced this egde, are moved to the "next higher" virtual layer (CDG[i+1]); .br 4.3) the cycle search is continued until all cycles are broken and routes are moved "up". .br 5) When the number of needed layers does not exceeds the number of available SL/VL to remove all cycles in all CDGs, the rounting is deadlock-free and an relation table is generated, which contains the assignment of routes from source to destination to a SL Note on SSSP: .br This algorithm does not perform the steps 3)-5) and can not be considered to be deadlock-free for all topologies. But on the one hand, you can choose this algorithm for really large networks (5,000+ CAs and deadlock-free by design) to reduce the runtime of the algorithm. On the other hand, you might use the SSSP routing algorithm as an alternative, when all deadlock-free routing algorithms fail to route the network for whatever reason. In the last case, SSSP was designed to deliver an equal or higher bandwidth due to better congestion avoidance than the Min Hop routing algorithm. Notes for usage: .br a) running DFSSSP: '-R dfsssp -Q' .br a.1) QoS has to be configured to equally spread the load on the available SL or virtual lanes .br a.2) applications must perform a path record query to get path SL for each route, which the application will use to transmite packages .br b) running SSSP: '-R sssp' .br c) both algorithms support LMC > 0 Hints for optimizing I/O traffic: .br Having more nodes (I/O and compute) connected to a switch than incoming links can result in a 'bad' routing of the I/O traffic as long as (DF)SSSP routing is not aware of the dedicated I/O nodes, i.e., in the following network configuration CN1-CN3 might send all I/O traffic via Link2 to IO1,IO2: CN1 Link1 IO1 .br \\ /----\\ / .br CN2 -- Switch1 Switch2 -- CN4 .br / \\----/ \\ .br CN3 Link2 IO2 To prevent this from happening (DF)SSSP can use both the compute node guid file and the I/O guid file specified by the \'-u\' or \'--cn_guid_file\' and \'-G\' or \'--io_guid_file\' options (similar to the Fat-Tree routing). This ensures that traffic towards compute nodes and I/O nodes is balanced separately and therefore distributed as much as possible across the available links. Port GUIDs, as listed by ibstat, must be specified (not Node GUIDs). .br The priority for the optimization is as follows: .br compute nodes -> I/O nodes -> other nodes .br Possible use case szenarios: .br a) neither \'-u\' nor \'-G\' are specified: all nodes a treated as \'other nodes\' and therefore balanced equally; .br b) \'-G\' is specified: traffic towards I/O nodes will be balanced optimally; .br c) the system has three node types, such as login/admin, compute and I/O, but the balancing focus should be I/O, then one has to use \'-u\' and \'-G\' with I/O guids listed in cn_guid_file and compute node guids listed in io_guid_file; .br d) ... Torus-2QoS Routing Algorithm Torus-2QoS is routing algorithm designed for large-scale 2D/3D torus fabrics; see torus-2QoS(8) for full documentation. Use '-R torus-2QoS -Q' or '-R torus-2QoS,no_fallback -Q' to activate the torus-2QoS algorithm. Routing References To learn more about deadlock-free routing, see the article "Deadlock Free Message Routing in Multiprocessor Interconnection Networks" by William J Dally and Charles L Seitz (1985). To learn more about the up/down algorithm, see the article "Effective Strategy to Compute Forwarding Tables for InfiniBand Networks" by Jose Carlos Sancho, Antonio Robles, and Jose Duato at the Universidad Politecnica de Valencia. To learn more about LASH and the flexibility behind it, the requirement for layers, performance comparisons to other algorithms, see the following articles: "Layered Routing in Irregular Networks", Lysne et al, IEEE Transactions on Parallel and Distributed Systems, VOL.16, No12, December 2005. "Routing for the ASI Fabric Manager", Solheim et al. IEEE Communications Magazine, Vol.44, No.7, July 2006. "Layered Shortest Path (LASH) Routing in Irregular System Area Networks", Skeie et al. IEEE Computer Society Communication Architecture for Clusters 2002. To learn more about the DFSSSP and SSSP routing algorithm, see the articles: .br J. Domke, T. Hoefler and W. Nagel: Deadlock-Free Oblivious Routing for Arbitrary Topologies, In Proceedings of the 25th IEEE International Parallel & Distributed Processing Symposium (IPDPS 2011) .br T. Hoefler, T. Schneider and A. Lumsdaine: Optimized Routing for Large-Scale InfiniBand Networks, In 17th Annual IEEE Symposium on High Performance Interconnects (HOTI 2009) Modular Routine Engine Modular routing engine structure allows for the ease of "plugging" new routing modules. Currently, only unicast callbacks are supported. Multicast can be added later. One existing routing module is up-down "updn", which may be activated with '-R updn' option (instead of old '-u'). General usage is: $ opensm -R 'module-name' There is also a trivial routing module which is able to load LFT tables from a file. Main features: - this will load switch LFTs and/or LID matrices (min hops tables) - this will load switch LFTs according to the path entries introduced in the file - no additional checks will be performed (such as "is port connected", etc.) - in case when fabric LIDs were changed this will try to reconstruct LFTs correctly if endport GUIDs are represented in the file (in order to disable this, GUIDs may be removed from the file or zeroed) The file format is compatible with output of 'ibroute' util and for whole fabric can be generated with dump_lfts.sh script. To activate file based routing module, use: opensm -R file -U /path/to/lfts_file If the lfts_file is not found or is in error, the default routing algorithm is utilized. The ability to dump switch lid matrices (aka min hops tables) to file and later to load these is also supported. The usage is similar to unicast forwarding tables loading from a lfts file (introduced by 'file' routing engine), but new lid matrix file name should be specified by -M or --lid_matrix_file option. For example: opensm -R file -M ./opensm-lid-matrix.dump The dump file is named \'opensm-lid-matrix.dump\' and will be generated in standard opensm dump directory (/var/log by default) when OSM_LOG_ROUTING logging flag is set. When routing engine 'file' is activated, but the lfts file is not specified or not cannot be open default lid matrix algorithm will be used. There is also a switch forwarding tables dumper which generates a file compatible with dump_lfts.sh output. This file can be used as input for forwarding tables loading by 'file' routing engine. Both or one of options -U and -M can be specified together with \'-R file\'. .SH PER MODULE LOGGING CONFIGURATION .PP To enable per module logging, configure per_module_logging_file to the per module logging config file name in the opensm options file. To disable, configure per_module_logging_file to (null) there. The per module logging config file format is a set of lines with module name and logging level as follows: is the file name including .c is either = , space, or tab is the same levels as used in the coarse/overall logging as follows: BIT LOG LEVEL ENABLED ---- ----------------- 0x01 - ERROR (error messages) 0x02 - INFO (basic messages, low volume) 0x04 - VERBOSE (interesting stuff, moderate volume) 0x08 - DEBUG (diagnostic, high volume) 0x10 - FUNCS (function entry/exit, very high volume) 0x20 - FRAMES (dumps all SMP and GMP frames) 0x40 - ROUTING (dump FDB routing information) 0x80 - SYS (syslog at LOG_INFO level in addition to OpenSM logging) .SH FILES .TP .B @OPENSM_CONFIG_DIR@/@OPENSM_CONFIG_FILE@ default OpenSM config file. .TP .B @OPENSM_CONFIG_DIR@/@NODENAMEMAPFILE@ default node name map file. See ibnetdiscover for more information on format. .TP .B @OPENSM_CONFIG_DIR@/@PARTITION_CONFIG_FILE@ default partition config file .TP .B @OPENSM_CONFIG_DIR@/@QOS_POLICY_FILE@ default QOS policy config file .TP .B @OPENSM_CONFIG_DIR@/@PREFIX_ROUTES_FILE@ default prefix routes file .TP .B @OPENSM_CONFIG_DIR@/@PER_MOD_LOGGING_FILE@ default per module logging config file .TP .B @OPENSM_CONFIG_DIR@/@TORUS2QOS_CONF_FILE@ default torus-2QoS config file .SH AUTHORS .TP Hal Rosenstock .RI < hal@mellanox.com > .TP Sasha Khapyorsky .RI < sashak@voltaire.com > .TP Eitan Zahavi .RI < eitan@mellanox.co.il > .TP Yevgeny Kliteynik .RI < kliteyn@mellanox.co.il > .TP Thomas Sodring .RI < tsodring@simula.no > .TP Ira Weiny .RI < weiny2@llnl.gov > .TP Dale Purdy .RI < purdy@sgi.com > .SH SEE ALSO torus-2QoS(8), torus-2QoS.conf(5). opensm-3.3.20/man/torus-2QoS.8.in0000644000205000001450000004576212104655724013243 00000000000000.TH TORUS\-2QOS 8 "November 10, 2010" "OpenIB" "OpenIB Management" . .SH NAME torus\-2QoS \- Routing engine for OpenSM subnet manager . .SH DESCRIPTION . Torus-2QoS is routing algorithm designed for large-scale 2D/3D torus fabrics. The torus-2QoS routing engine can provide the following functionality on a 2D/3D torus: .br \" roff illiteracy leads to following brain-dead list implementation \" .na \" otherwise line space adjustment can add spaces between dash and text .in +2m \[en] 'in +2m Routing that is free of credit loops. .in \[en] 'in +2m Two levels of Quality of Service (QoS), assuming switches support eight data VLs and channel adapters support two data VLs. .in \[en] 'in +2m The ability to route around a single failed switch, and/or multiple failed links, without .in .in +2m \[en] 'in +2 introducing credit loops, or .in \[en] 'in +2m changing path SL values. .in -4m \[en] 'in +2m Very short run times, with good scaling properties as fabric size increases. .ad . .SH UNICAST ROUTING . Unicast routing in torus-2QoS is based on Dimension Order Routing (DOR). It avoids the deadlocks that would otherwise occur in a DOR-routed torus using the concept of a dateline for each torus dimension. It encodes into a path SL which datelines the path crosses, as follows: \f(CR .P .nf sl = 0; for (d = 0; d < torus_dimensions; d++) { /* path_crosses_dateline(d) returns 0 or 1 */ sl |= path_crosses_dateline(d) << d; } .fi \fR .P On a 3D torus this consumes three SL bits, leaving one SL bit unused. Torus-2QoS uses this SL bit to implement two QoS levels. .P Torus-2QoS also makes use of the output port dependence of switch SL2VL maps to encode into one VL bit the information encoded in three SL bits. It computes in which torus coordinate direction each inter-switch link "points", and writes SL2VL maps for such ports as follows: \f(CR .P .nf for (sl = 0; sl < 16; sl++) { /* cdir(port) computes which torus coordinate direction * a switch port "points" in; returns 0, 1, or 2 */ sl2vl(iport,oport,sl) = 0x1 & (sl >> cdir(oport)); } .fi \fR .P Thus, on a pristine 3D torus, \fIi.e.\fR, in the absence of failed fabric switches, torus-2QoS consumes eight SL values (SL bits 0-2) and two VL values (VL bit 0) per QoS level to provide deadlock-free routing. .P Torus-2QoS routes around link failure by "taking the long way around" any 1D ring interrupted by link failure. For example, consider the 2D 6x5 torus below, where switches are denoted by [+a-zA-Z]: . . \# define macros to start and end ascii art, assuming Roman font. \# the start macro takes an argument which is the width in ems of \# the ascii art, and is used to center it. \# .de ascii_art .nop \f(CR .nr indent_in_ems ((((\\n[.ll] - \\n[.i]) / \\w'm') - \\$1)/2) .in +\\n[indent_in_ems]m .nf .. .de end_ascii_art .fi .in .nop \fR .. \# end of macro definitions . . .ascii_art 36 | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----D----+----+-- | | | | | | 2 --+----+----I----r----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P For a pristine fabric the path from S to D would be S-n-T-r-D. In the event that either link S-n or n-T has failed, torus-2QoS would use the path S-m-p-o-T-r-D. Note that it can do this without changing the path SL value; once the 1D ring m-S-n-T-o-p-m has been broken by failure, path segments using it cannot contribute to deadlock, and the x-direction dateline (between, say, x=5 and x=0) can be ignored for path segments on that ring. .P One result of this is that torus-2QoS can route around many simultaneous link failures, as long as no 1D ring is broken into disjoint segments. For example, if links n-T and T-o have both failed, that ring has been broken into two disjoint segments, T and o-p-m-S-n. Torus-2QoS checks for such issues, reports if they are found, and refuses to route such fabrics. .P Note that in the case where there are multiple parallel links between a pair of switches, torus-2QoS will allocate routes across such links in a round-robin fashion, based on ports at the path destination switch that are active and not used for inter-switch links. Should a link that is one of several such parallel links fail, routes are redistributed across the remaining links. When the last of such a set of parallel links fails, traffic is rerouted as described above. .P Handling a failed switch under DOR requires introducing into a path at least one turn that would be otherwise "illegal", \fIi.e.\fR, not allowed by DOR rules. Torus-2QoS will introduce such a turn as close as possible to the failed switch in order to route around it. .P In the above example, suppose switch T has failed, and consider the path from S to D. Torus-2QoS will produce the path S-n-I-r-D, rather than the S-n-T-r-D path for a pristine torus, by introducing an early turn at n. Normal DOR rules will cause traffic arriving at switch I to be forwarded to switch r; for traffic arriving from I due to the "early" turn at n, this will generate an "illegal" turn at I. .P Torus-2QoS will also use the input port dependence of SL2VL maps to set VL bit 1 (which would be otherwise unused) for y-x, z-x, and z-y turns, \fIi.e.\fR, those turns that are illegal under DOR. This causes the first hop after any such turn to use a separate set of VL values, and prevents deadlock in the presence of a single failed switch. .P For any given path, only the hops after a turn that is illegal under DOR can contribute to a credit loop that leads to deadlock. So in the example above with failed switch T, the location of the illegal turn at I in the path from S to D requires that any credit loop caused by that turn must encircle the failed switch at T. Thus the second and later hops after the illegal turn at I (\fIi.e.\fR, hop r-D) cannot contribute to a credit loop because they cannot be used to construct a loop encircling T. The hop I-r uses a separate VL, so it cannot contribute to a credit loop encircling T. .P Extending this argument shows that in addition to being capable of routing around a single switch failure without introducing deadlock, torus-2QoS can also route around multiple failed switches on the condition they are adjacent in the last dimension routed by DOR. For example, consider the following case on a 6x6 2D torus: . .ascii_art 36 | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----D----+----+-- | | | | | | 3 --+----+----I----u----+----+-- | | | | | | 2 --+----+----q----R----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P Suppose switches T and R have failed, and consider the path from S to D. Torus-2QoS will generate the path S-n-q-I-u-D, with an illegal turn at switch I, and with hop I-u using a VL with bit 1 set. .P As a further example, consider a case that torus-2QoS cannot route without deadlock: two failed switches adjacent in a dimension that is not the last dimension routed by DOR; here the failed switches are O and T: . .ascii_art 36 | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----+----D----+-- | | | | | | 2 --+----+----I----q----r----+-- | | | | | | 1 --m----S----n----O----T----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P In a pristine fabric, torus-2QoS would generate the path from S to D as S-n-O-T-r-D. With failed switches O and T, torus-2QoS will generate the path S-n-I-q-r-D, with illegal turn at switch I, and with hop I-q using a VL with bit 1 set. In contrast to the earlier examples, the second hop after the illegal turn, q-r, can be used to construct a credit loop encircling the failed switches. . .SH MULTICAST ROUTING . Since torus-2QoS uses all four available SL bits, and the three data VL bits that are typically available in current switches, there is no way to use SL/VL values to separate multicast traffic from unicast traffic. Thus, torus-2QoS must generate multicast routing such that credit loops cannot arise from a combination of multicast and unicast path segments. .P It turns out that it is possible to construct spanning trees for multicast routing that have that property. For the 2D 6x5 torus example above, here is the full-fabric spanning tree that torus-2QoS will construct, where "x" is the root switch and each "+" is a non-root switch: . .ascii_art 36 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 +----+----+----x----+----+ | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 .end_ascii_art .P For multicast traffic routed from root to tip, every turn in the above spanning tree is a legal DOR turn. .P For traffic routed from tip to root, and some traffic routed through the root, turns are not legal DOR turns. However, to construct a credit loop, the union of multicast routing on this spanning tree with DOR unicast routing can only provide 3 of the 4 turns needed for the loop. .P In addition, if none of the above spanning tree branches crosses a dateline used for unicast credit loop avoidance on a torus, and if multicast traffic is confined to SL 0 or SL 8 (recall that torus-2QoS uses SL bit 3 to differentiate QoS level), then multicast traffic also cannot contribute to the "ring" credit loops that are otherwise possible in a torus. .P Torus-2QoS uses these ideas to create a master spanning tree. Every multicast group spanning tree will be constructed as a subset of the master tree, with the same root as the master tree. .P Such multicast group spanning trees will in general not be optimal for groups which are a subset of the full fabric. However, this compromise must be made to enable support for two QoS levels on a torus while preventing credit loops. .P In the presence of link or switch failures that result in a fabric for which torus-2QoS can generate credit-loop-free unicast routes, it is also possible to generate a master spanning tree for multicast that retains the required properties. For example, consider that same 2D 6x5 torus, with the link from (2,2) to (3,2) failed. Torus-2QoS will generate the following master spanning tree: . .ascii_art 36 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 --+----+----+ x----+----+-- | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 .end_ascii_art .P Two things are notable about this master spanning tree. First, assuming the x dateline was between x=5 and x=0, this spanning tree has a branch that crosses the dateline. However, just as for unicast, crossing a dateline on a 1D ring (here, the ring for y=2) that is broken by a failure cannot contribute to a torus credit loop. .P Second, this spanning tree is no longer optimal even for multicast groups that encompass the entire fabric. That, unfortunately, is a compromise that must be made to retain the other desirable properties of torus-2QoS routing. .P In the event that a single switch fails, torus-2QoS will generate a master spanning tree that has no "extra" turns by appropriately selecting a root switch. In the 2D 6x5 torus example, assume now that the switch at (3,2), \fIi.e.\fR, the root for a pristine fabric, fails. Torus-2QoS will generate the following master spanning tree for that case: . .ascii_art 36 | 4 + + + + + + | | | | | | 3 + + + + + + | | | | | 2 + + + + + | | | | | 1 +----+----x----+----+----+ | | | | | | y=0 + + + + + + | x=0 1 2 3 4 5 .end_ascii_art .P Assuming the y dateline was between y=4 and y=0, this spanning tree has a branch that crosses a dateline. However, again this cannot contribute to credit loops as it occurs on a 1D ring (the ring for x=3) that is broken by a failure, as in the above example. . .SH TORUS TOPOLOGY DISCOVERY . The algorithm used by torus-2QoS to construct the torus topology from the undirected graph representing the fabric requires that the radix of each dimension be configured via torus-2QoS.conf. It also requires that the torus topology be "seeded"; for a 3D torus this requires configuring four switches that define the three coordinate directions of the torus. .P Given this starting information, the algorithm is to examine the cube formed by the eight switch locations bounded by the corners (x,y,z) and (x+1,y+1,z+1). Based on switches already placed into the torus topology at some of these locations, the algorithm examines 4-loops of inter-switch links to find the one that is consistent with a face of the cube of switch locations, and adds its swiches to the discovered topology in the correct locations. .P Because the algorithm is based on examining the topology of 4-loops of links, a torus with one or more radix-4 dimensions requires extra initial seed configuration. See torus-2QoS.conf(5) for details. Torus-2QoS will detect and report when it has insufficient configuration for a torus with radix-4 dimensions. .P In the event the torus is significantly degraded, \fIi.e.\fR, there are many missing switches or links, it may happen that torus-2QoS is unable to place into the torus some switches and/or links that were discovered in the fabric, and will generate a warning in that case. A similar condition occurs if torus-2QoS is misconfigured, \fIi.e.\fR, the radix of a torus dimension as configured does not match the radix of that torus dimension as wired, and many switches/links in the fabric will not be placed into the torus. . .SH QUALITY OF SERVICE CONFIGURATION . OpenSM will not program switchs and channel adapters with SL2VL maps or VL arbitration configuration unless it is invoked with -Q. Since torus-2QoS depends on such functionality for correct operation, always invoke OpenSM with -Q when torus-2QoS is in the list of routing engines. .P Any quality of service configuration method supported by OpenSM will work with torus-2QoS, subject to the following limitations and considerations. .P For all routing engines supported by OpenSM except torus-2QoS, there is a one-to-one correspondence between QoS level and SL. Torus-2QoS can only support two quality of service levels, so only the high-order bit of any SL value used for unicast QoS configuration will be honored by torus-2QoS. .P For multicast QoS configuration, only SL values 0 and 8 should be used with torus-2QoS. .P Since SL to VL map configuration must be under the complete control of torus-2QoS, any configuration via qos_sl2vl, qos_swe_sl2vl, \fIetc.\fR, must and will be ignored, and a warning will be generated. .P For inter-switch links, Torus-2QoS uses VL values 0-3 to implement one of its supported QoS levels, and VL values 4-7 to implement the other. For endport links (CA, router, switch management port), Torus-2QoS uses VL value 0 for one of its supported QoS levels and VL value 1 to implement the other. Hard-to-diagnose application issues may arise if traffic is not delivered fairly across each of these two VL ranges. For inter-switch links, Torus-2QoS will detect and warn if VL arbitration is configured unfairly across VLs in the range 0-3, and also in the range 4-7. Note that the default OpenSM VL arbitration configuration does not meet this constraint, so all torus-2QoS users should configure VL arbitration via qos_ca_vlarb_high, qos_swe_vlarb_high, qos_ca_vlarb_low, qos_swe_vlarb_low, \fIetc.\fR .P Note that torus-2QoS maps SL values to VL values differently for inter-switch and endport links. This is why qos_vlarb_high and qos_vlarb_low should not be used, as using them may result in VL arbitration for a QoS level being different across inter-switch links vs. across endport links. . .SH OPERATIONAL CONSIDERATIONS . Any routing algorithm for a torus IB fabric must employ path SL values to avoid credit loops. As a result, all applications run over such fabrics must perform a path record query to obtain the correct path SL for connection setup. Applications that use \fBrdma_cm\fR for connection setup will automatically meet this requirement. .P If a change in fabric topology causes changes in path SL values required to route without credit loops, in general all applications would need to repath to avoid message deadlock. Since torus-2QoS has the ability to reroute after a single switch failure without changing path SL values, repathing by running applications is not required when the fabric is routed with torus-2QoS. .P Torus-2QoS can provide unchanging path SL values in the presence of subnet manager failover provided that all OpenSM instances have the same idea of dateline location. See torus-2QoS.conf(5) for details. .P Torus-2QoS will detect configurations of failed switches and links that prevent routing that is free of credit loops, and will log warnings and refuse to route. If "no_fallback" was configured in the list of OpenSM routing engines, then no other routing engine will attempt to route the fabric. In that case all paths that do not transit the failed components will continue to work, and the subset of paths that are still operational will continue to remain free of credit loops. OpenSM will continue to attempt to route the fabric after every sweep interval, and after any change (such as a link up) in the fabric topology. When the fabric components are repaired, full functionality will be restored. .P In the event OpenSM was configured to allow some other engine to route the fabric if torus-2QoS fails, then credit loops and message deadlock are likely if torus-2QoS had previously routed the fabric successfully. Even if the other engine is capable of routing a torus without credit loops, applications that built connections with path SL values granted under torus-2QoS will likely experience message deadlock under routing generated by a different engine, unless they repath. .P To verify that a torus fabric is routed free of credit loops, use \fBibdmchk\fR to analyze data collected via \fBibdiagnet -vlr\fR. . .SH FILES .TP .B @OPENSM_CONFIG_DIR@/@OPENSM_CONFIG_FILE@ default OpenSM config file. .TP .B @OPENSM_CONFIG_DIR@/@QOS_POLICY_FILE@ default QoS policy config file. .TP .B @OPENSM_CONFIG_DIR@/@TORUS2QOS_CONF_FILE@ default torus-2QoS config file. . .SH SEE ALSO . opensm(8), torus-2QoS.conf(5), ibdiagnet(1), ibdmchk(1), rdma_cm(7). opensm-3.3.20/man/torus-2QoS.conf.5.in0000644000205000001450000001524512104655724014155 00000000000000.TH TORUS\-2QOS.CONF 5 "January 4, 2013" "OpenIB" "OpenIB Management" . .SH NAME torus\-2QoS.conf \- Torus-2QoS configuration for OpenSM subnet manager . .SH DESCRIPTION . The file .B torus-2QoS.conf contains configuration information that is specific to the OpenSM routing engine torus-2QoS. Blank lines and lines where the first non-whitespace character is "#" are ignored. A token is any contiguous group of non-whitespace characters. Any tokens on a line following the recognized configuration tokens described below are ignored. . .P \fR[\fBtorus\fR|\fBmesh\fR] \fIx_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] \fIy_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] \fIz_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] .RS Either \fBtorus\fR or \fBmesh\fR must be the first keyword in the configuration, and sets the topology that torus-2QoS will try to construct. A 2D topology can be configured by specifying one of \fIx_radix\fR, \fIy_radix\fR, or \fIz_radix\fR as 1. An individual dimension can be configured as mesh (open) or torus (looped) by suffixing its radix specification with one of \fBm\fR, \fBM\fR, \fBt\fR, or \fBT\fR. Thus, "mesh 3T 4 5" and "torus 3 4M 5M" both specify the same topology. .P Note that although torus-2QoS can route mesh fabrics, its ability to route around failed components is severely compromised on such fabrics. A failed fabric component is very likely to cause a disjoint ring; see \fBUNICAST ROUTING\fR in torus-2QoS(8). .RE . .P \fBxp_link \fIsw0_GUID sw1_GUID .br .ns \fByp_link \fIsw0_GUID sw1_GUID .br .ns \fBzp_link \fIsw0_GUID sw1_GUID .br .ns \fBxm_link \fIsw0_GUID sw1_GUID .br .ns \fBym_link \fIsw0_GUID sw1_GUID .br .ns \fBzm_link \fIsw0_GUID sw1_GUID \fR .RS These keywords are used to seed the torus/mesh topology. For example, "xp_link 0x2000 0x2001" specifies that a link from the switch with node GUID 0x2000 to the switch with node GUID 0x2001 would point in the positive x direction, while "xm_link 0x2000 0x2001" specifies that a link from the switch with node GUID 0x2000 to the switch with node GUID 0x2001 would point in the negative x direction. All the link keywords for a given seed must specify the same "from" switch. .P In general, it is not necessary to configure both the positive and negative directions for a given coordinate; either is sufficient. However, the algorithm used for topology discovery needs extra information for torus dimensions of radix four (see \fBTOPOLOGY DISCOVERY\fR in torus-2QoS(8)). For such cases both the positive and negative coordinate directions must be specified. .P Based on the topology specified via the \fBtorus\fR/\fBmesh\fR keyword, torus-2QoS will detect and log when it has insufficient seed configuration. .RE . .P \fBx_dateline \fIposition .br .ns \fBy_dateline \fIposition .br .ns \fBz_dateline \fIposition \fR .RS In order for torus-2QoS to provide the guarantee that path SL values do not change under any conditions for which it can still route the fabric, its idea of dateline position must not change relative to physical switch locations. The dateline keywords provide the means to configure such behavior. .P The dateline for a torus dimension is always between the switch with coordinate 0 and the switch with coordinate radix-1 for that dimension. By default, the common switch in a torus seed is taken as the origin of the coordinate system used to describe switch location. The \fIposition\fR parameter for a dateline keyword moves the origin (and hence the dateline) the specified amount relative to the common switch in a torus seed. .RE . .P \fBnext_seed \fR .RS If any of the switches used to specify a seed were to fail torus-2QoS would be unable to complete topology discovery successfully. The \fBnext_seed\fR keyword specifies that the following link and dateline keywords apply to a new seed specification. .P For maximum resiliency, no seed specification should share a switch with any other seed specification. Multiple seed specifications should use dateline configuration to ensure that torus-2QoS can grant path SL values that are constant, regardless of which seed was used to initiate topology discovery. .RE . .P \fBportgroup_max_ports \fImax_ports \fR .RS This keyword specifies the maximum number of parallel inter-switch links, and also the maximum number of host ports per switch, that torus-2QoS can accommodate. The default value is 16. Torus-2QoS will log an error message during topology discovery if this parameter needs to be increased. If this keyword appears multiple times, the last instance prevails. .P Note that the switch management port (switch port 0) gets put into the same port group with the host ports, so if you have 16 host ports per switch, portgroup_max_ports would need to be at least 17. .RE . .P \fBport_order \fIp1 p2 p3 ... \fR .RS This keyword specifies the order in which CA ports on a destination switch are visited when computing routes. When the fabric contains switches connected with multiple parallel links, routes are distributed in a round-robin fashion across such links, and so changing the order that CA ports are visited changes the distribution of routes across such links. This may be advantageous for some specific traffic patterns. .P The default is to visit CA ports in increasing port order on destination switches. .P Duplicate values in the list will be ignored. .RE . .P \fBmax_changes \fImax \fR .RS This keyword specifies the maximum number of torus changes reported. The default value is 32. .RE . .SH EXAMPLE . \f(RC .nf # Look for a 2D (since x radix is one) 4x5 torus. torus 1 4 5 # y is radix-4 torus dimension, need both # ym_link and yp_link configuration. yp_link 0x200000 0x200005 # sw @ y=0,z=0 -> sw @ y=1,z=0 ym_link 0x200000 0x20000f # sw @ y=0,z=0 -> sw @ y=3,z=0 # z is not radix-4 torus dimension, only need one of # zm_link or zp_link configuration. zp_link 0x200000 0x200001 # sw @ y=0,z=0 -> sw @ y=0,z=1 next_seed yp_link 0x20000b 0x200010 # sw @ y=2,z=1 -> sw @ y=3,z=1 ym_link 0x20000b 0x200006 # sw @ y=2,z=1 -> sw @ y=1,z=1 zp_link 0x20000b 0x20000c # sw @ y=2,z=1 -> sw @ y=2,z=2 y_dateline -2 # Move the dateline for this seed z_dateline -1 # back to its original position. # If OpenSM failover is configured, for maximum resiliency # one instance should run on a host attached to a switch # from the first seed, and another instance should run # on a host attached to a switch from the second seed. # Both instances should use this torus-2QoS.conf to ensure # path SL values do not change in the event of SM failover. # port_order defines the order on which the ports would be # chosen for routing. port_order 7 10 8 11 9 12 25 28 26 29 27 30 .fi \fR . .SH FILES .TP .B @OPENSM_CONFIG_DIR@/@TORUS2QOS_CONF_FILE@ Default torus-2QoS config file. . .SH SEE ALSO . opensm(8), torus-2QoS(8). opensm-3.3.20/man/opensm.80000644000205000001450000017661012726323447012202 00000000000000.TH OPENSM 8 "Sept 15, 2014" "OpenIB" "OpenIB Management" .SH NAME opensm \- InfiniBand subnet manager and administration (SM/SA) .SH SYNOPSIS .B opensm [\-\-version]] [\-F | \-\-config ] [\-c(reate-config) ] [\-g(uid) ] [\-l(mc) ] [\-p(riority) ] [\-\-smkey ] [\-\-sm_sl ] [\-r(eassign_lids)] [\-R | \-\-routing_engine ] [\-\-do_mesh_analysis] [\-\-lash_start_vl ] [\-A | \-\-ucast_cache] [\-z | \-\-connect_roots] [\-M | \-\-lid_matrix_file ] [\-U | \-\-lfts_file ] [\-S | \-\-sadb_file ] [\-a | \-\-root_guid_file ] [\-u | \-\-cn_guid_file ] [\-G | \-\-io_guid_file ] [\-\-port\-shifting] [\-\-scatter\-ports ] [\-H | \-\-max_reverse_hops ] [\-X | \-\-guid_routing_order_file ] [\-m | \-\-ids_guid_file ] [\-o(nce)] [\-s(weep) ] [\-t(imeout) ] [\-\-retries ] [\-\-maxsmps ] [\-\-console [off | local | socket | loopback]] [\-\-console-port ] [\-i | \-\-ignore_guids ] [\-w | \-\-hop_weights_file ] [\-O | \-\-port_search_ordering_file ] [\-O | \-\-dimn_ports_file ] (DEPRECATED) [\-f | \-\-log_file ] [\-L | \-\-log_limit ] [\-e(rase_log_file)] [\-P(config) ] [\-N | \-\-no_part_enforce] (DEPRECATED) [\-Z | \-\-part_enforce [both | in | out | off]] [\-W | \-\-allow_both_pkeys] [\-Q | \-\-qos [\-Y | \-\-qos_policy_file ]] [\-\-congestion\-control] [\-\-cckey ] [\-y | \-\-stay_on_fatal] [\-B | \-\-daemon] [\-J | \-\-pidfile ] [\-I | \-\-inactive] [\-\-perfmgr] [\-\-perfmgr_sweep_time_s ] [\-\-prefix_routes_file ] [\-\-consolidate_ipv6_snm_req] [\-\-log_prefix ] [\-\-torus_config ] [\-v(erbose)] [\-V] [\-D ] [\-d(ebug) ] [\-h(elp)] [\-?] .SH DESCRIPTION .PP opensm is an InfiniBand compliant Subnet Manager and Administration, and runs on top of OpenIB. opensm provides an implementation of an InfiniBand Subnet Manager and Administration. Such a software entity is required to run for in order to initialize the InfiniBand hardware (at least one per each InfiniBand subnet). opensm also now contains an experimental version of a performance manager as well. opensm defaults were designed to meet the common case usage on clusters with up to a few hundred nodes. Thus, in this default mode, opensm will scan the IB fabric, initialize it, and sweep occasionally for changes. opensm attaches to a specific IB port on the local machine and configures only the fabric connected to it. (If the local machine has other IB ports, opensm will ignore the fabrics connected to those other ports). If no port is specified, it will select the first "best" available port. opensm can present the available ports and prompt for a port number to attach to. By default, the run is logged to two files: /var/log/messages and /var/log/opensm.log. The first file will register only general major events, whereas the second will include details of reported errors. All errors reported in this second file should be treated as indicators of IB fabric health issues. (Note that when a fatal and non-recoverable error occurs, opensm will exit.) Both log files should include the message "SUBNET UP" if opensm was able to setup the subnet correctly. .SH OPTIONS .PP .TP \fB\-\-version\fR Prints OpenSM version and exits. .TP \fB\-F\fR, \fB\-\-config\fR The name of the OpenSM config file. When not specified \fB\% /usr/local/etc/opensm/opensm.conf\fP will be used (if exists). .TP \fB\-c\fR, \fB\-\-create-config\fR OpenSM will dump its configuration to the specified file and exit. This is a way to generate OpenSM configuration file template. .TP \fB\-g\fR, \fB\-\-guid\fR This option specifies the local port GUID value with which OpenSM should bind. OpenSM may be bound to 1 port at a time. If GUID given is 0, OpenSM displays a list of possible port GUIDs and waits for user input. Without -g, OpenSM tries to use the default port. .TP \fB\-l\fR, \fB\-\-lmc\fR This option specifies the subnet's LMC value. The number of LIDs assigned to each port is 2^LMC. The LMC value must be in the range 0-7. LMC values > 0 allow multiple paths between ports. LMC values > 0 should only be used if the subnet topology actually provides multiple paths between ports, i.e. multiple interconnects between switches. Without -l, OpenSM defaults to LMC = 0, which allows one path between any two ports. .TP \fB\-p\fR, \fB\-\-priority\fR This option specifies the SM\'s PRIORITY. This will effect the handover cases, where master is chosen by priority and GUID. Range goes from 0 (default and lowest priority) to 15 (highest). .TP \fB\-\-smkey\fR This option specifies the SM\'s SM_Key (64 bits). This will effect SM authentication. Note that OpenSM version 3.2.1 and below used the default value '1' in a host byte order, it is fixed now but you may need this option to interoperate with old OpenSM running on a little endian machine. .TP \fB\-\-sm_sl\fR This option sets the SL to use for communication with the SM/SA. Defaults to 0. .TP \fB\-r\fR, \fB\-\-reassign_lids\fR This option causes OpenSM to reassign LIDs to all end nodes. Specifying -r on a running subnet may disrupt subnet traffic. Without -r, OpenSM attempts to preserve existing LID assignments resolving multiple use of same LID. .TP \fB\-R\fR, \fB\-\-routing_engine\fR This option chooses routing engine(s) to use instead of Min Hop algorithm (default). Multiple routing engines can be specified separated by commas so that specific ordering of routing algorithms will be tried if earlier routing engines fail. If all configured routing engines fail, OpenSM will always attempt to route with Min Hop unless 'no_fallback' is included in the list of routing engines. Supported engines: minhop, updn, dnup, file, ftree, lash, dor, torus-2QoS, dfsssp, sssp. .TP \fB\-\-do_mesh_analysis\fR This option enables additional analysis for the lash routing engine to precondition switch port assignments in regular cartesian meshes which may reduce the number of SLs required to give a deadlock free routing. .TP \fB\-\-lash_start_vl\fR This option sets the starting VL to use for the lash routing algorithm. Defaults to 0. .TP \fB\-A\fR, \fB\-\-ucast_cache\fR This option enables unicast routing cache and prevents routing recalculation (which is a heavy task in a large cluster) when there was no topology change detected during the heavy sweep, or when the topology change does not require new routing calculation, e.g. when one or more CAs/RTRs/leaf switches going down, or one or more of these nodes coming back after being down. A very common case that is handled by the unicast routing cache is host reboot, which otherwise would cause two full routing recalculations: one when the host goes down, and the other when the host comes back online. .TP \fB\-z\fR, \fB\-\-connect_roots\fR This option enforces routing engines (up/down and fat-tree) to make connectivity between root switches and in this way to be fully IBA compliant. In many cases this can violate "pure" deadlock free algorithm, so use it carefully. .TP \fB\-M\fR, \fB\-\-lid_matrix_file\fR This option specifies the name of the lid matrix dump file from where switch lid matrices (min hops tables) will be loaded. .TP \fB\-U\fR, \fB\-\-lfts_file\fR This option specifies the name of the LFTs file from where switch forwarding tables will be loaded when using "file" routing engine. .TP \fB\-S\fR, \fB\-\-sadb_file\fR This option specifies the name of the SA DB dump file from where SA database will be loaded. .TP \fB\-a\fR, \fB\-\-root_guid_file\fR Set the root nodes for the Up/Down or Fat-Tree routing algorithm to the guids provided in the given file (one to a line). .TP \fB\-u\fR, \fB\-\-cn_guid_file\fR Set the compute nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms to the port GUIDs provided in the given file (one to a line). .TP \fB\-G\fR, \fB\-\-io_guid_file\fR Set the I/O nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms to the port GUIDs provided in the given file (one to a line). .br In the case of Fat-Tree routing: .br I/O nodes are non-CN nodes allowed to use up to max_reverse_hops switches the wrong way around to improve connectivity. .br In the case of (DF)SSSP routing: .br Providing guids of compute and/or I/O nodes will ensure that paths towards those nodes are as much separated as possible within their node category, i.e., I/O traffic will not share the same link if multiple links are available. .TP \fB\-\-port\-shifting\fR This option enables a feature called \fBport shifting\fR. In some fabrics, particularly cluster environments, routes commonly align and congest with other routes due to algorithmically unchanging traffic patterns. This routing option will "shift" routing around in an attempt to alleviate this problem. .TP \fB\-\-scatter\-ports\fR This option is used to randomize port selection in routing rather than using a round-robin algorithm (which is the default). Value supplied with option is used as a random seed. If value is 0, which is the default, the scatter ports option is disabled. .TP \fB\-H\fR, \fB\-\-max_reverse_hops\fR Set the maximum number of reverse hops an I/O node is allowed to make. A reverse hop is the use of a switch the wrong way around. .TP \fB\-m\fR, \fB\-\-ids_guid_file\fR Name of the map file with set of the IDs which will be used by Up/Down routing algorithm instead of node GUIDs (format: per line). .TP \fB\-X\fR, \fB\-\-guid_routing_order_file\fR Set the order port guids will be routed for the MinHop and Up/Down routing algorithms to the guids provided in the given file (one to a line). .TP \fB\-o\fR, \fB\-\-once\fR This option causes OpenSM to configure the subnet once, then exit. Ports remain in the ACTIVE state. .TP \fB\-s\fR, \fB\-\-sweep\fR This option specifies the number of seconds between subnet sweeps. Specifying -s 0 disables sweeping. Without -s, OpenSM defaults to a sweep interval of 10 seconds. .TP \fB\-t\fR, \fB\-\-timeout\fR This option specifies the time in milliseconds used for transaction timeouts. Timeout values should be > 0. Without -t, OpenSM defaults to a timeout value of 200 milliseconds. .TP \fB\-\-retries\fR This option specifies the number of retries used for transactions. Without --retries, OpenSM defaults to 3 retries for transactions. .TP \fB\-\-maxsmps\fR This option specifies the number of VL15 SMP MADs allowed on the wire at any one time. Specifying \-\-maxsmps 0 allows unlimited outstanding SMPs. Without \-\-maxsmps, OpenSM defaults to a maximum of 4 outstanding SMPs. .TP \fB\-\-console [off | local | loopback | socket]\fR This option brings up the OpenSM console (default off). Note, loopback and socket open a socket which can be connected to WITHOUT CREDENTIALS. Loopback is safer if access to your SM host is controlled. tcp_wrappers (hosts.[allow|deny]) is used with loopback and socket. loopback and socket will only be available if OpenSM was built with --enable-console-loopback (default yes) and --enable-console-socket (default no) respectively. .TP \fB\-\-console-port\fR Specify an alternate telnet port for the socket console (default 10000). Note that this option only appears if OpenSM was built with --enable-console-socket. .TP \fB\-i\fR, \fB\-\-ignore_guids\fR This option provides the means to define a set of ports (by node guid and port number) that will be ignored by the link load equalization algorithm. .TP \fB\-w\fR, \fB\-\-hop_weights_file\fR This option provides weighting factors per port representing a hop cost in computing the lid matrix. The file consists of lines containing a switch port GUID (specified as a 64 bit hex number, with leading 0x), output port number, and weighting factor. Any port not listed in the file defaults to a weighting factor of 1. Lines starting with # are comments. Weights affect only the output route from the port, so many useful configurations will require weights to be specified in pairs. .TP \fB\-O\fR, \fB\-\-port_search_ordering_file\fR This option tweaks the routing. It suitable for two cases: 1. While using DOR routing algorithm. This option provides a mapping between hypercube dimensions and ports on a per switch basis for the DOR routing engine. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. The order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. 2. While using general routing algorithm. This option provides the order of the ports that would be chosen for routing, from each switch rather than searching for an appropriate port from port 1 to N. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. In case of DOR, the order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. .TP \fB\-O\fR, \fB\-\-dimn_ports_file\fR \fB(DEPRECATED)\fR This is a deprecated flag. Please use \fB\-\-port_search_ordering_file\fR instead. This option provides a mapping between hypercube dimensions and ports on a per switch basis for the DOR routing engine. The file consists of lines containing a switch node GUID (specified as a 64 bit hex number, with leading 0x) followed by a list of non-zero port numbers, separated by spaces, one switch per line. The order for the port numbers is in one to one correspondence to the dimensions. Ports not listed on a line are assigned to the remaining dimensions, in port order. Anything after a # is a comment. .TP \fB\-x\fR, \fB\-\-honor_guid2lid\fR This option forces OpenSM to honor the guid2lid file, when it comes out of Standby state, if such file exists under OSM_CACHE_DIR, and is valid. By default, this is FALSE. .TP \fB\-f\fR, \fB\-\-log_file\fR This option defines the log to be the given file. By default, the log goes to /var/log/opensm.log. For the log to go to standard output use -f stdout. .TP \fB\-L\fR, \fB\-\-log_limit\fR This option defines maximal log file size in MB. When specified the log file will be truncated upon reaching this limit. .TP \fB\-e\fR, \fB\-\-erase_log_file\fR This option will cause deletion of the log file (if it previously exists). By default, the log file is accumulative. .TP \fB\-P\fR, \fB\-\-Pconfig\fR This option defines the optional partition configuration file. The default name is \fB\%/usr/local/etc/opensm/partitions.conf\fP. .TP \fB\-\-prefix_routes_file\fR Prefix routes control how the SA responds to path record queries for off-subnet DGIDs. By default, the SA fails such queries. The .B PREFIX ROUTES section below describes the format of the configuration file. The default path is \fB\%/usr/local/etc/opensm/prefix\-routes.conf\fP. .TP \fB\-Q\fR, \fB\-\-qos\fR This option enables QoS setup. It is disabled by default. .TP \fB\-Y\fR, \fB\-\-qos_policy_file\fR This option defines the optional QoS policy file. The default name is \fB\%/usr/local/etc/opensm/qos-policy.conf\fP. See QoS_management_in_OpenSM.txt in opensm doc for more information on configuring QoS policy via this file. .TP \fB\-\-congestion_control\fR (EXPERIMENTAL) This option enables congestion control configuration. It is disabled by default. See config file for congestion control configuration options. \fB\-\-cc_key\fR (EXPERIMENTAL) This option configures the CCkey to use when configuring congestion control. Note that this option does not configure a new CCkey into switches and CAs. Defaults to 0. .TP \fB\-N\fR, \fB\-\-no_part_enforce\fR \fB(DEPRECATED)\fR This is a deprecated flag. Please use \fB\-\-part_enforce\fR instead. This option disables partition enforcement on switch external ports. .TP \fB\-Z\fR, \fB\-\-part_enforce\fR [both | in | out | off] This option indicates the partition enforcement type (for switches). Enforcement type can be inbound only (in), outbound only (out), both or disabled (off). Default is both. .TP \fB\-W\fR, \fB\-\-allow_both_pkeys\fR This option indicates whether both full and limited membership on the same partition can be configured in the PKeyTable. Default is not to allow both pkeys. .TP \fB\-y\fR, \fB\-\-stay_on_fatal\fR This option will cause SM not to exit on fatal initialization issues: if SM discovers duplicated guids or a 12x link with lane reversal badly configured. By default, the SM will exit on these errors. .TP \fB\-B\fR, \fB\-\-daemon\fR Run in daemon mode - OpenSM will run in the background. .TP \fB\-J\fR, \fB\-\-pidfile \fR Makes the SM write its own PID to the specified file when started in daemon mode. .TP \fB\-I\fR, \fB\-\-inactive\fR Start SM in inactive rather than init SM state. This option can be used in conjunction with the perfmgr so as to run a standalone performance manager without SM/SA. However, this is NOT currently implemented in the performance manager. .TP \fB\-\-perfmgr\fR Enable the perfmgr. Only takes effect if --enable-perfmgr was specified at configure time. See performance-manager-HOWTO.txt in opensm doc for more information on running perfmgr. .TP \fB\-\-perfmgr_sweep_time_s\fR Specify the sweep time for the performance manager in seconds (default is 180 seconds). Only takes effect if --enable-perfmgr was specified at configure time. .TP .BI --consolidate_ipv6_snm_req Use shared MLID for IPv6 Solicited Node Multicast groups per MGID scope and P_Key. .TP \fB\-\-log_prefix\fR This option specifies the prefix to the syslog messages from OpenSM. A suitable prefix can be used to identify the IB subnet in syslog messages when two or more instances of OpenSM run in a single node to manage multiple fabrics. For example, in a dual-fabric (or dual-rail) IB cluster, the prefix for the first fabric could be "mpi" and the other fabric could be "storage". .TP \fB\-\-torus_config\fR This option defines the file name for the extra configuration information needed for the torus-2QoS routing engine. The default name is \fB\%/usr/local/etc/opensm/torus-2QoS.conf\fP .TP \fB\-v\fR, \fB\-\-verbose\fR This option increases the log verbosity level. The -v option may be specified multiple times to further increase the verbosity level. See the -D option for more information about log verbosity. .TP \fB\-V\fR This option sets the maximum verbosity level and forces log flushing. The -V option is equivalent to \'-D 0xFF -d 2\'. See the -D option for more information about log verbosity. .TP \fB\-D\fR This option sets the log verbosity level. A flags field must follow the -D option. A bit set/clear in the flags enables/disables a specific log level as follows: BIT LOG LEVEL ENABLED ---- ----------------- 0x01 - ERROR (error messages) 0x02 - INFO (basic messages, low volume) 0x04 - VERBOSE (interesting stuff, moderate volume) 0x08 - DEBUG (diagnostic, high volume) 0x10 - FUNCS (function entry/exit, very high volume) 0x20 - FRAMES (dumps all SMP and GMP frames) 0x40 - ROUTING (dump FDB routing information) 0x80 - SYS (syslog at LOG_INFO level in addition to OpenSM logging) Without -D, OpenSM defaults to ERROR + INFO (0x3). Specifying -D 0 disables all messages. Specifying -D 0xFF enables all messages (see -V). High verbosity levels may require increasing the transaction timeout with the -t option. .TP \fB\-d\fR, \fB\-\-debug\fR This option specifies a debug option. These options are not normally needed. The number following -d selects the debug option to enable as follows: OPT Description --- ----------------- -d0 - Ignore other SM nodes -d1 - Force single threaded dispatching -d2 - Force log flushing after each log message -d3 - Disable multicast support .TP \fB\-h\fR, \fB\-\-help\fR Display this usage info then exit. .TP \fB\-?\fR Display this usage info then exit. .SH ENVIRONMENT VARIABLES .PP The following environment variables control opensm behavior: OSM_TMP_DIR - controls the directory in which the temporary files generated by opensm are created. These files are: opensm-subnet.lst, opensm.fdbs, and opensm.mcfdbs. By default, this directory is /var/log. OSM_CACHE_DIR - opensm stores certain data to the disk such that subsequent runs are consistent. The default directory used is /var/cache/opensm. The following files are included in it: guid2lid - stores the LID range assigned to each GUID guid2mkey - stores the MKey previously assiged to each GUID neighbors - stores a map of the GUIDs at either end of each link in the fabric .SH NOTES .PP When opensm receives a HUP signal, it starts a new heavy sweep as if a trap was received or a topology change was found. .PP Also, SIGUSR1 can be used to trigger a reopen of /var/log/opensm.log for logrotate purposes. .SH PARTITION CONFIGURATION .PP The default name of OpenSM partitions configuration file is \fB\%/usr/local/etc/opensm/partitions.conf\fP. The default may be changed by using the --Pconfig (-P) option with OpenSM. The default partition will be created by OpenSM unconditionally even when partition configuration file does not exist or cannot be accessed. The default partition has P_Key value 0x7fff. OpenSM\'s port will always have full membership in default partition. All other end ports will have full membership if the partition configuration file is not found or cannot be accessed, or limited membership if the file exists and can be accessed but there is no rule for the Default partition. Effectively, this amounts to the same as if one of the following rules below appear in the partition configuration file. In the case of no rule for the Default partition: Default=0x7fff : ALL=limited, SELF=full ; In the case of no partition configuration file or file cannot be accessed: Default=0x7fff : ALL=full ; File Format Comments: Line content followed after \'#\' character is comment and ignored by parser. General file format: :[]; Partition Definition: [PartitionName][=PKey][,indx0][,ipoib_bc_flags][,defmember=full|limited] PartitionName - string, will be used with logging. When omitted, empty string will be used. PKey - P_Key value for this partition. Only low 15 bits will be used. When omitted will be autogenerated. indx0 - indicates that this pkey should be inserted in block 0 index 0. ipoib_bc_flags - used to indicate/specify IPoIB capability of this partition. defmember=full|limited|both - specifies default membership for port guid list. Default is limited. ipoib_bc_flags: ipoib_flag|[mgroup_flag]* ipoib_flag: ipoib - indicates that this partition may be used for IPoIB, as a result the IPoIB broadcast group will be created with the mgroup_flag flags given, if any. Partition Properties: [|]* | Port list: [,] Port Specifier: [=[full|limited|both]] PortGUID - GUID of partition member EndPort. Hexadecimal numbers should start from 0x, decimal numbers are accepted too. full, limited, - indicates full and/or limited membership for both this port. When omitted (or unrecognized) limited membership is assumed. Both indicates both full and limited membership for this port. MCast Group: mgid=gid[,mgroup_flag]* - gid specified is verified to be a Multicast address. IP groups are verified to match the rate and mtu of the broadcast group. The P_Key bits of the mgid for IP groups are verified to either match the P_Key specified in by "Partition Definition" or if they are 0x0000 the P_Key will be copied into those bits. mgroup_flag: rate= - specifies rate for this MC group (default is 3 (10GBps)) mtu= - specifies MTU for this MC group (default is 4 (2048)) sl= - specifies SL for this MC group (default is 0) scope= - specifies scope for this MC group (default is 2 (link local)). Multiple scope settings are permitted for a partition. NOTE: This overwrites the scope nibble of the specified mgid. Furthermore specifying multiple scope settings will result in multiple MC groups being created. Q_Key= - specifies the Q_Key for this MC group (default: 0x0b1b for IP groups, 0 for other groups) WARNING: changing this for the broadcast group may break IPoIB on client nodes!! TClass= - specifies tclass for this MC group (default is 0) FlowLabel= - specifies FlowLabel for this MC group (default is 0) Note that values for rate, mtu, and scope, for both partitions and multicast groups, should be specified as defined in the IBTA specification (for example, mtu=4 for 2048). There are several useful keywords for PortGUID definition: - 'ALL' means all end ports in this subnet. - 'ALL_CAS' means all Channel Adapter end ports in this subnet. - 'ALL_SWITCHES' means all Switch end ports in this subnet. - 'ALL_ROUTERS' means all Router end ports in this subnet. - 'SELF' means subnet manager's port. Empty list means no ports in this partition. Notes: White space is permitted between delimiters ('=', ',',':',';'). PartitionName does not need to be unique, PKey does need to be unique. If PKey is repeated then those partition configurations will be merged and first PartitionName will be used (see also next note). It is possible to split partition configuration in more than one definition, but then PKey should be explicitly specified (otherwise different PKey values will be generated for those definitions). Examples: Default=0x7fff : ALL, SELF=full ; Default=0x7fff : ALL, ALL_SWITCHES=full, SELF=full ; NewPartition , ipoib : 0x123456=full, 0x3456789034=limi, 0x2134af2306 ; YetAnotherOne = 0x300 : SELF=full ; YetAnotherOne = 0x300 : ALL=limited ; ShareIO = 0x80 , defmember=full : 0x123451, 0x123452; # 0x123453, 0x123454 will be limited ShareIO = 0x80 : 0x123453, 0x123454, 0x123455=full; # 0x123456, 0x123457 will be limited ShareIO = 0x80 : defmember=limited : 0x123456, 0x123457, 0x123458=full; ShareIO = 0x80 , defmember=full : 0x123459, 0x12345a; ShareIO = 0x80 , defmember=full : 0x12345b, 0x12345c=limited, 0x12345d; # multicast groups added to default Default=0x7fff,ipoib: mgid=ff12:401b::0707,sl=1 # random IPv4 group mgid=ff12:601b::16 # MLDv2-capable routers mgid=ff12:401b::16 # IGMP mgid=ff12:601b::2 # All routers mgid=ff12::1,sl=1,Q_Key=0xDEADBEEF,rate=3,mtu=2 # random group ALL=full; Note: The following rule is equivalent to how OpenSM used to run prior to the partition manager: Default=0x7fff,ipoib:ALL=full; .SH QOS CONFIGURATION .PP There are a set of QoS related low-level configuration parameters. All these parameter names are prefixed by "qos_" string. Here is a full list of these parameters: qos_max_vls - The maximum number of VLs that will be on the subnet qos_high_limit - The limit of High Priority component of VL Arbitration table (IBA 7.6.9) qos_vlarb_low - Low priority VL Arbitration table (IBA 7.6.9) template qos_vlarb_high - High priority VL Arbitration table (IBA 7.6.9) template Both VL arbitration templates are pairs of VL and weight qos_sl2vl - SL2VL Mapping table (IBA 7.6.6) template. It is a list of VLs corresponding to SLs 0-15 (Note that VL15 used here means drop this SL) Typical default values (hard-coded in OpenSM initialization) are: qos_max_vls 15 qos_high_limit 0 qos_vlarb_low 0:0,1:4,2:4,3:4,4:4,5:4,6:4,7:4,8:4,9:4,10:4,11:4,12:4,13:4,14:4 qos_vlarb_high 0:4,1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0 qos_sl2vl 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 The syntax is compatible with rest of OpenSM configuration options and values may be stored in OpenSM config file (cached options file). In addition to the above, we may define separate QoS configuration parameters sets for various target types. As targets, we currently support CAs, routers, switch external ports, and switch's enhanced port 0. The names of such specialized parameters are prefixed by "qos__" string. Here is a full list of the currently supported sets: qos_ca_ - QoS configuration parameters set for CAs. qos_rtr_ - parameters set for routers. qos_sw0_ - parameters set for switches' port 0. qos_swe_ - parameters set for switches' external ports. Examples: qos_sw0_max_vls=2 qos_ca_sl2vl=0,1,2,3,5,5,5,12,12,0, qos_swe_high_limit=0 .SH PREFIX ROUTES .PP Prefix routes control how the SA responds to path record queries for off-subnet DGIDs. By default, the SA fails such queries. Note that IBA does not specify how the SA should obtain off-subnet path record information. The prefix routes configuration is meant as a stop-gap until the specification is completed. .PP Each line in the configuration file is a 64-bit prefix followed by a 64-bit GUID, separated by white space. The GUID specifies the router port on the local subnet that will handle the prefix. Blank lines are ignored, as is anything between a \fB#\fP character and the end of the line. The prefix and GUID are both in hex, the leading 0x is optional. Either, or both, can be wild-carded by specifying an asterisk instead of an explicit prefix or GUID. .PP When responding to a path record query for an off-subnet DGID, opensm searches for the first prefix match in the configuration file. Therefore, the order of the lines in the configuration file is important: a wild-carded prefix at the beginning of the configuration file renders all subsequent lines useless. If there is no match, then opensm fails the query. It is legal to repeat prefixes in the configuration file, opensm will return the path to the first available matching router. A configuration file with a single line where both prefix and GUID are wild-carded means that a path record query specifying any off-subnet DGID should return a path to the first available router. This configuration yields the same behavior formerly achieved by compiling opensm with -DROUTER_EXP which has been obsoleted. .SH MKEY CONFIGURATION .PP OpenSM supports configuring a single management key (MKey) for use across the subnet. The following configuration options are available: m_key - the 64-bit MKey to be used on the subnet (IBA 14.2.4) m_key_protection_level - the numeric value of the MKey ProtectBits (IBA 14.2.4.1) m_key_lease_period - the number of seconds a CA will wait for a response from the SM before resetting the protection level to 0 (IBA 14.2.4.2). OpenSM will configure all ports with the MKey specified by m_key, defaulting to a value of 0. A m_key value of 0 disables MKey protection on the subnet. Switches and HCAs with a non-zero MKey will not accept requests to change their configuration unless the request includes the proper MKey. MKey Protection Levels MKey protection levels modify how switches and CAs respond to SMPs lacking a valid MKey. OpenSM will configure each port's ProtectBits to support the level defined by the m_key_protection_level parameter. If no parameter is specified, OpenSM defaults to operating at protection level 0. There are currently 4 protection levels defined by the IBA: 0 - Queries return valid data, including MKey. Configuration changes are not allowed unless the request contains a valid MKey. 1 - Like level 0, but the MKey is set to 0 (0x00000000) in queries, unless the request contains a valid MKey. 2 - Neither queries nor configuration changes are allowed, unless the request contains a valid MKey. 3 - Identical to 2. Maintained for backwards compatibility. MKey Lease Period InfiniBand supports a MKey lease timeout, which is intended to allow administrators or a new SM to recover/reset lost MKeys on a fabric. If MKeys are enabled on the subnet and a switch or CA receives a request that requires a valid MKey but does not contain one, it warns the SM by sending a trap (Bad M_Key, Trap 256). If the MKey lease period is non-zero, it also starts a countdown timer for the time specified by the lease period. If a SM (or other agent) responds with the correct MKey, the timer is stopped and reset. Should the timer reach zero, the switch or CA will reset its MKey protection level to 0, exposing the MKey and allowing recovery. OpenSM will initialize all ports to use a mkey lease period of the number of seconds specified in the config file. If no mkey_lease_period is specified, a default of 0 will be used. OpenSM normally quickly responds to all Bad_M_Key traps, resetting the lease timers. Additionally, OpenSM's subnet sweeps will also cancel any running timers. For maximum protection against accidentally-exposed MKeys, the MKey lease time should be a few multiples of the subnet sweep time. If OpenSM detects at startup that your sweep interval is greater than your MKey lease period, it will reset the lease period to be greater than the sweep interval. Similarly, if sweeping is disabled at startup, it will be re-enabled with an interval less than the Mkey lease period. If OpenSM is required to recover a subnet for which it is missing mkeys, it must do so one switch level at a time. As such, the total time to recover the subnet may be as long as the mkey lease period multiplied by the maximum number of hops between the SM and an endpoint, plus one. MKey Effects on Diagnostic Utilities Setting a MKey may have a detrimental effect on diagnostic software run on the subnet, unless your diagnostic software is able to retrieve MKeys from the SA or can be explicitly configured with the proper MKey. This is particularly true at protection level 2, where CAs will ignore queries for management information that do not contain the proper MKey. .SH ROUTING .PP OpenSM now offers nine routing engines: 1. Min Hop Algorithm - based on the minimum hops to each node where the path length is optimized. 2. UPDN Unicast routing algorithm - also based on the minimum hops to each node, but it is constrained to ranking rules. This algorithm should be chosen if the subnet is not a pure Fat Tree, and deadlock may occur due to a loop in the subnet. 3. DNUP Unicast routing algorithm - similar to UPDN but allows routing in fabrics which have some CA nodes attached closer to the roots than some switch nodes. 4. Fat Tree Unicast routing algorithm - this algorithm optimizes routing for congestion-free "shift" communication pattern. It should be chosen if a subnet is a symmetrical or almost symmetrical fat-tree of various types, not just K-ary-N-Trees: non-constant K, not fully staffed, any Constant Bisectional Bandwidth (CBB) ratio. Similar to UPDN, Fat Tree routing is constrained to ranking rules. 5. LASH unicast routing algorithm - uses Infiniband virtual layers (SL) to provide deadlock-free shortest-path routing while also distributing the paths between layers. LASH is an alternative deadlock-free topology-agnostic routing algorithm to the non-minimal UPDN algorithm avoiding the use of a potentially congested root node. 6. DOR Unicast routing algorithm - based on the Min Hop algorithm, but avoids port equalization except for redundant links between the same two switches. This provides deadlock free routes for hypercubes when the fabric is cabled as a hypercube and for meshes when cabled as a mesh (see details below). 7. Torus-2QoS unicast routing algorithm - a DOR-based routing algorithm specialized for 2D/3D torus topologies. Torus-2QoS provides deadlock-free routing while supporting two quality of service (QoS) levels. In addition it is able to route around multiple failed fabric links or a single failed fabric switch without introducing deadlocks, and without changing path SL values granted before the failure. 8. DFSSSP unicast routing algorithm - a deadlock-free single-source-shortest-path routing, which uses the SSSP algorithm (see algorithm 9.) as the base to optimize link utilization and uses Infiniband virtual lanes (SL) to provide deadlock-freedom. 9. SSSP unicast routing algorithm - a single-source-shortest-path routing algorithm, which globally balances the number of routes per link to optimize link utilization. This routing algorithm has no restrictions in terms of the underlying topology. OpenSM also supports a file method which can load routes from a table. See \'Modular Routing Engine\' for more information on this. The basic routing algorithm is comprised of two stages: 1. MinHop matrix calculation How many hops are required to get from each port to each LID ? The algorithm to fill these tables is different if you run standard (min hop) or Up/Down. For standard routing, a "relaxation" algorithm is used to propagate min hop from every destination LID through neighbor switches For Up/Down routing, a BFS from every target is used. The BFS tracks link direction (up or down) and avoid steps that will perform up after a down step was used. 2. Once MinHop matrices exist, each switch is visited and for each target LID a decision is made as to what port should be used to get to that LID. This step is common to standard and Up/Down routing. Each port has a counter counting the number of target LIDs going through it. When there are multiple alternative ports with same MinHop to a LID, the one with less previously assigned LIDs is selected. If LMC > 0, more checks are added: Within each group of LIDs assigned to same target port, a. use only ports which have same MinHop b. first prefer the ones that go to different systemImageGuid (then the previous LID of the same LMC group) c. if none - prefer those which go through another NodeGuid d. fall back to the number of paths method (if all go to same node). Effect of Topology Changes OpenSM will preserve existing routing in any case where there is no change in the fabric switches unless the -r (--reassign_lids) option is specified. -r .br --reassign_lids This option causes OpenSM to reassign LIDs to all end nodes. Specifying -r on a running subnet may disrupt subnet traffic. Without -r, OpenSM attempts to preserve existing LID assignments resolving multiple use of same LID. If a link is added or removed, OpenSM does not recalculate the routes that do not have to change. A route has to change if the port is no longer UP or no longer the MinHop. When routing changes are performed, the same algorithm for balancing the routes is invoked. In the case of using the file based routing, any topology changes are currently ignored The 'file' routing engine just loads the LFTs from the file specified, with no reaction to real topology. Obviously, this will not be able to recheck LIDs (by GUID) for disconnected nodes, and LFTs for non-existent switches will be skipped. Multicast is not affected by 'file' routing engine (this uses min hop tables). Min Hop Algorithm The Min Hop algorithm is invoked by default if no routing algorithm is specified. It can also be invoked by specifying '-R minhop'. The Min Hop algorithm is divided into two stages: computation of min-hop tables on every switch and LFT output port assignment. Link subscription is also equalized with the ability to override based on port GUID. The latter is supplied by: -i .br \-\-ignore_guids This option provides the means to define a set of ports (by guid) that will be ignored by the link load equalization algorithm. Note that only endports (CA, switch port 0, and router ports) and not switch external ports are supported. LMC awareness routes based on (remote) system or switch basis. Purpose of UPDN Algorithm The UPDN algorithm is designed to prevent deadlocks from occurring in loops of the subnet. A loop-deadlock is a situation in which it is no longer possible to send data between any two hosts connected through the loop. As such, the UPDN routing algorithm should be used if the subnet is not a pure Fat Tree, and one of its loops may experience a deadlock (due, for example, to high pressure). The UPDN algorithm is based on the following main stages: 1. Auto-detect root nodes - based on the CA hop length from any switch in the subnet, a statistical histogram is built for each switch (hop num vs number of occurrences). If the histogram reflects a specific column (higher than others) for a certain node, then it is marked as a root node. Since the algorithm is statistical, it may not find any root nodes. The list of the root nodes found by this auto-detect stage is used by the ranking process stage. Note 1: The user can override the node list manually. Note 2: If this stage cannot find any root nodes, and the user did not specify a guid list file, OpenSM defaults back to the Min Hop routing algorithm. 2. Ranking process - All root switch nodes (found in stage 1) are assigned a rank of 0. Using the BFS algorithm, the rest of the switch nodes in the subnet are ranked incrementally. This ranking aids in the process of enforcing rules that ensure loop-free paths. 3. Min Hop Table setting - after ranking is done, a BFS algorithm is run from each (CA or switch) node in the subnet. During the BFS process, the FDB table of each switch node traversed by BFS is updated, in reference to the starting node, based on the ranking rules and guid values. At the end of the process, the updated FDB tables ensure loop-free paths through the subnet. Note: Up/Down routing does not allow LID routing communication between switches that are located inside spine "switch systems". The reason is that there is no way to allow a LID route between them that does not break the Up/Down rule. One ramification of this is that you cannot run SM on switches other than the leaf switches of the fabric. UPDN Algorithm Usage Activation through OpenSM Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm. Use '-a ' for adding an UPDN guid file that contains the root nodes for ranking. If the `-a' option is not used, OpenSM uses its auto-detect root nodes algorithm. Notes on the guid list file: 1. A valid guid file specifies one guid in each line. Lines with an invalid format will be discarded. .br 2. The user should specify the root switch guids. However, it is also possible to specify CA guids; OpenSM will use the guid of the switch (if it exists) that connects the CA to the subnet as a root node. Purpose of DNUP Algorithm The DNUP algorithm is designed to serve a similar purpose to UPDN. However it is intended to work in network topologies which are unsuited to UPDN due to nodes being connected closer to the roots than some of the switches. An example would be a fabric which contains nodes and uplinks connected to the same switch. The operation of DNUP is the same as UPDN with the exception of the ranking process. In DNUP all switch nodes are ranked based solely on their distance from CA Nodes, all switch nodes directly connected to at least one CA are assigned a value of 1 all other switch nodes are assigned a value of one more than the minimum rank of all neighbor switch nodes. Fat-tree Routing Algorithm The fat-tree algorithm optimizes routing for "shift" communication pattern. It should be chosen if a subnet is a symmetrical or almost symmetrical fat-tree of various types. It supports not just K-ary-N-Trees, by handling for non-constant K, cases where not all leafs (CAs) are present, any CBB ratio. As in UPDN, fat-tree also prevents credit-loop-deadlocks. If the root guid file is not provided ('-a' or '--root_guid_file' options), the topology has to be pure fat-tree that complies with the following rules: - Tree rank should be between two and eight (inclusively) - Switches of the same rank should have the same number of UP-going port groups*, unless they are root switches, in which case the shouldn't have UP-going ports at all. - Switches of the same rank should have the same number of DOWN-going port groups, unless they are leaf switches. - Switches of the same rank should have the same number of ports in each UP-going port group. - Switches of the same rank should have the same number of ports in each DOWN-going port group. - All the CAs have to be at the same tree level (rank). If the root guid file is provided, the topology doesn't have to be pure fat-tree, and it should only comply with the following rules: - Tree rank should be between two and eight (inclusively) - All the Compute Nodes** have to be at the same tree level (rank). Note that non-compute node CAs are allowed here to be at different tree ranks. * ports that are connected to the same remote switch are referenced as \'port group\'. ** list of compute nodes (CNs) can be specified by \'-u\' or \'--cn_guid_file\' OpenSM options. Topologies that do not comply cause a fallback to min hop routing. Note that this can also occur on link failures which cause the topology to no longer be "pure" fat-tree. Note that although fat-tree algorithm supports trees with non-integer CBB ratio, the routing will not be as balanced as in case of integer CBB ratio. In addition to this, although the algorithm allows leaf switches to have any number of CAs, the closer the tree is to be fully populated, the more effective the "shift" communication pattern will be. In general, even if the root list is provided, the closer the topology to a pure and symmetrical fat-tree, the more optimal the routing will be. The algorithm also dumps compute node ordering file (opensm-ftree-ca-order.dump) in the same directory where the OpenSM log resides. This ordering file provides the CN order that may be used to create efficient communication pattern, that will match the routing tables. Routing between non-CN nodes The use of the cn_guid_file option allows non-CN nodes to be located on different levels in the fat tree. In such case, it is not guaranteed that the Fat Tree algorithm will route between two non-CN nodes. To solve this problem, a list of non-CN nodes can be specified by \'-G\' or \'--io_guid_file\' option. Theses nodes will be allowed to use switches the wrong way round a specific number of times (specified by \'-H\' or \'--max_reverse_hops\'. With the proper max_reverse_hops and io_guid_file values, you can ensure full connectivity in the Fat Tree. Please note that using max_reverse_hops creates routes that use the switch in a counter-stream way. This option should never be used to connect nodes with high bandwidth traffic between them ! It should only be used to allow connectivity for HA purposes or similar. Also having routes the other way around can in theory cause credit loops. Use these options with extreme care ! Activation through OpenSM Use '-R ftree' option to activate the fat-tree algorithm. Use '-a ' to provide root nodes for ranking. If the `-a' option is not used, routing algorithm will detect roots automatically. Use '-u ' to provide the list of compute nodes. If the `-u' option is not used, all the CAs are considered as compute nodes. Note: LMC > 0 is not supported by fat-tree routing. If this is specified, the default routing algorithm is invoked instead. LASH Routing Algorithm LASH is an acronym for LAyered SHortest Path Routing. It is a deterministic shortest path routing algorithm that enables topology agnostic deadlock-free routing within communication networks. When computing the routing function, LASH analyzes the network topology for the shortest-path routes between all pairs of sources / destinations and groups these paths into virtual layers in such a way as to avoid deadlock. Note LASH analyzes routes and ensures deadlock freedom between switch pairs. The link from HCA between and switch does not need virtual layers as deadlock will not arise between switch and HCA. In more detail, the algorithm works as follows: 1) LASH determines the shortest-path between all pairs of source / destination switches. Note, LASH ensures the same SL is used for all SRC/DST - DST/SRC pairs and there is no guarantee that the return path for a given DST/SRC will be the reverse of the route SRC/DST. 2) LASH then begins an SL assignment process where a route is assigned to a layer (SL) if the addition of that route does not cause deadlock within that layer. This is achieved by maintaining and analysing a channel dependency graph for each layer. Once the potential addition of a path could lead to deadlock, LASH opens a new layer and continues the process. 3) Once this stage has been completed, it is highly likely that the first layers processed will contain more paths than the latter ones. To better balance the use of layers, LASH moves paths from one layer to another so that the number of paths in each layer averages out. Note, the implementation of LASH in opensm attempts to use as few layers as possible. This number can be less than the number of actual layers available. In general LASH is a very flexible algorithm. It can, for example, reduce to Dimension Order Routing in certain topologies, it is topology agnostic and fares well in the face of faults. It has been shown that for both regular and irregular topologies, LASH outperforms Up/Down. The reason for this is that LASH distributes the traffic more evenly through a network, avoiding the bottleneck issues related to a root node and always routes shortest-path. The algorithm was developed by Simula Research Laboratory. Use '-R lash -Q ' option to activate the LASH algorithm. Note: QoS support has to be turned on in order that SL/VL mappings are used. Note: LMC > 0 is not supported by the LASH routing. If this is specified, the default routing algorithm is invoked instead. For open regular cartesian meshes the DOR algorithm is the ideal routing algorithm. For toroidal meshes on the other hand there are routing loops that can cause deadlocks. LASH can be used to route these cases. The performance of LASH can be improved by preconditioning the mesh in cases where there are multiple links connecting switches and also in cases where the switches are not cabled consistently. An option exists for LASH to do this. To invoke this use '-R lash -Q --do_mesh_analysis'. This will add an additional phase that analyses the mesh to try to determine the dimension and size of a mesh. If it determines that the mesh looks like an open or closed cartesian mesh it reorders the ports in dimension order before the rest of the LASH algorithm runs. DOR Routing Algorithm The Dimension Order Routing algorithm is based on the Min Hop algorithm and so uses shortest paths. Instead of spreading traffic out across different paths with the same shortest distance, it chooses among the available shortest paths based on an ordering of dimensions. Each port must be consistently cabled to represent a hypercube dimension or a mesh dimension. Alternatively, the -O option can be used to assign a custom mapping between the ports on a given switch, and the associated dimension. Paths are grown from a destination back to a source using the lowest dimension (port) of available paths at each step. This provides the ordering necessary to avoid deadlock. When there are multiple links between any two switches, they still represent only one dimension and traffic is balanced across them unless port equalization is turned off. In the case of hypercubes, the same port must be used throughout the fabric to represent the hypercube dimension and match on both ends of the cable, or the -O option used to accomplish the alignment. In the case of meshes, the dimension should consistently use the same pair of ports, one port on one end of the cable, and the other port on the other end, continuing along the mesh dimension, or the -O option used as an override. Use '-R dor' option to activate the DOR algorithm. DFSSSP and SSSP Routing Algorithm The (Deadlock-Free) Single-Source-Shortest-Path routing algorithm is designed to optimize link utilization thru global balancing of routes, while supporting arbitrary topologies. The DFSSSP routing algorithm uses Infiniband virtual lanes (SL) to provide deadlock-freedom. The DFSSSP algorithm consists of five major steps: .br 1) It discovers the subnet and models the subnet as a directed multigraph in which each node represents a node of the physical network and each edge represents one direction of the full-duplex links used to connect the nodes. .br 2) A loop, which iterates over all CA and switches of the subnet, will perform three steps to generate the linear forwarding tables for each switch: .br 2.1) use Dijkstra's algorithm to find the shortest path from all nodes to the current selected destination; .br 2.2) update the egde weights in the graph, i.e. add the number of routes, which use a link to reach the destination, to the link/edge; .br 2.3) update the LFT of each switch with the outgoing port which was used in the current step to route the traffic to the destination node. .br 3) After the number of available virtual lanes or layers in the subnet is detected and a channel dependency graph is initialized for each layer, the algorithm will put each possible route of the subnet into the first layer. .br 4) A loop iterates over all channel dependency graphs (CDG) and performs the following substeps: .br 4.1) search for a cycle in the current CDG; .br 4.2) when a cycle is found, i.e. a possible deadlock is present, one edge is selected and all routes, which induced this egde, are moved to the "next higher" virtual layer (CDG[i+1]); .br 4.3) the cycle search is continued until all cycles are broken and routes are moved "up". .br 5) When the number of needed layers does not exceeds the number of available SL/VL to remove all cycles in all CDGs, the rounting is deadlock-free and an relation table is generated, which contains the assignment of routes from source to destination to a SL Note on SSSP: .br This algorithm does not perform the steps 3)-5) and can not be considered to be deadlock-free for all topologies. But on the one hand, you can choose this algorithm for really large networks (5,000+ CAs and deadlock-free by design) to reduce the runtime of the algorithm. On the other hand, you might use the SSSP routing algorithm as an alternative, when all deadlock-free routing algorithms fail to route the network for whatever reason. In the last case, SSSP was designed to deliver an equal or higher bandwidth due to better congestion avoidance than the Min Hop routing algorithm. Notes for usage: .br a) running DFSSSP: '-R dfsssp -Q' .br a.1) QoS has to be configured to equally spread the load on the available SL or virtual lanes .br a.2) applications must perform a path record query to get path SL for each route, which the application will use to transmite packages .br b) running SSSP: '-R sssp' .br c) both algorithms support LMC > 0 Hints for optimizing I/O traffic: .br Having more nodes (I/O and compute) connected to a switch than incoming links can result in a 'bad' routing of the I/O traffic as long as (DF)SSSP routing is not aware of the dedicated I/O nodes, i.e., in the following network configuration CN1-CN3 might send all I/O traffic via Link2 to IO1,IO2: CN1 Link1 IO1 .br \\ /----\\ / .br CN2 -- Switch1 Switch2 -- CN4 .br / \\----/ \\ .br CN3 Link2 IO2 To prevent this from happening (DF)SSSP can use both the compute node guid file and the I/O guid file specified by the \'-u\' or \'--cn_guid_file\' and \'-G\' or \'--io_guid_file\' options (similar to the Fat-Tree routing). This ensures that traffic towards compute nodes and I/O nodes is balanced separately and therefore distributed as much as possible across the available links. Port GUIDs, as listed by ibstat, must be specified (not Node GUIDs). .br The priority for the optimization is as follows: .br compute nodes -> I/O nodes -> other nodes .br Possible use case szenarios: .br a) neither \'-u\' nor \'-G\' are specified: all nodes a treated as \'other nodes\' and therefore balanced equally; .br b) \'-G\' is specified: traffic towards I/O nodes will be balanced optimally; .br c) the system has three node types, such as login/admin, compute and I/O, but the balancing focus should be I/O, then one has to use \'-u\' and \'-G\' with I/O guids listed in cn_guid_file and compute node guids listed in io_guid_file; .br d) ... Torus-2QoS Routing Algorithm Torus-2QoS is routing algorithm designed for large-scale 2D/3D torus fabrics; see torus-2QoS(8) for full documentation. Use '-R torus-2QoS -Q' or '-R torus-2QoS,no_fallback -Q' to activate the torus-2QoS algorithm. Routing References To learn more about deadlock-free routing, see the article "Deadlock Free Message Routing in Multiprocessor Interconnection Networks" by William J Dally and Charles L Seitz (1985). To learn more about the up/down algorithm, see the article "Effective Strategy to Compute Forwarding Tables for InfiniBand Networks" by Jose Carlos Sancho, Antonio Robles, and Jose Duato at the Universidad Politecnica de Valencia. To learn more about LASH and the flexibility behind it, the requirement for layers, performance comparisons to other algorithms, see the following articles: "Layered Routing in Irregular Networks", Lysne et al, IEEE Transactions on Parallel and Distributed Systems, VOL.16, No12, December 2005. "Routing for the ASI Fabric Manager", Solheim et al. IEEE Communications Magazine, Vol.44, No.7, July 2006. "Layered Shortest Path (LASH) Routing in Irregular System Area Networks", Skeie et al. IEEE Computer Society Communication Architecture for Clusters 2002. To learn more about the DFSSSP and SSSP routing algorithm, see the articles: .br J. Domke, T. Hoefler and W. Nagel: Deadlock-Free Oblivious Routing for Arbitrary Topologies, In Proceedings of the 25th IEEE International Parallel & Distributed Processing Symposium (IPDPS 2011) .br T. Hoefler, T. Schneider and A. Lumsdaine: Optimized Routing for Large-Scale InfiniBand Networks, In 17th Annual IEEE Symposium on High Performance Interconnects (HOTI 2009) Modular Routine Engine Modular routing engine structure allows for the ease of "plugging" new routing modules. Currently, only unicast callbacks are supported. Multicast can be added later. One existing routing module is up-down "updn", which may be activated with '-R updn' option (instead of old '-u'). General usage is: $ opensm -R 'module-name' There is also a trivial routing module which is able to load LFT tables from a file. Main features: - this will load switch LFTs and/or LID matrices (min hops tables) - this will load switch LFTs according to the path entries introduced in the file - no additional checks will be performed (such as "is port connected", etc.) - in case when fabric LIDs were changed this will try to reconstruct LFTs correctly if endport GUIDs are represented in the file (in order to disable this, GUIDs may be removed from the file or zeroed) The file format is compatible with output of 'ibroute' util and for whole fabric can be generated with dump_lfts.sh script. To activate file based routing module, use: opensm -R file -U /path/to/lfts_file If the lfts_file is not found or is in error, the default routing algorithm is utilized. The ability to dump switch lid matrices (aka min hops tables) to file and later to load these is also supported. The usage is similar to unicast forwarding tables loading from a lfts file (introduced by 'file' routing engine), but new lid matrix file name should be specified by -M or --lid_matrix_file option. For example: opensm -R file -M ./opensm-lid-matrix.dump The dump file is named \'opensm-lid-matrix.dump\' and will be generated in standard opensm dump directory (/var/log by default) when OSM_LOG_ROUTING logging flag is set. When routing engine 'file' is activated, but the lfts file is not specified or not cannot be open default lid matrix algorithm will be used. There is also a switch forwarding tables dumper which generates a file compatible with dump_lfts.sh output. This file can be used as input for forwarding tables loading by 'file' routing engine. Both or one of options -U and -M can be specified together with \'-R file\'. .SH PER MODULE LOGGING CONFIGURATION .PP To enable per module logging, configure per_module_logging_file to the per module logging config file name in the opensm options file. To disable, configure per_module_logging_file to (null) there. The per module logging config file format is a set of lines with module name and logging level as follows: is the file name including .c is either = , space, or tab is the same levels as used in the coarse/overall logging as follows: BIT LOG LEVEL ENABLED ---- ----------------- 0x01 - ERROR (error messages) 0x02 - INFO (basic messages, low volume) 0x04 - VERBOSE (interesting stuff, moderate volume) 0x08 - DEBUG (diagnostic, high volume) 0x10 - FUNCS (function entry/exit, very high volume) 0x20 - FRAMES (dumps all SMP and GMP frames) 0x40 - ROUTING (dump FDB routing information) 0x80 - SYS (syslog at LOG_INFO level in addition to OpenSM logging) .SH FILES .TP .B /usr/local/etc/opensm/opensm.conf default OpenSM config file. .TP .B /usr/local/etc/opensm/ib-node-name-map default node name map file. See ibnetdiscover for more information on format. .TP .B /usr/local/etc/opensm/partitions.conf default partition config file .TP .B /usr/local/etc/opensm/qos-policy.conf default QOS policy config file .TP .B /usr/local/etc/opensm/prefix-routes.conf default prefix routes file .TP .B /usr/local/etc/opensm/per-module-logging.conf default per module logging config file .TP .B /usr/local/etc/opensm/torus-2QoS.conf default torus-2QoS config file .SH AUTHORS .TP Hal Rosenstock .RI < hal@mellanox.com > .TP Sasha Khapyorsky .RI < sashak@voltaire.com > .TP Eitan Zahavi .RI < eitan@mellanox.co.il > .TP Yevgeny Kliteynik .RI < kliteyn@mellanox.co.il > .TP Thomas Sodring .RI < tsodring@simula.no > .TP Ira Weiny .RI < weiny2@llnl.gov > .TP Dale Purdy .RI < purdy@sgi.com > .SH SEE ALSO torus-2QoS(8), torus-2QoS.conf(5). opensm-3.3.20/man/osmtest.80000644000205000001450000001407712502265712012365 00000000000000.TH OSMTEST 8 "March 9, 2013" "OpenIB" "OpenIB Management" .SH NAME osmtest \- InfiniBand subnet manager and administration (SM/SA) test program .SH SYNOPSIS .B osmtest [\-f(low) ] [\-w(ait) ] [\-d(ebug) ] [\-m(ax_lid) ] [\-g(uid)[=]] [-p(ort)] [\-i(nventory) ] [\-s(tress)] [\-M(ulticast_Mode)] [\-t(imeout) ] [\-l | \-\-log_file] [\-v] [\-vf ] [\-h(elp)] .SH DESCRIPTION .PP osmtest is a test program to validate InfiniBand subnet manager and administration (SM/SA). Default is to run all flows with the exception of the QoS flow. osmtest provides a test suite for opensm. osmtest has the following capabilities and testing flows: It creates an inventory file of all available Nodes, Ports, and PathRecords, including all their fields. It verifies the existing inventory, with all the object fields, and matches it to a pre-saved one. A Multicast Compliancy test. An Event Forwarding test. A Service Record registration test. An RMPP stress test. A Small SA Queries stress test. It is recommended that after installing opensm, the user should run "osmtest -f c" to generate the inventory file, and immediately afterwards run "osmtest -f a" to test OpenSM. Another recommendation for osmtest usage is to create the inventory when the IB fabric is stable, and occasionally run "osmtest -v" to verify that nothing has changed. .SH OPTIONS .PP .TP \fB\-f\fR, \fB\-\-flow\fR This option directs osmtest to run a specific flow: FLOW DESCRIPTION c = create an inventory file with all nodes, ports and paths a = run all validation tests (expecting an input inventory) v = only validate the given inventory file s = run service registration, deregistration, and lease test e = run event forwarding test f = flood the SA with queries according to the stress mode m = multicast flow q = QoS info: dump VLArb and SLtoVL tables t = run trap 64/65 flow (this flow requires running of external tool) (default is all flows except QoS) .TP \fB\-w\fR, \fB\-\-wait\fR This option specifies the wait time for trap 64/65 in seconds It is used only when running -f t - the trap 64/65 flow (default to 10 sec) .TP \fB\-d\fR, \fB\-\-debug\fR This option specifies a debug option. These options are not normally needed. The number following -d selects the debug option to enable as follows: OPT Description --- ----------------- -d0 - Ignore other SM nodes -d1 - Force single threaded dispatching -d2 - Force log flushing after each log message -d3 - Disable multicast support -d4 - Use full world path record queries .TP \fB\-m\fR, \fB\-\-max_lid\fR This option specifies the maximal LID number to be searched for during inventory file build (default to 100) .TP \fB\-g\fR, \fB\-\-guid\fR This option specifies the local port GUID value with which OpenSM should bind. OpenSM may be bound to 1 port at a time. If GUID given is 0, OpenSM displays a list of possible port GUIDs and waits for user input. Without -g, OpenSM trys to use the default port. .TP \fB\-p\fR, \fB\-\-port\fR This option displays a menu of possible local port GUID values with which osmtest could bind .TP \fB\-i\fR, \fB\-\-inventory\fR This option specifies the name of the inventory file. Normally, osmtest expects to find an inventory file, which osmtest uses to validate real-time information received from the SA during testing If -i is not specified, osmtest defaults to the file \'osmtest.dat\' See -f c option for related information .TP \fB\-s\fR, \fB\-\-stress\fR This option runs the specified stress test instead of the normal test suite Stress test options are as follows: OPT Description --- ----------------- -s1 - Single-MAD (RMPP) response SA queries -s2 - Multi-MAD (RMPP) response SA queries -s3 - Multi-MAD (RMPP) Path Record SA queries -s4 - Single-MAD (non RMPP) get Path Record SA queries Without -s, stress testing is not performed .TP \fB\-M\fR, \fB\-\-Multicast_Mode\fR This option specify length of Multicast test: OPT Description --- ----------------- -M1 - Short Multicast Flow (default) - single mode -M2 - Short Multicast Flow - multiple mode -M3 - Long Multicast Flow - single mode -M4 - Long Multicast Flow - multiple mode Single mode - Osmtest is tested alone, with no other apps that interact with OpenSM MC Multiple mode - Could be run with other apps using MC with OpenSM. Without -M, default flow testing is performed .TP \fB\-t\fR, \fB\-\-timeout\fR This option specifies the time in milliseconds used for transaction timeouts. Specifying -t 0 disables timeouts. Without -t, OpenSM defaults to a timeout value of 200 milliseconds. .TP \fB\-l\fR, \fB\-\-log_file\fR This option defines the log to be the given file. By default the log goes to stdout. .TP \fB\-v\fR, \fB\-\-verbose\fR This option increases the log verbosity level. The -v option may be specified multiple times to further increase the verbosity level. See the -vf option for more information about. log verbosity. .TP \fB\-V\fR This option sets the maximum verbosity level and forces log flushing. The -V is equivalent to '-vf 0xFF -d 2'. See the -vf option for more information about. log verbosity. .TP \fB\-vf\fR This option sets the log verbosity level. A flags field must follow the -D option. A bit set/clear in the flags enables/disables a specific log level as follows: BIT LOG LEVEL ENABLED ---- ----------------- 0x01 - ERROR (error messages) 0x02 - INFO (basic messages, low volume) 0x04 - VERBOSE (interesting stuff, moderate volume) 0x08 - DEBUG (diagnostic, high volume) 0x10 - FUNCS (function entry/exit, very high volume) 0x20 - FRAMES (dumps all SMP and GMP frames) 0x40 - ROUTING (dump FDB routing information) 0x80 - currently unused. Without -vf, osmtest defaults to ERROR + INFO (0x3) Specifying -vf 0 disables all messages Specifying -vf 0xFF enables all messages (see -V) High verbosity levels may require increasing the transaction timeout with the -t option .TP \fB\-h\fR, \fB\-\-help\fR Display this usage info then exit. .SH AUTHORS .TP Hal Rosenstock .RI < hal.rosenstock@gmail.com > .TP Eitan Zahavi .RI < eitan@mellanox.co.il > opensm-3.3.20/man/torus-2QoS.80000644000205000001450000004574712726323447012645 00000000000000.TH TORUS\-2QOS 8 "November 10, 2010" "OpenIB" "OpenIB Management" . .SH NAME torus\-2QoS \- Routing engine for OpenSM subnet manager . .SH DESCRIPTION . Torus-2QoS is routing algorithm designed for large-scale 2D/3D torus fabrics. The torus-2QoS routing engine can provide the following functionality on a 2D/3D torus: .br \" roff illiteracy leads to following brain-dead list implementation \" .na \" otherwise line space adjustment can add spaces between dash and text .in +2m \[en] 'in +2m Routing that is free of credit loops. .in \[en] 'in +2m Two levels of Quality of Service (QoS), assuming switches support eight data VLs and channel adapters support two data VLs. .in \[en] 'in +2m The ability to route around a single failed switch, and/or multiple failed links, without .in .in +2m \[en] 'in +2 introducing credit loops, or .in \[en] 'in +2m changing path SL values. .in -4m \[en] 'in +2m Very short run times, with good scaling properties as fabric size increases. .ad . .SH UNICAST ROUTING . Unicast routing in torus-2QoS is based on Dimension Order Routing (DOR). It avoids the deadlocks that would otherwise occur in a DOR-routed torus using the concept of a dateline for each torus dimension. It encodes into a path SL which datelines the path crosses, as follows: \f(CR .P .nf sl = 0; for (d = 0; d < torus_dimensions; d++) { /* path_crosses_dateline(d) returns 0 or 1 */ sl |= path_crosses_dateline(d) << d; } .fi \fR .P On a 3D torus this consumes three SL bits, leaving one SL bit unused. Torus-2QoS uses this SL bit to implement two QoS levels. .P Torus-2QoS also makes use of the output port dependence of switch SL2VL maps to encode into one VL bit the information encoded in three SL bits. It computes in which torus coordinate direction each inter-switch link "points", and writes SL2VL maps for such ports as follows: \f(CR .P .nf for (sl = 0; sl < 16; sl++) { /* cdir(port) computes which torus coordinate direction * a switch port "points" in; returns 0, 1, or 2 */ sl2vl(iport,oport,sl) = 0x1 & (sl >> cdir(oport)); } .fi \fR .P Thus, on a pristine 3D torus, \fIi.e.\fR, in the absence of failed fabric switches, torus-2QoS consumes eight SL values (SL bits 0-2) and two VL values (VL bit 0) per QoS level to provide deadlock-free routing. .P Torus-2QoS routes around link failure by "taking the long way around" any 1D ring interrupted by link failure. For example, consider the 2D 6x5 torus below, where switches are denoted by [+a-zA-Z]: . . \# define macros to start and end ascii art, assuming Roman font. \# the start macro takes an argument which is the width in ems of \# the ascii art, and is used to center it. \# .de ascii_art .nop \f(CR .nr indent_in_ems ((((\\n[.ll] - \\n[.i]) / \\w'm') - \\$1)/2) .in +\\n[indent_in_ems]m .nf .. .de end_ascii_art .fi .in .nop \fR .. \# end of macro definitions . . .ascii_art 36 | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----D----+----+-- | | | | | | 2 --+----+----I----r----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P For a pristine fabric the path from S to D would be S-n-T-r-D. In the event that either link S-n or n-T has failed, torus-2QoS would use the path S-m-p-o-T-r-D. Note that it can do this without changing the path SL value; once the 1D ring m-S-n-T-o-p-m has been broken by failure, path segments using it cannot contribute to deadlock, and the x-direction dateline (between, say, x=5 and x=0) can be ignored for path segments on that ring. .P One result of this is that torus-2QoS can route around many simultaneous link failures, as long as no 1D ring is broken into disjoint segments. For example, if links n-T and T-o have both failed, that ring has been broken into two disjoint segments, T and o-p-m-S-n. Torus-2QoS checks for such issues, reports if they are found, and refuses to route such fabrics. .P Note that in the case where there are multiple parallel links between a pair of switches, torus-2QoS will allocate routes across such links in a round-robin fashion, based on ports at the path destination switch that are active and not used for inter-switch links. Should a link that is one of several such parallel links fail, routes are redistributed across the remaining links. When the last of such a set of parallel links fails, traffic is rerouted as described above. .P Handling a failed switch under DOR requires introducing into a path at least one turn that would be otherwise "illegal", \fIi.e.\fR, not allowed by DOR rules. Torus-2QoS will introduce such a turn as close as possible to the failed switch in order to route around it. .P In the above example, suppose switch T has failed, and consider the path from S to D. Torus-2QoS will produce the path S-n-I-r-D, rather than the S-n-T-r-D path for a pristine torus, by introducing an early turn at n. Normal DOR rules will cause traffic arriving at switch I to be forwarded to switch r; for traffic arriving from I due to the "early" turn at n, this will generate an "illegal" turn at I. .P Torus-2QoS will also use the input port dependence of SL2VL maps to set VL bit 1 (which would be otherwise unused) for y-x, z-x, and z-y turns, \fIi.e.\fR, those turns that are illegal under DOR. This causes the first hop after any such turn to use a separate set of VL values, and prevents deadlock in the presence of a single failed switch. .P For any given path, only the hops after a turn that is illegal under DOR can contribute to a credit loop that leads to deadlock. So in the example above with failed switch T, the location of the illegal turn at I in the path from S to D requires that any credit loop caused by that turn must encircle the failed switch at T. Thus the second and later hops after the illegal turn at I (\fIi.e.\fR, hop r-D) cannot contribute to a credit loop because they cannot be used to construct a loop encircling T. The hop I-r uses a separate VL, so it cannot contribute to a credit loop encircling T. .P Extending this argument shows that in addition to being capable of routing around a single switch failure without introducing deadlock, torus-2QoS can also route around multiple failed switches on the condition they are adjacent in the last dimension routed by DOR. For example, consider the following case on a 6x6 2D torus: . .ascii_art 36 | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----D----+----+-- | | | | | | 3 --+----+----I----u----+----+-- | | | | | | 2 --+----+----q----R----+----+-- | | | | | | 1 --m----S----n----T----o----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P Suppose switches T and R have failed, and consider the path from S to D. Torus-2QoS will generate the path S-n-q-I-u-D, with an illegal turn at switch I, and with hop I-u using a VL with bit 1 set. .P As a further example, consider a case that torus-2QoS cannot route without deadlock: two failed switches adjacent in a dimension that is not the last dimension routed by DOR; here the failed switches are O and T: . .ascii_art 36 | | | | | | 5 --+----+----+----+----+----+-- | | | | | | 4 --+----+----+----+----+----+-- | | | | | | 3 --+----+----+----+----D----+-- | | | | | | 2 --+----+----I----q----r----+-- | | | | | | 1 --m----S----n----O----T----p-- | | | | | | y=0 --+----+----+----+----+----+-- | | | | | | x=0 1 2 3 4 5 .end_ascii_art .P In a pristine fabric, torus-2QoS would generate the path from S to D as S-n-O-T-r-D. With failed switches O and T, torus-2QoS will generate the path S-n-I-q-r-D, with illegal turn at switch I, and with hop I-q using a VL with bit 1 set. In contrast to the earlier examples, the second hop after the illegal turn, q-r, can be used to construct a credit loop encircling the failed switches. . .SH MULTICAST ROUTING . Since torus-2QoS uses all four available SL bits, and the three data VL bits that are typically available in current switches, there is no way to use SL/VL values to separate multicast traffic from unicast traffic. Thus, torus-2QoS must generate multicast routing such that credit loops cannot arise from a combination of multicast and unicast path segments. .P It turns out that it is possible to construct spanning trees for multicast routing that have that property. For the 2D 6x5 torus example above, here is the full-fabric spanning tree that torus-2QoS will construct, where "x" is the root switch and each "+" is a non-root switch: . .ascii_art 36 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 +----+----+----x----+----+ | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 .end_ascii_art .P For multicast traffic routed from root to tip, every turn in the above spanning tree is a legal DOR turn. .P For traffic routed from tip to root, and some traffic routed through the root, turns are not legal DOR turns. However, to construct a credit loop, the union of multicast routing on this spanning tree with DOR unicast routing can only provide 3 of the 4 turns needed for the loop. .P In addition, if none of the above spanning tree branches crosses a dateline used for unicast credit loop avoidance on a torus, and if multicast traffic is confined to SL 0 or SL 8 (recall that torus-2QoS uses SL bit 3 to differentiate QoS level), then multicast traffic also cannot contribute to the "ring" credit loops that are otherwise possible in a torus. .P Torus-2QoS uses these ideas to create a master spanning tree. Every multicast group spanning tree will be constructed as a subset of the master tree, with the same root as the master tree. .P Such multicast group spanning trees will in general not be optimal for groups which are a subset of the full fabric. However, this compromise must be made to enable support for two QoS levels on a torus while preventing credit loops. .P In the presence of link or switch failures that result in a fabric for which torus-2QoS can generate credit-loop-free unicast routes, it is also possible to generate a master spanning tree for multicast that retains the required properties. For example, consider that same 2D 6x5 torus, with the link from (2,2) to (3,2) failed. Torus-2QoS will generate the following master spanning tree: . .ascii_art 36 4 + + + + + + | | | | | | 3 + + + + + + | | | | | | 2 --+----+----+ x----+----+-- | | | | | | 1 + + + + + + | | | | | | y=0 + + + + + + x=0 1 2 3 4 5 .end_ascii_art .P Two things are notable about this master spanning tree. First, assuming the x dateline was between x=5 and x=0, this spanning tree has a branch that crosses the dateline. However, just as for unicast, crossing a dateline on a 1D ring (here, the ring for y=2) that is broken by a failure cannot contribute to a torus credit loop. .P Second, this spanning tree is no longer optimal even for multicast groups that encompass the entire fabric. That, unfortunately, is a compromise that must be made to retain the other desirable properties of torus-2QoS routing. .P In the event that a single switch fails, torus-2QoS will generate a master spanning tree that has no "extra" turns by appropriately selecting a root switch. In the 2D 6x5 torus example, assume now that the switch at (3,2), \fIi.e.\fR, the root for a pristine fabric, fails. Torus-2QoS will generate the following master spanning tree for that case: . .ascii_art 36 | 4 + + + + + + | | | | | | 3 + + + + + + | | | | | 2 + + + + + | | | | | 1 +----+----x----+----+----+ | | | | | | y=0 + + + + + + | x=0 1 2 3 4 5 .end_ascii_art .P Assuming the y dateline was between y=4 and y=0, this spanning tree has a branch that crosses a dateline. However, again this cannot contribute to credit loops as it occurs on a 1D ring (the ring for x=3) that is broken by a failure, as in the above example. . .SH TORUS TOPOLOGY DISCOVERY . The algorithm used by torus-2QoS to construct the torus topology from the undirected graph representing the fabric requires that the radix of each dimension be configured via torus-2QoS.conf. It also requires that the torus topology be "seeded"; for a 3D torus this requires configuring four switches that define the three coordinate directions of the torus. .P Given this starting information, the algorithm is to examine the cube formed by the eight switch locations bounded by the corners (x,y,z) and (x+1,y+1,z+1). Based on switches already placed into the torus topology at some of these locations, the algorithm examines 4-loops of inter-switch links to find the one that is consistent with a face of the cube of switch locations, and adds its swiches to the discovered topology in the correct locations. .P Because the algorithm is based on examining the topology of 4-loops of links, a torus with one or more radix-4 dimensions requires extra initial seed configuration. See torus-2QoS.conf(5) for details. Torus-2QoS will detect and report when it has insufficient configuration for a torus with radix-4 dimensions. .P In the event the torus is significantly degraded, \fIi.e.\fR, there are many missing switches or links, it may happen that torus-2QoS is unable to place into the torus some switches and/or links that were discovered in the fabric, and will generate a warning in that case. A similar condition occurs if torus-2QoS is misconfigured, \fIi.e.\fR, the radix of a torus dimension as configured does not match the radix of that torus dimension as wired, and many switches/links in the fabric will not be placed into the torus. . .SH QUALITY OF SERVICE CONFIGURATION . OpenSM will not program switchs and channel adapters with SL2VL maps or VL arbitration configuration unless it is invoked with -Q. Since torus-2QoS depends on such functionality for correct operation, always invoke OpenSM with -Q when torus-2QoS is in the list of routing engines. .P Any quality of service configuration method supported by OpenSM will work with torus-2QoS, subject to the following limitations and considerations. .P For all routing engines supported by OpenSM except torus-2QoS, there is a one-to-one correspondence between QoS level and SL. Torus-2QoS can only support two quality of service levels, so only the high-order bit of any SL value used for unicast QoS configuration will be honored by torus-2QoS. .P For multicast QoS configuration, only SL values 0 and 8 should be used with torus-2QoS. .P Since SL to VL map configuration must be under the complete control of torus-2QoS, any configuration via qos_sl2vl, qos_swe_sl2vl, \fIetc.\fR, must and will be ignored, and a warning will be generated. .P For inter-switch links, Torus-2QoS uses VL values 0-3 to implement one of its supported QoS levels, and VL values 4-7 to implement the other. For endport links (CA, router, switch management port), Torus-2QoS uses VL value 0 for one of its supported QoS levels and VL value 1 to implement the other. Hard-to-diagnose application issues may arise if traffic is not delivered fairly across each of these two VL ranges. For inter-switch links, Torus-2QoS will detect and warn if VL arbitration is configured unfairly across VLs in the range 0-3, and also in the range 4-7. Note that the default OpenSM VL arbitration configuration does not meet this constraint, so all torus-2QoS users should configure VL arbitration via qos_ca_vlarb_high, qos_swe_vlarb_high, qos_ca_vlarb_low, qos_swe_vlarb_low, \fIetc.\fR .P Note that torus-2QoS maps SL values to VL values differently for inter-switch and endport links. This is why qos_vlarb_high and qos_vlarb_low should not be used, as using them may result in VL arbitration for a QoS level being different across inter-switch links vs. across endport links. . .SH OPERATIONAL CONSIDERATIONS . Any routing algorithm for a torus IB fabric must employ path SL values to avoid credit loops. As a result, all applications run over such fabrics must perform a path record query to obtain the correct path SL for connection setup. Applications that use \fBrdma_cm\fR for connection setup will automatically meet this requirement. .P If a change in fabric topology causes changes in path SL values required to route without credit loops, in general all applications would need to repath to avoid message deadlock. Since torus-2QoS has the ability to reroute after a single switch failure without changing path SL values, repathing by running applications is not required when the fabric is routed with torus-2QoS. .P Torus-2QoS can provide unchanging path SL values in the presence of subnet manager failover provided that all OpenSM instances have the same idea of dateline location. See torus-2QoS.conf(5) for details. .P Torus-2QoS will detect configurations of failed switches and links that prevent routing that is free of credit loops, and will log warnings and refuse to route. If "no_fallback" was configured in the list of OpenSM routing engines, then no other routing engine will attempt to route the fabric. In that case all paths that do not transit the failed components will continue to work, and the subset of paths that are still operational will continue to remain free of credit loops. OpenSM will continue to attempt to route the fabric after every sweep interval, and after any change (such as a link up) in the fabric topology. When the fabric components are repaired, full functionality will be restored. .P In the event OpenSM was configured to allow some other engine to route the fabric if torus-2QoS fails, then credit loops and message deadlock are likely if torus-2QoS had previously routed the fabric successfully. Even if the other engine is capable of routing a torus without credit loops, applications that built connections with path SL values granted under torus-2QoS will likely experience message deadlock under routing generated by a different engine, unless they repath. .P To verify that a torus fabric is routed free of credit loops, use \fBibdmchk\fR to analyze data collected via \fBibdiagnet -vlr\fR. . .SH FILES .TP .B /usr/local/etc/opensm/opensm.conf default OpenSM config file. .TP .B /usr/local/etc/opensm/qos-policy.conf default QoS policy config file. .TP .B /usr/local/etc/opensm/torus-2QoS.conf default torus-2QoS config file. . .SH SEE ALSO . opensm(8), torus-2QoS.conf(5), ibdiagnet(1), ibdmchk(1), rdma_cm(7). opensm-3.3.20/man/torus-2QoS.conf.50000644000205000001450000001524112726323447013550 00000000000000.TH TORUS\-2QOS.CONF 5 "January 4, 2013" "OpenIB" "OpenIB Management" . .SH NAME torus\-2QoS.conf \- Torus-2QoS configuration for OpenSM subnet manager . .SH DESCRIPTION . The file .B torus-2QoS.conf contains configuration information that is specific to the OpenSM routing engine torus-2QoS. Blank lines and lines where the first non-whitespace character is "#" are ignored. A token is any contiguous group of non-whitespace characters. Any tokens on a line following the recognized configuration tokens described below are ignored. . .P \fR[\fBtorus\fR|\fBmesh\fR] \fIx_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] \fIy_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] \fIz_radix\fR[\fBm\fR|\fBM\fR|\fBt\fR|\fBT\fR] .RS Either \fBtorus\fR or \fBmesh\fR must be the first keyword in the configuration, and sets the topology that torus-2QoS will try to construct. A 2D topology can be configured by specifying one of \fIx_radix\fR, \fIy_radix\fR, or \fIz_radix\fR as 1. An individual dimension can be configured as mesh (open) or torus (looped) by suffixing its radix specification with one of \fBm\fR, \fBM\fR, \fBt\fR, or \fBT\fR. Thus, "mesh 3T 4 5" and "torus 3 4M 5M" both specify the same topology. .P Note that although torus-2QoS can route mesh fabrics, its ability to route around failed components is severely compromised on such fabrics. A failed fabric component is very likely to cause a disjoint ring; see \fBUNICAST ROUTING\fR in torus-2QoS(8). .RE . .P \fBxp_link \fIsw0_GUID sw1_GUID .br .ns \fByp_link \fIsw0_GUID sw1_GUID .br .ns \fBzp_link \fIsw0_GUID sw1_GUID .br .ns \fBxm_link \fIsw0_GUID sw1_GUID .br .ns \fBym_link \fIsw0_GUID sw1_GUID .br .ns \fBzm_link \fIsw0_GUID sw1_GUID \fR .RS These keywords are used to seed the torus/mesh topology. For example, "xp_link 0x2000 0x2001" specifies that a link from the switch with node GUID 0x2000 to the switch with node GUID 0x2001 would point in the positive x direction, while "xm_link 0x2000 0x2001" specifies that a link from the switch with node GUID 0x2000 to the switch with node GUID 0x2001 would point in the negative x direction. All the link keywords for a given seed must specify the same "from" switch. .P In general, it is not necessary to configure both the positive and negative directions for a given coordinate; either is sufficient. However, the algorithm used for topology discovery needs extra information for torus dimensions of radix four (see \fBTOPOLOGY DISCOVERY\fR in torus-2QoS(8)). For such cases both the positive and negative coordinate directions must be specified. .P Based on the topology specified via the \fBtorus\fR/\fBmesh\fR keyword, torus-2QoS will detect and log when it has insufficient seed configuration. .RE . .P \fBx_dateline \fIposition .br .ns \fBy_dateline \fIposition .br .ns \fBz_dateline \fIposition \fR .RS In order for torus-2QoS to provide the guarantee that path SL values do not change under any conditions for which it can still route the fabric, its idea of dateline position must not change relative to physical switch locations. The dateline keywords provide the means to configure such behavior. .P The dateline for a torus dimension is always between the switch with coordinate 0 and the switch with coordinate radix-1 for that dimension. By default, the common switch in a torus seed is taken as the origin of the coordinate system used to describe switch location. The \fIposition\fR parameter for a dateline keyword moves the origin (and hence the dateline) the specified amount relative to the common switch in a torus seed. .RE . .P \fBnext_seed \fR .RS If any of the switches used to specify a seed were to fail torus-2QoS would be unable to complete topology discovery successfully. The \fBnext_seed\fR keyword specifies that the following link and dateline keywords apply to a new seed specification. .P For maximum resiliency, no seed specification should share a switch with any other seed specification. Multiple seed specifications should use dateline configuration to ensure that torus-2QoS can grant path SL values that are constant, regardless of which seed was used to initiate topology discovery. .RE . .P \fBportgroup_max_ports \fImax_ports \fR .RS This keyword specifies the maximum number of parallel inter-switch links, and also the maximum number of host ports per switch, that torus-2QoS can accommodate. The default value is 16. Torus-2QoS will log an error message during topology discovery if this parameter needs to be increased. If this keyword appears multiple times, the last instance prevails. .P Note that the switch management port (switch port 0) gets put into the same port group with the host ports, so if you have 16 host ports per switch, portgroup_max_ports would need to be at least 17. .RE . .P \fBport_order \fIp1 p2 p3 ... \fR .RS This keyword specifies the order in which CA ports on a destination switch are visited when computing routes. When the fabric contains switches connected with multiple parallel links, routes are distributed in a round-robin fashion across such links, and so changing the order that CA ports are visited changes the distribution of routes across such links. This may be advantageous for some specific traffic patterns. .P The default is to visit CA ports in increasing port order on destination switches. .P Duplicate values in the list will be ignored. .RE . .P \fBmax_changes \fImax \fR .RS This keyword specifies the maximum number of torus changes reported. The default value is 32. .RE . .SH EXAMPLE . \f(RC .nf # Look for a 2D (since x radix is one) 4x5 torus. torus 1 4 5 # y is radix-4 torus dimension, need both # ym_link and yp_link configuration. yp_link 0x200000 0x200005 # sw @ y=0,z=0 -> sw @ y=1,z=0 ym_link 0x200000 0x20000f # sw @ y=0,z=0 -> sw @ y=3,z=0 # z is not radix-4 torus dimension, only need one of # zm_link or zp_link configuration. zp_link 0x200000 0x200001 # sw @ y=0,z=0 -> sw @ y=0,z=1 next_seed yp_link 0x20000b 0x200010 # sw @ y=2,z=1 -> sw @ y=3,z=1 ym_link 0x20000b 0x200006 # sw @ y=2,z=1 -> sw @ y=1,z=1 zp_link 0x20000b 0x20000c # sw @ y=2,z=1 -> sw @ y=2,z=2 y_dateline -2 # Move the dateline for this seed z_dateline -1 # back to its original position. # If OpenSM failover is configured, for maximum resiliency # one instance should run on a host attached to a switch # from the first seed, and another instance should run # on a host attached to a switch from the second seed. # Both instances should use this torus-2QoS.conf to ensure # path SL values do not change in the event of SM failover. # port_order defines the order on which the ports would be # chosen for routing. port_order 7 10 8 11 9 12 25 28 26 29 27 30 .fi \fR . .SH FILES .TP .B /usr/local/etc/opensm/torus-2QoS.conf Default torus-2QoS config file. . .SH SEE ALSO . opensm(8), torus-2QoS(8). opensm-3.3.20/scripts/0000755000205000001450000000000012726324754011573 500000000000000opensm-3.3.20/scripts/opensm.init.in0000644000205000001450000000643512357040123014277 00000000000000#!/bin/bash # # opensm: Manage OpenSM # # chkconfig: - 09 91 # description: Manage OpenSM # ### BEGIN INIT INFO # Provides: opensm # Required-Start: $syslog @RDMA_SERVICE@ # Required-Stop: $syslog @RDMA_SERVICE@ # Default-Start: @DEFAULT_START@ # Default-Stop: @DEFAULT_STOP@ # Description: Manage OpenSM ### END INIT INFO # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # Copyright 2006 PathScale, Inc. 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. prefix=@prefix@ exec_prefix=@exec_prefix@ pidfile=/var/run/opensm.pid # Source function library. if [[ -s /etc/init.d/functions ]]; then # RHEL / CentOS / SL / Fedora. . /etc/init.d/functions rc_status() { :; } rc_exit() { exit $RETVAL; } elif [[ -s /lib/lsb/init-functions ]]; then # SLES / openSuSE / Debian. . /lib/lsb/init-functions rc_exit() { exit $RETVAL; } success() { log_success_msg; } failure() { log_failure_msg; } elif [[ -s /etc/rc.status ]]; then # Older SuSE systems. . /etc/rc.status failure() { rc_status -v; } success() { rc_status -v; } fi CONFIG=@sysconfdir@/sysconfig/opensm if [[ -s $CONFIG ]]; then . $CONFIG fi running () { [ -e $pidfile ] && [ "$(readlink "/proc/$(<$pidfile)/exe")" = "@sbindir@/opensm" ] } start () { if running; then echo Already started return 1 fi echo -n "Starting opensm: " @sbindir@/opensm --daemon --pidfile $pidfile $OPTIONS > /dev/null RETVAL=$? if [[ $RETVAL -eq 0 ]]; then success else failure fi echo } stop () { echo -n "Shutting down opensm: " killproc opensm RETVAL=$? if [[ $RETVAL -eq 0 ]]; then success else failure fi echo } Xstatus () { pid="`pidof opensm`" ret=$? if [ $ret -eq 0 ] ; then echo "OpenSM is running... pid=$pid" else echo "OpenSM is not running." fi } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) Xstatus ;; restart | force-reload | reload) restart ;; try-restart | condrestart) [ -e $pidfile ] && restart ;; resweep) killall -HUP opensm RETVAL=$? ;; rotatelog) killall -USR1 opensm RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|status|restart|reload|condrestart|resweep|rotatelog}" RETVAL=1 ;; esac _rc_status_all=$RETVAL rc_exit opensm-3.3.20/scripts/redhat-opensm.init.in0000755000205000001450000001500012104655725015545 00000000000000#!/bin/bash # # Bring up/down opensm # # chkconfig: - 15 85 # description: Activates/Deactivates InfiniBand Subnet Manager # ### BEGIN INIT INFO # Provides: opensm # Required-Start: $syslog @RDMA_SERVICE@ # Required-Stop: $syslog @RDMA_SERVICE@ # Default-Start: @DEFAULT_START@ # Default-Stop: @DEFAULT_STOP@ # Description: Manage OpenSM ### END INIT INFO # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # 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. # # # $Id: openib-1.0-opensm.init,v 1.5 2006/08/02 18:18:23 dledford Exp $ # # processname: @sbindir@/opensm # config: @sysconfdir@/sysconfig/opensm # pidfile: /var/run/opensm.pid prefix=@prefix@ exec_prefix=@exec_prefix@ . /etc/rc.d/init.d/functions CONFIG=@sysconfdir@/sysconfig/opensm if [ -f $CONFIG ]; then . $CONFIG fi prog=@sbindir@/opensm bin=${prog##*/} # Handover daemon for updating guid2lid cache file sldd_prog=@sbindir@/sldd.sh sldd_bin=${sldd_prog##*/} sldd_pid_file=/var/run/sldd.pid ACTION=$1 # Setting OpenSM start parameters PID_FILE=/var/run/${bin}.pid touch $PID_FILE if [[ -n "${OSM_HOSTS}" && $(echo -n ${OSM_HOSTS} | wc -w | tr -d '[:space:]') -gt 1 ]]; then HONORE_GUID2LID="--honor_guid2lid" fi ######################################################################### start_sldd() { if [ -f $sldd_pid_file ]; then local line p read line < $sldd_pid_file for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p" done fi if [ -z "$sldd_pid" ]; then sldd_pid=`pidof -x $sldd_bin` fi if [ -n "${sldd_pid:-}" ] ; then kill -9 ${sldd_pid} > /dev/null 2>&1 fi $sldd_prog > /dev/null 2>&1 & sldd_pid=$! echo ${sldd_pid} > $sldd_pid_file # Sleep is needed in order to update local gid2lid cache file before running opensm sleep 3 } stop_sldd() { if [ -f $sldd_pid_file ]; then local line p read line < $sldd_pid_file for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p" done fi if [ -z "$sldd_pid" ]; then sldd_pid=`pidof -x $sldd_bin` fi if [ -n "${sldd_pid:-}" ] ; then kill -15 ${sldd_pid} > /dev/null 2>&1 fi } start() { local OSM_PID= pid="" if [ -f $PID_FILE ]; then local line p read line < $PID_FILE for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" done fi if [ -z "$pid" ]; then pid=`pidof -o $$ -o $PPID -o %PPID -x $bin` fi if [ -n "${pid:-}" ] ; then echo $"${bin} (pid $pid) is already running..." else if [ -n "${HONORE_GUID2LID}" ]; then # Run sldd daemod start_sldd fi # Start opensm echo -n "Starting IB Subnet Manager" $prog --daemon ${HONORE_GUID2LID} ${OPTIONS} > /dev/null cnt=0; alive=0 while [ $cnt -lt 6 -a $alive -ne 1 ]; do echo -n "."; sleep 1 alive=0 OSM_PID=`pidof $prog` if [ "$OSM_PID" != "" ]; then alive=1 fi let cnt++; done echo $OSM_PID > $PID_FILE checkpid $OSM_PID RC=$? [ $RC -eq 0 ] && echo_success || echo_failure [ $RC -eq 0 ] && touch /var/lock/subsys/opensm echo fi return $RC } stop() { local pid= local pid1= local pid2= # Stop sldd daemon stop_sldd if [ -f $PID_FILE ]; then local line p read line < $PID_FILE for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid1="$pid1 $p" done fi pid2=`pidof -o $$ -o $PPID -o %PPID -x $bin` pid=`echo "$pid1 $pid2" | sed -e 's/\ /\n/g' | sort -n | uniq | sed -e 's/\n/\ /g'` if [ -n "${pid:-}" ] ; then # Kill opensm echo -n "Stopping IB Subnet Manager." kill -15 $pid > /dev/null 2>&1 cnt=0; alive=1 while [ $cnt -lt 6 -a $alive -ne 0 ]; do echo -n "."; alive=0 for p in $pid; do if checkpid $p ; then alive=1; echo -n "-"; fi done let cnt++; sleep $alive done for p in $pid do while checkpid $p ; do kill -KILL $p > /dev/null 2>&1 echo -n "+" sleep 1 done done checkpid $pid RC=$? [ $RC -eq 0 ] && echo_failure || echo_success echo RC=$((! $RC)) else echo -n "Stopping IB Subnet Manager." echo_failure echo RC=1 fi # Remove pid file if any. rm -f $PID_FILE rm -f /var/lock/subsys/opensm return $RC } status() { local pid # First try "pidof" pid=`pidof -o $$ -o $PPID -o %PPID -x ${bin}` if [ -n "$pid" ]; then echo $"${bin} (pid $pid) is running..." return 0 fi # Next try "/var/run/opensm.pid" files if [ -f $PID_FILE ] ; then read pid < $PID_FILE if [ -n "$pid" ]; then echo $"${bin} dead but pid file $PID_FILE exists" return 1 fi fi echo $"${bin} is stopped" return 3 } case $ACTION in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; condrestart) pid=`pidof -o $$ -o $PPID -o %PPID -x $bin` if [ -n "$pid" ]; then stop sleep 1 start fi ;; *) echo echo "Usage: `basename $0` {start|stop|restart|status}" echo exit 1 ;; esac RC=$? exit $RC opensm-3.3.20/scripts/sldd.sh.in0000755000205000001450000001624712104655725013412 00000000000000#!/bin/bash # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # 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. # # # OpenSM found to have the following problem # when handover is performed: # If some of the cluster nodes are rebooted during the handover they loose their LID assignment. # The reason for it is that the standby SM does not obey its own Guid to LID table # and simply uses the discovered LIDs. If some nodes are not available for it # their previous LID assignment is lost forever. # The idea is to use an external daemon that will distribute # the semi-static LID assignment table from the master SM to all standby SMs. # A standby SM, becoming a master . needs to obey the copied semi static LID assignment table. prefix=@prefix@ exec_prefix=@exec_prefix@ CONFIG=@sysconfdir@/sysconfig/opensm if [ -f $CONFIG ]; then . $CONFIG fi SLDD_DEBUG=${SLDD_DEBUG:-0} CACHE_FILE=${CACHE_FILE:-/var/cache/opensm/guid2lid:/var/cache/opensm/guid2mkey:/var/cache/opensm/neighbors} declare -a arr_CACHE_FILES arr_CACHE_FILES=(`echo $CACHE_FILE| sed 's/:/\n/g' | sort | uniq`) PING='ping -w 1 -c 1' RCP=${RCP:-/usr/bin/scp} RSH=${RSH:-/usr/bin/ssh} IFCONFIG=${IFCONFIG:-'/sbin/ifconfig -a'} declare -i SLDD_DEBUG RESCAN_TIME=${RESCAN_TIME:-60} if [ -z "${OSM_HOSTS}" ]; then [ $SLDD_DEBUG -eq 1 ] && echo "No OpenSM servers (OSM_HOSTS) configured for the IB subnet." exit 0 fi declare -a arr_OSM_HOSTS arr_OSM_HOSTS=(${OSM_HOSTS}) num_of_osm_hosts=${#arr_OSM_HOSTS[@]} if [ ${num_of_osm_hosts} -eq 1 ]; then [ $SLDD_DEBUG -eq 1 ] && echo "One OpenSM server configured in the IB subnet." && echo "Nothing to be done for SLDD" exit 0 fi trap 'trap_handler' 15 trap_handler() { logger -i "SLDD: Exiting." exit 0 } is_alive() { $PING $1 > /dev/null 2>&1 return $? } is_local() { $IFCONFIG | grep -w "$1" > /dev/null 2>&1 return $? } update_remote_cache() { /bin/rm -f "$1.upd" /bin/cp -a "$1" "$1.upd" [ $SLDD_DEBUG -eq 1 ] && echo "Updating remote cache file" for host in ${OSM_HOSTS} do # Skip local host update if [ "${host}" == "${local_host}" ]; then continue fi if is_alive $host; then cache_dir=$(dirname "$1") stat=$($RSH $host "/bin/mkdir -p ${cache_dir} > /dev/null 2>&1; /bin/rm -f "$1.${local_host}" > /dev/null 2>&1; echo \$?" | tr -d '[:space:]') if [ "X${stat}" == "X0" ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Updating $host" logger -i "SLDD: updating $host with $1" $RCP "$1.upd" "${host}:$1.${local_host}" /bin/cp "$1.upd" "$1.${host}" else [ $SLDD_DEBUG -eq 1 ] && echo "$RSH to $host failed." logger -i "SLDD: Failed to update $host with $1. $RSH without password should be enabled" exit 5 fi else [ $SLDD_DEBUG -eq 1 ] && echo "$host is down." continue fi done } get_latest_remote_cache() { # Find most updated remote cache file (the suffix should be like ip address: *.*.*.*) echo -n "$(/bin/ls -1t $1.*.* 2> /dev/null | head -1)" } get_largest_remote_cache() { # Find largest (size) remote cache file (the suffix should be like ip address: *.*.*.*) echo -n "$(/bin/ls -1S $1.*.* 2> /dev/null | head -1)" } swap_cache_files() { /bin/rm -f "$1.old" /bin/mv "$1" "$1.old" /bin/cp "$2" "$1" touch "$1.tmp" } # Find local host in the osm hosts list local_host="" for host in ${OSM_HOSTS} do if is_local $host; then local_host=${host} fi done # Get cache file info declare -i new_size=0 declare -ai arr_last_size for i in ${!arr_CACHE_FILES[@]} do arr_last_size[$i]=0 done declare -i largest_remote_cache_size=0 for i in ${!arr_CACHE_FILES[@]} do cache_file=${arr_CACHE_FILES[$i]} if [ -e ${cache_file} ]; then arr_last_size[$i]=$(du -b ${cache_file} | awk '{print$1}' | tr -d '[:space:]') else touch ${cache_file} ${cache_file}.tmp fi # if [ ${arr_last_size[$i]} -gt 0 ]; then # # First time update # update_remote_cache ${cache_file} # fi done while true do for i in ${!arr_CACHE_FILES[@]} do cache_file=${arr_CACHE_FILES[$i]} if [ -s "${cache_file}" ]; then new_size=$(du -b ${cache_file} | awk '{print$1}' | tr -d '[:space:]') # Check if local cache file grew from its last version or the time stamp changed if [ ${new_size} -gt ${arr_last_size[$i]} ] [ "$(/bin/ls -1t ${cache_file} ${cache_file}.tmp 2> /dev/null | head -1)" != "${cache_file}.tmp" ]; then largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]') else largest_remote_cache_size=0 fi # Check if local cache file larger than remote chache file if [ ${new_size} -gt ${largest_remote_cache_size} ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file larger then remote. Update remote cache files" arr_last_size[$i]=${new_size} update_remote_cache ${cache_file} continue fi fi largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]') else largest_remote_cache_size=0 fi # Update local cache file from remote if [ ${largest_remote_cache_size} -gt ${new_size} ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file shorter then remote. Use ${largest_remote_cache}" logger -i "SLDD: updating local cache file with ${largest_remote_cache}" swap_cache_files ${cache_file} ${largest_remote_cache} arr_last_size[$i]=${largest_remote_cache_size} fi else # The local cache file is empty [ $SLDD_DEBUG -eq 1 ] && echo "${cache_file} is empty" largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then # Copy it to the current cache [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file is empty. Use ${largest_remote_cache}" logger -i "SLDD: updating local cache file with ${largest_remote_cache}" swap_cache_files ${cache_file} ${largest_remote_cache} fi fi done [ $SLDD_DEBUG -eq 1 ] && echo "Sleeping ${RESCAN_TIME} seconds." sleep ${RESCAN_TIME} done opensm-3.3.20/scripts/opensm.init0000644000205000001450000000641612726323447013706 00000000000000#!/bin/bash # # opensm: Manage OpenSM # # chkconfig: - 09 91 # description: Manage OpenSM # ### BEGIN INIT INFO # Provides: opensm # Required-Start: $syslog openibd # Required-Stop: $syslog openibd # Default-Start: null # Default-Stop: 0 1 6 # Description: Manage OpenSM ### END INIT INFO # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # Copyright 2006 PathScale, Inc. 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. prefix=/usr/local exec_prefix=${prefix} pidfile=/var/run/opensm.pid # Source function library. if [[ -s /etc/init.d/functions ]]; then # RHEL / CentOS / SL / Fedora. . /etc/init.d/functions rc_status() { :; } rc_exit() { exit $RETVAL; } elif [[ -s /lib/lsb/init-functions ]]; then # SLES / openSuSE / Debian. . /lib/lsb/init-functions rc_exit() { exit $RETVAL; } success() { log_success_msg; } failure() { log_failure_msg; } elif [[ -s /etc/rc.status ]]; then # Older SuSE systems. . /etc/rc.status failure() { rc_status -v; } success() { rc_status -v; } fi CONFIG=${prefix}/etc/sysconfig/opensm if [[ -s $CONFIG ]]; then . $CONFIG fi running () { [ -e $pidfile ] && [ "$(readlink "/proc/$(<$pidfile)/exe")" = "${exec_prefix}/sbin/opensm" ] } start () { if running; then echo Already started return 1 fi echo -n "Starting opensm: " ${exec_prefix}/sbin/opensm --daemon --pidfile $pidfile $OPTIONS > /dev/null RETVAL=$? if [[ $RETVAL -eq 0 ]]; then success else failure fi echo } stop () { echo -n "Shutting down opensm: " killproc opensm RETVAL=$? if [[ $RETVAL -eq 0 ]]; then success else failure fi echo } Xstatus () { pid="`pidof opensm`" ret=$? if [ $ret -eq 0 ] ; then echo "OpenSM is running... pid=$pid" else echo "OpenSM is not running." fi } restart() { stop start } # See how we were called. case "$1" in start) start ;; stop) stop ;; status) Xstatus ;; restart | force-reload | reload) restart ;; try-restart | condrestart) [ -e $pidfile ] && restart ;; resweep) killall -HUP opensm RETVAL=$? ;; rotatelog) killall -USR1 opensm RETVAL=$? ;; *) echo $"Usage: $0 {start|stop|status|restart|reload|condrestart|resweep|rotatelog}" RETVAL=1 ;; esac _rc_status_all=$RETVAL rc_exit opensm-3.3.20/scripts/opensm.logrotate0000644000205000001450000000013612104655725014731 00000000000000/var/log/opensm.log { missingok notifempty copytruncate weekly compress } opensm-3.3.20/scripts/opensm.sysconfig0000644000205000001450000000005312104655725014733 00000000000000# It will be used for sldd.sh OSM_HOSTS="" opensm-3.3.20/scripts/redhat-opensm.init0000644000205000001450000001477412726323450015153 00000000000000#!/bin/bash # # Bring up/down opensm # # chkconfig: - 15 85 # description: Activates/Deactivates InfiniBand Subnet Manager # ### BEGIN INIT INFO # Provides: opensm # Required-Start: $syslog openibd # Required-Stop: $syslog openibd # Default-Start: null # Default-Stop: 0 1 6 # Description: Manage OpenSM ### END INIT INFO # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # 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. # # # $Id: openib-1.0-opensm.init,v 1.5 2006/08/02 18:18:23 dledford Exp $ # # processname: ${exec_prefix}/sbin/opensm # config: ${prefix}/etc/sysconfig/opensm # pidfile: /var/run/opensm.pid prefix=/usr/local exec_prefix=${prefix} . /etc/rc.d/init.d/functions CONFIG=${prefix}/etc/sysconfig/opensm if [ -f $CONFIG ]; then . $CONFIG fi prog=${exec_prefix}/sbin/opensm bin=${prog##*/} # Handover daemon for updating guid2lid cache file sldd_prog=${exec_prefix}/sbin/sldd.sh sldd_bin=${sldd_prog##*/} sldd_pid_file=/var/run/sldd.pid ACTION=$1 # Setting OpenSM start parameters PID_FILE=/var/run/${bin}.pid touch $PID_FILE if [[ -n "${OSM_HOSTS}" && $(echo -n ${OSM_HOSTS} | wc -w | tr -d '[:space:]') -gt 1 ]]; then HONORE_GUID2LID="--honor_guid2lid" fi ######################################################################### start_sldd() { if [ -f $sldd_pid_file ]; then local line p read line < $sldd_pid_file for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p" done fi if [ -z "$sldd_pid" ]; then sldd_pid=`pidof -x $sldd_bin` fi if [ -n "${sldd_pid:-}" ] ; then kill -9 ${sldd_pid} > /dev/null 2>&1 fi $sldd_prog > /dev/null 2>&1 & sldd_pid=$! echo ${sldd_pid} > $sldd_pid_file # Sleep is needed in order to update local gid2lid cache file before running opensm sleep 3 } stop_sldd() { if [ -f $sldd_pid_file ]; then local line p read line < $sldd_pid_file for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && sldd_pid="$sldd_pid $p" done fi if [ -z "$sldd_pid" ]; then sldd_pid=`pidof -x $sldd_bin` fi if [ -n "${sldd_pid:-}" ] ; then kill -15 ${sldd_pid} > /dev/null 2>&1 fi } start() { local OSM_PID= pid="" if [ -f $PID_FILE ]; then local line p read line < $PID_FILE for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" done fi if [ -z "$pid" ]; then pid=`pidof -o $$ -o $PPID -o %PPID -x $bin` fi if [ -n "${pid:-}" ] ; then echo $"${bin} (pid $pid) is already running..." else if [ -n "${HONORE_GUID2LID}" ]; then # Run sldd daemod start_sldd fi # Start opensm echo -n "Starting IB Subnet Manager" $prog --daemon ${HONORE_GUID2LID} ${OPTIONS} > /dev/null cnt=0; alive=0 while [ $cnt -lt 6 -a $alive -ne 1 ]; do echo -n "."; sleep 1 alive=0 OSM_PID=`pidof $prog` if [ "$OSM_PID" != "" ]; then alive=1 fi let cnt++; done echo $OSM_PID > $PID_FILE checkpid $OSM_PID RC=$? [ $RC -eq 0 ] && echo_success || echo_failure [ $RC -eq 0 ] && touch /var/lock/subsys/opensm echo fi return $RC } stop() { local pid= local pid1= local pid2= # Stop sldd daemon stop_sldd if [ -f $PID_FILE ]; then local line p read line < $PID_FILE for p in $line ; do [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid1="$pid1 $p" done fi pid2=`pidof -o $$ -o $PPID -o %PPID -x $bin` pid=`echo "$pid1 $pid2" | sed -e 's/\ /\n/g' | sort -n | uniq | sed -e 's/\n/\ /g'` if [ -n "${pid:-}" ] ; then # Kill opensm echo -n "Stopping IB Subnet Manager." kill -15 $pid > /dev/null 2>&1 cnt=0; alive=1 while [ $cnt -lt 6 -a $alive -ne 0 ]; do echo -n "."; alive=0 for p in $pid; do if checkpid $p ; then alive=1; echo -n "-"; fi done let cnt++; sleep $alive done for p in $pid do while checkpid $p ; do kill -KILL $p > /dev/null 2>&1 echo -n "+" sleep 1 done done checkpid $pid RC=$? [ $RC -eq 0 ] && echo_failure || echo_success echo RC=$((! $RC)) else echo -n "Stopping IB Subnet Manager." echo_failure echo RC=1 fi # Remove pid file if any. rm -f $PID_FILE rm -f /var/lock/subsys/opensm return $RC } status() { local pid # First try "pidof" pid=`pidof -o $$ -o $PPID -o %PPID -x ${bin}` if [ -n "$pid" ]; then echo $"${bin} (pid $pid) is running..." return 0 fi # Next try "/var/run/opensm.pid" files if [ -f $PID_FILE ] ; then read pid < $PID_FILE if [ -n "$pid" ]; then echo $"${bin} dead but pid file $PID_FILE exists" return 1 fi fi echo $"${bin} is stopped" return 3 } case $ACTION in start) start ;; stop) stop ;; restart) stop start ;; status) status ;; condrestart) pid=`pidof -o $$ -o $PPID -o %PPID -x $bin` if [ -n "$pid" ]; then stop sleep 1 start fi ;; *) echo echo "Usage: `basename $0` {start|stop|restart|status}" echo exit 1 ;; esac RC=$? exit $RC opensm-3.3.20/scripts/sldd.sh0000644000205000001450000001624612726323450012776 00000000000000#!/bin/bash # # Copyright (c) 2008 Voltaire, Inc. All rights reserved. # 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. # # # OpenSM found to have the following problem # when handover is performed: # If some of the cluster nodes are rebooted during the handover they loose their LID assignment. # The reason for it is that the standby SM does not obey its own Guid to LID table # and simply uses the discovered LIDs. If some nodes are not available for it # their previous LID assignment is lost forever. # The idea is to use an external daemon that will distribute # the semi-static LID assignment table from the master SM to all standby SMs. # A standby SM, becoming a master . needs to obey the copied semi static LID assignment table. prefix=/usr/local exec_prefix=${prefix} CONFIG=${prefix}/etc/sysconfig/opensm if [ -f $CONFIG ]; then . $CONFIG fi SLDD_DEBUG=${SLDD_DEBUG:-0} CACHE_FILE=${CACHE_FILE:-/var/cache/opensm/guid2lid:/var/cache/opensm/guid2mkey:/var/cache/opensm/neighbors} declare -a arr_CACHE_FILES arr_CACHE_FILES=(`echo $CACHE_FILE| sed 's/:/\n/g' | sort | uniq`) PING='ping -w 1 -c 1' RCP=${RCP:-/usr/bin/scp} RSH=${RSH:-/usr/bin/ssh} IFCONFIG=${IFCONFIG:-'/sbin/ifconfig -a'} declare -i SLDD_DEBUG RESCAN_TIME=${RESCAN_TIME:-60} if [ -z "${OSM_HOSTS}" ]; then [ $SLDD_DEBUG -eq 1 ] && echo "No OpenSM servers (OSM_HOSTS) configured for the IB subnet." exit 0 fi declare -a arr_OSM_HOSTS arr_OSM_HOSTS=(${OSM_HOSTS}) num_of_osm_hosts=${#arr_OSM_HOSTS[@]} if [ ${num_of_osm_hosts} -eq 1 ]; then [ $SLDD_DEBUG -eq 1 ] && echo "One OpenSM server configured in the IB subnet." && echo "Nothing to be done for SLDD" exit 0 fi trap 'trap_handler' 15 trap_handler() { logger -i "SLDD: Exiting." exit 0 } is_alive() { $PING $1 > /dev/null 2>&1 return $? } is_local() { $IFCONFIG | grep -w "$1" > /dev/null 2>&1 return $? } update_remote_cache() { /bin/rm -f "$1.upd" /bin/cp -a "$1" "$1.upd" [ $SLDD_DEBUG -eq 1 ] && echo "Updating remote cache file" for host in ${OSM_HOSTS} do # Skip local host update if [ "${host}" == "${local_host}" ]; then continue fi if is_alive $host; then cache_dir=$(dirname "$1") stat=$($RSH $host "/bin/mkdir -p ${cache_dir} > /dev/null 2>&1; /bin/rm -f "$1.${local_host}" > /dev/null 2>&1; echo \$?" | tr -d '[:space:]') if [ "X${stat}" == "X0" ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Updating $host" logger -i "SLDD: updating $host with $1" $RCP "$1.upd" "${host}:$1.${local_host}" /bin/cp "$1.upd" "$1.${host}" else [ $SLDD_DEBUG -eq 1 ] && echo "$RSH to $host failed." logger -i "SLDD: Failed to update $host with $1. $RSH without password should be enabled" exit 5 fi else [ $SLDD_DEBUG -eq 1 ] && echo "$host is down." continue fi done } get_latest_remote_cache() { # Find most updated remote cache file (the suffix should be like ip address: *.*.*.*) echo -n "$(/bin/ls -1t $1.*.* 2> /dev/null | head -1)" } get_largest_remote_cache() { # Find largest (size) remote cache file (the suffix should be like ip address: *.*.*.*) echo -n "$(/bin/ls -1S $1.*.* 2> /dev/null | head -1)" } swap_cache_files() { /bin/rm -f "$1.old" /bin/mv "$1" "$1.old" /bin/cp "$2" "$1" touch "$1.tmp" } # Find local host in the osm hosts list local_host="" for host in ${OSM_HOSTS} do if is_local $host; then local_host=${host} fi done # Get cache file info declare -i new_size=0 declare -ai arr_last_size for i in ${!arr_CACHE_FILES[@]} do arr_last_size[$i]=0 done declare -i largest_remote_cache_size=0 for i in ${!arr_CACHE_FILES[@]} do cache_file=${arr_CACHE_FILES[$i]} if [ -e ${cache_file} ]; then arr_last_size[$i]=$(du -b ${cache_file} | awk '{print$1}' | tr -d '[:space:]') else touch ${cache_file} ${cache_file}.tmp fi # if [ ${arr_last_size[$i]} -gt 0 ]; then # # First time update # update_remote_cache ${cache_file} # fi done while true do for i in ${!arr_CACHE_FILES[@]} do cache_file=${arr_CACHE_FILES[$i]} if [ -s "${cache_file}" ]; then new_size=$(du -b ${cache_file} | awk '{print$1}' | tr -d '[:space:]') # Check if local cache file grew from its last version or the time stamp changed if [ ${new_size} -gt ${arr_last_size[$i]} ] [ "$(/bin/ls -1t ${cache_file} ${cache_file}.tmp 2> /dev/null | head -1)" != "${cache_file}.tmp" ]; then largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]') else largest_remote_cache_size=0 fi # Check if local cache file larger than remote chache file if [ ${new_size} -gt ${largest_remote_cache_size} ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file larger then remote. Update remote cache files" arr_last_size[$i]=${new_size} update_remote_cache ${cache_file} continue fi fi largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then largest_remote_cache_size=$(du -b ${largest_remote_cache} 2> /dev/null | awk '{print$1}' | tr -d '[:space:]') else largest_remote_cache_size=0 fi # Update local cache file from remote if [ ${largest_remote_cache_size} -gt ${new_size} ]; then [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file shorter then remote. Use ${largest_remote_cache}" logger -i "SLDD: updating local cache file with ${largest_remote_cache}" swap_cache_files ${cache_file} ${largest_remote_cache} arr_last_size[$i]=${largest_remote_cache_size} fi else # The local cache file is empty [ $SLDD_DEBUG -eq 1 ] && echo "${cache_file} is empty" largest_remote_cache=$(get_largest_remote_cache ${cache_file}) if [[ -n "${largest_remote_cache}" && -s "${largest_remote_cache}" ]]; then # Copy it to the current cache [ $SLDD_DEBUG -eq 1 ] && echo "Local cache file is empty. Use ${largest_remote_cache}" logger -i "SLDD: updating local cache file with ${largest_remote_cache}" swap_cache_files ${cache_file} ${largest_remote_cache} fi fi done [ $SLDD_DEBUG -eq 1 ] && echo "Sleeping ${RESCAN_TIME} seconds." sleep ${RESCAN_TIME} done opensm-3.3.20/README0000644000205000001450000000155012104655724010677 00000000000000OpenSM README: -------------- OpenSM provides an implementation for an InfiniBand Subnet Manager and Administrator. Such a software entity is required to run for in order to initialize the InfiniBand hardware (at least one per each InfiniBand subnet). The full list of OpenSM features is described in the user manual provided in the doc sub directory. The installation of OpenSM includes: sbin/ opensm - the SM/SA executable osmtest - a test program for the SM/SA lib/ libosmcomp.{a,so} - component library with generic services and containers libopensm.{a,so} - opensm services for logs and mad buffer pool libosmvendor.{a,so} - interface to the user mad service of the driver include/ iba/ib_types.h - IBA types header file complib/ - component library includes vendor/ - vendor library includes opensm/ - public opensm library includes opensm-3.3.20/configure.in0000644000205000001450000002143512726304517012335 00000000000000dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) AC_INIT(opensm, 3.3.20, linux-rdma@vger.kernel.org) AC_CONFIG_SRCDIR([opensm/osm_opensm.c]) AC_CONFIG_AUX_DIR(config) AC_CONFIG_MACRO_DIR(config) AC_CONFIG_HEADERS(include/config.h include/opensm/osm_config.h) AM_INIT_AUTOMAKE AC_SUBST(RELEASE, ${RELEASE:-${VERSION}}) AC_SUBST(TARBALL, ${TARBALL:-${PACKAGE}-${VERSION}.tar.gz}) default_rdma_service=openibd AC_ARG_WITH([rdma_service], AC_HELP_STRING([--with-rdma-service=name], [name of the RDMA service: "rdma" when using /etc/init.d/rdma to start RDMA services; "openibd" when using /etc/init.d/openibd to start RDMA services [default=${default_rdma_service}]])) AC_SUBST(RDMA_SERVICE, ${with_rdma_service:-${default_rdma_service}}) if { rpm -q sles-release || rpm -q openSUSE-release; } >/dev/null 2>&1; then default_stop="0 1 4 6" else default_stop="0 1 6" fi default_start="null" AC_SUBST(DEFAULT_START, $default_start) AC_SUBST(DEFAULT_STOP, $default_stop) dnl NOTE: AC_DEFINE's and AC_DEFINE_UNQUOTED's which are used in header files dnl MUST have a corresponding entry in include/opensm/osm_config.h.in to dnl ensure plugin compatibility. AC_DEFINE(_OSM_CONFIG_H_, 1, mark config.h inclusion) dnl Defines the Language AC_LANG_C dnl Required for cases make defines a MAKE=make ??? Why AC_PROG_MAKE_SET AC_PROG_CC AC_PROG_LIBTOOL AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_YACC AC_PROG_LEX AC_CHECK_PROGS(_YACC_,$YACC,none) if test "$_YACC_" = "none" then AC_MSG_ERROR([No bison/byacc/yacc found.]) fi AC_CHECK_PROGS(_LEX_,$LEX,none) if test "$_LEX_" = "none" then AC_MSG_ERROR([No flex/lex found.]) fi dnl Checks for libraries AC_CHECK_LIB(pthread, pthread_mutex_init, [], AC_MSG_ERROR([pthread_mutex_init() not found. libosmcomp requires libpthread.])) AC_CHECK_LIB(dl, dlopen, [], AC_MSG_ERROR([dlopen() not found. OpenSM requires libdl.])) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_PID_T AC_TYPE_SIZE_T AC_HEADER_TIME AC_STRUCT_TM AC_C_VOLATILE dnl See if we have __builtin_expect AC_MSG_CHECKING([if the compiler supports __builtin_expect]) AC_TRY_COMPILE(, [ return __builtin_expect(1, 1) ? 1 : 0], [ have_builtin_expect=yes AC_MSG_RESULT([yes]) ], [ have_builtin_expect=no AC_MSG_RESULT([no]) ]) if test "x_$have_builtin_expect" = "x_yes" ; then AC_DEFINE([HAVE_BUILTIN_EXPECT], [1], [Define to 1 if the compiler supports __builtin_expect.]) fi dnl We use --version-script with ld if possible AC_CACHE_CHECK(whether ld accepts --version-script, ac_cv_version_script, if test -n "`$LD --help < /dev/null 2>/dev/null | grep version-script`"; then ac_cv_version_script=yes else ac_cv_version_script=no fi) AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$ac_cv_version_script" = "yes") dnl Define an input config option to control debug compile AC_ARG_ENABLE(debug, [ --enable-debug Turn on debugging], [case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; esac],debug=false) if test x$debug = xtrue ; then AC_DEFINE(OSM_DEBUG, 1, [ define 1 if OpenSM build is in a debug mode ]) AC_DEFINE(_DEBUG_, 1, [ define 1 if OpenSM build is in a debug mode ]) fi AM_CONDITIONAL(DEBUG, test x$debug = xtrue) AC_ARG_ENABLE(libcheck, [ --disable-libcheck do not test for presence of ib libraries], [if test x$enableval = xno ; then disable_libcheck=yes fi]) dnl check if they want the socket console OPENIB_OSM_CONSOLE_SOCKET_SEL dnl select performance manager or not OPENIB_OSM_PERF_MGR_SEL dnl resolve config dir. conf_dir_tmp1="`eval echo ${sysconfdir} | sed 's/^NONE/$ac_default_prefix/'`" SYS_CONFIG_DIR="`eval echo $conf_dir_tmp1`" dnl Check for a different subdir for the config files. OPENSM_CONFIG_SUB_DIR=opensm AC_MSG_CHECKING(for --with-opensm-conf-sub-dir) AC_ARG_WITH(opensm-conf-sub-dir, AC_HELP_STRING([--with-opensm-conf-sub-dir=dir], [define a directory name for opensm's conf files / (default "opensm")]), [ case "$withval" in no) ;; *) OPENSM_CONFIG_SUB_DIR=$withval ;; esac ] ) dnl this needs to be configured for rpmbuilds separate from the full path dnl "OPENSM_CONFIG_DIR" AC_SUBST(OPENSM_CONFIG_SUB_DIR) OPENSM_CONFIG_DIR=$SYS_CONFIG_DIR/$OPENSM_CONFIG_SUB_DIR AC_MSG_RESULT($OPENSM_CONFIG_DIR) AC_DEFINE_UNQUOTED(OPENSM_CONFIG_DIR, ["$OPENSM_CONFIG_DIR"], [Define OpenSM config directory]) AC_SUBST(OPENSM_CONFIG_DIR) dnl Check for a different default OpenSm config file OPENSM_CONFIG_FILE=opensm.conf AC_MSG_CHECKING(for --with-opensm-conf-file ) AC_ARG_WITH(opensm-conf-file, AC_HELP_STRING([--with-opensm-conf-file=file], [define a default OpenSM config file (default opensm.conf)]), [ case "$withval" in no) ;; *) OPENSM_CONFIG_FILE=$withval ;; esac ] ) AC_MSG_RESULT(${OPENSM_CONFIG_FILE}) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_OPENSM_CONFIG_FILE, ["$OPENSM_CONFIG_DIR/$OPENSM_CONFIG_FILE"], [Define a default OpenSM config file]) AC_SUBST(OPENSM_CONFIG_FILE) dnl Check for a different default node name map file NODENAMEMAPFILE=ib-node-name-map AC_MSG_CHECKING(for --with-node-name-map ) AC_ARG_WITH(node-name-map, AC_HELP_STRING([--with-node-name-map=file], [define a default node name map file (default ib-node-name-map)]), [ case "$withval" in no) ;; *) NODENAMEMAPFILE=$withval ;; esac ] ) AC_MSG_RESULT($NODENAMEMAPFILE) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_NODENAME_MAP, ["$OPENSM_CONFIG_DIR/$NODENAMEMAPFILE"], [Define a default node name map file]) AC_SUBST(NODENAMEMAPFILE) dnl Check for a different partition conf file PARTITION_CONFIG_FILE=partitions.conf AC_MSG_CHECKING(for --with-partitions-conf) AC_ARG_WITH(partitions-conf, AC_HELP_STRING([--with-partitions-conf=file], [define a partitions config file (default partitions.conf)]), [ case "$withval" in no) ;; *) PARTITION_CONFIG_FILE=$withval ;; esac ] ) AC_MSG_RESULT($PARTITION_CONFIG_FILE) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_PARTITION_CONFIG_FILE, ["$OPENSM_CONFIG_DIR/$PARTITION_CONFIG_FILE"], [Define a Partition config file]) AC_SUBST(PARTITION_CONFIG_FILE) dnl Check for a different QOS policy file QOS_POLICY_FILE=qos-policy.conf AC_MSG_CHECKING(for --with-qos-policy-conf) AC_ARG_WITH(qos-policy-conf, AC_HELP_STRING([--with-qos-policy-conf=file], [define a QOS policy config file (default qos-policy.conf)]), [ case "$withval" in no) ;; *) QOS_POLICY_FILE=$withval ;; esac ] ) AC_MSG_RESULT($QOS_POLICY_FILE) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_QOS_POLICY_FILE, ["$OPENSM_CONFIG_DIR/$QOS_POLICY_FILE"], [Define a QOS policy config file]) AC_SUBST(QOS_POLICY_FILE) dnl For now, this does not need to be configurable TORUS2QOS_CONF_FILE=torus-2QoS.conf AC_SUBST(TORUS2QOS_CONF_FILE) dnl Check for a different prefix-routes file PREFIX_ROUTES_FILE=prefix-routes.conf AC_MSG_CHECKING(for --with-prefix-routes-conf) AC_ARG_WITH(prefix-routes-conf, AC_HELP_STRING([--with-prefix-routes-conf=file], [define a Prefix Routes config file (default is prefix-routes.conf)]), [ case "$withval" in no) ;; *) PREFIX_ROUTES_FILE=$withval ;; esac ] ) AC_MSG_RESULT($PREFIX_ROUTES_FILE) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_PREFIX_ROUTES_FILE, ["$OPENSM_CONFIG_DIR/$PREFIX_ROUTES_FILE"], [Define a Prefix Routes config file]) AC_SUBST(PREFIX_ROUTES_FILE) dnl Check for a different per-module-logging file PER_MOD_LOGGING_FILE=per-module-logging.conf AC_MSG_CHECKING(for --with-per-module-logging-conf) AC_ARG_WITH(per-module-logging.conf, AC_HELP_STRING([--with-per-module-logging-conf=file], [define a Per Module Logging config file (default is per-module-logging.conf)]), [ case "$withval" in no) ;; *) PER_MOD_LOGGING_FILE=$withval ;; esac ] ) AC_MSG_RESULT($PER_MOD_LOGGING_FILE) AC_DEFINE_UNQUOTED(HAVE_DEFAULT_PER_MOD_LOGGING_FILE, ["$OPENSM_CONFIG_DIR/$PER_MOD_LOGGING_FILE"], [Define a Per Module Logging config file]) AC_SUBST(PER_MOD_LOGGING_FILE) dnl select example event plugin or not OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL dnl Provide user option to select vendor OPENIB_APP_OSMV_SEL dnl Checks for headers and libraries OPENIB_APP_OSMV_CHECK_HEADER OPENIB_APP_OSMV_CHECK_LIB AC_CONFIG_FILES([man/opensm.8 man/torus-2QoS.8 man/torus-2QoS.conf.5 scripts/opensm.init scripts/redhat-opensm.init scripts/sldd.sh]) dnl Create the following Makefiles AC_OUTPUT([include/opensm/osm_version.h Makefile include/Makefile complib/Makefile libvendor/Makefile opensm/Makefile osmeventplugin/Makefile osmtest/Makefile opensm.spec]) opensm-3.3.20/aclocal.m40000644000205000001450000010377312726323424011670 00000000000000# generated automatically by aclocal 1.11.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.11.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.11.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 16 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.62])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl ]) dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 6 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([config/libtool.m4]) m4_include([config/ltoptions.m4]) m4_include([config/ltsugar.m4]) m4_include([config/ltversion.m4]) m4_include([config/lt~obsolete.m4]) m4_include([config/osmvsel.m4]) opensm-3.3.20/Makefile.am0000644000205000001450000000205312360514442012045 00000000000000 # note that order matters: make the libs first then use them SUBDIRS = complib libvendor opensm osmtest include $(DEFAULT_EVENT_PLUGIN) DIST_SUBDIRS = complib libvendor opensm osmtest include osmeventplugin ACLOCAL_AMFLAGS = -I config # we should provide a hint for other apps about the build mode of this project install-exec-hook: $(top_srcdir)/config/install-sh -m 755 -d $(DESTDIR)/$(sysconfdir)/init.d cp $(top_builddir)/scripts/opensm.init $(DESTDIR)/$(sysconfdir)/init.d/opensmd chmod 755 $(DESTDIR)/$(sysconfdir)/init.d/opensmd man_MANS = man/opensm.8 man/osmtest.8 man/torus-2QoS.8 man/torus-2QoS.conf.5 various_scripts = $(wildcard scripts/*) docs = doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt \ doc/partition-config.txt doc/opensm-sriov.txt \ doc/current-routing.txt doc/opensm_release_notes-3.3.txt EXTRA_DIST = autogen.sh opensm.spec $(various_scripts) $(man_MANS) $(docs) dist-hook: $(EXTRA_DIST) if [ -x $(top_srcdir)/gen_chlog.sh ] ; then \ cd $(top_srcdir); ./gen_chlog.sh > $(distdir)/ChangeLog ; cd - ; \ fi opensm-3.3.20/Makefile.in0000644000205000001450000007540012726323426012072 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/opensm.spec.in \ $(top_srcdir)/configure \ $(top_srcdir)/include/opensm/osm_config.h.in \ $(top_srcdir)/include/opensm/osm_version.h.in \ $(top_srcdir)/man/opensm.8.in \ $(top_srcdir)/man/torus-2QoS.8.in \ $(top_srcdir)/man/torus-2QoS.conf.5.in \ $(top_srcdir)/scripts/opensm.init.in \ $(top_srcdir)/scripts/redhat-opensm.init.in \ $(top_srcdir)/scripts/sldd.sh.in AUTHORS COPYING ChangeLog \ INSTALL NEWS config/compile config/config.guess \ config/config.sub config/depcomp config/install-sh \ config/ltmain.sh config/missing config/ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = man/opensm.8 man/torus-2QoS.8 \ man/torus-2QoS.conf.5 scripts/opensm.init \ scripts/redhat-opensm.init scripts/sldd.sh \ include/opensm/osm_version.h opensm.spec CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' man5dir = $(mandir)/man5 am__installdirs = "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)" man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d "$(distdir)" \ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr "$(distdir)"; }; } am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # note that order matters: make the libs first then use them SUBDIRS = complib libvendor opensm osmtest include $(DEFAULT_EVENT_PLUGIN) DIST_SUBDIRS = complib libvendor opensm osmtest include osmeventplugin ACLOCAL_AMFLAGS = -I config man_MANS = man/opensm.8 man/osmtest.8 man/torus-2QoS.8 man/torus-2QoS.conf.5 various_scripts = $(wildcard scripts/*) docs = doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt \ doc/partition-config.txt doc/opensm-sriov.txt \ doc/current-routing.txt doc/opensm_release_notes-3.3.txt EXTRA_DIST = autogen.sh opensm.spec $(various_scripts) $(man_MANS) $(docs) all: all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): include/opensm/osm_config.h: include/opensm/stamp-h2 @if test ! -f $@; then \ rm -f include/opensm/stamp-h2; \ $(MAKE) $(AM_MAKEFLAGS) include/opensm/stamp-h2; \ else :; fi include/opensm/stamp-h2: $(top_srcdir)/include/opensm/osm_config.h.in $(top_builddir)/config.status @rm -f include/opensm/stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status include/opensm/osm_config.h $(top_srcdir)/include/opensm/osm_config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f include/opensm/stamp-h2 touch $@ distclean-hdr: -rm -f include/opensm/osm_config.h include/opensm/stamp-h2 man/opensm.8: $(top_builddir)/config.status $(top_srcdir)/man/opensm.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ man/torus-2QoS.8: $(top_builddir)/config.status $(top_srcdir)/man/torus-2QoS.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ man/torus-2QoS.conf.5: $(top_builddir)/config.status $(top_srcdir)/man/torus-2QoS.conf.5.in cd $(top_builddir) && $(SHELL) ./config.status $@ scripts/opensm.init: $(top_builddir)/config.status $(top_srcdir)/scripts/opensm.init.in cd $(top_builddir) && $(SHELL) ./config.status $@ scripts/redhat-opensm.init: $(top_builddir)/config.status $(top_srcdir)/scripts/redhat-opensm.init.in cd $(top_builddir) && $(SHELL) ./config.status $@ scripts/sldd.sh: $(top_builddir)/config.status $(top_srcdir)/scripts/sldd.sh.in cd $(top_builddir) && $(SHELL) ./config.status $@ include/opensm/osm_version.h: $(top_builddir)/config.status $(top_srcdir)/include/opensm/osm_version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ opensm.spec: $(top_builddir)/config.status $(srcdir)/opensm.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-man5: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" @list=''; test -n "$(man5dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man5dir)" && rm -f $$files; } install-man8: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list=''; test -n "$(man8dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod u+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @$(am__cd) '$(distuninstallcheck_dir)' \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(MANS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man5 install-man8 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-man uninstall-man: uninstall-man5 uninstall-man8 .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-exec-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzma dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-man install-man5 install-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am uninstall-man \ uninstall-man5 uninstall-man8 # we should provide a hint for other apps about the build mode of this project install-exec-hook: $(top_srcdir)/config/install-sh -m 755 -d $(DESTDIR)/$(sysconfdir)/init.d cp $(top_builddir)/scripts/opensm.init $(DESTDIR)/$(sysconfdir)/init.d/opensmd chmod 755 $(DESTDIR)/$(sysconfdir)/init.d/opensmd dist-hook: $(EXTRA_DIST) if [ -x $(top_srcdir)/gen_chlog.sh ] ; then \ cd $(top_srcdir); ./gen_chlog.sh > $(distdir)/ChangeLog ; cd - ; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/opensm.spec.in0000644000205000001450000001136712360514442012603 00000000000000%define RELEASE @RELEASE@ %define rel %{?CUSTOM_RELEASE}%{!?CUSTOM_RELEASE:%RELEASE} %if %{?_with_console_socket:1}%{!?_with_console_socket:0} %define _enable_console_socket --enable-console-socket %endif %if %{?_without_console_socket:1}%{!?_without_console_socket:0} %define _disable_console_socket --disable-console-socket %endif %if %{?_with_perf_mgr:1}%{!?_with_perf_mgr:0} %define _enable_perf_mgr --enable-perf-mgr %endif %if %{?_without_perf_mgr:1}%{!?_without_perf_mgr:0} %define _disable_perf_mgr --disable-perf-mgr %endif %if %{?_with_event_plugin:1}%{!?_with_event_plugin:0} %define _enable_event_plugin --enable-default-event-plugin %endif %if %{?_without_event_plugin:1}%{!?_without_event_plugin:0} %define _disable_event_plugin --disable-default-event-plugin %endif %if %{?_with_node_name_map:1}%{!?_with_node_name_map:0} %define _enable_node_name_map --with-node-name-map%{?_with_node_name_map} %endif Summary: InfiniBand subnet manager and administration Name: opensm Version: @VERSION@ Release: %rel%{?dist} License: GPLv2 or BSD Group: System Environment/Daemons URL: http://openfabrics.org/ Source: http://www.openfabrics.org/downloads/management/@TARBALL@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libibumad-devel, libtool Requires: %{name}-libs = %{version}-%{release}, logrotate %description OpenSM provides an implementation of an InfiniBand Subnet Manager and Administration. Such a software entity is required to run for in order to initialize the InfiniBand hardware (at least one per each InfiniBand subnet). %package libs Summary: Libraries from the opensm package Group: System Environment/Libraries Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig Obsoletes: libopensm, libosmcomp, libosmvendor %description libs Shared libraries that are part of the opensm package but are also used by other applications. If you don't need opensm itself installed, these libraries can be installed to satisfy dependencies of other applications. %package devel Summary: Development files for OpenSM Group: System Environment/Libraries Requires: %{name}-libs = %{version}-%{release} libibumad-devel Obsoletes: libopensm-devel, libosmcomp-devel, libosmvendor-devel %description devel Header files for OpenSM. %package static Summary: Static version of the opensm libraries Group: System Environment/Libraries Requires: %{name}-libs = %{version}-%{release} libibumad-devel %description static Static version of the opensm libraries %prep %setup -q %build %configure \ %{?_enable_console_socket} \ %{?_disable_console_socket} \ %{?_enable_perf_mgr} \ %{?_disable_perf_mgr} \ %{?_enable_event_plugin} \ %{?_disable_event_plugin} \ %{?_enable_node_name_map} make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -f $RPM_BUILD_ROOT%{_libdir}/*.la etc=$RPM_BUILD_ROOT%{_sysconfdir} mkdir -p ${RPM_BUILD_ROOT}/var/cache/opensm if [ -f /etc/redhat-release -o -s /etc/redhat-release ]; then REDHAT="redhat-" else REDHAT="" fi mkdir -p $etc/{init.d,logrotate.d} $etc/@OPENSM_CONFIG_SUB_DIR@ install -m 755 scripts/${REDHAT}opensm.init $etc/init.d/opensmd install -D -m 644 scripts/opensm.logrotate $etc/logrotate.d/opensm install -m 755 scripts/sldd.sh $RPM_BUILD_ROOT%{_sbindir}/sldd.sh %clean rm -rf $RPM_BUILD_ROOT %post if [ $1 = 1 ]; then if [ -e /sbin/chkconfig ]; then /sbin/chkconfig --add opensmd elif [ -e /usr/sbin/update-rc.d ]; then /usr/sbin/update-rc.d opensmd defaults else /usr/lib/lsb/install_initd /etc/init.d/opensmd fi if type systemctl >/dev/null 2>&1; then systemctl --system daemon-reload fi else /etc/init.d/opensmd condrestart fi %preun if [ $1 = 0 ]; then /etc/init.d/opensmd stop if [ -e /sbin/chkconfig ]; then /sbin/chkconfig --del opensmd elif [ -e /usr/sbin/update-rc.d ]; then /usr/sbin/update-rc.d -f opensmd remove else /usr/lib/lsb/remove_initd /etc/init.d/opensmd fi rm -f /var/cache/opensm/* fi %post libs -p /sbin/ldconfig %postun libs -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_sbindir}/opensm %{_sbindir}/osmtest %{_mandir}/man8/* %{_mandir}/man5/* %doc AUTHORS COPYING README doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt doc/partition-config.txt doc/opensm-sriov.txt doc/current-routing.txt doc/opensm_release_notes-3.3.txt %{_sysconfdir}/init.d/opensmd %{_sbindir}/sldd.sh %config(noreplace) %{_sysconfdir}/logrotate.d/opensm %dir /var/cache/opensm %dir %{_sysconfdir}/@OPENSM_CONFIG_SUB_DIR@ %files libs %defattr(-,root,root,-) %{_libdir}/*.so.* %files devel %defattr(-,root,root,-) %{_includedir}/infiniband/* %{_libdir}/*.so %files static %defattr(-,root,root,-) %{_libdir}/*.a opensm-3.3.20/configure0000755000205000001450000150161712726323426011741 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for opensm 3.3.20. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: linux-rdma@vger.kernel.org about your system, including $0: any error possibly output before this message. Then $0: install a modern shell, or manually run the script $0: under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac ECHO=${lt_ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF $* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='opensm' PACKAGE_TARNAME='opensm' PACKAGE_VERSION='3.3.20' PACKAGE_STRING='opensm 3.3.20' PACKAGE_BUGREPORT='linux-rdma@vger.kernel.org' PACKAGE_URL='' ac_unique_file="opensm/osm_opensm.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS OSMV_INCLUDES OSMV_LDADD OSMV_OPENIB_FALSE OSMV_OPENIB_TRUE OSMV_SIM_FALSE OSMV_SIM_TRUE OSMV_GEN1_FALSE OSMV_GEN1_TRUE OSMV_VAPI_FALSE OSMV_VAPI_TRUE DEFAULT_EVENT_PLUGIN PER_MOD_LOGGING_FILE PREFIX_ROUTES_FILE TORUS2QOS_CONF_FILE QOS_POLICY_FILE PARTITION_CONFIG_FILE NODENAMEMAPFILE OPENSM_CONFIG_FILE OPENSM_CONFIG_DIR OPENSM_CONFIG_SUB_DIR DEBUG_FALSE DEBUG_TRUE HAVE_LD_VERSION_SCRIPT_FALSE HAVE_LD_VERSION_SCRIPT_TRUE _LEX_ _YACC_ LEXLIB LEX_OUTPUT_ROOT LEX YFLAGS YACC CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL lt_ECHO RANLIB AR OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC DEFAULT_STOP DEFAULT_START RDMA_SERVICE TARBALL RELEASE am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_rdma_service enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock enable_debug enable_libcheck enable_console_loopback enable_console_socket enable_perf_mgr enable_perf_mgr_profile with_opensm_conf_sub_dir with_opensm_conf_file with_node_name_map with_partitions_conf with_qos_policy_conf with_prefix_routes_conf with_per_module_logging_conf enable_default_event_plugin with_osmv with_umad_prefix with_umad_includes with_umad_libs with_sim ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP YACC YFLAGS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures opensm 3.3.20 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/opensm] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of opensm 3.3.20:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-debug Turn on debugging --disable-libcheck do not test for presence of ib libraries --enable-console-loopback Enable a console socket on the loopback interface, requires tcp_wrappers (default yes) --enable-console-socket Enable a console socket, requires --enable-console-loopback (default no) --enable-perf-mgr Enable the performance manager (default yes) --enable-perf-mgr-profile Enable the performance manager profiling (default no) --enable-default-event-plugin Enable a default event plugin "osmeventplugin" (default no) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-rdma-service=name name of the RDMA service: "rdma" when using /etc/init.d/rdma to start RDMA services; "openibd" when using /etc/init.d/openibd to start RDMA services [default=${default_rdma_service}] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-opensm-conf-sub-dir=dir define a directory name for opensm's conf files / (default "opensm") --with-opensm-conf-file=file define a default OpenSM config file (default opensm.conf) --with-node-name-map=file define a default node name map file (default ib-node-name-map) --with-partitions-conf=file define a partitions config file (default partitions.conf) --with-qos-policy-conf=file define a QOS policy config file (default qos-policy.conf) --with-prefix-routes-conf=file define a Prefix Routes config file (default is prefix-routes.conf) --with-per-module-logging-conf=file define a Per Module Logging config file (default is per-module-logging.conf) --with-osmv= define the osm vendor type to build --with-umad-prefix= define the dir used as prefix for ibumad installation --with-umad-includes= define the dir where ibumad includes are installed --with-umad-libs= define the dir where ibumad libs are installed --with-sim= define the simulator prefix for building sim vendor (default /usr) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF opensm configure 3.3.20 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ----------------------------------------- ## ## Report this to linux-rdma@vger.kernel.org ## ## ----------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by opensm $as_me 3.3.20, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in config "$srcdir"/config; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. ac_config_headers="$ac_config_headers include/config.h include/opensm/osm_config.h" am__api_version='1.11' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; esac # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='opensm' VERSION='3.3.20' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' RELEASE=${RELEASE:-${VERSION}} TARBALL=${TARBALL:-${PACKAGE}-${VERSION}.tar.gz} default_rdma_service=openibd # Check whether --with-rdma_service was given. if test "${with_rdma_service+set}" = set; then : withval=$with_rdma_service; fi RDMA_SERVICE=${with_rdma_service:-${default_rdma_service}} if { rpm -q sles-release || rpm -q openSUSE-release; } >/dev/null 2>&1; then default_stop="0 1 4 6" else default_stop="0 1 6" fi default_start="null" DEFAULT_START=$default_start DEFAULT_STOP=$default_stop $as_echo "#define _OSM_CONFIG_H_ 1" >>confdefs.h ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.2.6b' macro_revision='1.3017' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$ac_tool_prefix"; then for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:4729: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:4732: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:4735: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5941 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7470: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7474: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7809: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7813: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7914: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7918: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7969: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7973: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(void) {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Add ABI-specific directories to the system library path. sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib" # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10339 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10435 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_YACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LEX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LEX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ yyless ((input () != 0)); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { { ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if ${ac_cv_prog_lex_root+:} false; then : $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if ${ac_cv_lib_lex+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lex=$ac_lib fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if ${ac_cv_prog_lex_yytext_pointer+:} false; then : $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_prog_lex_yytext_pointer=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then $as_echo "#define YYTEXT_POINTER 1" >>confdefs.h fi rm -f conftest.l $LEX_OUTPUT_ROOT.c fi for ac_prog in $YACC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog__YACC_+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$_YACC_"; then ac_cv_prog__YACC_="$_YACC_" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog__YACC_="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi _YACC_=$ac_cv_prog__YACC_ if test -n "$_YACC_"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_YACC_" >&5 $as_echo "$_YACC_" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$_YACC_" && break done test -n "$_YACC_" || _YACC_="none" if test "$_YACC_" = "none" then as_fn_error $? "No bison/byacc/yacc found." "$LINENO" 5 fi for ac_prog in $LEX do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog__LEX_+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$_LEX_"; then ac_cv_prog__LEX_="$_LEX_" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog__LEX_="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi _LEX_=$ac_cv_prog__LEX_ if test -n "$_LEX_"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_LEX_" >&5 $as_echo "$_LEX_" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$_LEX_" && break done test -n "$_LEX_" || _LEX_="none" if test "$_LEX_" = "none" then as_fn_error $? "No flex/lex found." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 $as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_mutex_init (); int main () { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pthread_pthread_mutex_init=yes else ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 $as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" else as_fn_error $? "pthread_mutex_init() not found. libosmcomp requires libpthread." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBDL 1 _ACEOF LIBS="-ldl $LIBS" else as_fn_error $? "dlopen() not found. OpenSM requires libdl." "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5 $as_echo_n "checking for working volatile... " >&6; } if ${ac_cv_c_volatile+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { volatile int x; int * volatile y = (int *) 0; return !x && !y; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_volatile=yes else ac_cv_c_volatile=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5 $as_echo "$ac_cv_c_volatile" >&6; } if test $ac_cv_c_volatile = no; then $as_echo "#define volatile /**/" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler supports __builtin_expect" >&5 $as_echo_n "checking if the compiler supports __builtin_expect... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return __builtin_expect(1, 1) ? 1 : 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : have_builtin_expect=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else have_builtin_expect=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test "x_$have_builtin_expect" = "x_yes" ; then $as_echo "#define HAVE_BUILTIN_EXPECT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ld accepts --version-script" >&5 $as_echo_n "checking whether ld accepts --version-script... " >&6; } if ${ac_cv_version_script+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "`$LD --help < /dev/null 2>/dev/null | grep version-script`"; then ac_cv_version_script=yes else ac_cv_version_script=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_version_script" >&5 $as_echo "$ac_cv_version_script" >&6; } if test "$ac_cv_version_script" = "yes"; then HAVE_LD_VERSION_SCRIPT_TRUE= HAVE_LD_VERSION_SCRIPT_FALSE='#' else HAVE_LD_VERSION_SCRIPT_TRUE='#' HAVE_LD_VERSION_SCRIPT_FALSE= fi # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; case "${enableval}" in yes) debug=true ;; no) debug=false ;; *) as_fn_error $? "bad value ${enableval} for --enable-debug" "$LINENO" 5 ;; esac else debug=false fi if test x$debug = xtrue ; then $as_echo "#define OSM_DEBUG 1" >>confdefs.h $as_echo "#define _DEBUG_ 1" >>confdefs.h fi if test x$debug = xtrue; then DEBUG_TRUE= DEBUG_FALSE='#' else DEBUG_TRUE='#' DEBUG_FALSE= fi # Check whether --enable-libcheck was given. if test "${enable_libcheck+set}" = set; then : enableval=$enable_libcheck; if test x$enableval = xno ; then disable_libcheck=yes fi fi # --- BEGIN OPENIB_OSM_CONSOLE_SOCKET_SEL --- { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable console loopback" >&5 $as_echo_n "checking to enable console loopback... " >&6; } # Check whether --enable-console-loopback was given. if test "${enable_console_loopback+set}" = set; then : enableval=$enable_console_loopback; case $enableval in yes) console_loopback=yes ;; no) console_loopback=no ;; esac else console_loopback=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $console_loopback" >&5 $as_echo "$console_loopback" >&6; } if test $console_loopback = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for request_init in -lwrap" >&5 $as_echo_n "checking for request_init in -lwrap... " >&6; } if ${ac_cv_lib_wrap_request_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lwrap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char request_init (); int main () { return request_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_wrap_request_init=yes else ac_cv_lib_wrap_request_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wrap_request_init" >&5 $as_echo "$ac_cv_lib_wrap_request_init" >&6; } if test "x$ac_cv_lib_wrap_request_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBWRAP 1 _ACEOF LIBS="-lwrap $LIBS" else console_loopback=no { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libwrap is missing. setting console_loopback=no" >&5 $as_echo "$as_me: WARNING: libwrap is missing. setting console_loopback=no" >&2;} fi fi if test $console_loopback = yes; then $as_echo "#define ENABLE_OSM_CONSOLE_LOOPBACK 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable console socket" >&5 $as_echo_n "checking to enable console socket... " >&6; } # Check whether --enable-console-socket was given. if test "${enable_console_socket+set}" = set; then : enableval=$enable_console_socket; case $enableval in yes) console_socket=yes ;; no) console_socket=no ;; esac else console_socket=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $console_socket" >&5 $as_echo "$console_socket" >&6; } if test $console_socket = yes; then if test $console_loopback = no; then as_fn_error $? "--enable-console-socket requires --enable-console-loopback" "$LINENO" 5 fi $as_echo "#define ENABLE_OSM_CONSOLE_SOCKET 1" >>confdefs.h fi # --- END OPENIB_OSM_CONSOLE_SOCKET_SEL --- # --- BEGIN OPENIB_OSM_PERF_MGR_SEL --- { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable perf mgr" >&5 $as_echo_n "checking to enable perf mgr... " >&6; } # Check whether --enable-perf-mgr was given. if test "${enable_perf_mgr+set}" = set; then : enableval=$enable_perf_mgr; case $enableval in yes) perf_mgr=yes ;; no) perf_mgr=no ;; esac else perf_mgr=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $perf_mgr" >&5 $as_echo "$perf_mgr" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable perf mgr profiling" >&5 $as_echo_n "checking to enable perf mgr profiling... " >&6; } # Check whether --enable-perf-mgr-profile was given. if test "${enable_perf_mgr_profile+set}" = set; then : enableval=$enable_perf_mgr_profile; case $enableval in yes) perf_mgr_profile=yes ;; no) perf_mgr_profile=no ;; esac else perf_mgr_profile=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $perf_mgr_profile" >&5 $as_echo "$perf_mgr_profile" >&6; } if test $perf_mgr = yes; then $as_echo "#define ENABLE_OSM_PERF_MGR 1" >>confdefs.h if test $perf_mgr_profile = yes; then $as_echo "#define ENABLE_OSM_PERF_MGR_PROFILE 1" >>confdefs.h fi fi # --- END OPENIB_OSM_PERF_MGR_SEL --- conf_dir_tmp1="`eval echo ${sysconfdir} | sed 's/^NONE/$ac_default_prefix/'`" SYS_CONFIG_DIR="`eval echo $conf_dir_tmp1`" OPENSM_CONFIG_SUB_DIR=opensm { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-opensm-conf-sub-dir" >&5 $as_echo_n "checking for --with-opensm-conf-sub-dir... " >&6; } # Check whether --with-opensm-conf-sub-dir was given. if test "${with_opensm_conf_sub_dir+set}" = set; then : withval=$with_opensm_conf_sub_dir; case "$withval" in no) ;; *) OPENSM_CONFIG_SUB_DIR=$withval ;; esac fi OPENSM_CONFIG_DIR=$SYS_CONFIG_DIR/$OPENSM_CONFIG_SUB_DIR { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENSM_CONFIG_DIR" >&5 $as_echo "$OPENSM_CONFIG_DIR" >&6; } cat >>confdefs.h <<_ACEOF #define OPENSM_CONFIG_DIR "$OPENSM_CONFIG_DIR" _ACEOF OPENSM_CONFIG_FILE=opensm.conf { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-opensm-conf-file " >&5 $as_echo_n "checking for --with-opensm-conf-file ... " >&6; } # Check whether --with-opensm-conf-file was given. if test "${with_opensm_conf_file+set}" = set; then : withval=$with_opensm_conf_file; case "$withval" in no) ;; *) OPENSM_CONFIG_FILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${OPENSM_CONFIG_FILE}" >&5 $as_echo "${OPENSM_CONFIG_FILE}" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_OPENSM_CONFIG_FILE "$OPENSM_CONFIG_DIR/$OPENSM_CONFIG_FILE" _ACEOF NODENAMEMAPFILE=ib-node-name-map { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-node-name-map " >&5 $as_echo_n "checking for --with-node-name-map ... " >&6; } # Check whether --with-node-name-map was given. if test "${with_node_name_map+set}" = set; then : withval=$with_node_name_map; case "$withval" in no) ;; *) NODENAMEMAPFILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NODENAMEMAPFILE" >&5 $as_echo "$NODENAMEMAPFILE" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_NODENAME_MAP "$OPENSM_CONFIG_DIR/$NODENAMEMAPFILE" _ACEOF PARTITION_CONFIG_FILE=partitions.conf { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-partitions-conf" >&5 $as_echo_n "checking for --with-partitions-conf... " >&6; } # Check whether --with-partitions-conf was given. if test "${with_partitions_conf+set}" = set; then : withval=$with_partitions_conf; case "$withval" in no) ;; *) PARTITION_CONFIG_FILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PARTITION_CONFIG_FILE" >&5 $as_echo "$PARTITION_CONFIG_FILE" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_PARTITION_CONFIG_FILE "$OPENSM_CONFIG_DIR/$PARTITION_CONFIG_FILE" _ACEOF QOS_POLICY_FILE=qos-policy.conf { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-qos-policy-conf" >&5 $as_echo_n "checking for --with-qos-policy-conf... " >&6; } # Check whether --with-qos-policy-conf was given. if test "${with_qos_policy_conf+set}" = set; then : withval=$with_qos_policy_conf; case "$withval" in no) ;; *) QOS_POLICY_FILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $QOS_POLICY_FILE" >&5 $as_echo "$QOS_POLICY_FILE" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_QOS_POLICY_FILE "$OPENSM_CONFIG_DIR/$QOS_POLICY_FILE" _ACEOF TORUS2QOS_CONF_FILE=torus-2QoS.conf PREFIX_ROUTES_FILE=prefix-routes.conf { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-prefix-routes-conf" >&5 $as_echo_n "checking for --with-prefix-routes-conf... " >&6; } # Check whether --with-prefix-routes-conf was given. if test "${with_prefix_routes_conf+set}" = set; then : withval=$with_prefix_routes_conf; case "$withval" in no) ;; *) PREFIX_ROUTES_FILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PREFIX_ROUTES_FILE" >&5 $as_echo "$PREFIX_ROUTES_FILE" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_PREFIX_ROUTES_FILE "$OPENSM_CONFIG_DIR/$PREFIX_ROUTES_FILE" _ACEOF PER_MOD_LOGGING_FILE=per-module-logging.conf { $as_echo "$as_me:${as_lineno-$LINENO}: checking for --with-per-module-logging-conf" >&5 $as_echo_n "checking for --with-per-module-logging-conf... " >&6; } # Check whether --with-per-module-logging.conf was given. if test "${with_per_module_logging_conf+set}" = set; then : withval=$with_per_module_logging_conf; case "$withval" in no) ;; *) PER_MOD_LOGGING_FILE=$withval ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PER_MOD_LOGGING_FILE" >&5 $as_echo "$PER_MOD_LOGGING_FILE" >&6; } cat >>confdefs.h <<_ACEOF #define HAVE_DEFAULT_PER_MOD_LOGGING_FILE "$OPENSM_CONFIG_DIR/$PER_MOD_LOGGING_FILE" _ACEOF # --- BEGIN OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL --- { $as_echo "$as_me:${as_lineno-$LINENO}: checking to enable default event plugin" >&5 $as_echo_n "checking to enable default event plugin... " >&6; } # Check whether --enable-default-event-plugin was given. if test "${enable_default_event_plugin+set}" = set; then : enableval=$enable_default_event_plugin; case $enableval in yes) default_event_plugin=yes ;; no) default_event_plugin=no ;; esac else default_event_plugin=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $default_event_plugin" >&5 $as_echo "$default_event_plugin" >&6; } if test $default_event_plugin = yes; then $as_echo "#define ENABLE_OSM_DEFAULT_EVENT_PLUGIN 1" >>confdefs.h DEFAULT_EVENT_PLUGIN=osmeventplugin else DEFAULT_EVENT_PLUGIN= fi # --- END OPENIB_OSM_DEFAULT_EVENT_PLUGIN_SEL --- # --- BEGIN OPENIB_APP_OSMV_SEL --- # Check whether --with-osmv was given. if test "${with_osmv+set}" = set; then : withval=$with_osmv; { $as_echo "$as_me:${as_lineno-$LINENO}: Using OSM Vendor Type:$with_osmv" >&5 $as_echo "$as_me: Using OSM Vendor Type:$with_osmv" >&6;} else with_osmv="openib" fi # Check whether --with-umad-prefix was given. if test "${with_umad_prefix+set}" = set; then : withval=$with_umad_prefix; { $as_echo "$as_me:${as_lineno-$LINENO}: Using ibumad installation prefix:$with_umad_prefix" >&5 $as_echo "$as_me: Using ibumad installation prefix:$with_umad_prefix" >&6;} else with_umad_prefix="" fi # Check whether --with-umad-includes was given. if test "${with_umad_includes+set}" = set; then : withval=$with_umad_includes; { $as_echo "$as_me:${as_lineno-$LINENO}: Using ibumad includes from:$with_umad_includes" >&5 $as_echo "$as_me: Using ibumad includes from:$with_umad_includes" >&6;} else with_umad_includes="" fi if test x$with_umad_includes = x; then if test x$with_umad_prefix != x; then with_umad_includes=$with_umad_prefix/include fi fi # Check whether --with-umad-libs was given. if test "${with_umad_libs+set}" = set; then : withval=$with_umad_libs; { $as_echo "$as_me:${as_lineno-$LINENO}: Using ibumad libs from:$with_umad_libs" >&5 $as_echo "$as_me: Using ibumad libs from:$with_umad_libs" >&6;} else with_umad_libs="" fi if test x$with_umad_libs = x; then if test x$with_umad_prefix != x; then if test "$(uname -m)" = "x86_64" -o "$(uname -m)" = "ppc64"; then with_umad_libs=$with_umad_prefix/lib64 else with_umad_libs=$with_umad_prefix/lib fi fi fi # Check whether --with-sim was given. if test "${with_sim+set}" = set; then : withval=$with_sim; { $as_echo "$as_me:${as_lineno-$LINENO}: Using Simulator from:$with_sim" >&5 $as_echo "$as_me: Using Simulator from:$with_sim" >&6;} else with_sim="/usr" fi if test $with_osmv = "openib"; then $as_echo "#define OSM_VENDOR_INTF_OPENIB 1" >>confdefs.h OSMV_INCLUDES="-I\$(srcdir)/../include -I\$(srcdir)/../../libibumad/include -I\$(includedir)" OSMV_LDADD="-L\$(abs_srcdir)/../../libibumad/.libs -L\$(libdir) -libumad" if test "x$with_umad_libs" != "x"; then OSMV_LDADD="-L$with_umad_libs $OSMV_LDADD" fi if test "x$with_umad_includes" != "x"; then OSMV_INCLUDES="-I$with_umad_includes $OSMV_INCLUDES" fi $as_echo "#define DUAL_SIDED_RMPP 1" >>confdefs.h elif test $with_osmv = "sim" ; then $as_echo "#define OSM_VENDOR_INTF_SIM 1" >>confdefs.h OSMV_INCLUDES="-I$with_sim/include -I\$(srcdir)/../include" OSMV_LDADD="-L$with_sim/lib -libmscli" elif test $with_osmv = "gen1"; then $as_echo "#define OSM_VENDOR_INTF_TS 1" >>confdefs.h if test -z $MTHOME; then MTHOME=/usr/local/ibgd/driver/infinihost fi OSMV_INCLUDES="-I$MTHOME/include -I\$(srcdir)/../include" osmv_found=0 if test -z $TSHOME; then osmv_dir=`uname -r|sed 's/-smp//'` osmv_dir_smp=`uname -r` for d in /usr/src/linux-$osmv_dir /usr/src/linux-$osmv_dir_smp /lib/modules/$osmv_dir/build /lib/modules/$osmv_dir_smp/build/; do if test -f $d/drivers/infiniband/include/ts_ib_useraccess.h; then OSMV_INCLUDES="$OSMV_INCLUDES -I$d/drivers/infiniband/include" osmv_found=1 fi done else if test -f $TSHOME/ts_ib_useraccess.h; then OSMV_INCLUDES="$OSMV_INCLUDES -I$TSHOME" osmv_found=1 fi fi if test $osmv_found = 0; then as_fn_error $? "Fail to find gen1 include files dir" "$LINENO" 5 fi OSMV_LDADD="-L/usr/local/ibgd/driver/infinihost/lib -lvapi -lmosal -lmtl_common -lmpga" elif test $with_osmv = "vapi"; then $as_echo "#define OSM_VENDOR_INTF_MTL 1" >>confdefs.h OSMV_INCLUDES="-I/usr/mellanox/include -I/usr/include -I\$(srcdir)/../include" OSMV_LDADD="-L/usr/lib -L/usr/mellanox/lib -lib_mgt -lvapi -lmosal -lmtl_common -lmpga" else as_fn_error $? "Invalid Vendor Type provided:$with_osmv should be either openib,sim,gen1" "$LINENO" 5 fi if test $with_osmv = "vapi"; then OSMV_VAPI_TRUE= OSMV_VAPI_FALSE='#' else OSMV_VAPI_TRUE='#' OSMV_VAPI_FALSE= fi if test $with_osmv = "gen1"; then OSMV_GEN1_TRUE= OSMV_GEN1_FALSE='#' else OSMV_GEN1_TRUE='#' OSMV_GEN1_FALSE= fi if test $with_osmv = "sim"; then OSMV_SIM_TRUE= OSMV_SIM_FALSE='#' else OSMV_SIM_TRUE='#' OSMV_SIM_FALSE= fi if test $with_osmv = "openib"; then OSMV_OPENIB_TRUE= OSMV_OPENIB_FALSE='#' else OSMV_OPENIB_TRUE='#' OSMV_OPENIB_FALSE= fi $as_echo "#define VENDOR_RMPP_SUPPORT 1" >>confdefs.h # --- END OPENIB_APP_OSMV_SEL --- # --- BEGIN OPENIB_APP_OSMV_CHECK_HEADER --- if test "$disable_libcheck" != "yes"; then if test $with_osmv = "openib"; then osmv_headers=infiniband/umad.h elif test $with_osmv = "sim" ; then osmv_headers=ibmgtsim/ibms_client_api.h elif test $with_osmv = "gen1"; then osmv_headers= elif test $with_osmv = "vapi"; then osmv_headers=vapi.h else as_fn_error $? "OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_HEADER" "$LINENO" 5 fi if test "x$osmv_headers" != "x"; then for ac_header in $osmv_headers do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi fi # --- END OPENIB_APP_OSMV_CHECK_HEADER --- # --- BEGIN OPENIB_APP_OSMV_CHECK_LIB --- if test "$disable_libcheck" != "yes"; then if test $with_osmv = "openib"; then LDADD="$LDADD $OSMV_LDADD" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for umad_init in -libumad" >&5 $as_echo_n "checking for umad_init in -libumad... " >&6; } if ${ac_cv_lib_ibumad_umad_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-libumad $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char umad_init (); int main () { return umad_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ibumad_umad_init=yes else ac_cv_lib_ibumad_umad_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ibumad_umad_init" >&5 $as_echo "$ac_cv_lib_ibumad_umad_init" >&6; } if test "x$ac_cv_lib_ibumad_umad_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBIBUMAD 1 _ACEOF LIBS="-libumad $LIBS" else as_fn_error $? "umad_init() not found. libosmvendor of type openib requires libibumad." "$LINENO" 5 fi elif test $with_osmv = "sim" ; then LDFLAGS="$LDFLAGS -L$with_sim/lib" as_ac_File=`$as_echo "ac_cv_file_$with_sim/lib/libibmscli.a" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $with_sim/lib/libibmscli.a" >&5 $as_echo_n "checking for $with_sim/lib/libibmscli.a... " >&6; } if eval \${$as_ac_File+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$with_sim/lib/libibmscli.a"; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes"; then : else as_fn_error $? "ibms_bind() not found. libosmvendor of type sim requires libibmscli." "$LINENO" 5 fi elif test $with_osmv = "gen1"; then LDFLAGS="$LDFLAGS -L$MTHOME/lib -L$MTHOME/lib64 -lmosal -lmtl_common -lmpga" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vipul_init in -lvapi" >&5 $as_echo_n "checking for vipul_init in -lvapi... " >&6; } if ${ac_cv_lib_vapi_vipul_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lvapi $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char vipul_init (); int main () { return vipul_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_vapi_vipul_init=yes else ac_cv_lib_vapi_vipul_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vapi_vipul_init" >&5 $as_echo "$ac_cv_lib_vapi_vipul_init" >&6; } if test "x$ac_cv_lib_vapi_vipul_init" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBVAPI 1 _ACEOF LIBS="-lvapi $LIBS" else as_fn_error $? "vipul_init() not found. libosmvendor of type gen1 requires libvapi." "$LINENO" 5 fi elif test $with_osmv != "vapi"; then as_fn_error $? "OSM Vendor Type not defined: please make sure OPENIB_APP_OSMV SEL is run before CHECK_LIB" "$LINENO" 5 fi fi # --- END OPENIB_APP_OSMV_CHECK_LIB --- ac_config_files="$ac_config_files man/opensm.8 man/torus-2QoS.8 man/torus-2QoS.conf.5 scripts/opensm.init scripts/redhat-opensm.init scripts/sldd.sh" ac_config_files="$ac_config_files include/opensm/osm_version.h Makefile include/Makefile complib/Makefile libvendor/Makefile opensm/Makefile osmeventplugin/Makefile osmtest/Makefile opensm.spec" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then as_fn_error $? "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then as_fn_error $? "conditional \"DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSMV_VAPI_TRUE}" && test -z "${OSMV_VAPI_FALSE}"; then as_fn_error $? "conditional \"OSMV_VAPI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSMV_GEN1_TRUE}" && test -z "${OSMV_GEN1_FALSE}"; then as_fn_error $? "conditional \"OSMV_GEN1\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSMV_SIM_TRUE}" && test -z "${OSMV_SIM_FALSE}"; then as_fn_error $? "conditional \"OSMV_SIM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${OSMV_OPENIB_TRUE}" && test -z "${OSMV_OPENIB_FALSE}"; then as_fn_error $? "conditional \"OSMV_OPENIB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by opensm $as_me 3.3.20, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ opensm config.status 3.3.20 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ AR \ AR_FLAGS \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ SHELL \ ECHO \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` ;; esac ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "include/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;; "include/opensm/osm_config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/opensm/osm_config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "man/opensm.8") CONFIG_FILES="$CONFIG_FILES man/opensm.8" ;; "man/torus-2QoS.8") CONFIG_FILES="$CONFIG_FILES man/torus-2QoS.8" ;; "man/torus-2QoS.conf.5") CONFIG_FILES="$CONFIG_FILES man/torus-2QoS.conf.5" ;; "scripts/opensm.init") CONFIG_FILES="$CONFIG_FILES scripts/opensm.init" ;; "scripts/redhat-opensm.init") CONFIG_FILES="$CONFIG_FILES scripts/redhat-opensm.init" ;; "scripts/sldd.sh") CONFIG_FILES="$CONFIG_FILES scripts/sldd.sh" ;; "include/opensm/osm_version.h") CONFIG_FILES="$CONFIG_FILES include/opensm/osm_version.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "complib/Makefile") CONFIG_FILES="$CONFIG_FILES complib/Makefile" ;; "libvendor/Makefile") CONFIG_FILES="$CONFIG_FILES libvendor/Makefile" ;; "opensm/Makefile") CONFIG_FILES="$CONFIG_FILES opensm/Makefile" ;; "osmeventplugin/Makefile") CONFIG_FILES="$CONFIG_FILES osmeventplugin/Makefile" ;; "osmtest/Makefile") CONFIG_FILES="$CONFIG_FILES osmtest/Makefile" ;; "opensm.spec") CONFIG_FILES="$CONFIG_FILES opensm.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == "file_magic". file_magic_cmd=$lt_file_magic_cmd # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name of the directory that contains temporary libtool files. objdir=$objdir # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that does not interpret backslashes. ECHO=$lt_ECHO # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $* )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[^=]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$@"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1+=\$2" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1=\$$1\$2" } _LT_EOF ;; esac sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi opensm-3.3.20/AUTHORS0000644000205000001450000000060312104655724011065 00000000000000 By the chronological order of involvement: Steve King, Intel Anil Keshavamurthy, Intel Eitan Zahavi, Mellanox Technologies, eitan@mellanox.co.il Yael Kalka, Mellanox Technologies, yael@mellanox.co.il Shahar Frank, Voltaire Hal Rosenstock, Voltaire, halr@voltaire.com Sasha Khapyorsky, Voltaire, sashak@voltaire.com opensm-3.3.20/COPYING0000644000205000001450000000274012104655724011054 00000000000000 Copyright (c) 2004-2008 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. opensm-3.3.20/ChangeLog0000644000205000001450000145525012726325077011611 00000000000000 ** Version: HEAD Thu Jun 9 19:10:28 2016 +0300 Hal Rosenstock 9bf9def273a832780e36c4ff448e515847795b3e * Update opensm_release_notes-3.3.txt Thu Jun 9 18:21:12 2016 +0300 Hal Rosenstock ed5b8fe0080a6e88675b474500ea6b7fd33a6bff * Update package number for OpenSM to 3.3.20 for release Thu Jun 9 18:19:23 2016 +0300 Hal Rosenstock da90f1cfa0c2925fba398b824ab0e199e8324470 * Update (internal) shared library versions Tue Jun 7 12:08:35 2016 +0300 Daniel Klein bb15d2f4af15fdfe6289284e9243aec82fec2967 * osm_service.c: Fix missing endian conversion in log message Tue May 24 13:27:44 2016 +0300 Shlomi Nimrodi c0e81418cddb44f1332cb018ddae2eee418fd6a2 * Fix various coverity issues Wed Sep 19 15:42:26 2012 +0300 Alex Netes a0d915733f5cbbde8082fe8f0aeafd9dec928605 * osm_subnet.c: Add guid_routing_order_no_scatter option to opensm.conf Mon May 23 12:49:37 2016 +0300 Hal Rosenstock 5d521c14c14f4889c4280f99f49614c75561040f * osm_state_mgr.c: Update comment in state_mgr_check_tbl_consistency Thu May 19 18:17:33 2016 +0300 Shlomi Nimrodi 62ea61a15e1b90ce8b8bc864791275edb1527d42 * osm_state_mgr.c: Fix bug in handling of PortInfo Set timeout Sun May 1 13:14:10 2016 +0300 Shlomi Nimrodi ccefa3d737d2f50918ba54504ead52d02740e06a * osm_sm_mad_ctrl.c: Add ':' to "ERR 3120" error message Tue Nov 24 16:56:12 2015 +0200 Shlomi Nimrodi fbe51070dee095ee10c588526fc763275640ded7 * osm_subnet.c: Add support for Switch-IB2 in is_mlnx_ext_port_info_supported Tue Mar 1 20:46:35 2016 +0200 Hal Rosenstock dc45fca09b86fe365e58df787b050a8d83e6bcf9 * ib_types.h: Comment change to indicate 1.3.1 rather than 1.2 IBA spec Tue Mar 1 20:45:22 2016 +0200 Hal Rosenstock 37e1246eb05b9371419ad84a2aa1006653daaf7b * ib_types.h: Cosmetic formatting changes Mon Dec 28 13:34:10 2015 +0200 Vladimir Koushnir 6eb8b964f1a2563b20e750b2253eff2a9881f709 * ftree: Additional ftree indexing algorithm Fri Feb 26 12:05:21 2016 +0200 Hal Rosenstock 73fd8ee8df2c82910b8ca0c11bd1d92dd46ff73b * man/opensm.8.in: Fix typo (missing close parenthesis) Fri Feb 26 11:59:38 2016 +0200 Hal Rosenstock c32b8139a154626722d9b18bfaadf53502fe3d74 * doc/current-routing.txt: Fix typo Wed Feb 24 14:55:48 2016 +0200 Hal Rosenstock c4691e795e892c9b427dadb335445373d10973fa * ib_types.h: Cosmetic commentary fix Thu Feb 11 16:48:47 2016 +0200 Shlomi Nimrodi 85e2214dd8005fbd2225c5ea5fbe6795b6e94823 * osm_sa_mcmember_record.c: Prevent log errors swamp in MC query scenario Mon Jan 11 14:00:43 2016 +0200 Tomer Cohen 34e81dffaa1ce1b909733432a8c013f539cf4245 * Change precedence in pkey manager with indx0 feature Tue Mar 24 10:34:11 2015 +0200 Shlomi Nimrodi aa905e299715c79d3bce38c7f3cf7a0b3b76d294 * osm_pkey.[h c], osm_prtn.c: Create method to set pkey at indx0 Wed Jan 13 10:44:12 2016 +0200 Shlomi Nimrodi 8a696eb25930d6414dbe9eb6003c6875463dd2a1 * osm_base.h: Fix OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED definition Tue Dec 18 13:43:28 2012 +0200 Hal Rosenstock 70a364f7c4da48328ccd3ceda48c9dd7dde31353 * opensm/osm_pkey_mgr.c: Fix pkey index wraparound/reuse Tue Sep 9 15:28:09 2014 +0300 Tomer Cohen c1f7ffd24c762fa30f802d7ba5626e8fc80fa674 * Support configuration for index 0 in pkey table Fri Nov 20 17:56:22 2015 +0200 Hal Rosenstock 88626f4bb4b4f6a4444ae8b44393fbc18b0abbcd * osm_sa_mcmember_record.c: Updated Mellanox copyright years Fri Nov 20 17:54:55 2015 +0200 Hal Rosenstock 432727b8a0e7d73a966e0d573e4fed079ae5f311 * osm_sa_mcmember_record.c: Cosmetic formatting change to mcmr_rcv_create_new_mgrp Fri Nov 20 17:47:12 2015 +0200 Hal Rosenstock b85c31e230b831d4411cc2f875c017e01f32db69 * osm_prtn_config.c: Cosmetic formatting changes in manage_membership_change Fri Nov 20 17:43:26 2015 +0200 Hal Rosenstock 1a2a6d762dc25948be2efc9715b18e048ef58d76 * osm_prtn_config.c: Updated Mellanox copyright years Fri Nov 20 17:30:05 2015 +0200 Hal Rosenstock 8b288b88501468a5dcbf13561967d4dd70f94601 * osm_mcast_mgr.c: Cosmetic formatting change in create_mgrp_switch_map Sun Nov 1 16:50:56 2015 +0200 Rafi Wiener 4772806964efe9cc2e6934ab29f6a4bb28305ed3 * osm_state_mgr.c: Fix uninitialized area of SMInfo SET mad Mon Jul 27 22:08:32 2015 +0300 Daniel Klein 6e27bbabbdcb7b74e37b77ff650c51b25b9aa409 * osm_multicast.c: Dump sa after deleting well known mc group Tue Sep 3 15:17:20 2013 +0300 Daniel Klein df212a6e197401943a740701bc58c50efa44b5f9 * osm_multicast.c: Fix not dumping empty predefined mc groups Wed Nov 4 17:07:45 2015 +0200 Hal Rosenstock 175de416b6c4c00779c00ca8fbcbe21fa5610e7f * osm_prtn.c: Cosmetic formatting change Mon Nov 2 10:13:47 2015 +0200 Daniel Klein 1007810297d7f115a5d72dd095937246a415b0bd * osm_sa_guidinfo_record.c: Fix memory leak in set_guidinfo Thu Oct 1 18:07:59 2015 +0300 Hal Rosenstock 1b73efd8176e9d3ee6c7c0ab79d86695642a9f5e * osm_sa_mcmember_record.c: Conditionalize multicast join parameter validation on new mcgroup_join_validation option Wed Sep 30 14:25:15 2015 +0300 Hal Rosenstock 4cd7ec3c6617b944ef5d23ec0a07eaf00728825c * osm_sa_mcmember_record.c: Validate IPoIB non broadcast group parameters on group creation Thu Oct 15 16:55:22 2015 +0300 Hal Rosenstock 6272a56ca5c7db89a299e8b68380fe3d7f2a85ae * osm_ucast_dfsssp.c: In dfsssp_do_mcast_routing, update adj_list first Thu Oct 15 16:48:38 2015 +0300 Hal Rosenstock 870b21a8ae67e24d957151f7298f737e9b8c9bc4 * osm_ucast_dfsssp.c: Fix some commentary typos Tue Oct 13 15:25:50 2015 +0200 Jens Domke 44b4edcb336d90dfef352cdfd63f417ccfff2324 * osm_ucast_mgr.c: LFT update breaks if IB_SMP_DATA_SIZE changes Tue Oct 13 17:19:06 2015 +0300 Hal Rosenstock d5c51e9c0c2be63ccc47b3dffa2b046f00ca5561 * osm_ucast_mgr.c: Cosmetic formatting change Thu Oct 1 10:33:23 2015 +0200 Daniel Klein f234d8300b88113b5e54d9abe27a4a6a35fc96a8 * osm_inform.c: Cosmetic code refactoring in match_inf_rec Thu Oct 1 20:08:51 2015 +0300 Hal Rosenstock fdd1a68d3364082d7c7fc34634df463cedffc2e6 * Updated some Mellanox copyrights Thu Oct 1 22:55:11 2015 +0300 Hal Rosenstock ecf07ebe7b525a8faefc4fdd6eb61ef950d61d24 * Set Type field in Notice attribute using IB_NOTICE_TYPE_SUBN_MGMT define Thu Oct 1 20:04:34 2015 +0300 Hal Rosenstock 022e6af863cc558b9ef9b9d8cda14f217404788e * Use SM trap defines from ib_types.h rather than hard coded values Thu Oct 1 20:00:01 2015 +0300 Hal Rosenstock d111a2c1553e1ae175493cef57a0eaba301b2f46 * ib_types.h: Cosmetic formatting change Thu Oct 1 18:19:00 2015 +0300 Hal Rosenstock 1cbea4b653018e5e3d7059a8681232e0f4aa7dd0 * osmtest/osmt_multicast.c: Cosmetic changes Fri Oct 2 17:10:59 2015 +0300 Hal Rosenstock c52a1b2ff9f38e944cc5265581c0a6b96e765e3c * osm_drop_mgr.c: Eliminated redundant check for switch node type Mon Oct 5 19:59:58 2015 +0200 Jens Domke 2c4771ff8eeb4c10df5550d1f992d47a2b5baffa * osm_ucast_dfsssp.c: Minor change to setting dropped when switch exists Thu Oct 1 17:24:59 2015 +0200 Jens Domke 19dbb679d80d5997363ded11cc59576f19605d84 * osm_ucast_dfsssp.c: Fix dangling pointer when dfsssp used with ucast cache Thu Oct 1 16:08:22 2015 +0200 Jens Domke e94fc29c515d3d00ceb4d9dea97a147407ce2416 * osm_subnet.[h c]: Fix wrong function documentation and parameter list Thu Sep 10 22:36:11 2015 +0300 Hal Rosenstock 76bd8cd45ab58a66da9dae83a7e5d09b1aedaff8 * osm_sa_mcmember_record.c: Add error logging for mismatches to validate_other_comp_fields Wed Sep 9 20:04:51 2015 +0300 Hal Rosenstock 122cad3ccf8e3bc84a5da80527bf9f5c30a82f18 * osm_sa_mcmember_record.c: When joining MC group and MC group already exists, validate other components if supplied Wed Sep 23 17:20:41 2015 +0300 Hal Rosenstock 098259eafa55e8b05054342204f6f93c8c3eb3d1 * Updated Mellanox copyrights in some recently changed files Sun Feb 3 16:46:03 2013 +0200 Alex Netes 909976db07885439c77d9a353601048d8d3b58bc * Add more checks for physp validity Sun Feb 3 16:46:03 2013 +0200 Alex Netes b37560b1519511ff91cfb322f906becec5df39b4 * osm_mcast_mgr.c: Add check for physp validity to create_mgrp_switch_map Thu Sep 10 21:45:18 2015 +0300 Hal Rosenstock 1f3dcb4434cdca002f80263eb8fdd9d49d31da8d * osm_ucast_ftree.c: Cosmetic formatting changes in fabric_construct_hca_ports Wed Sep 9 13:52:28 2015 +0300 Hal Rosenstock e92cfe5650a69b4932f3c25875d50ad342dba813 * iba/ib_types.h: Fix commentary typo Tue Sep 8 16:36:03 2015 +0300 Hal Rosenstock 5109f44c5a8d34d3b084e76c3f299b6900c6a2a7 * osm_ucast_ftree.c: Cosmetic formatting change Tue Sep 8 16:27:20 2015 +0300 Hal Rosenstock 0bc858e6f9cff0c102da7f186125bcc165ac0ea5 * osm_ucast_ftree.c: Cosmetic variable name changes in ftree_port_group_t struct Tue Sep 1 16:20:33 2015 +0300 Daniel Klein 08e8a9aa4be53ace4d91f59c460ca7cf5f85e7dc * osm_sa_path_record.c: Refactored PR [D/S] GID and LID validation Thu Sep 3 13:13:21 2015 +0300 Vladimir Koushnir e4e449e67c02a26b4941cb5024a986aea495d433 * osm_ucast_ftree.c: Fix wrong is_io assignment to the second HCA port Wed Sep 2 16:34:59 2015 +0300 Vladimir Koushnir e9bbf4434f2b0adc71e11588841c86e9681a3101 * osm_ucast_ftree.c: Fix wrong handling of dual port HCA Sun Aug 30 11:23:22 2015 +0300 Vladimir Koushnir ccab3b83f463cde7e9a538a2ba6e5dfb01ad6977 * osm_ucast_ftree.c: ftree calculates wrong number of compute nodes per leaf Thu Sep 3 15:32:31 2015 +0300 Hal Rosenstock 7777987fe792d4a40c8c12c97d42a9aa4759543c * osm_sa_path_record.c: Cosmetic formatting change Thu Aug 20 18:34:00 2015 +0300 Shlomi Nimrodi a7ac5fc190fa2fd1386cd23ebac2087a2a8c550d * osm_prtn_config.c: Handle valgrind warning in osm_prtn_config_parse_file Mon Aug 31 23:28:49 2015 +0300 Hal Rosenstock 609b7775f1e3040edb3b8240f32d3b89de8e0f63 * osm_ucast_ftree.c: Cosmetic formatting change Mon Aug 17 19:19:05 2015 +0300 Daniel Klein 06ae3ad6cb2d4839453a39e751f054bd3e3108d3 * osm_sa.c: Fix osm_db_file_dump Sun Jul 26 11:18:45 2015 +0300 Tomer Cohen f1ab545af5965a8894a6a1c2a41fea99869645aa * osm_drop_mgr.c: Do not set SM port discovery count to 0 when switch remote port is nonresponsive Wed Aug 26 18:41:14 2015 +0300 Vladimir Koushnir cd12dcdda09ef10ba8f79ed96ef8cc6d5e344cce * osm_port_info_rcv.c: Fix calculation of minimum data VLs Sun Jun 14 11:33:42 2015 +0300 Daniel Klein cb20b11e7ca3c3fd6ff7d5e6b6f452ee99d4b9b4 * osm_ucast_ftree.c: Fail routing if max rank is 0 and more than one root Sun Jun 14 11:04:59 2015 +0300 Daniel Klein d9a601b044188d3194ee7ac74306bf802243cbad * osm_ucast_ftree.c: Remove no longer needed code in remove_depended_hca Thu Jun 11 14:47:01 2015 +0300 Daniel Klein c633e05067018a2ac35c557f78039afbb9177bdf * osm_ucast_ftree.c: Mark HCA ports connected to unranked switches Sun Aug 16 16:09:06 2015 +0300 Rafi Wiener f004819d8ff7b77f9e8317ce69a79aa235c82d3c * osm_sa.c: Fix race condition when writing SA DB file Mon Aug 17 17:11:28 2015 +0300 Hal Rosenstock 1f6cd87e948a9f6027618a235cec5ceb9947a5ce * osm_state_mgr.c: Cosmetic formatting changes Wed Jun 24 17:59:57 2015 +0300 Vladimir Koushnir a64de2e4ed6c53e004f3e7bc7c74b0c8dc799e22 * osm_prtn_config.c: Fix wrong pkey table calculation in allow_both_pkeys mode Mon Jun 22 14:03:35 2015 +0300 Daniel Klein 0b6d8ea015b7ef506105ae996e5ca1d2124ce997 * osm_sa_mcmember_record.c: Validate port's neighbor_mtu when joining MC group Thu Aug 6 17:37:48 2015 +0300 Hal Rosenstock 7f2f902543086baeb72f504fcfcb9ec551856532 * libvendor/osm_vendor_ibumad_sa.c: Cosmetic formatting change to ERR 5501 log message Thu Aug 6 17:31:56 2015 +0300 Hal Rosenstock 80ca401092da7f6ae6edc72fd5289f85451d723e * osm_sa_path_record.c: When both [D S] GID and LID are supplied, validate that underlying ports are the same Thu Aug 6 15:13:10 2015 +0300 Hal Rosenstock 1fa8089fdad0932cef9b11f24327f9914440dbfb * osm_sa_path_record.c: Handle path query by DGID and SLID Mon Aug 3 22:36:24 2015 +0300 Hal Rosenstock e527ec68f229ce1753ea39208dd13e4e1ccc3684 * libvendor/osm_vendor_ibumad_sa.c: Cosmetic formatting changes to osmv_query_sa Thu Jun 25 17:48:39 2015 +0300 Daniel Klein 141293d07872d2f9214621dd3f3d42bf85a9afde * osmtest/osmt_multicast.c: Fix MC join with unrealistic rate test Thu Jul 9 18:34:16 2015 +0300 Shlomi Nimrodi ec2e2bf56ed4832e00ecc030d4462e0dd9c3c232 * osm_pkey.h: Fix osm_physp_has_pkey method description Wed Jul 8 10:29:21 2015 +0300 Vladimir Koushnir fd754d25d60eed63bbd2811b5dece3f6a6423985 * Support another new MLNX OUI Sun Jul 5 14:49:34 2015 +0300 Vladimir Koushnir f4715713eebaf7ece5f9305d5eba50a9d488272e * osm_subnet.c: Remove support for changing allow_both_pkeys on the fly Sun May 17 11:46:03 2015 +0300 Daniel Klein cd31ff6275f4d1212757bf6228c031b346db72b8 * osm_port_info_rcv.c: Sending MEPI(Get) to local switch ports on hop 0 Sun Jun 21 17:46:46 2015 +0300 Daniel Klein 4c3d782a82fc1c7dd3bbe0c8add503a0585fa666 * osm_state_mgr.c: Mark port as undiscovered when removed by drop_mgr Wed Jun 24 13:58:04 2015 +0300 Shlomi Nimrodi bf3818b8d1a6fb662100ee55afbb28f2862156c1 * partition_config.txt: Small correction in doc file Thu Jun 4 16:16:00 2015 +0200 Vangelis Tasoulas 9fa761cc637558dd6ee1d345198079cca759dfef * osm_ucast_ftree.c: Removed *p_ftree parameter from sw_destroy function Thu Jun 4 14:12:51 2015 +0200 Vangelis Tasoulas 652b0633f347dadd856b259941745c6549e09eff * osm_ucast_ftree.c: Removed *p_ftree parameter from sw_create function Mon May 11 10:36:46 2015 +0300 Daniel Klein 953b70d4febe6cd87a6fe34a2d7c1320de9ba99f * osm_opensm.c: Fix race condition between traps handling and SA shutdown Tue May 26 14:38:21 2015 +0300 Daniel Klein a1c4bc253770cb25d65a1388f4e1ecb3be28304c * osm_console.c: Fix display of negative counters in console Sun Aug 19 18:39:44 2012 +0300 Alex Netes a6c2bf83af5822b0f455d01fa58b2f46e52a09b9 * Add cleanup of SA cache after handover Mon Jan 28 13:53:38 2013 +0200 Ilya Nelkenbaum 075ff44d89c0066df44d8e6f163054f00e55fdbd * osm_mcast_tbl.c: Wrong assert placement in osm_mcast_tbl_get_block Mon Apr 13 18:52:35 2015 +0300 Hal Rosenstock d504e7634512ea8f2a49b1be6b61d4389bce3596 * doc/QoS_management_in_OpenSM.txt: Cosmetic changes Fri Mar 27 10:00:52 2015 +0100 Jens Domke a28d63ee74bc7390c0dc3bde165946f96e9249de * Fix documentation on ignore-guids command line option Sat Mar 21 15:18:31 2015 +0200 Hal Rosenstock df326446b93657db68652ecf54ce6e62f47c866b * osm_subnet.c: Minor clarification to SwitchCongestionSetting Control Map description in generated option file Wed Mar 18 14:14:23 2015 +0200 Hal Rosenstock 483ff006a87d66c8b4f73e6684b3844dd05a4cff * man/osmtest.8: Minor tweaks to inventory option description Tue Feb 10 19:06:32 2015 +0200 Daniel Klein 5e50a3c4e7fcdbf205a0d444d378b5304511aea0 * osm_sa_mcmember_record.c: Extend P_Pkey validation on MCMemberRecord(Join) Fri Mar 13 14:30:13 2015 +0200 Hal Rosenstock 8d3c6f85347a7ffc6627c0205033983124ff75f7 * osm_sa_mcmember_record.c: Change to log messages for PKey consistency Mon Mar 2 22:01:13 2015 +0200 Hal Rosenstock 3fcb121dde4b4b9c5c5e00da6cbaa7cee593bbd4 * osm_subnet.c: Improved m_key_lookup description in generated conf file Mon Mar 2 21:54:44 2015 +0200 Hal Rosenstock b4d20d75ed8479a387ece69cb09f65d050290414 * osm_port_info_rcv.c: In pi_rcv_process_switch_port0, store port 0's PortInfo before querying switch external ports Fri Feb 27 16:44:10 2015 +0200 Hal Rosenstock 504e43f8f1b61238542ad8a938a7fc86ba834178 * osm_req.c: Cosmetic formatting change Thu Feb 26 16:56:44 2015 +0200 Hal Rosenstock 062d35de9d51458303052f7ed0945c5147172540 * osm_port_info_rcv.c: In pi_rcv_process_switch_port0, determine mkey Tue Feb 24 01:14:47 2015 +0200 Hal Rosenstock a5e484b834e63bc77ec1161a3f44df1919a93868 * osm_node.h: Fix commentary typo Thu Feb 19 16:24:01 2015 +0200 Hal Rosenstock 6ceb0ce7d1d4cd7ce904cb015083a5313d2fa8cd * osm_sa_mcmember_record.c: Removed redundancy in comment Mon Feb 9 23:36:44 2015 +0200 Vladimir Koushnir 899664d9f866aac2ffb7647bf8d995eb3e5cc10f * osm_ucast_mgr.c: Support diverse paths for LMC > 0 when scatter_ports is enabled Tue Feb 3 20:14:49 2015 +0200 Hal Rosenstock 9e0cba39f0fcfba258192f7335809ef532103798 * osm_prtn_config.c: Cosmetic formatting change Sun Feb 1 13:30:06 2015 +0200 Daniel Klein 6dc0b8088a717c225c908b47351ff5d1136e0f67 * osm_opensm.c: Call cl_disp_shutdown for SA SET dispatcher Tue Jan 27 18:40:02 2015 +0200 Ilya Nelkenbaum 3199d3441448e2d614a22b8c06c265c43ea1a9f6 * osmeventplugin.c: Modify osm_event_plugin_t initialization Sat Jan 24 14:46:16 2015 +0200 Hal Rosenstock 0eb5117bd188f8d386ca1eb4c75041d52e68adee * osm_sa_mcmember_record.c: Cosmetic formatting change Thu Jan 15 18:15:01 2015 +0200 Daniel Klein 94c2d74d96f7f8ddda264b3ee5926697fa18eb86 * Revert "osm_ucast_mgr.c: Force unicast routing to fail when lft allocations fail" patch Mon Jan 12 20:19:36 2015 +0200 Hal Rosenstock 66301d8225586d47b17698aa9c9deee13fd7aa3c * osm_subnet.c: Add more supported device IDs Sun Aug 3 14:26:48 2014 +0300 Daniel Klein 1d205bc99eab68c8063c7164bedfe68fdc234a2b * osm_ucast_mgr.c: Select exit ports for lid offset > 0 using new_lft Wed Oct 1 17:09:10 2014 +0200 Daniel Klein 2a320950556522a18a959e58905daef4eed3d06e * osm_ucast_cache.c: Rewrite p_sw->lft allocation in osm_ucast_cache_process Sun Aug 3 12:27:51 2014 +0300 Daniel Klein e2ee83ee4a1322b0ce2b9c16ec6a1aed21087679 * Use routing engine calculated LFT for SA queries Wed Jul 30 18:52:46 2014 +0300 Daniel Klein 1413d64ba610edf8e950673f80bbaf6fec4e681b * osm_state_mgr.c: Remove new_lft buffers cleanup Sun Dec 14 18:00:28 2014 +0200 Daniel Klein f2b96de26867d5e1c69ff2c9d60947030a14e0a1 * osm_ucast_mgr.c: Force unicast routing to fail when lft allocations fail Tue Jan 6 18:12:19 2015 +0200 Hal Rosenstock 2541ed94869edc5a389f8e873887a739e2140a63 * osm_ucast_mgr.c: Cosmetic formatting change Sun Sep 28 16:41:03 2014 +0200 Daniel Klein 948e2b1b08788e4be8e2fd34f876fa493a469ca3 * Add separate dispatcher for SA set and delete requests Mon Dec 22 15:32:21 2014 -0800 Albert Chu 8ea4e0609f022c1458164c4e775d4afab020862d * osm_congestion_control.c: Reset cc_timeout_count when count threshold passed Mon Dec 22 15:32:14 2014 -0800 Albert Chu 0b7c80ce97306a4dde18784ba6e32093ed965463 * osm_congestion_control.c: Consistently set cc_unavailable_flag Mon Dec 22 15:32:12 2014 -0800 Albert Chu e590ebcf35139faf351f93316a3e3d5b6c7203cd * osm_congestion_control.c: Add additional header status check in cc_rcv_mad Mon Jan 5 11:28:10 2015 -0800 Albert Chu f130d5a4cf798e2bda9a625278ee00f61d8fbdf3 * osm_subnet.c: Correct output error with congestion control table entries Sat Dec 20 19:10:33 2014 +0100 Vangelis Tasoulas 0a695aeeb01ed8056cae66e4fe18fb047c75526c * osm_switch.c: Fix wrong assertion failed in osm_switch_get_lft_block() ** Version: opensm-3.3.19 Wed Dec 17 20:01:21 2014 +0200 Hal Rosenstock fa92807d9c0d60b6aaa66c5303b19a8c5ec101c6 * Update opensm_release_notes-3.3.txt Wed Dec 17 19:41:39 2014 +0200 Hal Rosenstock 2a30f922f4414763aac72d7f55c00c919bd2e63b * Update package number for OpenSM to 3.3.19 for release Wed Dec 17 19:38:29 2014 +0200 Hal Rosenstock e29f77a6996da847e235b75316be9577b081f498 * Update (internal) shared library versions Sat Dec 13 18:19:13 2014 +0200 Hal Rosenstock 28fd4eefb2e112039a3ac0081890adb4d6fd3597 * osm_[subnet congestion_control].c: Cosmetic commentary change Sat Dec 13 16:54:51 2014 +0200 Hal Rosenstock 391c244f350b91a03a4b3a0591737f27ca3bbb33 * osm_congestion_control.c: Added Mellanox copyright Sat Dec 13 16:49:48 2014 +0200 Hal Rosenstock 7e08621264f70af7f9875409bae86938f0aaa448 * osm_congestion_control.c: In cc_rcv_mad, add attribute ID and modifier to log message Sat Dec 13 16:37:31 2014 +0200 Hal Rosenstock 62075d689bee0fd75beb5ecdace97424670930f4 * osm_perfmgr.c: Fix endian of MAD status in pc_recv_process Sat Dec 13 16:36:03 2014 +0200 Hal Rosenstock cd94c9cc7c4d096c4450e760b392f0c23cdc6753 * osm_congestion_control.c: Fix endian of MAD status in cc_rcv_mad Sat Dec 13 16:31:44 2014 +0200 Hal Rosenstock cb5df8bbbbb67aceb6ddfd15fbff4979d5bed437 * osm_congestion_control.c: Fix endian of node and port GUIDs in some log messages Sat Dec 13 16:11:34 2014 +0200 Hal Rosenstock 68887fb2388a6f1c7154ffa70bc89eab43177f98 * osm_congestion_control.c: Cosmetic changes Tue Dec 9 19:32:18 2014 +0200 Daniel Klein 5077198d156636c547f2a4ab4099439ddccd390e * osm_perfmgr.c: Reset physp_discovered before discovery Wed Dec 10 09:30:50 2014 +0200 Shlomi Nimrodi 1331a46b017ff83e819f85bdbd3d1659182c3225 * osm_subnet.[h c]: Fix possibility for open file descriptor issue Mon Dec 8 10:39:12 2014 -0800 Albert Chu ce15bb76b58e50f2606e1c96077d40216a610bcc * osm_perfmgr.c: Output remote port on perfmgr error counter log messages Mon Dec 1 11:11:00 2014 +0200 Tomer Cohen 030ac82209e920f09ff24ebe101a41e5c9bb3103 * osm_sa.c: Improve ERR 4C05 log message Tue Dec 2 14:01:33 2014 +0200 Daniel Klein fbb63d6c3d9b7bcaf34c47a7840b74d39b0c8807 * osm_subnet.c: Update MEPI supported devices white list Tue Dec 2 20:52:21 2014 +0200 Hal Rosenstock 0774229f1f2ec90665b6798456921c6b661b7d76 * osm_subnet.c: Cosmetic formatting change Tue Nov 18 16:14:22 2014 +0200 Daniel Klein 5871ef71c177de927f105caa7c6a56aadc3d3d1d * osm_sa.c: Check return value from chmod in opensm_dump_to_file Thu Nov 20 11:15:11 2014 +0200 Daniel Klein 8d51ae5dabdbe66f8e276ad372c8f4adcada85b2 * osm_state_mgr.c: Avoid continuing discovery when SM port is unresponsive Mon Nov 17 19:18:39 2014 +0200 Daniel Klein 61cd0cfb9760904d1d49cf190bbaffe4c058d781 * osm_switch.c: Fix potential memory leak due to misuse of realloc Tue Dec 11 12:27:03 2012 +0200 Alex Netes c78adde242ddcd67f8f1a84ab8721d25fa886f03 * osm_req.c: Initialize dest_port_guid in req_determine_mkey Tue Nov 4 16:03:21 2014 +0200 Daniel Klein dd5e5dff8e1865a6c2d06ebbdf2a303562885a85 * osm_mcast_mgr.c: Add MLID to error 0A06 log message Thu Apr 25 19:20:31 2013 +0300 Alex Netes f017063f57ce2abaedd24c420915c72db9815c91 * Better way to handle polling other MASTER SM Thu Oct 30 16:30:15 2014 +0200 Hal Rosenstock 63900bcc9fdba2c02b32a8ace2123f28ffaf276e * osm_vendor_ibumad.h: Use UMAD_MAX_DEVICES for OSM_UMAD_MAX_CAS Tue Oct 14 08:53:08 2014 +0200 Daniel Klein 25e5ee52cc2df4fba81483d0c9d220b5dbbbf975 * complib/cl_dispatcher.c: Check registrations vector size when searching for handlers Tue Oct 7 16:17:47 2014 +0200 Dan Ben Yosef a5c0200ea101a24f3f1753e608cb0b677403a562 * iba/ib_types.h: Add support for new MAD SM:PortInfoExtended and for modifying PM:PortExtendedSpeedsCounters Tue Oct 21 17:18:21 2014 +0200 Hal Rosenstock 3f9953573f0cecb482d17d01da7cb8e2f867a85e * osm_port_info_rcv.c: In osm_pi_rcv_process, move assert before first log message Tue Oct 21 10:26:02 2014 +0200 Vladimir Koushnir 6b0fb4d1881e3c227d4c2950b1bee208728a81d9 * osm_lid_mgr.c: Send client reregistration in case of SM LID change Sun Oct 19 18:25:09 2014 +0200 Shlomi Nimrodi 5d231f8791fc166ceba6a5171d122e7409f2524c * osm_pkey_mgr.c: Use calloc instead of malloc in pkey_mgr_process_physical_port Mon Oct 13 15:29:24 2014 +0200 Vladimir Koushnir 985859e552dcb8802b1bad1250cf848745f2373d * Fix turning on first_time_master_sweep flag Tue Oct 7 10:01:10 2014 +0200 Daniel Klein 4629e80e48d6a618e55b372a191d884b556738b3 * osm_mcast_mgr.c: Invalidate cache due to multicast routing errors Tue Sep 16 16:32:38 2014 +0300 Daniel Klein a0b94442bfb217fbecf2f108781cc0863ae8da08 * Change osm_subn_t.log_max_size type to uint32_t Thu Sep 25 17:40:40 2014 +0300 Hal Rosenstock b5abaa2883ecb3973febe97bcc15c7ce45b3c97d * osmeventplugin.c: Add include of osm_config.h as first OpenSM include Sat Sep 20 14:43:04 2014 +0300 Hal Rosenstock ecce4e36ac1c1cc270a266195add5fe257e5b1e8 * osm_console.c: Handle LinkSpeed[Ext]Active 0 for portstatus command Sat Sep 20 14:40:14 2014 +0300 Hal Rosenstock f6228104335e429a3803facba6daa3e79fd86061 * osm_console.c: Fix unknown speed/width port reporting for portstatus command Sat Sep 20 00:59:21 2014 +0300 Hal Rosenstock ffdd042751408e73c722e12658fccc44bb8a5778 * osm_console_io.c: In is_authorized, STRING_UNKNOWN is define Mon Sep 15 14:29:06 2014 +0300 Tomer Cohen a6ba88828ae6ca19689b10e5802e7d60967a8d00 * Add missing keyword in partition definition in man page and partition.txt doc Wed Sep 17 14:14:55 2014 +0300 Hal Rosenstock 7444e5e2e83d69aa8842217bd5b5e32ca1ecd52f * Fix the difference in osm_opensm struct size between OpenSM and plugin(s) Sun Sep 14 15:13:18 2014 +0300 Hal Rosenstock caf764fc02e8ec5997436f3ceafa5ae2abdb291c * osm_subnet.h: Fixed commentary typo Thu Sep 11 18:13:56 2014 +0300 Vladimir Koushnir 117bc826b396acc118974f66cbf00e27741344fe * osm_prtn.c: Change message verbosity for log message in osm_prtn_add_port Sun Sep 7 11:34:17 2014 +0300 Daniel Klein b6a1dd4741bc4c49ccd15bf5de8003bf097ee068 * osm_state_mgr.c: Avoid ucast cache invalidation due to errors during initialization Mon Sep 1 17:49:48 2014 +0300 Tomer Cohen 3b172ab597516e05aa691aae22f210d73016257a * osm_config.h.in: Fixed the difference in osm_opensm_t struct size between opensm and plugins Thu Sep 4 20:46:25 2014 +0300 Hal Rosenstock d13d4bdbab25aefa58762d371b55d03b613868f1 * osm_console.c: Track and report unknown/speed width ports Thu Aug 28 14:44:39 2014 +0300 Hal Rosenstock d63e7f6d79ebbf3bb2ce43eb2ab5e22fefb6d8dc * osm_sa_path_record.c: Cosmetic formatting changes Mon Aug 18 18:57:57 2014 +0300 Hal Rosenstock 48d159b7b9f631d6b2e62360bf351e0fe9c2d77c * libvendor/osm_vendor_ibumad.c: Remove GID index 0 check in umad_receiver Tue Aug 12 17:23:51 2014 +0300 Tomer Cohen d7f1d02bb4855d8941765ea2095c4f6ee945a63c * libvendor/osm_vendor_ibumad.c: memset osm_mad_addr_t before setting fields Tue Aug 12 15:32:17 2014 +0300 Hal Rosenstock 96f89d61f28a74256410e8b02203e0926ddaf9fa * osm_console.c: Included unknown speed/width ports in "possible issues" Thu Aug 7 21:12:56 2014 +0300 Hal Rosenstock 44df23554aeb7b498b0ed01c778371119575aa38 * osm_dump.c: In dump_topology_node, handle link_width_active of 4 for 8X Mon Aug 4 15:40:43 2014 +0300 Shlomi Nimrodi a1e58e03840fae6b334caf908a95da7c76c39b41 * osm_link_mgr.c: Fix bug in mlnx extended port info setting Wed Aug 6 23:25:18 2014 +0300 Hal Rosenstock fcb696784930ef2a2c9f665a90003da3ac5edd1e * osm_subnet.c: Improve sweep_on_trap documentation in generated conf file Mon Aug 4 03:13:04 2014 +0300 Hal Rosenstock 47a6b00477bff9d83376bf97452b8871c1fc08df * osm_sa_multipath_record.c: Better logging for 4514, 4515, and 4505 error messages Mon Aug 4 03:10:52 2014 +0300 Hal Rosenstock 115529be7bf139357e6554f54ccd342813448f2d * osm_sa_path_record.c: Better logging for 1F02 error message Sun Aug 3 11:12:54 2014 +0300 Vladimir Koushnir fe079dfe054d35fcb107df4bca6fa95f79ec2cce * osm_sa_path_record.c: Better logging for 1F05 and 1F03 error messages Sun Aug 3 02:22:33 2014 +0300 Hal Rosenstock 43c378f4b5ca4856995722998f985f46a6437c3e * osm_ucast_mgr.c: A couple of cosmetic log message changes in ucast_mgr_route Thu Jul 24 14:18:01 2014 +0300 Hal Rosenstock 9a5e51405392ba13770bd5d909f1d6aee40cb599 * osmtest/osmtest.c: Cosmetic formatting change Tue Jul 22 17:32:15 2014 +0300 Hal Rosenstock 90db6c3da1947de2b0860319a50e1df451e21572 * osm_state_mgr.c: Cosmetic formatting changes Tue Jul 22 14:16:11 2014 +0300 Hal Rosenstock e7139affd49237d3e5ed1ef55154772053958f69 * osmtest/osmtest.c: Fix osmtest_get_sm_gid when running osmtest on node other than SM node Tue Jul 22 04:27:58 2014 +0300 Hal Rosenstock 83ea812d714e50601dc2aa89fd30e55a3d6ef84c * doc/performance-manager-HOWTO.txt: Update perfmgr config options documentation Mon Jul 21 18:52:22 2014 +0300 Hal Rosenstock d4d5af39285fc7fd720c412455c58b494065bc16 * libvendor/osm_vendor_ibumad_sa.c: Fixed endian in debug log message Mon Jul 21 18:49:47 2014 +0300 Hal Rosenstock c1080b9cc58fb0b1db7b3c3a4a8c7338f91cf31c * osmtest/main.c: Cosmetic change to output for consistency ** Version: opensm-3.3.18 Wed Jul 16 22:28:15 2014 +0300 Hal Rosenstock 77f713a8fdb1ce31a24488b370b14dd6f3cf7aaf * Update package number for OpenSM to 3.3.18 for release Wed Jul 16 22:26:35 2014 +0300 Hal Rosenstock b2116433f65ebf00d861c875c89aecf88abc05fa * Update opensm_release_notes-3.3.txt Wed Jul 16 21:58:35 2014 +0300 Hal Rosenstock 7a55d6eafe0800ebf5ef107784417034605e5370 * Update (internal) shared library versions Tue Jul 15 16:03:25 2014 +0300 Hal Rosenstock 179fbacc38a9eefde1cb5c9899e46771d81e6edd * Add support for additional Mellanox OUI Mon Jul 14 13:40:26 2014 +0300 Shlomi Nimrodi be3e4f1209e03f1bf8469e85b8fa505cb222985c * osm_subnet.c: Remove duplicate strcmp check in osm_subn_rescan_conf_files method Mon Mar 31 17:52:51 2014 +0300 Ilya Nelkenbaum e6fc2f8032d45eeefbe1d6ff12a37ef13354aa0b * Add some missing documentation files to installation Fri Jul 11 23:55:34 2014 +0300 Hal Rosenstock ed1571a2c2eaa98357918b494a670f2d0baf5b05 * osm_subnet.c: Change default for perfmgr_query_cpi option Fri Jul 11 16:31:25 2014 +0300 Hal Rosenstock 3a1b458a969a4ebb6eab6257081eee6aac6b470a * osm_mcast_mgr.c: Cosmetic change to error log mesage Mon Jun 2 09:49:56 2014 +0300 Daniel Klein 56bd96411d84e3818467eeabfd7c556489d0c823 * opensm.init.in: Fix return value checking in opensm.init script Wed Jul 2 13:31:47 2014 +0300 Shlomi Nimrodi 787c16e1dea267ced6be376abb93a5e16342bb94 * Eliminate redundant calls to ib_port_info_compute_rate Mon Jun 30 12:35:58 2014 +0300 Shlomi Nimrodi 6a2d0819e8b4b1468222400baa7a9d4cdeb466df * Shorten long lines while calculating SA rate Fri Jul 4 12:21:03 2014 +0300 Hal Rosenstock 6ec10d6508127e4ec8ab8a37e26b6e6c338817e8 * man/opensm.8.in: Update date on man page Fri Jul 4 12:17:22 2014 +0300 Hal Rosenstock 1dcf322f2f53c190335403ba46e7006f2d5ad409 * Improve scatter ports documentation Fri Jul 4 11:51:47 2014 +0300 Hal Rosenstock b1a8fb0612d7bef23456a812087b14021877e417 * osm_subnet.c: Cosmetic formatting change in subn_validate_neighbor Tue Jul 1 11:43:39 2014 -0700 Albert Chu db69cd8dbbbd76b3a0ce9834d18320c29a8b0a99 * osm_perfmgr.c: Fix perfmgr sweep_state race Fri Jun 27 10:55:33 2014 -0700 Albert Chu d1b70fccba48f732d3e76caad0207985caa4387a * osm_perfmgr.c: Add log message when perfmgr sweep is skipped Fri Jun 27 10:55:19 2014 -0700 Albert Chu 8098a4d7eaa00a1994d3290825cb7030a77233c7 * osm_perfmgr.c: Remove unnecessary log message Wed Jun 18 16:53:22 2014 +0300 Vladimir Koushnir 38bc2e449cc171b17c4dc39e79a0c7242dc33d60 * Skip state_mgr_check_tbl_consistency when no LID is changed by lid or link managers Thu Jun 26 14:27:53 2014 +0300 Vladimir Koushnir ce73c60d761ab33c3edd6c9fd969be6970896e07 * osm_drop_mgr.c: Add missing CR at end of log message in drop_mgr_check_node Tue Jun 17 16:08:21 2014 +0300 Vladimir Koushnir 8255f8f90bf9e383ff8392735d7f96b748f03644 * osm_state_mgr.c: Improve error flow with wrong LIDs Tue Jun 24 18:13:01 2014 +0300 Hal Rosenstock 86f1720d0ec0ee13accfa65a80c5c21b578fe874 * osm_sa_path_record.c: Fix some commentary typos Tue Jun 24 18:11:56 2014 +0300 Hal Rosenstock 2bc6074c23f3d2759a8fdefe300600938229cb7a * osmtest/main.c: Output formatting change for case 'x' Thu Jun 12 17:24:49 2014 +0300 Dan Ben Yosef 60727f7193823a50849a67dab9c5ebd54e39dc93 * osmtest: Add GRH tests for SA queries Tue Aug 28 18:04:04 2012 +0300 Hal Rosenstock b42f11f87dc7f4944eab7f883248210402451f5d * osm_vendor_ibumad.c: Better match table eviction strategy Sun Jun 8 13:46:24 2014 +0300 Vladimir Koushnir cc0d61b60db5e2b10c38f414a0e713ae423ffe00 * libvendor/osm_vendor_ibumad.c: Check the next CA if an error is returned for the current one Thu Jun 5 12:52:40 2014 +0300 Vladimir Koushnir a16349de0c5a8ae55407700459a16d7e196667cc * osm_trap_rcv.c: Lock released without locking in some cases of trap processing Sun Jun 1 15:55:34 2014 +0300 Vladimir Koushnir 6c6e4cced86f56966a2b5eb9f6687858ccba966e * osm_sa_guidinfo_record.c: Fix crash when receiving AGUID SET/DELETE with block_num equal to max_block Sun Jun 1 09:44:26 2014 +0300 Tomer Cohen a8b23b7b15f2457d4f2f72d6345224f1bed8a466 * osm_vl15intf.c: Fix potential NULL dereference in vl15_send_mad Sun Jun 1 09:13:03 2014 +0300 Tomer Cohen d29dcd71eab6f970b3c2be7d0e1c01dd145a85cc * osm_sa_path_record.c: Fix misleading error messages during sweep Thu Nov 8 15:33:32 2012 +0200 Alex Netes e91908bd2fc5524017095765b272c2c4e4274a3b * Add osm_congestion_control.c to per module logging support Wed Jan 16 21:57:31 2013 +0200 Hal Rosenstock 3de10912416a7aba8b95a7f741dc71ed9f3cea1b * osm_congestion_control.c: Fix error code Wed May 28 23:14:52 2014 +0300 Hal Rosenstock 3ee0a22d7a9765aede09c3ec8aaf1f01183a0c6d * osm_sm.c: In sm_sweeper, no need to check for timeout after cl_event_wait_on EVENT_NO_TIMEOUT Wed May 28 23:13:32 2014 +0300 Hal Rosenstock f3e19243b1161964b3522e583ae84b7d8719cfb3 * osm_trap_rcv.c: In shutup_noisy_port, improve ERR 3811 log message Wed May 28 23:12:20 2014 +0300 Hal Rosenstock f73ff4349349be7443f45c49504563d134370077 * osm_mcast_mgr.c: In mcast_mgr_process_mlid, cosmetic change to log message Wed May 28 23:10:32 2014 +0300 Hal Rosenstock ab9fec9da0dce24f7534f862019e0b0191cde4a1 * osm_congestion_control.c: In cc_poller_send, handle cl_event_wait_on return status Wed Jan 9 19:31:04 2013 +0200 Hal Rosenstock af04af757f11f487ff290863299ac46848f2426d * osm_[sm sa]_mad_ctrl.c: Improve unsupported attribute error messages Tue May 27 19:03:14 2014 +0300 Shlomi Nimrodi 16fee25cecdf47dd357dbbd928f3f346011815b2 * osm_helper.c: In osm_get_lsa_str, fix printing of wrong FDR10 data if link is down Wed May 28 22:58:38 2014 +0300 Hal Rosenstock 6c70bf17da72294d31bab7882fed9fba1ec94d33 * PerfMgr: Eliminate no longer used sig_sweep variable Thu May 15 16:23:19 2014 +0300 Hal Rosenstock 41d0a42ad7c207640f97a653c3ff65c73acfe00c * osm_perfmgr.c: In perfmgr_send_mad, handle cl_event_wait_on return status Thu May 15 16:11:13 2014 +0300 Hal Rosenstock d764777305f3bd9065eb2fa5946c375fc1c6e2b5 * osm_perfmgr.c: Minor code factoring in perfmgr_send_mad Wed May 14 20:50:50 2014 +0300 Hal Rosenstock fa31298650410b2da0201b1d3afe489b458c9bcd * doc/opensm_release_notes-3.3.txt: Updated repo location Tue May 13 15:59:40 2014 +0300 Hal Rosenstock 8394ef8e066ac058241e0a7134e4c7bccad364a9 * libvendor/osm_vendor_ibumad.c: Commentary change Wed May 7 21:21:47 2014 +0300 Hal Rosenstock 0ab7492e87eed3acaf6afd429ce6966283597758 * osm_subnet.c: More cosmetic changes to opensm conf file PerfMgr documentation Wed May 7 21:12:25 2014 +0300 Hal Rosenstock cc977bed550ad985ed3e24dfd844d04630904587 * osm_subnet.c: Enhance opensm conf file documentation for PerfMgr options Sun Apr 13 15:26:47 2014 +0300 Tomer Cohen 38273db59e80fb5672d16003b72f8acf59069cef * osm_port_info_rcv.c: Fixed calculation of min_data_vls Wed May 7 08:55:39 2014 +0300 Hal Rosenstock dc3259eafdc8eae5be5704d52ad8abb13ef05660 * Add support for additional Mellanox OUI Sun May 4 11:38:01 2014 +0300 Tomer Cohen 99a8e74c976035b3b921635ac42f1aac1917c752 * osmtest.c: Fixed missing assignment of return value from function osmtest_get_port_rec_by_num Mon Mar 17 13:10:01 2014 +0200 Daniel Klein 9ffa520210a805b62067d2600325c57b17d781fb * Fix the creation of empty multicast groups from SADB Sat May 3 08:24:35 2014 +0300 Hal Rosenstock 1d3aacfc0ff05dd25922a15eaa4e88a0cb6ef145 * osm_perfmgr_db.c: Add missing clear of new xmit_wait counter in clear_counters Wed Apr 30 12:21:06 2014 +0300 Vladimir Koushnir 0f9b15c76369e17fece0960f094705b46df40e79 * SM should resweep the fabric if vl15_send_mad fails Thu May 1 11:47:29 2014 +0300 Hal Rosenstock ee5f6d567d89ae0e997d9959854c131f91fd4428 * osm_perfmgr.c: Added Mellanox copyright Thu May 1 11:45:25 2014 +0300 Hal Rosenstock 05be6c47089731ad77d12bc493261b2cc42d6188 * osm_perfmgr.c: Eliminate unneeded initialization in pc_recv_process Thu May 1 11:43:16 2014 +0300 Hal Rosenstock 9ac71fd59d90b547766fa86be2c8683f6822b328 * osm_perfmgr.c: Cosmetic formatting changes Tue Apr 22 10:14:55 2014 +0300 Tomer Cohen 54c6c8692068c314cc609cc621849541eea63ff2 * osm_log.c: Fix wrong hour and date display in log when CL_ASSERT fail Tue Apr 1 11:46:13 2014 +0300 Tomer Cohen 5c81051ac07c2db916e86bc40a86fba3a06f5997 * osm_console_io.c: Handle return value of function setsockopt Sun Mar 30 15:51:14 2014 +0300 Tomer Cohen 2e1294a6d5b9ad5890f0c486907207c8079b2498 * osm_sa_[mcmember path]_record.c: Optimize clearing of SA record items Mon Apr 28 18:27:33 2014 +0300 Hal Rosenstock db9c45056d0a47c7d70325678c1627cda72074ce * osm_guid_info_rcv.c: Fix assert placement in osm_gi_rcv_process Fri Apr 25 05:25:42 2014 +0300 Hal Rosenstock 44a6358d79594af30f71dad714120e95252f4de4 * libvendor/osm_vendor_ibumad.c: Support GRH (for GS classes) Fri Apr 25 04:59:29 2014 +0300 Hal Rosenstock bb723ae6f8a68fd702b2242a41b4f0ffa0c46288 * libvendor/osm_vendor_ibumad.c: Cosmetic change to umad_set_grh calls Thu Apr 24 20:55:55 2014 +0300 Hal Rosenstock 5ca6bdc7cea0ce245a8cae3dc3640fb84843afce * osm_perfmgr.c: Add current PerfMgr sweep state to 54FF error log message Fri Apr 4 20:07:04 2014 -0400 Ira Weiny 672de651baaacb4ca05ff77c3a32d368a4d26c91 * perfmgr: Add xmit_wait to event plugin error counters data structure Sat Apr 5 11:41:12 2014 -0400 Ira Weiny d86e7e3f7828c9f2240cca8de83e28e4ab6e09d9 * perfmgr: Add xmit_wait support Wed Apr 23 22:20:20 2014 +0300 Hal Rosenstock 753af81f6461a9d8415c501e35c8c8198cc113ea * osm_mcast_mgr.c: Add missing new line at end of ERR 0A21 log message Wed Apr 23 18:29:36 2014 +0300 Hal Rosenstock d437d58ec08fb6694d71437969c3299d08152aa5 * osm_mcast_mgr.c: Fix endian of port GUID in ERR 0A06 log message Thu Apr 10 11:33:03 2014 +0300 Shlomi Nimrodi 51fb51db9220c765eebdb5bd013b964b24355590 * osm_ucast_mgr.c: Fix duplicated error codes Fri Apr 11 07:23:06 2014 -0400 Hal Rosenstock 21c2ab7ca44695f0f4f5107f789803f4f5ef2df5 * osm_sa_mad_ctrl.c: In sa_mad_ctrl_rcv_callback, improve 1A04 error log message Fri Apr 11 18:12:01 2014 +0300 Hal Rosenstock c83bde443b0b843011696f9d46b7f8276aff52b2 * doc/performance-manager-HOWTO.txt: Fix typo Thu Mar 27 18:52:49 2014 +0200 Shlomi Nimrodi e94d4712772a3c50620a98f7a55fbe0d143496e3 * osm_torus.c: Fix torus crash when actual topology is not torus Thu Mar 27 14:38:02 2014 +0200 Hal Rosenstock a20cd5f02b9cd7eef99de10c37d3eb01ef096e6c * osm_sa_service_record.c: Fix locking issue in osm_sr_rcv_process Thu Mar 27 12:21:14 2014 +0200 Hal Rosenstock 127acf187ec9a2cb0f14b24d322e3491a4940e66 * osm_sa_mcmember_record.c: Fix double locking in mcmr_rcv_join_mgrp Tue Mar 25 12:01:56 2014 +0200 Alex Netes abaf91ba6b4134b1207e88c2af4a687ccb669dcf * osm_sa_service_record.c: Improved locking Thu Feb 27 11:46:22 2014 +0200 Alex Netes c86c30abd4c4df59561665077d982e926640ca77 * All SA queries should validate the requester port under lock Sun Mar 16 17:35:13 2014 +0200 Tomer Cohen 1f4de5850d38b3a75bf228650af3c3094da78ace * osm_subnet.c: Fix bug in parsing configuration file Thu Mar 20 10:26:51 2014 +0200 Daniel Klein 0fa5fc1ceb88226d5a0b03fc895989a7e57b5612 * osm_sa_mcmember_record.c: Fix removing members from existing mc group due to invalid requests Sun Mar 23 16:58:40 2014 +0200 Tomer Cohen e1566267b103b08350da984b4147137ad4719d74 * osm_qos_parser_y.y: Added range check for mtu limit parsing Tue Mar 18 08:27:00 2014 +0200 Tomer Cohen cb439b3cc226df279c2a677b243462965395de1e * osm_qos_parser_y.y: Added range check for rate limit parsing Wed Mar 19 02:07:17 2014 +0200 Hal Rosenstock a556f82d8f08a41e45130071d5e9179bbfcccde7 * man/opensm.8.in: Minor fixes to per module logging configuration Thu Mar 6 16:33:21 2014 +0200 Daniel Klein 79917450678fcf5aa460ea6eceb93a7e04bc1b7e * osm_node_info_rcv.c: Update local copy of node info for known nodes Tue Aug 7 10:58:16 2012 +0300 Alex Netes 1c637df9a00d5550a0dc81bbc4021bb130582525 * osm_node_info_rcv.c: Update NodeInfo.SysImageGUID on heavy sweep Wed Nov 24 11:18:44 2010 +0200 Eli Dorfman 275a56a2901bcc9e53dd06980d9ee80da0587731 * osm_state_mgr.c: Clear first time sweep even after subnet error Thu Mar 6 20:35:05 2014 +0200 Hal Rosenstock 09b5ffe4537be4bb63c799c61b66c40b31da1618 * osm_sa_path_record.c: In osm_pr_rcv_process, release lock before log message Fri Mar 7 17:05:29 2014 +0200 Hal Rosenstock ef7a6511c298a52fdb71bf8acc1f538e572efe46 * osm_state_mgr.c: Revert commit to "remove redundant unset to first_time_master_sweep" Thu Mar 6 15:01:01 2014 +0200 Alex Netes 80e1e59ac329e8fbd50fd434f5acdb1a64b75bab * osm_sminfo_rcv.c: Send trap 144 to a newly found MASTER SM when in MASTER state Thu Jul 18 11:08:14 2013 +0300 Alex Netes 23dfbf8a5fa3cf601d36511cd1bea1e623d73411 * osm_state_mgr.c: Remove redundant unset to first_time_master_sweep Mon Dec 3 14:45:24 2012 +0200 Alex Netes e5a87dd459417cc5b84f7c7e6044d0ae3f3151c8 * Revert "Reset client reregistration when receiving handover" Mon Apr 8 20:09:23 2013 +0300 Vladimir Koushnir 0189deaac8025874038b62be52fcfee0da80b675 * osm_sm_state_mgr.c: Fix opensm crash after handover Sun Aug 5 11:50:07 2012 +0300 Alex Netes 52c4a301f1dd7b73132be700fe3f08d86ef0868d * osm_sm_state_mgr.c: Reconfigure the fabric when receiving HANDOVER/POLLING_TIMEOUT in MASTER state Tue Mar 4 13:07:48 2014 +0200 Alex Netes 26af3a9c0d921a834f3ce2ce3fee2c6168e64537 * Fix crash during handover Sun Feb 10 14:34:12 2013 +0200 Ilya Nelkenbaum 28e5fa7c33121117cbf0378d4a78bd6c96744937 * osm_sw_info_rcv.c: Add check of switch mcast_cap Wed Feb 26 12:52:01 2014 +0200 Alex Netes f775a1a16afcaf988260508e57fb7c156607b314 * osm_sa_path_record.c: Search for requester port should be under lock Sun Mar 17 10:17:00 2013 +0200 Alex Netes 24d6219cbea9b3d36dd662cf758097a989b5b927 * osm_sw_info_rcv.c: Fix sending PortInfo during lightsweep Tue Dec 11 09:37:23 2012 +0200 Dan Ben Yosef 78b6e8fa47922650404b5a8a888ba48285d0df62 * osm_subnet.c: Fix resource leak neighbor parser ("subn_validate_neighbor" function) Tue Dec 11 09:07:22 2012 +0200 Dan Ben Yosef 46749c088d889bf73e9c82681f93b4febe42cb89 * osm_subnet.c: Fix resource leak guid2mkey parser (guid validation function) Sun Feb 23 10:53:54 2014 +0200 Rafi Wiener 6212e4b2dc24177d4016a5703c34c481ef227116 * osm_ucast_ftree.c: Fix memory leak in ftree fabric_rank Wed Feb 12 18:54:25 2014 +0200 Hal Rosenstock afb6cb88df55fb8f02282a31d702e53692381002 * osm_ucast_mgr.c: Use LFT block of all port 0s to indicate resend Wed Feb 5 14:25:11 2014 +0200 Alex Netes 319e065aea18d1906ec88d9817c20323d1a3e953 * ib_types.h: Rename ib_switch_info_set_state_change function Wed Feb 5 12:08:18 2014 +0200 Alex Netes 12d2c8ea7c6057f0c7c1a280016b3fa2d0e4921d * osm_node_info_rcv.c: Fix multiple switch discovery during a sweep Tue Aug 13 12:24:53 2013 +0300 Alex Netes ef22eb9ad5d88ce7dd4c3cf858ace035240a2785 * osm_qos.c: Fix possible seg fault Tue Feb 4 15:54:13 2014 +0200 Jens Domke 9dd8f45616c0a4489594da4907f26f8bd6f95582 * dfsssp: avoid crash due to port initialisation errors Tue Feb 4 21:18:46 2014 +0900 Jens Domke f6418cf03b8df1b32e800c42554f06e5b3248926 * osm_ucast_dfsssp.c: prevent double free error Mon Feb 3 13:05:16 2014 +0200 Alex Netes 1633550020087f3296dbc2f7b1dd533cd83a6398 * Resend LFTs/VLArb/SL2VL MADs in case of error Mon Feb 3 13:05:15 2014 +0200 Alex Netes 90d19c2dacb63bb9dd2912fdb1303daced98a5ed * osm_port_info_rcv.c: Reread pkeys from SP0 if switch rebooted during a sweep Mon Feb 3 13:05:14 2014 +0200 Alex Netes 6e90421fe34190e2fb62c3f9092ef39f6a971ea1 * Better handling of topology changes in the fabric Mon Feb 3 13:05:13 2014 +0200 Alex Netes b33c3ba29be21f5d3b7912dfcf213bfe180c6d14 * Change discovery order of switch data Mon Feb 3 13:05:12 2014 +0200 Alex Netes b1c17a8b6d8e66ca73b5912f61b4b4ddd93c44de * ib_types.h: Fix shadow declaration warnings Thu Nov 14 11:07:11 2013 -0600 Mohammad Ismail e3f0440183cf246a735bad733a25f0de9319049b * osm_ucast_updn.c: Fix the AA0B error number Wed Nov 14 09:30:50 2012 +0200 Ilya Nelkenbaum 30d9020ba95c904fb59d3baef765d06093b0dc89 * osm_ucast_updn.c: Add missing ERR number to log message Wed Aug 22 10:30:21 2012 +0300 Hal Rosenstock 395b5f0ef9b224d11acc6fd69e8536d9beee8d98 * Handle bad SMP status Sat Feb 1 18:16:23 2014 +0200 Hal Rosenstock e8a92759ea44b0af29e6ac970c25993f52a132fb * osm_port.c: Improve ERR 4108 log message ** Version: opensm-3.3.17 Thu Jan 30 21:03:46 2014 +0200 Hal Rosenstock 650b60c0b77bcbd0d8912c4f241ff774705cd564 * Update package number for OpenSM to 3.3.17 for release Thu Jan 30 21:01:54 2014 +0200 Hal Rosenstock 94d947ce6d21e802d22502c087e3842014a7a81e * Update opensm_release_notes-3.3.txt Thu Jan 30 18:53:58 2014 +0200 Hal Rosenstock 49132000b9208213a191e8e075f8b99a23a1bef7 * Update (internal) shared library versions Wed Jan 29 22:17:48 2014 +0200 Hal Rosenstock 074ec5a4d2e7c3200aab383cd633e150bb8c1583 * osm_perfmgr.h: Cosmetic formatting changes Mon Jan 27 14:39:45 2014 +0200 Alex Netes 05af77646d156d285d2d3122dd65f8ad9c600991 * osm_drop_mgr.c: Add missing assert Sun Jan 26 18:14:27 2014 +0200 Alex Netes de254f9901c0a2f8187c56026a7f414bceb58786 * osm_opensm.c: Add missing ERR number Mon Jan 13 15:26:35 2014 +0900 Jens Domke 5b2390eac3ef47a8b6f9330e9a904ad7af6f241a * dfsssp: optimization for dedicated compute and IO nodes Tue Jan 21 23:33:01 2014 -0500 Hal Rosenstock b1e58bbf50ca403199a9c1ea49b4b74fdd312c5c * osmeventplugin: Fix compile warning Thu Jan 16 18:15:02 2014 +0200 Hal Rosenstock 48c9f436d6c85d32d2748ba4c2756e2736bc5e7e * osm_prtn_config.c: Some changes to osm_prtn_config_parse_file Sun May 5 12:20:40 2013 +0300 Alex Netes 0ff054ae2f6e53e9e908f72f23b35cb40b3aeab4 * osm_trap_rcv.c: Removed unneeded lock when disabling port Thu Nov 15 18:09:57 2012 +0200 Hal Rosenstock e7c4ec39fff6c6c243ac57434eb8f8bbe6f783f8 * osm_trap_rcv.c: Minimize time holding RW lock for SystemImageGUID changed trap 145 Thu Oct 18 17:59:04 2012 +0200 Hal Rosenstock 1418f8a2673162fa888cf42f51ca5c4890dde3e8 * osm_trap_rcv.c: In trap_rcv_process_request, change locking strategy Wed Aug 29 19:31:19 2012 +0300 Alex Netes 280a2ac0ba17b909481ebbd3ed406104629f2a36 * osm_trap_rcv.c: fix locking in trap_rcv_process_request() Mon Jan 13 13:45:09 2014 -0500 Vladimir Koushnir 33f4f174be6f11466c789410946159636ad3a046 * Add new option for guid_routing_order_no_scatter Mon Jan 13 13:19:29 2014 -0500 Vladimir Koushnir a5f54f1e4bede8e1deef242e9e63f6ebb0ba526a * osm_ucast_mgr.c: After applying guid_order options, add nodes sorted by neighbor switch load Sat Jan 4 12:37:59 2014 -0500 Bernd Schubert 5a97c782a4b4f968c2d964c371decec5083f8499 * Try default partition config if parsing partitions.conf fails Sun Jan 5 17:53:40 2014 +0200 Hal Rosenstock 6321afa188af556850811739630cfaf854dfec23 * osm_subnet.c: Cosmetic change to config file output Sat Jan 4 17:25:11 2014 +0200 Hal Rosenstock a45e311710b58ecee0dee74a0b48eabe63c10a6a * osm_db_files.c: Minor improvement to fix in previous commit 86cf679666f49f6073c1ddf2b9ff644a41537a57 Sat Jan 4 17:10:51 2014 +0200 Hal Rosenstock 86cf679666f49f6073c1ddf2b9ff644a41537a57 * osm_db_files.c: Fix issue introduced in commit aaa7b1e67ec6e5fc2a10accf46d538f9d47c6323 Fri Jan 3 08:40:48 2014 -0500 Ilya Nelkenbaum ed7be1a62f30e7e065a5a536e8fec33d158b1326 * Add client_rereg flag to Port Info context Mon Dec 30 10:59:54 2013 -0500 Hal Rosenstock aaa7b1e67ec6e5fc2a10accf46d538f9d47c6323 * osm_db_files.c: Some minor fixes/improvements to osm_db_store Sat Jan 4 16:41:17 2014 +0200 Hal Rosenstock 3cae07c6390ef8b85d93e90f2dbe1f0a42c57a5e * osm_perfmgr.c: Cosmetic formatting changes Wed Jan 1 08:44:28 2014 -0500 Alex Netes 07b24a3e1335d3d53e0ea85b162ec901b369a469 * osm_port_info_rcv.c: Reset client reregister bit only on a response to SET Mon Dec 30 07:24:57 2013 -0500 Alex Netes 413e4fa2fbd12c7c9f8018b5ef2b4e67449e5c1f * osm_trap_rcv.c: fix race condition during sweep Mon Dec 30 07:24:48 2013 -0500 Daniel Klein 84c9832d5ce4b557295bd0cdd540848c3367fc77 * osm_ucast_ftree.c: replace assert with error return value Thu Dec 26 08:39:12 2013 -0500 Vladimir Koushnir 90a7960db7fc078201013faf421bcb554dcf8aef * osm_ucast_file.c: Fix crash when port is invalid in LFT file Sat Dec 21 07:54:48 2013 -0500 Hal Rosenstock cc5fa1774f6bc98e1ae22522171a25522d443038 * Add support for synchronizing in memory files with storage Wed Dec 11 15:38:18 2013 +0200 Vladimir Koushnir 0a1c0f0d94ccf10c43b59ee8cf249f2a441f99ae * osm_sa_path_record.c: Improve ERR 1F1D to show the pkey specified in PathQuery Sun Dec 1 18:23:26 2013 +0200 Daniel Klein 94e99a80e01cb07f3e2d01bdbf69b06dd9ac3b7e * osm_mcast_mgr.c: Removed mcast_mgr_purge_tree_node due to code duplication Tue Dec 10 11:13:38 2013 +0200 Vladimir Koushnir 929934e881f21efe68f6b099abef7e788b7b8ff0 * osm_pkey.[h c]: Remove dead function osm_pkey_tbl_clear_accum_pkeys Mon Dec 2 14:58:03 2013 +0200 Alex Netes bf42ec8ccbd2cc4af3fabe3b1926a0595ba16ad4 * osm_mtree.c: Cosmetic change in osm_mtree_destroy function Wed Dec 4 14:00:54 2013 +0200 Vladimir Koushnir a1ccf88513dba90ef2697f7f512a360d338ea006 * osm_sa_path_record.c: path_sl may return SL different from requested SL Thu Dec 5 06:10:19 2013 -0800 Line Holen 7e96f32172fafea3f0340764286dfb9f53658566 * osm_sm_state_mgr.c: Fix handling of polling retry number Tue Dec 3 08:25:06 2013 -0500 Daniel Klein 8f3f7d04eb9fe16f36529c5da6a85a8ad8495421 * osm_sm_state_mgr.c: Fix race condition during sm_state_mgr_send_master_sm_info_req Wed Nov 27 16:27:52 2013 +0200 Daniel Klein 78d87b9a89641ffc42b36b1bd6c05348fea3a025 * osm_mcast_mgr.c: fixed missing error message number Tue Nov 19 16:34:37 2013 +0200 Alex Netes b1b1b37b7e4f83804dbc8ae780a067c0641c1097 * Fix minhop population in fabric with duplicate lids Tue Nov 19 14:15:20 2013 +0200 Alex Netes a1df1d7e1a3930d35ec3876c1c0a4a0fe5040f35 * osm_state_mgr.c: Fix error print in state_mgr_check_tbl_consistency() Tue Nov 19 14:10:06 2013 +0200 Alex Netes ed9de4c80981a7ff47791e15ad466bd9f948572d * osm_mcast_mgr.c: Fix wrong comparison in mcast_mgr_subdivide() Fri Nov 15 04:53:31 2013 -0800 Line Holen 1441937446ce61c4c550b1a5034c005187a0a3b4 * osm_mcast_mgr.c Add block number to error message Wed Nov 13 14:28:47 2013 +0200 Vladimir Koushnir c5d5faa1b10f33ab8c5e06fa9af71eb222643000 * Only rewrite db files during heavy sweep when there is a real change Tue Nov 12 17:42:02 2013 +0200 Vladimir Koushnir edd5e74562908141ecaf67cf3c20b791923c570e * Redundant remove() function call during db file generation Sun Nov 10 18:09:25 2013 +0200 Vladimir Koushnir 9853841f369decde551d03ff4c1f21a59afbc23e * Implement atomic update operation for sa_db_file Tue Nov 12 06:18:36 2013 -0500 Vladimir Koushnir 175455201dc349dfee1253386ae5c0f90e83be33 * Remove unused lid matrix calculation in Torus_2Qos routing Tue Nov 12 16:27:42 2013 -0500 Alex Netes dcb2df0f0f13aa8b77c5f16bdcc4c27d11dae6df * osm_link_mgr.c: Fix uninitialized value (physp0) Mon Sep 16 10:38:45 2013 +0200 Shlomi Nimrodi 7160cce6e2ec517fd573364ee271f6380d549b89 * osm_link_mgr.c: Fix uninitialized value (physp0) Thu May 9 17:45:19 2013 +0300 Alex Netes 5aa4ea3a20ba7732460d0040cbed4acd0d09907c * osm_link_mgr.c: fix uninitialized variable usage Wed Nov 6 17:24:12 2013 +0200 Alex Netes 9aa6dcd284223a782e62534dc099b50828c9155b * osm_drop_mgr.c: fix timeouts on Get Pkey from ext switch ports Tue Nov 5 17:15:26 2013 +0200 Dan Ben Yosef 361c01435734c9c00bc936e4236668d3e1b6c0ef * Fix dropping node after setPkey mad Mon Nov 4 12:43:08 2013 -0500 Vladimir Koushnir 2585f585f28f5e3b4cd14ba489d0b6d1f476ceea * Improve memory consumption of pkey manager by using cl_map for accum_pkeys Mon Nov 4 15:11:13 2013 +0200 Vladimir Koushnir 754bd75336e4a8202d2e0782a29a4cf765ca44a7 * osm_opensm.c: When exiting, update SADB only in MASTER state Mon Nov 4 07:52:56 2013 -0500 Dan Ben Yosef 3cc0a3e642facf7ea21e960b31fd9834df7d3a82 * Fix timeout handling for pkeyGet for sw port 0 Fri Nov 1 09:17:57 2013 -0400 Dan Ben Yosef 189a39d748a049f002032abf52c935ed294ca967 * Fix possible use of lid 0 when sending set PortInfo after failure of the first PortInfo set Fri Nov 1 08:10:23 2013 -0400 Dan Ben Yosef 6d1d1a4cbf07a1dda1df016c10aaf3b72ec0342a * Fix handling of get P_KeyTable on timeout Sun Oct 27 16:19:47 2013 +0200 Alex Netes df385e88f8a9158cf34ab67eba800463067f4016 * osm_ucast_cache.c: Fix memory leak in ucast_cache Mon Oct 28 12:35:04 2013 +0200 Vladimir Koushnir 79ba8770ef909d94f051c612f1b7180d7b9b726d * osm_link_mgr.c: active_transition parameter in PortInfo(Set) context may not be initialized Wed Oct 23 10:38:17 2013 -0400 Alex Netes b44206235abc6a6f144cf5b9395bd62965b1532d * Resend trap 144 when detecting remote MASTER SM with lower priority Thu Oct 17 13:10:46 2013 +0200 Bernd Schubert cf014ec7d2188c34f3f66a00efc2db1b2ddcb203 * reduce log level for missing partition configuration file. Sun Oct 20 08:30:08 2013 -0400 Daniel Klein 49ea151795e5a99741bb92d35536ff0b9df7868a * osm_pkey.c: Fix find common pkey bug fix Mon Oct 7 16:35:46 2013 -0400 Hal Rosenstock d3aeae83fe7c71bd052376ae155eb2bfd9e2720d * osmtest: Handle other than default subnet prefix Mon Oct 7 16:35:40 2013 -0400 Hal Rosenstock de029540feb2882c23fb43abb88583680d6356f4 * osm_trap_rcv.c: Log DR path to node when trap 128 Mon Oct 7 16:35:36 2013 -0400 Hal Rosenstock 181c863180df272500ff993abb1e62ca56bd2729 * osm_vendor_ibumad.c: Improve ERR 5430 log message Fri Oct 4 00:03:06 2013 +0900 Jens Domke e3aa9e8461a15654985d27148db7af2dd33fe797 * dfsssp: send multicast forwarding tables to switches Fri Oct 4 00:03:05 2013 +0900 Jens Domke 4a39fb11387284d60a680ec62a9b50a9415a1461 * dfsssp: send multicast forwarding tables to switches Tue Oct 1 12:41:40 2013 +0300 Alex Netes d5f6e254c4f34b81ef3962e6c142828e748b1c67 * osm_sa_mcmember_record.c: Fix incorrect comparison of IPv6 MGID when searching for SNM MLID Mon Sep 30 17:05:55 2013 +0300 Alex Netes 908c524296a2f94e5fd11f55a2f0049be404aa40 * osm_guid_mgr.c: Fix GUIDInfo SET function Mon Sep 16 07:38:38 2013 -0700 Line Holen 7321689517078ea643f1275c99674fce935d7cc2 * osm_state_mgr.c Add info to some error messages Sat Sep 14 17:08:50 2013 +0300 Hal Rosenstock 0fc753d342e8487d097d9cfef9493e8e40d4b0d0 * osm_sa_path_record.c: Eliminate extraneous space in 1F1A log message Wed Sep 11 09:29:39 2013 -0400 Hal Rosenstock 18b3be9269ddbb58f02bd06f0a7b8678fc81a646 * Use trap number defines rather than actual trap numbers Thu Sep 12 16:41:33 2013 +0300 Hal Rosenstock 270a7004877308fa80fb68ac64aafb388efa953d * osm_db_files.c: Add osm_db_domain_init failure handling into test program Thu Sep 12 01:14:13 2013 -0700 Line Holen 2b82c1cd758c395d94c24f6afd9a3c2fb4895d86 * Handle memory allocation failure in osm_db_domain_init() Wed Sep 11 12:41:58 2013 +0200 Vladimir Koushnir 82841323af4cc56535f334a0d0c3af11343e2633 * Use after free in osm_prtn_delete Tue Sep 10 03:50:12 2013 -0700 Line Holen e8bf592d7bb2f0ca357985ac0c7f2a765b7f50b8 * Clean up event subscriptions if a port goes away Thu Sep 5 10:18:38 2013 -0400 Hal Rosenstock e186b4a37995405d787b92b89292c20f08f84bfd * osm_sa_guidinfo_record.c: False duplicate GUID error messages Tue Sep 3 04:31:23 2013 -0700 Line Holen d95d461bc1a1ac63a84b37bfc2a09ca8aca1e79e * osm_sa_informinfo.c Add attribute info to log messages Wed May 1 18:10:17 2013 +0300 Alex Netes 7c9afa00b00bc0fe08363dfc1c155bf39a88d3ba * Improve m_key lookup Wed May 1 19:14:34 2013 +0300 Alex Netes 3e146fa76deae23442b6a9d74b6725e2d7dd0030 * Add option to disable M_Key lookup Wed Aug 14 03:26:42 2013 -0700 Line Holen 94789a85a870752c5e574281e6eb8f7a6f56baa4 * osm_port_info_rcv.c Issue a log message if we cannot read the MKey of a port Thu Aug 22 10:31:06 2013 -0400 Alex Netes 807d9ed630266bd60dd783faf364ea5e7c4358d5 * osm_trap_rcv.c: Fix locking in aging callback Thu Aug 22 10:54:09 2013 -0400 Dan Ben Yosef b67db2b87f0d460a8bccf9cf2c644cd7197d7e02 * osm_helper.c: Fix out-of-bounds read Tue Aug 20 12:31:50 2013 -0400 Dan Ben Yosef ef86015aadcf9b90726cc72868be38109f04a4e5 * osm_db_files.c : Fix resource leak guid2lid parser Tue Aug 20 10:28:49 2013 -0400 Vladimir Koushnir 4a2d2d84e8b0fd0754d6a67f0dce4d9398393cff * osm_subnet.c: Fix memory leak caused by commit dc0760cb8088fbe079e19682570a884ba01e94ff Tue Aug 20 17:23:14 2013 +0300 Alex Netes 168eaeb522bcb34406e12c45eff5fc68fbb4e834 * osm_db_files.c: Fix memory leak when deleting entries from osm db Wed Aug 14 17:29:08 2013 +0300 Alex Netes eb294d5454d74a54753b95a016a0c478e641d04e * osm_lid_mgr.c: Don't configure MTU and LMC for base SP0 Wed Jul 31 17:11:36 2013 +0300 Hal Rosenstock edfaddc7b7788297fcce19d9890f0e7191b9e2da * osm_ucast_dfsssp.c: Fix some typos Wed Jul 31 15:04:06 2013 +0900 Jens Domke e1804f4fdd148fc9cc45798b8b45e86efd61dee1 * dfsssp - add missing and change existing return values Tue Jul 30 11:03:17 2013 +0300 Daniel Klein d5ef9afb82dfe1007cf044490387b9e38c65a8e6 * update man page and usage explanation for --lfts_file Tue Jul 30 17:08:06 2013 +0300 Hal Rosenstock 6fdd84495fdf83d2b59ce9f7846ea4edbd1091df * osm_sa_path_record.c: Fix rate setting issue in SA PR handling Mon Jul 29 10:37:36 2013 +0300 Alex Netes 4d6925caa05a41fa155c8a00d329cc97e7d88b57 * osm_vendor_ibumad.c: Fix explicit null derefenced issue found by coverity Tue Nov 27 16:06:25 2012 +0200 Alex Netes 2d67f3e34c190b3e647e70aa3754bed3d6c062c5 * opensm/osm_db_pack.c: Removed uneeded asserts Mon Jul 22 21:19:48 2013 -0400 Eitan Zahavi 09e1e7ee1399cb4d81cd0b821fda8a4a29f1021e * libvendor/osm_pkt_randomizer.c: Fix broken compilation with vendor sim Thu Jul 18 09:53:34 2013 -0400 Alex Netes a47e5d049eb3f2e3ded70e3e61e04608f2451d4e * complib/cl_event_wheel.c: Roundup timeout to nearest msec Tue Jul 9 10:52:53 2013 +0300 Alex Netes 6ff99aa57af9608945e69e41b1e707b14331d6f1 * complib/cl_event_wheel.c: Add print of num_regs in cl_event_wheel_dump Tue Jul 9 10:43:43 2013 +0300 Alex Netes a3957f258a8cfd70ccdead1ede1452a65ec809df * complib/cl_event_wheel.c: Fix duplicate error codes Thu Jul 4 14:00:22 2013 +0300 Alex Netes ceb4041ff7bc6b6caaccd1c6ca7b68507a9b80ba * Fix test scenario in cl_event_wheel Wed Jul 3 20:06:48 2013 +0300 Hal Rosenstock 51b187bc4843e741171bbcfad3e9ecd2d929f7dc * Add flags to OSM_EVENT_ID_UCAST_ROUTING_DONE Tue Jul 2 17:55:12 2013 +0300 Hal Rosenstock 5824714a0892e45038c0620d056f6926710e06c8 * osmeventplugin/osmeventplugin.c: Add Mellanox copyright Tue Jul 2 17:46:09 2013 +0300 Hal Rosenstock 7186965c3a02fea16e63b2815b68a2504606bdef * osm_event_plugin.h: Add Mellanox copyright Tue Jul 2 16:40:38 2013 +0300 Jeff Becker c97bd7b5d3f621c10f95ed3d0553c6c57cfe2874 * Permit toggling log flush from console Fri Jun 28 01:07:00 2013 -0700 Roland Dreier cd3b715107c7499be0c1b632cc2b2bf2aeaaf95e * osmtest: Make the "-guid" option's argument mandatory Wed Apr 3 11:28:12 2013 +0300 Alex Netes 0154977f90422ce6c1b457e2634d4cbfad075511 * complib/cl_event_wheel.h: Some cosmetic fixes Wed Jun 26 01:18:13 2013 -0700 Line Holen b78b1d53cf9a9ff6269b658b3a4a8cd15f8894b8 * osm_sa_mcmember_record.c validate_requested_mgid returning boolean Mon Jun 24 12:47:39 2013 -0400 Vladimir Koushnir 58ee065dbdeaa714379466cf864bbf6f306cb21b * osm_ucast_mgr.c: Fix extra copy in set_lft_block routine Sat Jun 22 18:21:51 2013 +0300 Vladimir Koushnir 2a8c474fd61be844fdb5e1a7202bf45cabcd5c5a * complib: Fix memory leak in cl_thread_pool_destroy function Tue Jun 25 21:46:24 2013 +0300 Vladimir Koushnir 5bf6e727fd909d1548f88f96e107c2e06920e058 * osm_ucast_mgr.c: Fix duplicated code for fallback routing engine Mon Jun 24 08:02:58 2013 +0300 Alex Netes 1960fbc63acc2bb165ffe0337692838ade932b9d * osm_trap_rcv.c: Fix crash in babbling port feature Sun Jun 9 18:05:01 2013 +0300 Vladimir Koushnir 96eafa0544ba3a2040dfb43b1df5be5d77f73d95 * ftree: Allow defining only io_guids file and consider rest of nodes as CN nodes Thu Jun 20 00:44:02 2013 -0700 Line Holen 2e5966eaadb64f748462831014660a8f350171b9 * osm_sm_state_mgr.c Trivial log changes Wed Jun 5 11:14:59 2013 +0000 Line Holen aed167565a9571efed67805634988911de54bb06 * Log changes related to event subscription and forwarding Wed Jun 5 14:52:01 2013 +0300 Dan Ben Yosef 1872d116e9cf27399307e1d3aad5eb54824251e8 * osm_sa_sminfo_record.c: fix sminfo sa query returns all sminfo records when filtering by LID in osm_smir_rcv_process Tue Dec 4 16:44:06 2012 +0200 Dan Ben Yosef b92f25acc193e870dd8fa47c766a4b1a02bc815e * osm_ucast_cache.c : Fix dereference null return value Sun Apr 28 10:06:00 2013 +0300 Alex Netes 21765ade61c96c319d157293e57e10f2f0e07846 * When SM fails to load/parse root_guids file use MinHop heuristics Mon Jun 3 11:44:01 2013 +0300 Vladimir Koushnir 7c21c145e228cab52670819a22478fba409efb6c * Fix shift pattern support in FTREE routing for native ftree topologies Sun Dec 2 16:07:49 2012 +0200 Dan Ben Yosef 35f4419e6f2451f2124e826e8e93b02c733d068c * osm_ucast_ftree.c: fix dereferencing null variable Sun Dec 2 13:48:47 2012 +0200 Dan Ben Yosef 4d36d6d133c09e45fe394b3519ac9cae5ebbe1c5 * osm_ucast_ftree.c : fix dereferencing null variable Thu Aug 16 16:33:55 2012 +0300 Dan Ben Yosef 49f1a71299e4aa28a8319334c772525f67cbd1ca * opensm: fix possible double free in osm_ucast_ftree.c Sun Apr 29 12:25:41 2012 +0300 Vladimir Koushnir 269512894d0bbb814707bf0aae56e832228f32f9 * Fix fat-tree routing for CAs with more than 1 connected port Tue Jun 11 14:30:41 2013 +0300 Hal Rosenstock 75bba51121c5545209b15489b9928fe4fd826007 * Minor log formatting changes Mon Jun 3 11:40:47 2013 +0000 Line Holen 16b4dfc9f8c1cf7283590607b7bfd83ab287260e * Some log changes Thu Jun 6 14:35:45 2013 +0000 Line Holen 51f87eec666f0a3911df301195c63b42bbdf6dc6 * Add attribute information to SA request error messages Wed Jun 5 11:14:12 2013 +0000 Line Holen 42558d6dc04d748ba0c923bf5f3eae065da55c60 * osm_sm_state_mgr.c Don't clear IS_SM bit when changing state to NOT_ACTIVE Mon Jun 3 11:39:46 2013 +0000 Line Holen abd47ccc7b18d54f7c6caf593dbdf4726a8af5d4 * osm_sa_mcmember_record.c Reduce number of error messages the for same event Thu May 30 18:16:43 2013 +0000 Line Holen ae9d7e7f4e2f62eabad4cf9d60cd5b68a8295147 * Add trap details to notice log message Thu May 30 21:14:00 2013 +0300 Jens Domke 21a5b5f988c20a9ed024cc039b4cf56198b6aadd * DFSSSP - workaround for better VL balancing Thu May 30 07:38:56 2013 -0700 Line Holen b42ae68c0b2341308d66fe07f271a76c16ee9cfc * osm_console_io.c Memory leak when closing console Wed May 29 15:41:41 2013 +0300 Dan Ben Yosef bcf00cb2036530de2c2a1b04708a836fb612653f * osm_ucast_dfsssp.c: Fix memory leak in dfsssp_do_dijkstra_routing Tue May 28 04:20:54 2013 -0700 Line Holen f42a23223142fe2a984f37b3f3aa71dddef86ec7 * Fix segfault in osm_mgrp_delete_port() Sat May 25 18:01:46 2013 +0300 Hal Rosenstock 886de5d544bfc80c6ded7f424296a7f0afff7043 * ib_types.h: Fix commentary typo Wed May 22 17:31:29 2013 +0300 Hal Rosenstock 234401bda9a5185acad047ab97725b8524afac3b * cl_threadpool.h: Remove vestigial mention of cl_thread_pool_construct Tue May 14 04:26:51 2013 -0700 Line Holen e20f37aa46eebaa505bfa87c82556d0139126bed * osm_subnet.c Remove empty syslog message Mon May 13 09:30:43 2013 -0700 Line Holen 1a94326774821805588de4abf382265d69c95bbe * osm_sa_multipath_record.c Use aliasGUIDs when building responses Mon May 13 20:13:52 2013 +0300 Hal Rosenstock 898e9a321edae75152d490017846c317ea3f23bb * osm_ucast_lash.c: Cosmetic formatting change Thu May 9 18:48:09 2013 +0300 Alex Netes 6d0413dfc662bd8749655fbb7a5c2c5bb1962973 * opensm/osm_ucast_dfsssp.c: Fix unused variable in update_mcft() Thu May 2 21:15:26 2013 +0900 Jens Domke 83950842ea845dd2803d80c685ebdad9fabb0622 * OpenSM: dfsssp - add support for multicast Tue Apr 23 17:09:19 2013 +0300 Alex Netes 943a40a5890db9874eceaa63461ecf99eb60ae12 * opensm: Fix Q_Key, TClass and limited keys parsing warnings in partitions.conf Thu Apr 11 10:19:35 2013 -0400 Alex Netes 0fc6e8b996951eff2e1b40599af9b0deefb35009 * osm_lid_mgr.c: Fix duplicate LID assignment after SM port down Thu Apr 11 14:19:27 2013 +0000 Ira Weiny 583d4cf3729f805a15b2260ccf92fe166f4e579f * osm_console_io.c: Handle another write-strings issue Wed Apr 10 14:18:53 2013 +0300 Hal Rosenstock becc27ece0815807f39e45ac8016df18dabd9b29 * osm_sa_mad_ctrl.c: Drop incoming SA queries when shutting down Wed Apr 10 00:50:01 2013 +0300 Hal Rosenstock dbeb7a790227914618e342b1bc04a21f347e9331 * Change LFT event to be per block/per switch rather than just per switch Wed Apr 10 00:43:17 2013 +0300 Hal Rosenstock 25c088aa6256d435b07c0b7dca8b14e907faa112 * Setup SM port GUID in subnet object as soon as it is known Wed Apr 10 00:37:14 2013 +0300 Hal Rosenstock 92c502aeb960edbfbb0c7c13bac3565a485a129f * osm_sa_mcmember_record.c: On join and leave, validate subnet prefix in port GID Wed Apr 10 00:35:07 2013 +0300 Hal Rosenstock cbbe385b81744b6caa5d982b03c9156470239edf * osm_sa_mcmember_record.c: Improve debug log message in validate_modify Wed Apr 10 00:32:42 2013 +0300 Hal Rosenstock 4f835ae9a0450573e76f23805b41bccd26a170c8 * osm_congestion_control.c: Simplify some code Wed Apr 10 00:31:19 2013 +0300 Hal Rosenstock 23ebbe96ce2beca4846726891f5d1c4eacb887c3 * osm_log.c: Remove unneeded initialization in osm_log Tue Apr 9 22:50:57 2013 +0300 Hal Rosenstock 550fdeb2b02abc7b653825ded9f5f9446657ef34 * osm_lid_mgr.c: Some commentary fixes/updates Fri Apr 5 15:32:35 2013 -0700 Albert Chu 1d5084577ae686620df9dc6695087b7fea8c3f4c * opensm: Add configure output messages for several configure options Fri Apr 5 05:31:44 2013 +0300 Hal Rosenstock 91384edf75306acf70be78f114253efbe9c460f9 * osm_lid_mgr.c: Fix a couple of commentary typos Mon Apr 1 16:16:25 2013 +0300 Hal Rosenstock a23880018798d6715b179f95e85d7b83bbf8463c * ib_types.h: Trap 144 PortInfo:CapabilityMask2 changed bit definition Mon Mar 25 12:41:35 2013 +0200 Ammar Haj Hamad 564b6eb858f319e4282c7925ef6ace7c1f9bd74f * opensm: fix dfsssp uninitialized value Mon Mar 18 17:42:11 2013 +0200 Hal Rosenstock 6cd61141d8442c49d4e5b6bcb29eeeb037384c83 * opensm: Add support for LFT changed event Mon Mar 18 17:41:39 2013 +0200 Hal Rosenstock c0602edd30b9e2efbd3e2d917a423c120f8dbd4d * opensm/osm_port_info_rcv.c: Fix min_sw_data_vls calculation Thu Mar 14 20:18:20 2013 +0200 Hal Rosenstock 395157e5de360e02c5e4c827febc21442af3ad67 * opensm/osm_node.h: Fix some commentary typos Thu Mar 14 17:42:22 2013 +0200 Hal Rosenstock 2d8df36729434a8ab68035eec9898b512b918e91 * opensm/osm_sw_info_rcv.c: Fix double release of lock in osm_si_rcv_process Thu Mar 14 13:08:39 2013 +0200 Hal Rosenstock 664494a8157684f2f277fb457556a7c27feae0af * opensm: Fix issues causing const warnings for strings Mon Mar 11 15:35:29 2013 +0200 Hal Rosenstock 8840f825a7a2800acfa4b9559c111dff30f9b6af * opensm/osm_switch.h: Cosmetic change Sat Mar 9 17:25:38 2013 +0200 Hal Rosenstock 1a06167c7a2450e110ffcba179c829fa43b6ac9b * opensm/man/osmtest.8: Add option for using full world path queries Fri Mar 8 09:31:10 2013 -0700 Jim Schutt eb43f7e5fd768b24148924c2443774525b4f15e0 * opensm/osm_torus.c: clarify log messages on stale priv pointers Fri Mar 8 08:59:01 2013 -0700 Jim Schutt e7435ef51bd6f07c2d9520e959a731e78e83078e * opensm/osm_torus.c: avoid the possibility of following stale ->priv pointers Fri Mar 8 18:35:29 2013 -0800 Ira Weiny 1f7ceb8c05fdbe84d75c79d8abb768000ec520ad * opensm/osmtest: fix debug build Thu Mar 7 16:11:08 2013 +0200 Hal Rosenstock dc0760cb8088fbe079e19682570a884ba01e94ff * opensm/osm_subnet.c: Miscellaneous minor fixes Mon Mar 4 23:45:10 2013 +0200 Hal Rosenstock 4924ea7283e2027a49e8a8a7ca33b20f96af2ae7 * osmtest: Add support for full world path records back as option Mon Mar 4 22:52:38 2013 +0200 Hal Rosenstock 6f1a67e966d62040319f093eb61d9c72e2a4390a * osmtest/osmtest.c: Minor reordering of code in osmtest_write_all_path_recs Mon Feb 25 16:02:54 2013 +0200 Dan Ben Yosef e9556df81f50ee3653bc10420a7529a81804e331 * opensm/osmtest.c: half_world_query when creating inventory file Sat Mar 2 18:02:39 2013 +0200 Hal Rosenstock 81d3ea3a41af100f8e6b61ea1c68eabfed0b815f * opensm/osm_subnet.c: Change default for perfmgr_query_cpi to FALSE Fri Mar 1 16:39:13 2013 -0800 Albert Chu 309317deaa08cc3937d2676b43390f85c2c6c7da * opensm/osm_ucast_ftree.c: Fix invalid debug output message Thu Feb 28 17:08:51 2013 -0800 Ira Weiny 904a555396482fdfdf0253d4dd778093950c64d1 * opensm/perfmgr: fix access to shared sweep_state variable Thu Feb 28 17:08:49 2013 -0800 Ira Weiny 1458263d0646045559a827e7ab40990658b3eeae * opensm/perfmgr: don't clear data counters in PortCounters when ExtendedPortCounters is supported Thu Feb 28 17:08:07 2013 -0800 Ira Weiny b73c378e4003e095c6ac41ac2b545c315d1e7fdc * opensm/perfmgr; add support for PortCountersExtended NOIETF Thu Feb 28 17:06:18 2013 -0800 Ira Weiny 70f58208bcb021774a6d502643ca7cdc26a231e6 * opensm/perfmgr: Issue PortCountersExtended query when supported Thu Feb 28 17:05:26 2013 -0800 Ira Weiny d0a85322aa6a69d21e9538f03d1f8c30e1ea745a * opensm/perfmgr: clean up: break out redirect processing from pc_recv_process Thu Feb 28 17:05:23 2013 -0800 Ira Weiny b6d0001f6918c6557980931c7487a5954559aa12 * opensm/perfmgr: issue ClassPortInfo as first query to each port. Thu Feb 28 17:31:19 2013 +0200 Hal Rosenstock e1af1ce730a419fe2210b5fa073f2fe84a7c8524 * opensm/osm_console.c: Use ib_port_info_get_link_speed_ext_enabled Tue Feb 26 13:54:42 2013 -0800 Albert Chu 2ba9919a459129a055d97691af7d366e159cb8c2 * opensm/osm_console.c: Do not perform portstatus checks on down ports Tue Feb 26 13:54:40 2013 -0800 Albert Chu 5c45f606fed1c6952863bec0de88215e908aeb6c * opensm/osm_console.c: Support portstatus output for unenabled width/speed Mon Feb 25 08:30:54 2013 -0800 Ira Weiny ef32e127a9ea0d08af4133cc13c4002bfa86bcd6 * opensm: make osm_pr_rcv_get_end_points, osm_pr_rcv_process_pair, osm_pr_rcv_process_half public Mon Feb 25 08:30:10 2013 -0800 Ira Weiny 7723c07d86d1ea62594c7d91cea16f78df030d25 * opensm: make osm_get_path_params public Mon Feb 25 18:43:54 2013 +0200 Hal Rosenstock 7ac18bb72b1349e962c81e201bd87be6db81f6c2 * opensm/osm_perfmgr.c: Cosmetic changes Sat Feb 23 16:17:41 2013 -0800 Ira Weiny fe52571755d64248830dc4abdfb735128f8fd28f * opensm/perfmgr: add failed port guid to error message Fri Feb 22 18:23:57 2013 +0200 Alex Netes 8b67a1c803eee5a23eb5514510fef4a41f93bdec * opensm/osm_req.c: Better implementation of req_determine_mkey Thu Feb 21 13:44:13 2013 -0800 Ira Weiny 37eecc80c828ad12a8c346407e0fbd669f80afd7 * opensm/libibvendor: osm_vendor_get_all_port_attr include sm_sl value in port attribute struct Tue Feb 12 22:40:05 2013 +0200 Hal Rosenstock 8ac930e1313a5dda6919d9986bb0ed588a12c45a * osmtest/osmt_multicast.c: Fix IPoIB MC group recognition Thu Feb 21 17:40:47 2013 +0200 Hal Rosenstock 5a33cc67319b0deab2294d936b014299cb1151b4 * osmtest/osmt_multicast.c: Fix commentary typo Tue Feb 12 08:56:39 2013 +0200 Dan Ben Yosef 19476441c62b5cf5b6841fc6dbedbd3777e60d63 * opensm/osm_qos_policy.c: fix memory leak when parsing policy file Wed Feb 20 20:37:38 2013 +0200 Hal Rosenstock 935816436789b998dcb9387ccc9037f6bce2341d * opensm/osm_sa_multipath_record.c: Validate required components are indicated Wed Feb 20 20:35:15 2013 +0200 Hal Rosenstock fbe0d0275c926244bfef3d73c9fe74ebdfee57e6 * opensm/osm_sa_multipath_record.c: Make sure either none or both ServiceID parameters are supplied Wed Feb 20 20:31:25 2013 +0200 Hal Rosenstock f929ac163eb91fa1064d0b8d86005fd23e0955ae * opensm/osm_sa_path_record.c: Make sure either none or both ServiceID parameters are supplied Wed Feb 20 20:29:20 2013 +0200 Hal Rosenstock 43efbc20443288f539307147256ccc12365b20f5 * opensm/osm_sa_multipath_record.c: Fix seg fault in mpr_rcv_get_apm_paths Wed Feb 20 20:22:55 2013 +0200 Hal Rosenstock 186a59884c1260286fc7512a134fa102ddf4e7f7 * opensm/osm_sa_multipath_record.c: Fix commentary typo Sun Nov 11 15:49:03 2012 +0200 Ilya Nelkenbaum 4cb3751024ba9a45b2d305c06c907b5e95e38b3b * osm_dump.c: Fix typo in dump_lid_matrix Wed Feb 20 20:04:29 2013 +0200 Hal Rosenstock a0deac6cdb3ea10a7970a41a5b3108d8299ba7fc * opensm/osm_dump.c: Fix enhanced switch port 0 handling in print_node_report Wed Feb 20 19:48:14 2013 +0200 Hal Rosenstock 250802dd5d5706e910c887d832091a962ae7edba * opensm/osm_qos_policy.c: Fix source & destination GUID policy check Wed Feb 20 16:55:02 2013 +0200 Daniel Klein 9f231a8e55f103db4e9808636afa799ead55e5ef * libvendor/osm_vendor_ibumad.c: fix mad validation in case of multipath record response Wed Feb 20 13:58:27 2013 +0200 Hal Rosenstock abbbe8ae825054172614fc016024b019631fbf78 * opensm/ib_types.h: Add missing IB_MPR_COMPMASK_SERVICEID define Tue Feb 19 15:06:34 2013 -0800 Ira Weiny 2be4e201b1c997321d11d8b5d0c5c0975472fa7b * opensm/perfmgr: update node name when Node Description is received from node Wed Feb 13 13:52:03 2013 -0800 Ira Weiny f37bf3c615f230577408ad779c1dc6c6080e899f * opensm/perfmgr: skip data counters when only printing errors Wed Feb 13 13:51:23 2013 -0800 Ira Weiny 8412591dd0b83eb37d371c7b68e04caadd4ca98c * opensm/perfmgr: mark/report time of last counter update Tue Feb 19 19:56:50 2013 +0200 Hal Rosenstock 505d48b9b54dad9ffeab940dc257e53c0c499432 * opensm/osm_torus.c: Cosmetic formatting changes Fri Feb 15 21:21:07 2013 +0200 Hal Rosenstock dc44d485710cad711dfab653db2e728fc04a3952 * opensm/ib_types.h: Add missing IB_PR_COMPMASK_SERVICEID define ** Version: opensm-3.3.16 Tue Feb 5 19:11:07 2013 +0200 Alex Netes c7837ce677a7a719aa46565b83c87350ccceb8df * opensm: packages versions update Tue Feb 5 18:12:49 2013 +0200 Alex Netes 387f554a2867e6a1e2cc85789370e7e27a7c38e9 * opensm_release_notes-3.3: update Tue Feb 5 17:57:55 2013 +0200 Alex Netes c491dae684a2eb722b58d9f53a2ae4ee61701112 * opensm: update shared library versions Mon Jan 28 15:42:05 2013 +0200 Hal Rosenstock d7e4da1035ed409d9ac478da8e304eaaf7895856 * opensm: Use IB_PATH_SELECTOR_EXACTLY rather than harded coded constant Thu Jan 24 17:16:28 2013 +0200 Hal Rosenstock 735c86d85ff4e818d9bc0d1202da2fe6fb414e6e * opensm/osm_sa_informinfo.c: Fix infr_rcv_respond to only copy InformInfo Wed Jan 23 13:53:37 2013 +0200 Hal Rosenstock f1186689d416198cd84b2899cf619ad57a5df6a3 * opensm/osm_sa: Improve SA record response handling (osm_sa_respond) Wed Jul 25 06:40:06 2012 -0400 Hal Rosenstock b09ac65a7757711b5eaf56712df6b1c4afa773fb * opensm/osm_sa_informinfo.c: Add trusted support for InformInfo/InformInfoRecord Tue Feb 5 17:29:48 2013 +0200 Alex Netes 3a87fa2d6a3c81174198629295f9317a34544177 * opensm/osm_req.c: fix first sweep m_key search algorithm Tue Jan 29 19:18:50 2013 +0200 Alex Netes 5fdb0b91601ff2506578b0dd7363ad6050c9e1b2 * opensm/configure.in: Remove Default-Start from opensmd init script Mon Feb 4 16:02:01 2013 +0200 Alex Netes b9661000fd939cf7ea67261398779626a7d4019a * opensm/osm_sm_state_mgr.c: Start sweep immedeately when recieving HANDOVER in DISCOVERING state Sun Nov 25 18:19:44 2012 +0200 Alex Netes 4349c07d15df9f59ca5c86228c08c6390e679151 * opensm: Add physp_p discovery count support Tue Dec 11 14:12:10 2012 +0200 Alex Netes d706cbf2ead6953151400faa7c808050bb8806cf * opensm/osm_sm_mad_ctrl.c: Upon receiving trap repress we should decrease qp0_mads_outstanding_on_wire Thu May 10 09:33:31 2012 +0200 Vincent Ficet 9cbb8af93ec4b67bfc2f7e20d516ec8172f9870f * opensm/osm_ucast_ftree.c: fix opensm segfault in osm_ucast_ftree.c Mon Feb 4 12:24:39 2013 +0200 Alex Netes e1e470681f1beb26b86b73ed6bd7fb2fae386d19 * opensm: Revert "opensm/osm_ucast_ftree: When roots are not connected, update hop count but not lft" Wed Dec 19 15:39:01 2012 +0200 Alex Netes d2312af6e312dbd5ad10edeb0b7648bf45c21992 * opensm/osm_link_mgr.c: Fix sending PortInfo(Set) with AM SMSupportExtendedSpeeds bit set for switch base port 0 Wed Dec 19 11:21:11 2012 +0200 Alex Netes 06ae82c66fcdb50236987c07d13e1af3a2094c53 * opensm/osm_link_mgr.c: Set AM SMSupportExtendedSpeeds bit if port supports ExtPortInfo Thu Jan 3 15:33:58 2013 +0200 Shlomi Nimrodi b2cd2d7308a84e0c3dde2639c2f74b9127dca4f5 * opensm/osm_ucast_ftree.c: Fix unranked nodes bug in FTree Wed Jan 9 17:30:44 2013 +0200 Alex Netes 7a49366ea2f08fbf01145853536925457bcd3c56 * opensm: Changed #if to #ifdef when using ENABLE_OSM_PERF_MGR_PROFILE Tue Jan 15 10:26:30 2013 +0200 Ilya Nelkenbaum 1cf0bb972094c6e590ad9137a752f9576cd5a5b5 * opensm/osm_congestion_control.c: fix use-after-free found by coverity Wed Jan 16 11:06:44 2013 +0200 Shlomi Nimrodi edd0552d1d11ffe9d348327c340d2a8ce0102f9c * opensm/osm_qos_policy.c: fix segmentation fault on osm_qos_policy_match_rule_destroy (osm_qos_policy.c) Wed Jan 16 21:54:57 2013 +0200 Hal Rosenstock 34af1a57b472d76297289b2716a7ce43ee5ef3e2 * opensm/osm_torus.c: torus routing should fail with VLCap 1 on switch external ports Mon Jan 14 15:31:42 2013 +0200 Hal Rosenstock 2b8940ba8c251b9055c4505a5638a295cff19f0f * opensm/osm_torus.c: In dump_torus, make sure switch is present before dumping Fri Nov 9 13:55:24 2012 -0800 Albert Chu 2364e8e185ab2814cb0c642994f9c490e271cfec * opensm: Add better error output when parsing node name maps Fri Jan 25 08:07:34 2013 -0500 Hal Rosenstock 7204287ed84bca90a4aebf67a87ddb6f1a2f6a90 * opensm/osm_sa_mcmember_record.c: Only use scope from MC group in copy_from_create_mc_rec Thu Jan 24 09:45:48 2013 -0500 Hal Rosenstock 4eb0f694c7a68b08865e826f092137b5c2011d17 * opensm/osm_dump.c: Remove incorrect assert Wed Jan 23 01:42:04 2013 +0900 Jens Domke 1ddb44b612cd29830e9589a5265801bdddb49cda * OpenSM: dfsssp - moved paths from one to another VL might be counted multiple times Wed Jan 23 01:41:47 2013 +0900 Jens Domke a0a9eeafb11bb639696bd84f3fdd213e51b6ee2a * OpenSM: DFSSSP does not find LIDs due to wrong byte order (v2) Wed Jan 23 01:41:31 2013 +0900 Jens Domke 13fd9522bbc5f98e13b988ffddcf35d784dcbc2d * OpenSM: dfsssp - avoid unnecessary nested loop in vltable_print for OSM_LOG_INFO Wed Jan 23 01:41:07 2013 +0900 Jens Domke 1cbed64100d6382b08cc4a19ee1422d7bc524d77 * OpenSM: dfsssp - change the port traversal for sssp Wed Jan 23 01:40:49 2013 +0900 Jens Domke c2f0bb97afd0eef149e70ddf569a2788d43f33de * OpenSM: dfsssp - add support for base/enhanced switch port Wed Jan 23 01:40:29 2013 +0900 Jens Domke 64873fff7a9b28b1cfebd5872260d41899f7561e * OpenSM: dfsssp ignores differences in the lmc value Wed Jan 23 01:40:07 2013 +0900 Dan Ben Yosef ab5af498c76f4dd38b0dbb3a0b469b72987a7c9a * opensm/osm_ucast_dfsssp.c : fix dereference before null check Wed Jan 23 01:39:42 2013 +0900 Dan Ben Yosef b6a2f6aefbb1bce1b5365e01a2986c8a6b6e034a * opensm/osm_ucast_dfsssp.c : fix dereference null return value Wed Jan 23 01:39:13 2013 +0900 Dan Ben Yosef e9cc52302a2475ab820cb2cf63bba4209fd96b45 * opensm/osm_ucast_dfsssp.c : Fix resource leak Wed Jan 23 01:38:18 2013 +0900 Jens Domke dec11095c30d082273a126cc73ef33f568aef4a2 * DFSSSP: fix a memory leak in dfsssp_build_graph Mon Nov 12 11:51:09 2012 -0800 Ira Weiny df66c1fa0783940fee61b2402038a5c755206689 * opensm: Fix incorrect use of sizeof Mon Dec 3 10:25:21 2012 -0500 Hal Rosenstock 162493efd0bed6c3c9cb53bcf106525b2a4d9122 * opensm/osm_req.c: In req_determine_mkey, use osm_physp APIs Mon Dec 3 10:25:12 2012 -0500 Hal Rosenstock d5fe52812175f9dbbaf7608805142b5620418d62 * opensm/osm_req.c: In req_determine_mkey, fix DR algorithm Mon Jan 7 14:50:42 2013 -0500 Hal Rosenstock fc53bdc19b548912b4739fb2ab59e9ca5a931fbc * opensm/osm_torus.c: Dump torus when OSM_LOG_ROUTING specified Mon Jan 7 14:50:31 2013 -0500 Hal Rosenstock 434afa6505f608739be37d3e42c090e8d557297d * opensm/torus: Add configuration for max_changes to report Mon Jan 7 14:50:23 2013 -0500 Hal Rosenstock 35bcddf6f7ec80de40d850229efd3d4c8bb3088b * opensm/osm_torus.c: Consolidate some parsing with parse_unsigned Wed Dec 19 14:16:47 2012 -0500 Hal Rosenstock 3f3d26faf686535f0e8091502079c22e37348e46 * opensm/osm_prtn_config.c: Insert autogenerated pkey into MGID for IPoIB Mon Dec 17 11:55:31 2012 -0500 Hal Rosenstock c58a416ff1fd43cf3b06fc59384cc0973d7b7c6c * opensm/osm_dump.c: Fix output port on SL2VL table for non switch nodes Mon Dec 17 11:55:27 2012 -0500 Hal Rosenstock 8af5bce91b4692c0b7b2e4f8aff22e4d9de564d5 * opensm/osm_sa_slvl_record.c: Fix out port for CAs and routers Mon Dec 17 11:55:21 2012 -0500 Hal Rosenstock 18a77f9efed31bb15e3a5a1644828d8e464e66c6 * opensm/osm_torus.c: Fix memory leak Sun Dec 9 02:54:57 2012 -0800 Garrett Cooper 4ccbdc1901766509bfac3e4aa5c75065b5892687 * Fix -Wformat-security warnings with clang Sun Dec 9 12:14:12 2012 -0800 Garrett Cooper c7623891d879b37716d71e06364c872fd1ce09a7 * Fix -Wtautological-compare warnings with clang Tue Dec 11 02:09:13 2012 -0800 Garrett Cooper 9e6dd8fc905917a10d43ec480def4dbec19e6bae * Fix linker error with clang with -O < 2 Mon Dec 3 16:26:08 2012 -0500 Hal Rosenstock d80ca1e892ef87bf11a410419995cc3433da30b0 * opensm/osm_port_info_rcv.c: Don't modify subnet minimal values when PortState DOWN Mon Dec 3 16:25:30 2012 -0500 Hal Rosenstock 8384156f077c7d09d5864404e72cee547121a83b * opensm/osm_torus.c: Fix crash in torus_update_osm_vlarb Mon Dec 3 10:26:07 2012 -0500 Hal Rosenstock f97a2e9873d1a3beb22a7206720ca36d19c3c4ff * opensm/osm_ucast_ftree.c: Eliminate unneeded NULL pointer checks prior to calls to free Mon Dec 3 10:25:57 2012 -0500 Hal Rosenstock 8a77f23540ff995a3193edceadc82688702b6c6e * opensm/osm_ucast_ftree.c: Remove duplicate free in fabric_create_leaf_switch_array Mon Dec 3 10:25:39 2012 -0500 Hal Rosenstock 338a67b4f7c3dde3b353f2d7b863e71dfbcec0df * opensm/osm_subnet.c: Improve error messages in subn_validate_neighbor Mon Dec 3 10:25:04 2012 -0500 Hal Rosenstock 0a1c9bf43745e390d7edf9e254efb932a3299bde * opensm/osm_req.c: In req_determine_mkey, add more info when ERR 1107 occurs Thu Nov 29 14:11:42 2012 -0500 Hal Rosenstock b974ca301d960a2de7eb71a844823942eca8b306 * opensm/osm_torus.c: Improve some misconfiguration error messages Wed Nov 28 14:03:44 2012 -0500 Hal Rosenstock e986d57d58fcb7d58dde0df30cd1006e3fd4b799 * opensm/osm_torus.c: Minor simplification to check_qos_config Wed Nov 28 14:03:39 2012 -0500 Hal Rosenstock 95b6f8345c1ac9aa4eb058dcb11c5960a91944ae * opensm: Update doc for changes to torus routing for, endport support Wed Nov 28 14:03:33 2012 -0500 Hal Rosenstock 998fb4383dc4c49b595545a2e54f35108e9d4fd7 * opensm/osm_torus.c: Add copyright Wed Nov 28 14:03:26 2012 -0500 Hal Rosenstock 268d327559d5a7bdf235c463c8c4489e32867221 * opensm/osm_torus.c: Improve QoS configuration Wed Nov 28 14:03:19 2012 -0500 Hal Rosenstock d1d2de57c34997b8d29f069e4631a484ce371ea2 * opensm: Update doc for changes to torus routing for CA, support Wed Nov 28 14:03:11 2012 -0500 Hal Rosenstock a362b5bae31664b9d1bee8f8cc31276656ae4b3f * opensm/osm_torus.c: Require only 2 data VLs supported (PortInfo.VLCap) and use VLs 0-1 on CA links Wed Nov 28 14:03:01 2012 -0500 Hal Rosenstock 3f536aea6bb3645545b9c53b7381928b28d0e121 * opensm: Add routing specific update_vlarb hook routine Wed Nov 28 14:02:54 2012 -0500 Hal Rosenstock 27da5eb71981c750ba4eabb0ce246b394597d52f * opensm/include/osm_opensm.h: Fix commentary typo Fri Nov 9 08:36:46 2012 -0500 Hal Rosenstock a2415f37a18808ccab18e37c4285a1b972376b34 * Add Per Module Logging support for Congestion Manager Tue Jan 15 17:40:09 2013 -0800 Ira Weiny a6d36947064d775a0acf137346e75d3c08c86a21 * opensm: clean up error message, function name is printed by logging code Fri Jan 11 14:33:56 2013 -0500 Hal Rosenstock 2cf80781aa91da7d119a6486d01a0656980fee8a * opensm/osm_sa_mcmember_record.c: Return proper scope for query with valid SA key Mon Jan 7 14:50:53 2013 -0500 Hal Rosenstock b9067ba9cb90a6817e4929eca97f1a87f045af8b * opensm/include/complib/cl_packon.h: Fix some commentary typos Thu Nov 8 10:32:59 2012 -0800 Albert Chu e522f749854d64dc2c95def7d90f6a8bb20b993c * opensm/osm_perfmgr_db.c: Fix output error due to possible 32bit int overflow Thu Nov 8 08:22:37 2012 -0800 Ira Weiny c1a206e25351129e6ec014d872451f04c21b4a28 * opensm: update performance manager documentation Mon Oct 29 16:45:02 2012 -0700 Albert Chu f204e9c9e9843cf0a2ef98a294d506f5f1cead84 * opensm: Protect against spurious wakeups when calling cl_event_wait_on Mon Oct 29 16:44:59 2012 -0700 Albert Chu 6f94c4c7bd0cfb16101c8680bcb515ac99839ff3 * opensm: Fix signed vs unsigned int comparison Wed Oct 24 18:26:27 2012 +0200 Alex Netes 7db5c7521998f6d2f93986bcc245348d9886657d * opensm/osm_subnet.c: Only parameters that marked with can_update flag should be updated during conf file rescan Thu Oct 25 11:59:38 2012 +0200 Bart Van Assche 282714a6f3e0e48eede83e0922515df3fc9fb497 * /etc/init.d/opensmd: Improve systemd integration Wed Oct 24 09:42:24 2012 -0400 Hal Rosenstock 2ea2cf366beac1592f35374ff2cfac58b7bba7c0 * opensm/osm_vl15intf.c: Fix commentary typo Wed Oct 24 09:42:11 2012 -0400 Hal Rosenstock 8b116d7c67276e682071ab3117e7f4b2c753d54d * opensm/osm_trap_rcv.c: Eliminate unneeded trap_rcv_process_response routine Wed Oct 24 09:42:01 2012 -0400 Hal Rosenstock f396936682083f351adc7812f42020106184ce30 * opensm/complib/cl_atomic_osd.h: Fix long standing bug in cl_atomic_sub Fri Sep 21 16:46:12 2012 +0200 Bart Van Assche 4008c2fe8cf50931d69e5618358aa6537e9ddb8e * opensm.spec.in: Improve portability Fri Sep 21 16:43:03 2012 +0200 Bart Van Assche 01ab74450fd1227cf2dfb9219ffd697d3beb4a45 * Make it possible to enable opensm with chkconfig Fri Sep 21 16:42:04 2012 +0200 Bart Van Assche c68ae6319211d462734b5e5c88401768d02bddf0 * Add command-line option --pidfile Wed Oct 10 19:40:13 2012 -0400 Hal Rosenstock ffb9a8227ee2e98c16ca2d19d2c840a32c8dcaef * opensm/osm_torus.c: Check fabric minimum data VLs on switch external ports Wed Oct 10 19:40:09 2012 -0400 Hal Rosenstock d0258f3cede60c321077697469bf247820e6087f * opensm: Track minimum value in the fabric for data VLs supported on switch external ports Wed Oct 10 19:40:05 2012 -0400 Hal Rosenstock 36159c2f925f52eee76cc568f1f11acf0808a3fc * opensm/osm_torus.c: Cosmetic formatting change Wed Oct 3 19:57:54 2012 -0400 Hal Rosenstock dba3f9289d4277f67474e75cfe5979a6cc74487c * opensm/osm_helper.c: Add some missing new lines to log message output Wed Oct 3 19:57:46 2012 -0400 Hal Rosenstock 94468b5462b20f86e0e9e8cc62a7418aef7f5520 * opensm/osm_ucast_updn.c: Add error codes to a couple of log messages Thu Sep 20 18:27:57 2012 +0200 Bart Van Assche 86a203b86dcc64c868f281cb45e5cb67c0fde17a * Correct option names in opensm man page Thu Sep 20 15:01:04 2012 +0300 Yevgeny Kliteynik dae214fcb4429c05a50849d7a34f2afaaef3466b * opensm/osm_log.h: fix function documentation Tue Sep 18 14:53:33 2012 -0400 Hal Rosenstock 34824382bdf7242e95f02ca3647608d99960d3e6 * opensm/osm_sa.h: Cosmetic commentary change Tue Sep 18 14:53:28 2012 -0400 Hal Rosenstock 824e1f0b05740ac80d324a25ab53b48e6a91b2fe * opensm/ib_types.h: Commentary and cosmetic formatting change Tue Sep 18 14:53:21 2012 -0400 Hal Rosenstock 3711e8a4a42b284cf1c517695526a3bbee026ced * opensm/complib/cl_spinlock.h: Remove some unimplemented routines Tue Sep 18 14:53:10 2012 -0400 Hal Rosenstock 0c3f57fe921159c88b760231ce8bca48578c4430 * opensm/osm_torus.c: Add error code to error log message Tue Sep 11 16:15:53 2012 +0200 Bart Van Assche 8e6dfbd0b9284fe0083b3f378ec313c3acfb060c * opensm: Add .gitignore Tue Sep 11 18:33:31 2012 +0300 Yevgeny Kliteynik 62484956a890b81fc0de592e959e156f5067f0d1 * opensm/osm_port_info_rcv.c: use PF() hint on fatal conditions Tue Sep 11 18:32:11 2012 +0300 Yevgeny Kliteynik dff59276cdf1a6f158e4d2f6c277508cb1efda02 * opensm/osm_port_info_rcv.c: check received local_port_num Tue Sep 11 18:29:52 2012 +0300 Yevgeny Kliteynik b7b1505ddfae733cfc088d1cd4f49529666d17af * opensm/libvendor/osm_vendor_ibumad.c: validate response MAD properties Tue Sep 11 18:29:07 2012 +0300 Yevgeny Kliteynik c215eea1235771ee50b0b9f65d988a9d8d5cdb1b * opensm/libvendor/osm_vendor_ibumad.c:rename "mad" to "p_mad" to indicate pointer Tue Sep 11 18:28:23 2012 +0300 Yevgeny Kliteynik e00f67bc9fe79cce4c6c5be9701e284373071194 * opensm/libvendor/osm_vendor_ibumad_sa.c: use wrapper function instead of direct access Tue Sep 11 18:26:55 2012 +0300 Yevgeny Kliteynik ebc772c89f638c406a5a16915151845c38a0832c * opensm/osm_node_info_rcv.c: using "PF" hint for all the fatal conditions Tue Sep 11 18:25:49 2012 +0300 Yevgeny Kliteynik e2f06cdde6a8ed3037c5740a4b0298c7d565589c * opensm/complib: define macros for for "if" statements with branch prediction hints Tue Sep 11 18:24:30 2012 +0300 Yevgeny Kliteynik 0e33c113f5980133f95cc86b16a18e1eb7ff120a * opensm/configure.in: check that compiler supports __builtin_expect() Wed Sep 5 13:02:23 2012 -0400 Hal Rosenstock 606157c06fae69dd7b63af36d5eb722ecb827ce9 * osmtest/osmt_multicast.c: Fix 02BF error Tue Sep 4 08:18:53 2012 -0400 Hal Rosenstock 2cb1854f51015b929331c1608a2cc86ab868594b * OpenSM: Add new Mellanox OUI Tue Sep 11 16:19:17 2012 +0200 Bart Van Assche 8e5fc5770903ba12804831dad3e9bfdcfbd80531 * opensm: osm_pkey: Remove unused variables Wed Aug 29 10:40:32 2012 -0700 Albert Chu e96a9334c9d14261430b6fd93ce5c282bd21fd65 * opensm: Manage ports that do not support congestion control Wed Jul 18 17:07:59 2012 +0300 Daniel Klein fbb74cae98063d45473f00f053961ecf872ffac0 * opensm: improve search common pkeys. Tue Aug 28 14:10:18 2012 -0400 Hal Rosenstock 03d55f611025ee933d8ef13f4ad2a57117a5a0dc * opensm/osm_sw_info_rcv.c: Fixed locking issue on osm_get_node_by_guid error Sun Aug 26 15:19:10 2012 +0300 Alex Netes 21084319505d8bd29f470407efe23961e2ff408c * opensm: fix default cc_max_outstanding_mads assignment Thu Aug 9 02:27:51 2012 -0400 Hal Rosenstock db34e30a172de1e2c054b2fa4cca4d6d75e3840f * opensm/osm_vendor_ibumad.c: Add management class to error log message Sun Aug 12 09:44:33 2012 +0300 Alex Netes a46b33e33cad38bec99d2faf63a765a9238413e9 * opensm: fix crash in DFSSSP routing engine on reroute Tue Jul 17 11:50:41 2012 -0700 Ira Weiny ba36f8156df2dc6396231ede9f3ae86c7455afa3 * opensm/perfmgr/console: add 'pm sweep' ** Version: opensm-3.3.15 Thu Aug 2 11:56:48 2012 +0300 Alex Netes 98273dd3fe4e4d53036c6a5567294a04cd1aa208 * opensm: packages versions update Thu Aug 2 11:55:46 2012 +0300 Alex Netes f415dc2f1b0570ed9f4f531e4dd35470a8e1722a * opensm_release_notes-3.3: update Thu Aug 2 11:38:05 2012 +0300 Alex Netes e283ca619f9cf48f252e15a54a32d026456f3add * opensm: update shared library versions Wed Aug 1 15:36:33 2012 -0700 Ira Weiny e7d4574f0d1442e41530b105bb40d50d57700c02 * opensm/perfmgr: update new error codes to '54' prefix Wed Aug 1 14:39:35 2012 -0700 Jim Foraker 7e6bdefa28dfbecba69ae3d2baeafe6b5b1a9713 * opensm/man/opensm.8.in: Add section for MKey support Wed Aug 1 14:41:27 2012 -0400 Hal Rosenstock 7d18662bd73ed1d80c34de841ba8def8f4ab8217 * osmtest/osmtest.c: Fix permissions Wed Aug 1 11:29:12 2012 -0400 Hal Rosenstock aebe678b0a6a20923e06d380b94712dc0fbbcf86 * opensm: Add support for multicast service records Wed Aug 1 07:52:35 2012 -0700 Jim Foraker 5509234bb31274a90703345d18fffa82b71f4b68 * opensm/scripts/sldd.sh: Update to support guid2mkey/neighbors Wed Aug 1 07:52:34 2012 -0700 Jim Foraker 2ae1477d3db4cb4ca653edbacbd72f1eb6165821 * opensm: Ensure sweep interval/mkey lease are sensibly set Wed Aug 1 07:52:33 2012 -0700 Jim Foraker cefe79b1c75e4d53396e77464aaf5b5b795f9872 * opensm: Check for valid mkey protection level in config file Wed Aug 1 07:52:32 2012 -0700 Jim Foraker 8fa0d2ccdcde3222451d6fb1003d750e53a1717e * opensm: Add neighboring link cache file Wed Aug 1 07:52:31 2012 -0700 Jim Foraker 5088d08e7c150f382ee76299bbbca14a8ae189b0 * opensm: Log errors on SubnGet timeouts Wed Aug 1 07:52:30 2012 -0700 Jim Foraker 9eed9c602558a336a512c3698649656a8ec383a6 * opensm: Add support for setting mkey protection levels Wed Aug 1 07:52:29 2012 -0700 Jim Foraker 5c4157d42bb6b3d32610e2e59184d1bf8d862d7c * opensm: Add locking where necessary around osm_req_* Wed Aug 1 07:52:28 2012 -0700 Jim Foraker 2f74f34a93100091ce7b501dc83e49ccef66940e * opensm: Allow recovery of subnets with misset mkeys Wed Aug 1 07:52:27 2012 -0700 Jim Foraker e5dc557125b453261dfac5f1efe61894462dd67d * opensm: Add guid2mkey cache file support Wed Aug 1 09:58:04 2012 -0400 Hal Rosenstock 3659b370651d1237289401aad3dcced95c14b43c * opensm/osm_sa_class_port_info.c: Indicate support for PortInfo CapMask2 matching in SA ClassPortInfo:CapabilityMask2 Wed Aug 1 09:57:52 2012 -0400 Hal Rosenstock 8016d3bc6b75ef95ad318a511e3cff0b0f4a8827 * opensm/osm_base.h: Add some SA ClassPortInfo CapabilityMask2 bits Tue Jul 31 10:18:19 2012 -0700 Albert Chu 20e1a460c4e146590e7e30ac6c6e77b960cd3521 * opensm/osm_congestion_control.c: Fix initialization hex string Tue Jul 31 12:27:09 2012 -0400 Hal Rosenstock a59072db80c08325f25a9577e986846cb3d903bb * opensm/osm_congestion_control.c: Skip TID 0 on 32 bit wraparound Mon Jul 30 09:25:34 2012 -0400 Hal Rosenstock 1a31c4429a18e7417a0eef18c26664c46beb55aa * opensm/osm_perfmgr.c: Use non conflicting error codes in log messages Mon Jul 30 07:34:47 2012 -0400 Hal Rosenstock 03a75d08fa7058187523d502d4176d1854ddc4fd * opensm/osm_sa_path_record.c: Restore osm_get_path_params functionality Tue Jul 31 05:13:37 2012 -0400 Hal Rosenstock a9340cf7e2fefa1c07cce730f20a88f3f49c245d * opensm: Support (null) being specified for per_module_logging_file option Tue Jul 31 02:44:43 2012 -0400 Hal Rosenstock 00375aa03dbfff4edbccd2dfd2809fe90a5c993f * opensm/osm_perfmgr.c: Eliminate compile warning Tue Jul 31 02:44:12 2012 -0400 Hal Rosenstock 7868c98bdd9974dd99d8547783435f69de4da44e * opensm: Remove unused per_module_logging option Wed Jul 4 13:48:15 2012 +0300 Alex Netes 49c460b351ed44e9ec66843490d61f835e2b5670 * Call drop manager before checking for other Master SM in the fabric Wed Jun 27 16:16:06 2012 +0300 Yevgeny Kliteynik 3585f8b84661852daecb520d4e1b91ede1159f56 * opensm: Fix crash found with ucast cache Mon Jun 18 14:44:59 2012 +0300 Alex Netes c0604f38a0fdc46d12bf60655237e1678310cec4 * Increase p_port->discovery_count only when received PortInfo for port 0 of the switch Sun Jun 24 10:54:10 2012 +0300 Hal Rosenstock 24b30d2aee2a347d448d55ff05aa2689664745f0 * opensm/osm_node_info_rcv.c: Handle non-compliant SMA gracefully Sun Jun 24 10:19:47 2012 +0300 Hal Rosenstock a4f2689178e2d963cab1c06b65fff824a674c9f6 * opensm/osm_vendor_ibumad: Add management class into match criteria Thu Jun 21 19:13:22 2012 +0300 Alex Netes a322f51f6b7ec58e5063be0269c6bda4dfec9aab * Skip TID 0 on 32 bit wraparound for SMP, SA and PerfMgt queries Thu Jun 21 14:52:46 2012 +0300 Alex Netes cded9afd9642e73ec9e5989e14685f6a072a37bb * Fix transaction id casting Wed Jun 13 18:07:33 2012 +0300 Alex Netes 63ebd0d01c92af990b4d5dafb251c2dbb1daabf0 * Fix crash in ucast cache when chain of switches connected back at once to the fabric Sun Jun 17 11:46:18 2012 +0300 Alex Netes 3b21d6f2eea9b3ef235148681a88eaecdd576735 * Fix crash in ucast cache when ucast cache invalidates after updating one of the switches Mon Apr 23 22:20:36 2012 +0300 Hal Rosenstock 4be63753f56008aba6da0d1008510a795d73813a * opensm/osm_sa*.c: Log requester port GUID at DEBUG level Mon Apr 23 23:09:34 2012 +0300 Hal Rosenstock 4cca51d5453469e8472f2467f057210895261cb8 * opensm/osm_sa_mcmember_record.c: Log requester port GUID at DEBUG level Mon Apr 23 22:19:43 2012 +0300 Hal Rosenstock 15b3eae8ae0af555283fb3fbda0649e82cb485c0 * opensm/osm_sa_path_record.c: Log requester port GUID at DEBUG level Tue Apr 17 13:09:42 2012 +0300 Hal Rosenstock 0b580cadf390a912b3b5d149c7672f884107730b * opensm/osm_sa_path_record.c: Add debug logging to pr_match_mgrp_attributes Tue Apr 17 13:09:42 2012 +0300 Hal Rosenstock ed4b7fb61deb51baa5b588cee9d03dd6b4224a87 * opensm/osm_sa_mcmember_record.c: In mcmr_rcv_join_mgrp, add MGID to log message Wed Apr 18 15:54:27 2012 +0300 Alex Netes 7e395427b69bfedee425e421d1dd907589c61011 * Fix pre-creation of MC group with MGID containing P_Key Sun Apr 22 13:37:07 2012 +0300 Hal Rosenstock 872dae4c494dd8ac51c07bfb42251798d4150823 * opensm/osm_sa_mcmember_record.c: Dump MCMemberRecord in mcmr_query_mgrp Thu Apr 19 19:08:31 2012 +0300 Alex Netes 69741e6e66ca9731f9efdaf65d5f2f6e7e03b2cc * Fix base port0 sl2vl mapping optimization Thu Apr 19 18:37:34 2012 +0300 Alex Netes bcda38eaeaf5abfcec4418bce91459ab437f5599 * Fix SL2VL configuration Mon Apr 9 15:19:02 2012 +0300 Vladimir Koushnir 71f2ce7b6684fa461fa1b10e6511d8bcd178ee51 * Sending SL2VL and VLARB SET MADs in distributed manner Wed Apr 11 16:47:15 2012 +0300 Vladimir Koushnir 086d611a238bcb817e4697eea401ee8fdc49b975 * Fixes in SL2VL table distribution algorithm Thu Mar 22 14:38:45 2012 +0200 Alex Netes 7d9f0c95e4a37b3f35ccbfc83eee73836793d818 * Fix deadlock between sminfo_set_req() and osm_sm_state_mgr() Wed Mar 7 19:57:39 2012 +0200 Hal Rosenstock f07bcc10bd45f5843f83ae872f1ad7f42e5b3705 * opensm/osm_subnet.c: Cosmetic formatting change Thu Feb 9 18:56:23 2012 +0200 Vladimir Koushnir 647a98e74a8cc7f0d7b95c3b8fe789af7e89e9a0 * Fixed crash in sm_state_mgr_send_master_sm_info_req() during fabric merge Sun Jan 22 10:25:53 2012 +0200 Alex Netes 048c66e39afbd6259faf1f1b4d2f04d93d550da9 * Fixed Multicast precreation parsing Wed Aug 31 22:51:48 2011 +0300 Hal Rosenstock c823a5b08ff166c8f41334840f9f4f460f28cf30 * opensm/osm_link_mgr.c: Set PortInfo:PortState to LinkDown when remote port isn't accessible Mon Oct 3 11:50:50 2011 +0200 Alex Netes ab88df6a3714f5cf7312bf62c756c1981dcf132d * Add support to reread configuration file when stacked in rediscovery loop. Wed Nov 17 15:40:30 2010 -0500 Hal Rosenstock 3fc662d26387f49a7e7ed717cd1745a57043d704 * opensm/torus-2QoS: Fix some typos in documentation Mon Jul 30 15:06:47 2012 -0700 Albert Chu fe62e5eaf9d4b20beb96b80e9ac780aaa670d3b9 * opensm: Add initial congestion control configuration support Mon Jul 30 10:57:44 2012 +0300 Alex Netes 67c9bae737a1f755df8c8b4f7163c588cdd5f015 * opensm: Move per_mod_log_tbl array from subn to log structure Sun Jul 29 07:26:30 2012 -0400 Hal Rosenstock 2cbd9f57b405a8e39240b2bdf191bbbaf701e8d0 * opensm/cl_atomic_osd.h: Cosmetic formatting change Wed Jul 25 06:40:59 2012 -0400 Hal Rosenstock cd63decfb07dab62162264c199e6caf915956141 * opensm/osm_helper.c: Add CapabilityMask2 to notice dump for trap 144 Wed Jul 25 06:40:53 2012 -0400 Hal Rosenstock 92058127aa04ba8a79d6a7e5e2b7e2a27593720c * opensm/ib_types.h: Add CapabilityMask2 to notice for trap 144 Wed Jul 25 06:40:46 2012 -0400 Hal Rosenstock 1d5213a8f37b54fd51beaf5c15b3fd1adb6f6415 * opensm/osm_madw.h: Fix a couple of cut 'n paste commentary errors Wed Jul 25 06:40:33 2012 -0400 Hal Rosenstock 25de7064e1fce178479712df4ef32af8e2217fcc * opensm/osm_sa_path_record.c: Add missing end-of-line in the log message Wed Jul 25 06:40:14 2012 -0400 Hal Rosenstock 3551530abf5d558049d99bdc18e87b660d8f515d * opensm/osm_trap_rcv.c: Remove vestigial comment Wed Jul 25 06:39:56 2012 -0400 Hal Rosenstock 324f269f8ec197f2bc78d7274622d9b85241cf7c * opensm/osm_sa_inform_info.c: Fix some error log messages Wed Jul 25 06:39:46 2012 -0400 Hal Rosenstock 067d21767cd29f1c5b5a6641ed4352e025f6032d * opensm/osm_inform.c: Make log message format consistent for error messages Wed Jul 25 06:39:36 2012 -0400 Hal Rosenstock 759b82ae4d2fb3218472ed88c53318d08ffc82e4 * opensm/osm_trap_rcv.c: Add better logging for traps 257 and 258 Wed Jul 25 06:37:33 2012 -0400 Hal Rosenstock b806657d814b02a284c18c38edc475a021bfbf97 * opensm/osm_sa_mad_ctrl.c: Eliminate commented out code line Tue Jul 24 22:49:17 2012 -0700 Ira Weiny 9d16039950f962bba4c427a8dc8e846215a0eeb1 * opensm/perfmgr: fix endian conversion of PortCounters Tue Jul 17 11:40:41 2012 -0700 Ira Weiny a851693ef7d235bd03b43e05bdf5d53803440565 * opensm/perfmgr: add logging of error counters Wed Jul 11 11:48:19 2012 -0700 Ira Weiny 52fa6597dda08b4b04897bcdcf9f586ddfde5f5f * opensm/console: add perfmgr "print_errors" (pe) console command. Tue Jul 3 16:54:00 2012 -0700 Ira Weiny a832ce2a3695aab4839bd371dc251ae23c1305db * opensm/console: Add human readable output for perfmgr data counters Wed Jul 11 11:48:16 2012 -0700 Ira Weiny 77a17569f7aba7b18977cacd7860c785a4e85288 * opensm/console: add abreviations for perfmgr commands Wed Jul 11 11:48:14 2012 -0700 Ira Weiny aca9a079453af49cb0c50c080af75e5ac6b439f7 * opensm/console; add port option to perfmgr print_counters Tue Jul 3 16:53:33 2012 -0700 Ira Weiny 00628cca9b5ff6ef554b1fa289bbad309137d2ea * opensm/console: add "print all" to print_counters console command Tue Jul 3 16:53:22 2012 -0700 Ira Weiny f5de9b53b02aa41aeed2f9d1ca9a8ba18cc988aa * opensm: perfmgr mark inactive nodes in perfmgr db Tue Jul 3 16:53:12 2012 -0700 Ira Weiny ff06340a3ffdbec408bfd7a54b28ec4a59d16fa7 * opensm: perfmgr delete "inactive" nodes from the DB Tue Jul 3 16:53:00 2012 -0700 Ira Weiny 68b1d92141dc91c47e4db12f677301f5531ef461 * opensm: perfmgr fix dump_counters Tue Jul 3 16:52:50 2012 -0700 Ira Weiny 059d8f49b579b1b648b67d21e26d95672c0761b6 * opensm/console: protect against 0 entered for the perfmgr sweep_time Tue Jul 3 16:52:23 2012 -0700 Ira Weiny cc866077edd13ccd52a917c9413940adad54b17a * opensm/perfmgr: Add config option to ignore Channel Adapters. Mon Jul 16 11:57:38 2012 +0300 Alex Netes 74e12d9c53e1d98cce45b780c7991c411a8b5402 * opensm: fix part_enforce parameter parsing crash Thu Jul 12 12:23:06 2012 -0400 Hal Rosenstock 91f0c004baadaaa77a20d9b14e0be82c63ff3dc1 * opensm/osm_node_info_rcv.c: In ni_rcv_process_existing_ca_or_router, handle error Tue Jul 10 13:09:10 2012 -0400 Hal Rosenstock c930a236b71f8e2aa9592ee2acad7283a743f87c * opensm/osm_subnet.c: Indicate lmc and lmc_esp0 are not changeable "on the fly" Tue Jul 10 17:23:35 2012 +0300 Daniel Klein 3e4e00b3cf8c229e791ff85fcbe5a6256535d75e * opensm/osmtest: fix osmtest ignores timeout parameter Mon Jul 9 13:15:16 2012 -0400 Hal Rosenstock 7825e67826c67efc351240569ad80c4fa1c73750 * opensm/libopensm.map: Removed unimplemented routine Mon Jul 9 13:15:10 2012 -0400 Hal Rosenstock 7de7b04b31ab7eddf3c52a7448e2684876d30ed9 * opensm/main.c: Handle daemon mode with guid specified as 0 more gracefully Sun Jul 8 11:43:21 2012 -0400 Hal Rosenstock 9478fbf6113efb74e90561cc5dc8becd1d60d932 * opensm/osm_subnet.c: Support MLNX ExtendedPortInfo for ConnectIB device Mon Jul 2 08:54:36 2012 -0400 Hal Rosenstock f8fc3347fca4f5a78cd0652e330b5561bb534532 * opensm/osm_node_info_rec.c: Also handle non compliant SMA in ni_rcv_process_existing Fri Jun 15 06:31:55 2012 -0400 Hal Rosenstock b4a481d933c5694a25cf65444741682ced742fb7 * opensm: Eliminate unneeded field in DR path structure Mon Jun 18 13:14:28 2012 -0400 Hal Rosenstock 01bc8c9221754393e66696982ca210bc524f89f8 * opensm/osm_state_mgr.c: Force subn->need_update when coming out of STANDBY Mon Jun 18 06:13:32 2012 -0400 Hal Rosenstock 276be8bfec8f2c92e52bada43be0522d69008ae5 * opensm: Dump info functions update for per module logging Fri Jun 15 06:32:08 2012 -0400 Hal Rosenstock 63c6609c6dae4ef0a11087eaea999e9dc14adec6 * opensm/osm_port.h: Fix commentary typo Fri Jun 15 06:32:02 2012 -0400 Hal Rosenstock 64b512a7cd5c2920d2de235e1bf884ff2fa7132d * opensm/osm_vendor_ibumad.c: Make binding log message clearer Wed Jun 6 20:35:05 2012 -0400 Hal Rosenstock e70c8c17f0f459a05604663fd030654e45cad1dd * opensm: Add enum for FILE_ID for per module logging Thu Jun 7 02:59:52 2012 +0300 Hal Rosenstock 2a2db8c020afdbe352902b2b26db9f17418e56dd * opensm: Add per module logging support Thu Jun 7 19:16:55 2012 +0000 Bart Van Assche 4d682bb8ba05e0a6c5f616e70dc28bfa85ef7cce * opensm: Fix pthread_create() return value checks Wed Jun 6 20:34:56 2012 -0400 Hal Rosenstock e21b106de1558ad5207076f8fb36cd5988f3762d * opensm: Cosmetic changes Wed Jun 6 13:04:15 2012 -0400 Hal Rosenstock 3ddb2e3b68dad08d4c4bf7d089c1886a75adfec3 * opensm: Add partition manager configuration doc to docs Sun Jun 3 12:08:42 2012 +0300 Alex Netes 8a9d2679c1d67a2592ff19f0a38ca2dc14158a10 * opensm: fix locking in osm_guid_mgr_process Wed May 30 19:28:53 2012 -0400 Hal Rosenstock 13ebee481707a92d2237481237f9b2e1211ee537 * opensm/osm_subnet.c: Fixed ftree/updn configuration failure when root_guid_file points to non-existing file Wed May 30 11:26:34 2012 -0400 Hal Rosenstock 95866491ea2864b226348a89f3551d49f1098fb6 * opensm/opensm_release_notes-3.3.txt: Update Unsupported IB Compliance Statements Wed May 30 10:49:52 2012 -0400 Hal Rosenstock 826b5c46d671bb257943589cb48ff972ca3f8759 * opensm/osm_ucast_dfsssp.c: Use osm_log_is_active Wed May 30 10:43:01 2012 -0400 Hal Rosenstock b2cad9d3aaadb3905e64db8c4b6023d3ce117d30 * opensm/complib/cl_fleximap.h: Cosmetic changes Wed May 30 10:42:55 2012 -0400 Hal Rosenstock 740c22b333f65c34e13c04d0c89338d8e8b9bc91 * opensm/include/opensm/osm_log.h: Fix commentary cut 'n paste error Wed May 30 10:33:31 2012 -0400 Hal Rosenstock 322a3103f179d1448c00ef25713a3373e07918dc * opensm/osm_ucast_ftree.c: Add a couple of asserts ** Version: opensm-3.3.14 Thu May 24 18:28:22 2012 +0300 Alex Netes c9ecfbd48de724a1ba30f74bf1b5b213b11afda9 * opensm: packages versions update Thu May 24 18:20:16 2012 +0300 Alex Netes 4a29c9425781bc8a0c6afbaf50397883d47d8f97 * opensm_release_notes-3.3: update Mon Apr 23 21:26:10 2012 +0300 Hal Rosenstock c3633e819c39f861b5313ae825fd6a0ebb157836 * opensm/osm_sminfo_rcv.c: Handle SMP status Wed Apr 18 13:37:07 2012 +0300 Vladimir Koushnir 5b88b445d4483171407882cb69c7a9d7484fe6f9 * Fix logging messages about op_vls and mtu mismatch Sun Apr 29 17:00:33 2012 +0300 Alex Netes 6a916fee03b6bef375f3fff426774af7c6052301 * Fix ucast cache crash, when switch doesn't have valid phys ports Tue Feb 14 16:13:56 2012 +0200 Alex Netes b9b3102ea478f21cde3c730cc60b7797b54895a6 * opensm: fix crash in osm_ucast_mgr Sun Apr 29 12:09:43 2012 +0300 Alex Netes 84567b155e53b2880c7821d2321a2c6147813cc8 * opensm/osm_ucast_cache.c: fix crash in ucast cache when switch with lid 0 dropped Wed May 9 19:17:34 2012 +0300 Daniel Klein 715d327e182ba1bf67112ebe83ec2b82c0a0e313 * opensm: fix search common pkeys Fri May 11 08:58:23 2012 -0400 Hal Rosenstock ca3c12b5840e1dce9c6b8f92b0759b6016e25b88 * opensm/osm_switch.c: In osm_switch_set_hops, return, error when port_num is invalid Wed Mar 28 18:48:01 2012 +0200 Alex Netes 1552edb449bfdc09c43c147f7b0c19c49696d656 * Fix memory leak on dfsssp_context_destroy() Wed Mar 28 14:05:06 2012 +0200 Alex Netes e772c5b7f6fd1917f820f4b5c41576909b60a86e * Changed sl_path API to include slid and dlid only Thu Mar 29 15:10:57 2012 +0200 Alex Netes 433859f2280e307421d72f89a9e94f571e0e1bd0 * Removed unused variables Thu Jan 26 04:48:01 2012 +0100 Jens Domke caade28efe469a67a2be046a7d65aa5b2f413577 * Optimized and deadlock-free routing algorithm for InfiniBand Wed May 9 07:41:18 2012 -0400 Hal Rosenstock 390493e75d1b4cb4874fb46cc43c1affb9405975 * opensm/osm_link_mgr.c: Fix sending PortInfo Set for ports supporting extended speed Sun Apr 29 21:30:50 2012 +0300 Alex Netes e24ff397a9e48331f3bca334dbfa5ac576ef77ea * Fix Pkey enforcement configuration Tue Feb 14 10:09:39 2012 +0200 Alex Netes 041e47aa8221aabed81c09d2e0ce9f6c78e9fb0c * Fix PathRecord reply to be the same for allow_both_pkeys ON and OFF Tue Nov 15 10:42:41 2011 +0200 Alex Netes a6ac5e37a4b3072082e3616312feb9cd81ccb71f * opensm/osm_drop_mgr.c: GID out trap fix Tue Apr 10 11:58:56 2012 +0300 Alex Netes 3c9b81d4a345a8d25c1d4b1e451460a191ae544f * OpenSM/osm_prtn_config.c: Fix non-initialized pointer usage Tue Apr 17 07:49:45 2012 -0400 Hal Rosenstock de5e3781107c8e10b2891db6cbadb233dfc90655 * opensm/complib/cl_[ptr_]vector.h: Commentary change for consistency Tue Apr 17 07:49:41 2012 -0400 Hal Rosenstock 45f93ec8c9cc1880f31664d0e354ac56946a8d9b * opensm: Add additional IBM vendor ID/OUI Sun Apr 15 11:56:29 2012 -0400 Hal Rosenstock c386eb211d8f4b742bf7d398ea1f6978b13e0c9b * opensm/osm_state_mgr.c: Cosmetic change to log message Sun Jul 24 17:42:55 2011 +0300 Alex Netes 703e5961055612833cee8ad92d2624cf9250f92f * opensm: Add support for partition enforcement types to accomodate IBA extended link speeds Wed Feb 22 16:52:50 2012 +0200 Alex Netes a2a03a8921fb40399061453cd88787fc573084c6 * Check block_num validity in set_guidinfo() and del_guidinfo() requests Mon Feb 27 15:33:14 2012 +0200 Alex Netes 8d764b8a9f115126c4771de805fbfea004c22064 * Fix continous looping when clearing accum_pkeys table Mon Feb 27 15:59:44 2012 +0200 Daniel Klein e6ec61fdf9b2f76ec9dbb4d85050c5d9ed2a4815 * end error resoponse to invalid LID in GUIDInfo request Wed Nov 30 10:09:04 2011 +0200 Daniel Klein 77175057c673e2fca6cf8064faf8f5465f8e9479 * opensm/osm_pkey_mgr.c: fix segfault when trying to access not allocated block Thu Dec 29 21:45:10 2011 -0500 Hal Rosenstock 7fce50001e04f016dc6ec694fd9483a99404d098 * opensm/Makefile.am: Add doc/opensm-sriov.txt to docs Thu Dec 29 21:45:03 2011 -0500 Hal Rosenstock 264aeb10bd4122934c1961017684094770da91f9 * opensm: Add documentation for SRIOV support Tue Nov 22 15:23:59 2011 -0500 Hal Rosenstock c6398325759c7df0c6a730056a4396e9b2758c4f * opensm: Enhance osm_physp_share_this_pkey for allow_both_pkeys policy Tue Nov 22 15:23:52 2011 -0500 Hal Rosenstock b17b63c5bdb80140cb64cd382b0e7d7161113b40 * opensm: When allowing both pkeys, on a switch external, (peer) port eliminate limited pkey when full pkey with same base is present Tue Nov 22 15:23:45 2011 -0500 Hal Rosenstock a758da24b2cc669b9bae014cb6888dcca9783bf6 * opensm: Add command line option for allow_both_pkeys Tue Nov 22 15:23:40 2011 -0500 Hal Rosenstock f412de3ba9748386a80799594f297a06b8fa4cd4 * opensm: Update partition documentation and man page for (allowing) both (limited and full) memberships in the same partition Tue Nov 22 15:23:32 2011 -0500 Hal Rosenstock 726ce6ab6ca9acb21cf2b1fb4348956afebf0253 * Support allowing both full and limited members of same partition Tue May 24 13:25:35 2011 -0400 Hal Rosenstock 4ccf32f71e4b8434f09e37f9ca21419d81f45a5d * opensm/PKeyMgr: Support pkey index reuse when there are no longer any previously unused indices available Tue May 24 13:25:29 2011 -0400 Hal Rosenstock ef9cf49fd46fd4dde6edf78181bd928fa589171c * opensm/osm_pkey.h: Commentary change Tue May 24 13:25:21 2011 -0400 Hal Rosenstock eb375a6b2227a58fee436d82fdf5cc108818b1a4 * opensm/osm_pkey_mgr.c: Detect pkey table overflow in pkey_mgr_update_port Tue May 24 13:24:57 2011 -0400 Hal Rosenstock 411e7426e7f3995e69bd0b2000bf1ed424f67eae * opensm/PkeyMgr: Don't change end port pkey index when simultaneously adding and removing partitions Tue Nov 22 15:24:09 2011 -0500 Hal Rosenstock 15e7223fb92b42b3cdad9e70d33a97093e7444b1 * opensm/osm_sa_guidinfo_record.c: In set_guidinfo, better SM reassigned guid handing Sat May 21 10:56:26 2011 -0400 Hal Rosenstock 8d49c5d49a6392f0297496db1260492568125a6f * opensm/osm_sa_guidinfo_record.c: Fix locking Sat May 21 17:17:34 2011 +0300 Hal Rosenstock e79b7252d1b8eccf222023ddc7c54145876a5955 * opensm: Handle SubnSet GUIDInfo asynchronously from GUIDInfoRecord handling Fri Apr 29 13:45:27 2011 +0300 Hal Rosenstock 96c741dc04392f2f643e8cbc2397252a810f713c * opensm: Some cosmetic formatting changes Fri Apr 29 13:44:49 2011 +0300 Hal Rosenstock 1d5e37035ab0e39f8e59f02ec2e123bb629fcc13 * opensm/osm_sa_guidinfo_record.c: Better status for SA response Fri Apr 29 03:19:55 2011 +0300 Hal Rosenstock efd3ba2e571c34a58b80e3db7df75b945fcaf2dc * opensm/osm_sa.c: Change log level of message Fri Apr 29 00:03:29 2011 +0300 Hal Rosenstock db8b7da5033bf10600a3239a2731b6f1abadeb92 * opensm/osm_sa_service_record.c: Alias GUID support Fri Apr 29 00:00:56 2011 +0300 Hal Rosenstock 53309869319a740597facff60977217512072b63 * opensm/osm_sa_multipath_record.c: Add support for alias GUIDs Thu Apr 28 23:55:35 2011 +0300 Hal Rosenstock 44168c98cf0627e411b6e37f9237d6fd09224954 * opensm/osm_sa_guidinfo_record.c: In del_guidinfo, validate guid not in use Thu Apr 28 23:52:51 2011 +0300 Hal Rosenstock 63eb65b54cd8d7539c3bf3725faa550eda5ed9fc * opensm: Add multicast support for alias GUIDs Thu Apr 28 23:36:38 2011 +0300 Hal Rosenstock 700d15f0bdb239bab7d0311a4b59fa007bc090a5 * opensm/osm_sa_path_record.c: Add support for alias GUIDs Thu Apr 28 23:29:55 2011 +0300 Hal Rosenstock f81838737ac1152352e1e7424c1a7caea0b72da8 * opensm/osm_sa_guidinfo_record.c: Use OSM_VENDOR_ID_OPENIB define rather than IB_OPENIB_OUI Fri May 20 15:50:14 2011 -0400 Hal Rosenstock 97e360e78cca8db569cb84b7d819a056bad5896a * opensm: Dump/load SA GUIDInfoRecords Fri May 20 15:49:55 2011 -0400 Hal Rosenstock fe74f1d678c4c096b81393749b1f51ad300ea0a9 * opensm: Make SA assigned guids persistent across port down/up events Thu Apr 28 22:43:07 2011 +0300 Hal Rosenstock eb8f1d94f443ec6fcacaec318a66fc83ab3e0b7a * opensm: Add support for alias GUIDs Wed Feb 29 12:54:16 2012 -0600 Mike Heinz b3b18617c6d31a25d6c6f7eb3a5ce2d786cab9f7 * opensm: osm_subnet.c: Updated patch to add error-reporting to the parsing of opensm.conf Fri Mar 2 08:10:27 2012 -0500 Hal Rosenstock cd8a708ae0d0762511be5946256234d64d580876 * opensm/man/opensm.8.in: Add description for OSM_LOG_SYS logging flag Thu Mar 8 08:04:14 2012 -0500 Hal Rosenstock 1308e5ca42091643baf53660b32173af5901e186 * opensm/osm_console.c: Add display of FDR10 ports to portstatus_parse Mon Mar 5 17:39:18 2012 -0800 Albert Chu eb90efd0bd953b4cb891e58bad179607dd0eb18f * include/opensm/osm_subnet.h: fix comment typos Thu Mar 8 15:45:27 2012 -0800 Albert Chu 0a315e3665bedbcf1af641ffe15d886d043236b2 * opensm/include/iba/ib_types.h: fix comment typos and errors Thu Feb 23 07:41:44 2012 -0500 Hal Rosenstock 125baa0616a6588cd300fe5e033326da1bdccb9c * opensm/opensm.8.in: Fix cut 'n paste error Thu Feb 23 07:41:36 2012 -0500 Hal Rosenstock f0d14d2aa2e4f07c582c02b3ae013dc478cd7080 * opensm/osm_ucast_ftree.c: Fix some typos Thu Feb 16 10:46:55 2012 -0800 Albert Chu f4722b0f833ed7a060f80b6757cfb9af78252678 * opensm: Reset client reregistration when receiving handover Mon Feb 13 16:13:47 2012 -0800 Albert Chu 841096f370ae87d2829e852521911be317cb1a63 * opensm: Fix opensm handover/relinquish corner case Mon Feb 6 11:29:59 2012 -0500 Hal Rosenstock bf420ac9199ac6b9fea7e7d358e43d3d0dc03cf6 * opensm/osm_helper.c: Fix commentary typo Wed Jan 18 20:16:22 2012 +0200 Alex Netes 2be999c3152a7822550ceb58609eec1ac0202554 * opensm: fixed description in osm_routing_engine Tue Jan 17 16:48:54 2012 +0200 Alex Netes cf3d1859b334b34c5da7aa1415d656b61a330f05 * gen_chlog.sh: fixed version ordering ** Version: opensm-3.3.13 Tue Jan 17 15:15:55 2012 +0200 Alex Netes 437939d091b03df365b747eba966f8457f8adad4 * opensm: packages versions update Tue Jan 17 14:07:31 2012 +0200 Alex Netes e62d4c5bdf827aeb87f9ec8ed80f3a685c46b259 * opensm_release_notes-3.3: update Tue Jan 17 13:56:56 2012 +0200 Alex Netes 52d28db27190f84bc14205d3c6138ddd5de1e4dd * opensm: update shared library versions Thu Jan 12 16:14:35 2012 +0200 Alex Netes 110ae103cbc6087f70bdcdd8be50e419ee4a6fab * opensm: fixed segfault in osm_destroy Tue Dec 27 19:11:26 2011 -0500 Hal Rosenstock d66620555b751ebfa808c13e335c8fde81406752 * opensm/osm_prtn.c: Fix typo in log message Thu Apr 28 16:21:47 2011 -0700 Hefty, Sean f3ccb45f2cd6359cd1e8de2b02cbe42230911a96 * opensm: Remove duplicate definition of IB_MAD_STATUS_CLASS_MASK Mon Nov 14 14:50:43 2011 -0800 Albert Chu 917070c6da6473854549bb37a36d443d9a99cd2d * Move no_fallback_routing_engine from osm_subn_opt_t to osm_opensm_t. Mon Nov 14 14:49:49 2011 -0800 Albert Chu d71a924736707400bed47a3c69395cf864c970bb * Free memory from osm_subn_opt_t when osm_subn_t destroyed Mon Nov 14 14:53:42 2011 -0800 Albert Chu 1b75fa4885603a8c00ad9f0090d7187d78f36a7f * Remove duplicate initialization of scatter_ports Thu Nov 10 10:01:40 2011 -0800 Albert Chu b5f4570414666314bf81c3b4bba1c86fa0dd05be * Do not load configs from the default config file and specified config file Fri Nov 11 10:04:52 2011 -0800 Albert Chu f24a089783fa177b6df41639a0a2830e437f0ada * Fix memleak and segfault Tue Dec 27 14:28:42 2011 -0500 Hal Rosenstock 9b50961e4e58ad742c296bddbf9cbd4663b4af95 * opensm: Change osm_routing_engine struct to not use C++ reserved word Mon Jan 9 14:00:52 2012 +0200 Alex Netes 247d0d8820d0536150869cfc00799b15a9a3d01f * Fix IPoIB broadcast group creation on non-default Pkey Fri Jan 6 13:53:29 2012 +0200 Alex Netes 0456b3f12fbbf7cf6bef5862c50d24e6b9ff41f5 * Fixed multicast groups reconfiguration during heawy sweep Mon Nov 7 13:45:39 2011 -0500 Hal Rosenstock c9c0aa61b3ab427a44763816eb11776e0c65d86f * opensm/man/torus-2QoS.conf.5.in: Update portgroup_max_ports section Tue Nov 22 14:03:00 2011 -0500 Hal Rosenstock 78d86bdba3cf55dd6792caeeeafbdd51bf330a79 * opensm/osm_subnet.c: Trivial optimization to code flow in subn_verify_sl2vl Mon Nov 21 07:02:05 2011 -0500 Hal Rosenstock 6bb41e3ad339426f35a3cc80c4f460c72b19602b * opensm/complib/cl_atomic.h: Commentary changes Fri Dec 9 08:06:38 2011 -0500 Hal Rosenstock 28ee7b9bef9a7441865f1f07134758a586651fae * opensm/osm_sa_class_port_info.c: Conditionalize setting of OSM_CAP2_IS_MCAST_TOP_SUPPORTED Fri Dec 23 13:47:53 2011 +0200 Alex Netes 29e59a2e80de631fd8a0c80c6228b3a3ab5b616a * Removed unused parameter "ib_mad_addr" from umad_reciever() Tue Dec 20 15:08:50 2011 -0500 Hal Rosenstock 63ad0bb2974f3fabac5c38470d56ca58b32d7edc * opensm/osmeventplugin/src/osmeventplugin.c: Output LIDs in decimal Tue Dec 20 15:08:40 2011 -0500 Hal Rosenstock 17967c2c981e5dba906ae9914e485f373ea89d37 * opensm/osm_switch.h: Fix commentary typo Tue Dec 20 15:08:27 2011 -0500 Hal Rosenstock 6d3e2230be5c31d83d28e78a2183d8cded73cfaa * opensm/osm_perfmgr.c: Enhance send error log message Tue Dec 20 15:08:21 2011 -0500 Hal Rosenstock 08abcd4275aef4a09250c1e3060ad46e108c8687 * opensm/osm_sa_mad_ctrl.c: Enhance send error log message Tue Dec 20 15:08:14 2011 -0500 Hal Rosenstock 13f3e0f0e239eb950fb1ca4da6f0732e0361c6d7 * opensm/libvendor/osm_vendor_ibumad.c: Fix DR path printing on send timeouts Fri Nov 4 12:26:00 2011 -0700 Ira Weiny 3c97f061af82b0bb0088ca624a98166160eb991a * opensm: Add the precreation of multicast groups Tue Nov 8 17:01:24 2011 +0200 Alex Netes 0dfd760a879176fb424c029f38f36bb7fbf1cb05 * Fix suggest parentheses around operand warning Mon Nov 7 13:26:36 2011 -0800 Albert Chu ad2dbf87b62d7c2c49b782a5c23d23fccbaf3fda * Support source-target-port-guid QoS policy configuration with ULP 'any' Mon Nov 7 13:26:33 2011 -0800 Albert Chu 080e3ad3335c284d8942f8154e6334fcaf529b1a * Support source-port-guid QoS policy configuration with ULP 'any' Mon Nov 7 13:26:25 2011 -0800 Albert Chu 49777a9f92ce7d3c0a0b86c60606d02464f8bc86 * Fix typo in qos-ulps parsing comment Mon Nov 7 10:20:46 2011 -0500 Hal Rosenstock bcfe1b99d09bceb74a5f0b2bdb920f4171a97557 * opensm/osm_torus.c: Use "OpenSM standard" error codes Mon Nov 7 18:12:35 2011 +0200 Alex Netes 683397d831cbd9c8ac3c2aaed206b001916f5177 * Fix use of GNU old-style field designator extension Mon Nov 7 18:07:30 2011 +0200 Alex Netes 719fcd451c836ee5c52922396219d3aeb96b64d5 * Fix use of logical && with constant operand; switch to bitwise & ** Version: opensm-3.3.12 Thu Nov 3 08:37:59 2011 +0200 Alex Netes dbcf81ffb651b9e15798259526ea2383efd7cff1 * opensm: packages versions update Thu Nov 3 08:37:06 2011 +0200 Alex Netes fca31d7073aecf82f5ecd4055b123f2b97d50117 * opensm_release_notes-3.3: update Tue Nov 1 08:37:55 2011 -0400 Hal Rosenstock 7c1ee6449eb53422e9e1acbb731e313de4b0e5c5 * opensm: Fix typo in routing section in man page and doc Wed Nov 2 14:35:19 2011 +0200 Daniel Klein d206011ea20a8be19a73721fdc971b1b8ce251eb * opensm/osmtest/osmtest.c: inventory file parsing bugfix Fri Sep 30 11:41:59 2011 -0400 Hal Rosenstock 32945398527ee61f0fd51ae8b16f2c3833282b9b * opensm: Only log SM PORT "state" when it changes Sun Sep 11 11:01:46 2011 +0300 Alex Netes e01121a93d5788627b52d36084bbfbc1c95ee7ee * fixed deprecated conversion from string constant to char* warning Mon Oct 17 13:34:09 2011 -0400 Hal Rosenstock a7ba101c3f8bd1694a549d4ca0c6e0fa52253674 * opensm/main.c: Change size parameter in setvbuf call from 0 to BUFSIZ Mon Oct 17 13:46:04 2011 -0400 Hal Rosenstock 15525794298439350d646158b707614c600a5260 * opensm/osm_sa_mcmember_record.c: Commentary changes relating to SA assigned MGIDs Tue Oct 18 09:17:38 2011 -0400 Hal Rosenstock b3bb0ab4a45b74cde70be0597a39d066df23357c * opensm/osm_dump.c: Dump SL2VL tables if routing engine might have modified them Tue Oct 18 09:17:33 2011 -0400 Hal Rosenstock 8a087199dfbda641303f9791db27acd61074c2aa * opensm/osm_dump.c: dump SL2VL tables in debug verbosity level when QoS is on Thu Oct 27 12:55:51 2011 -0400 Hal Rosenstock 7b3f43529de9b80ff701005a35751504eba3cb79 * opensm/osm_link_mgr.c: Remove no longer needed memset Thu Sep 29 08:49:32 2011 -0400 Hal Rosenstock 2a9255499f0b908537bf015855a77f5b582e9099 * opensm/osmtest/osmt_multicast.c: Fix multicast flow failures on pkey validation Wed Sep 28 08:50:49 2011 -0400 Hal Rosenstock 364e65b054fc8a7dfb135cb5adbf60241050d188 * opensm/osm_dump.c: Fix FDR10 speed dumping Tue Oct 4 09:53:28 2011 -0400 Hal Rosenstock fc908c91ecff3caeaf15ddad7580ca932ed9e82a * opensm/osm_sa_multipath_record.c: Add mtu validation if supplied Tue Oct 4 09:53:23 2011 -0400 Hal Rosenstock 687e1f81eff036e7b69592793ff90d27e7f544d4 * opensm/osm_sa_mcmember_record.c: Add mtu validation if supplied Tue Oct 4 09:53:18 2011 -0400 Hal Rosenstock 76f5b0991101c06c57cd3c335b2593c2251d7b58 * opensm/osm_sa_path_record.c: Add mtu validation if supplied Tue Oct 4 09:53:10 2011 -0400 Hal Rosenstock 9f38fae39262991ddd68a98fd72a45979fd3422b * opensm/osm_helper: Add ib_mtu_is_valid Sat Oct 1 09:16:15 2011 -0400 Hal Rosenstock 80e11b93e25542e1865844f77cf044d2a3b491f8 * osmtest/osmt_multicast.c: Fix check of partial JoinState delete request - removing NonMember (o15.0.1.14) Sat Oct 1 09:16:11 2011 -0400 Hal Rosenstock 78e1e4e56697b6cb66b69e31b7699dd286f197e5 * osmtest/osmt_multicast.c: Fix check of BAD RATE when connecting to existing MGID (o15.0.1.13) Sat Oct 1 09:16:05 2011 -0400 Hal Rosenstock e94e972b493443d8a8979c38881045e4c17cba6c * osmtest/osmt_multicast.c: Fix first MGID=0 MC group creation case Sat Oct 1 09:16:01 2011 -0400 Hal Rosenstock 655230bcf7715ee13c90b8e8431d964881f8194f * opensm/osm_sa_multipath_record.c: Add rate validation if supplied Sat Oct 1 09:15:51 2011 -0400 Hal Rosenstock cb1484df09ae6d742b323f7d27cfc457f24e0be5 * opensm/osm_sa_mcmember_record.c: Add rate validation if supplied Sat Oct 1 09:15:40 2011 -0400 Hal Rosenstock 485d0686abdff272b308bb457f4c0d151da67c9f * opensm/osm_sa_path_record.c: Add rate validation if supplied Sat Oct 1 09:15:32 2011 -0400 Hal Rosenstock 300f4d9a158e98b99628411f59b457032aa990f3 * opensm/osm_helper: Add ib_rate_is_valid Thu Sep 22 14:22:46 2011 -0400 Hal Rosenstock daedad72461991e824ad2d2bb6ba4539fbecc19e * opensm/osmtest/osmt_multicast.c: Fix an unrealistic rate case ** Version: opensm-3.3.11 Fri Sep 2 09:45:57 2011 +0300 Alex Netes 15ad41de7cc9ccda61c5e3aec91e198bd09f04ca * opensm: packages versions update Fri Sep 2 09:44:50 2011 +0300 Alex Netes 8a8afa0bd9e9d8f26f078f9c54cce18f982b7d57 * opensm_release_notes-3.3: update Thu Sep 1 16:24:27 2011 -0700 Albert Chu 5654e22c71a4655c46339162fa19bc79a5403bb9 * Fix invalid error check, which lead to segfault ** Version: opensm-3.3.10 Thu Sep 1 23:00:42 2011 +0300 Alex Netes 73e24137c44c7c5f383a7714c6ec43f26368b22a * opensm: packages versions update Thu Sep 1 22:58:21 2011 +0300 Alex Netes caf88987da287d081bb62ee4225d3d764c26f526 * opensm: update shared library versions Thu Sep 1 22:44:43 2011 +0300 Alex Netes 4771a28fcdde59dad89c85fa81745c3ce52b9a69 * opensm_release_notes-3.3: update Thu Aug 18 05:40:50 2011 -0400 Hal Rosenstock e3a946d95eafb8061d932959ba8bd02ed200c120 * opensm: Add FDR10 support Wed Aug 31 13:35:14 2011 +0300 Alex Netes ec9adcc75aa3b6975ca36f5faf8496468b2e9c26 * add DnUp to list of supported engine names Fri Aug 19 14:06:38 2011 -0700 Ira Weiny 9559dda77fd99f140e51b1b1f3412cd5862dd7c1 * opensm: add torus-2QoS to list of supported engine names Wed Aug 17 14:40:13 2011 -0400 Hal Rosenstock 6cea3df28335200a0c60140090a767daf39b9a04 * opensm/osm_sa_portinfo_record.c: Add SA PortInfoRecord support for CapabilityMask2 matching Wed Aug 17 14:40:07 2011 -0400 Hal Rosenstock 9ac7eebe2efbc1d52836fb0ff965e43737fe8c47 * opensm: Add infrastructure support for CapabilityMask2 field in PortInfo Wed Aug 17 14:39:48 2011 -0400 Hal Rosenstock e17dae69013d1999430c39efe52b9a96876e2b70 * opensm/osm_sa_portinfo_record.c: In pir_rcv_new_pir, fix switch port 0 physp Tue Aug 9 10:30:45 2011 -0400 Hal Rosenstock a33a8af18c502cfb1162f4b36735a474dbc276c2 * opensm: Add extended link speeds support Wed Aug 3 15:42:30 2011 -0700 Ira Weiny 8bc7c30187c35bd149c53c0d50d13925045febb9 * opensm: make loopback console compile on by default. Tue Jul 26 12:24:47 2011 -0400 Hal Rosenstock e26fe06a942dc92de9471b110d2d8475ae3b2c2f * opensm/osm_sa_multipath_record.c: Proper rate comparison and selection Tue Jul 26 11:23:51 2011 -0400 Hal Rosenstock 2f32ea8526e7c14216341011be1501dcf94bdab7 * opensm/osm_sa_mcmember_record.c: Proper rate comparison and selection Tue Jul 26 11:23:46 2011 -0400 Hal Rosenstock 45111c29b93b14effbb024e5c72b0c163dfcfbb5 * opensm/osm_sa_path_record.c: Proper rate comparison and selection Fri Jul 29 08:36:47 2011 -0400 Hal Rosenstock cc7ff0751ff23ca6e7c9dc5f261c1fb865ca2c15 * opensm/osm_helper: Add rate related routines Mon Jul 11 20:46:52 2011 +0300 Alex Netes 37086c07880a5ec8e1415525204e0170ed34ad4a * Remove unused variables from code Mon Jul 11 20:46:26 2011 +0300 Alex Netes 93b2f567dabd5b73581c78c1b63d1561d69f11ed * libvendor/osm_vendor_ibumad.c: fix unused-but-set warning Mon Jul 11 20:45:54 2011 +0300 Alex Netes cda58af67dec78c03e7d3ad86aaefe8958b51595 * fixed unsused-but-set warning for DEBUG variables Thu Jul 28 09:59:10 2011 -0400 Hal Rosenstock f427600259f3c7b3ba6518b4ecadd5201e1b0fda * opensm/osm_sa_class_port_info.c: Minor simplification to setting CapabilityMask2 Thu Jul 28 09:58:58 2011 -0400 Hal Rosenstock 566b4625a421aa258b98113775b50af4e0b3f08c * opensm/ib_types.h: Update SA PortInfoRecord component masks Tue Jul 26 08:31:13 2011 -0400 Hal Rosenstock b8c7632fe0c8be2467bc3063610e528f8bc4daf6 * opensm/osm_[lid pkey]_mgr.c: Remove no longer needed memset Mon Jul 18 07:45:28 2011 -0400 Hal Rosenstock f999195c2b80a89d70c20295bd876db253ba771c * OpenSM: Add infrastructure for "full" SM PortInfo and SA PortInfoRecord attributes Wed Jul 20 08:44:15 2011 -0400 Hal Rosenstock f7d813d5ef53d657f8f3c9237bbd4ecb3ce36258 * opensm/doc/todo: Minor update Wed Jul 13 19:37:01 2011 -0400 Hal Rosenstock 480de4ae8e75b7cc6fd19f1235b8c7ed974843c0 * opensm: Use forward extensible and safer way to compare mkey_lmc field in PortInfo attribute Wed Jul 6 15:11:16 2011 -0700 Ira Weiny 22ca9662c6ec110a5f3390f2ac61476e5758f744 * opensm: enable perfmgr build by default Tue Jul 12 18:09:31 2011 -0700 Ira Weiny 4250c598e0cd5f07d73c05948a76aac479b947a9 * opensm: perfmgr only run sweep timer when enabled. Tue Jul 5 13:24:34 2011 -0400 Hal Rosenstock dfeb3f6a9bbdfdb7dd18587d8fadc2710ed6c0bd * opensm/osmtest/osmt_multicast.c: Use proper defines for rate Fri May 27 13:52:12 2011 -0400 Hal Rosenstock 0ef986ad03a4f5db38190a7a52f1c1d31d80aae2 * opensm/osm_db_files.c: In osm_db_delete, don't free p_key Thu Jun 16 09:31:59 2011 -0400 Hal Rosenstock 2d85bcd2b208d21cadd2317b95f7e4ba5ef0af56 * opensm/osm_sminfo_rcv.c: Eliminate unneeded return parameter from internal routine Wed Jun 22 09:50:14 2011 -0400 Hal Rosenstock e881d0ece885f4bb0748b6ecf9c6219e56bafbfa * opensm/osmtest/osmt_multicast.: Fix typo in log message Mon Jun 27 20:08:03 2011 +0300 Alex Netes 8ae061c752b070dc77476b43418f070ee99e8929 * opensm: don't set switch hops to lid 0 Tue Jul 5 18:51:08 2011 +0300 Alex Netes 5dffc78a51ba6e39b1b53e519a8b8436f80ec1f6 * renaming dimn_ports_file parameter to route_port_ordering_file Tue Jul 5 07:33:42 2011 -0400 Hal Rosenstock 203f3c62b444a4c301c6b378ddcf20241800cb08 * opensm/osm_switch.c: Fix compile warnings Tue Jul 5 07:33:20 2011 -0400 Hal Rosenstock f87fb59e1c4dae7454fbd4c624adc91057b8150a * opensm/current-routing.txt: Add DnUp description Tue Jul 5 07:33:01 2011 -0400 Hal Rosenstock 67c2538e1969056e71466ef3cd01c1c7c8ac0be8 * opensm/man/opensm.8.in: Fix some typos Wed Mar 23 16:04:12 2011 -0700 Ken Schmidt f532007d2c9f354ad98f6f7b8481e87962e8e40c * OpenSM - The DnUp routing algorithm. Wed Apr 6 17:40:22 2011 -0700 Albert L. Chu 43ef9fe082c4038b6e2605c53032a660f265a7ae * Cleanup scatter ports patch. Wed Apr 6 17:35:43 2011 -0700 Jared Carr 18106723eb28efef352d32320df47226f99f8cee * Support scatter ports. Wed Apr 6 15:27:20 2011 -0700 Albert L. Chu dd2110721e254c7bdec23ea4105cf31fee59e69d * Support port shifting. Sun Apr 17 22:32:08 2011 -0700 Weiny, Ira K 008af843a6faa434258e77d20a838ce9da30e71e * opensm: perfmgr, only set orig_lid when we have a valid port. Otherwise leave it as 0 Sat Jun 4 11:06:35 2011 -0400 Hal Rosenstock 7338efc631ef74838637eb1b9d740a58c0b456a8 * opensm/osmtest/osmtest.c: Fix endian in some log messages Fri Apr 22 17:21:48 2011 -0400 Hal Rosenstock 8a9021d1583f4573c5b73fb684506993c2aef9a6 * opensm: Provide option to disable use of MulticastFDBTop even if advertised Thu Jun 2 20:40:27 2011 -0400 Hal Rosenstock 26f2be49e628a8b0ca77602c615cf3242fc4708b * opensm/osm_ucast_ftree.c: Handle [sw hca]_create failures Thu Jun 2 20:40:21 2011 -0400 Hal Rosenstock b9837cceb27c54730b950fe373f9eaa868d97a14 * opensm/osm_switch.c: In switch_find_guid_common, handle NULL parameter Thu Jun 2 15:03:06 2011 -0400 Hal Rosenstock 67063ca66008bfdb9aa4692a30f692d0dc28ea9b * opensm/libvendor: Fix compile warnings on 64 bit machines when building --with-osmv=sim Wed Jun 1 16:33:01 2011 -0600 Jim Schutt efadfe9b926fb6165ca98cdcfbfcaebeb97f9d69 * opensm: use OSM_LOG_INFO on duplicate torus port order parsing Wed Jun 1 16:33:00 2011 -0600 Jim Schutt d3df5ef2b6467cdc01decbe70a0cd4c34039f865 * opensm: fail if configured torus port order references a port not available in all switches Wed Jun 1 18:40:46 2011 +0300 Alex Netes a8c209c7351d01f40f917a8ae2df19cc5c01fa26 * opensm: fixed port order configuration in torus routing engine Tue May 31 07:30:13 2011 -0400 Hal Rosenstock 7359cfcfa70372b97db01e368423c88cf2801aa7 * opensm/osm_ucast_mgr.c: Fix some issues found by Coverity Tue May 31 07:30:07 2011 -0400 Hal Rosenstock 0150ab9e099b4923ae0e06e0cf1d722b6dc0010b * opensm/osm_ucast_ftree.c: Fix some issues found by Coverity Fri May 20 10:35:46 2011 -0400 Hal Rosenstock 267a08f9a0072b05b55aae6987a08ab1758f5908 * opensm/osm_pkey_mgr.c: Fix cast Mon Apr 11 15:39:43 2011 -0400 Hal Rosenstock bfefac3f0a627c1bab99a3f43908104de3a6d5c6 * opensm/osm_pkey_mgr.c: Handle osm_pkey_tbl_new_block_get returning NULL Fri May 20 14:09:04 2011 -0400 Hal Rosenstock a9fc120718cf44d160d9b2ea5698f3d7fe701169 * opensm/osm_pkey_mgr.c: Pack switch peer port PKey tables Sun May 15 09:47:31 2011 +0300 Eli Dorfman 2c5148408d562d86e1dd5d90939a58533ddebbe6 * opensm/osm_pkey_mgr: clean partition enforcement on inter-switch links Mon May 2 18:41:31 2011 +0300 David McMillen 1c2a298b295eba7e24205519abc24e47106d15df * OpenSM torus routing order list Thu Apr 28 10:31:01 2011 -0700 Hefty, Sean b92d21f040805b91ee6691e0b0e3f1dec37d4a67 * opensm: Create all directories in database path on Windows Wed Apr 20 10:32:05 2011 -0400 Hal Rosenstock bbfa9e03f3eb17f22a0e8b797af5b8e5d415b83f * opensm: Prepare for alias GUID support Mon Apr 11 11:00:17 2011 -0400 Hal Rosenstock e1ffb57b5a309b15b0ed52ae6ec8b91647c90bd9 * opensm/osm_port: Add infrastructure for alias GUID support Mon Apr 18 09:29:57 2011 -0400 Hal Rosenstock 0c496d0accfe7ac1d584d98da729e1fdc2ae7b23 * opensm/osm_perfmgr.c: Don't rely on PortInfo:PortState for base SP0 Mon Apr 18 09:29:48 2011 -0400 Hal Rosenstock 7f4a76535b6abc4acba910defe4d9ac13ddc6ac4 * opensm/osm_state_mgr.c: Don't rely on PortInfo:PortState for base SP0 Tue Apr 26 17:35:38 2011 -0700 Ira Weiny cdad6e34375306986a64a5a886e796c8e24d3380 * opensm: ib_types.h add defines for PM CPI SamplesOnlySupported and PortCountersXmitWaitSupported Tue Apr 19 10:26:41 2011 -0400 Hal Rosenstock 83b67527d161e695d67c68826f1d4b26fdd683dd * opensm/osm_subnet.c: In osm_subn_destroy, delete service records Tue Apr 19 15:05:12 2011 -0400 Hal Rosenstock 12f772d10c4ff42a4fc0cd1a6254f364064948e4 * opensm: Fix some OSM_SIGNAL and OSM_SM_SIGNAL numbering Tue Apr 19 10:27:52 2011 -0400 Hal Rosenstock c29c4f1a33f676fc553b2e301310023a95fdfbe9 * opensm/osm_sa_service_record.c: Fix minor memory leak Tue Apr 19 10:27:39 2011 -0400 Hal Rosenstock adc616159845617439b4c45eec64d0ea55c0cf35 * opensm/osm_sa_service_record.c: Remove useless if Fri Apr 15 15:19:22 2011 -0700 Ira Weiny f936f8b74a463737a3ddc32ec13107cc27e678f0 * opensm: fix strtoull error handling Tue Mar 22 17:36:16 2011 -0700 Albert L. Chu 7bf74822cd2a0188c9a7135a7a2dfc7ea3fc9494 * fix segfault corner case w/ updn routing and LMC > 0 Wed Apr 13 10:52:00 2011 +0300 Alex Netes 0292ae223b9c4e45eb702a0d9fbc70bef8b37539 * opensm: fixed segfault when enable qos on fabric with no switches Thu Apr 7 15:02:53 2011 -0400 Hal Rosenstock 619fa64c0fb683be3b25a697e009d116ff1da892 * osmtest/osmt_multicast.c: Fixed another insufficient component case Mon Apr 4 14:45:52 2011 -0400 Hal Rosenstock 1618803da072cad3bb9c9f809f399ec6e88f2f5e * opensm/osm_sa.c: Fix commentary typo Tue Apr 5 14:05:05 2011 -0400 Hal Rosenstock aebd9f9d9cdd1c60c2b3784c0c03cfe8f4014019 * opensm/osm_pkey_mgr.c: In pkey_mgr_update_peer_port, better last block handling Tue Apr 5 14:05:17 2011 -0400 Hal Rosenstock ffdcdec8a6557088b23e273c5d605465501d2d24 * osmtest/osmt_multicast.c: In osmt_run_mcast_flow, handle invalid status better Tue Apr 5 14:04:59 2011 -0400 Hal Rosenstock 4656d0e106d892dade0760b8a942bd921f7619c7 * opensm/osm_pkey_mgr.c: In pkey_mgr_update_peer_port, initialize p_peer_pkey_tbl later in flow Thu Apr 7 10:49:52 2011 -0400 Hal Rosenstock f91441c1b32e7896741c31efe4ae097a70fe859c * opensm/libvendor/osm_vendor_mlx_sa.c: Sync with osm_vendor_ibumad_sa.c Tue Apr 5 14:24:24 2011 -0400 Hal Rosenstock 2f011c8f92dca815a1d8b51ee43960750420c973 * opensm/osm_helper: Add osm_dump_guid_info Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock a4144c5314911b5aa5e36c1b07291a4a3bb1b919 * osmtest/osmt_multicast.c: In some multicast flows, insufficient comps is warning Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock de5264380e41016d7bcfddbf08d9f2e5593d9711 * opensm/osm_pkey_mgr.c: Change log message to reflect used rather than max blocks Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock c98fec917342cb960b8458885edc85505da079ce * opensm/osm_subnet.c: Fix description of max_msg_fifo_timeout Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock 0a3839fc04d5d78f8a7ba162766eebb13f806419 * osmtest/osmtest.c: Fix trap flow not implemented log message Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock 0fc8124c6cffbd70b1feae6893791ac91430a876 * opensm: Add OSM_VENDOR_ID_OPENIB support Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock c0d8b56a4531b76efa915e40cd0b1669f158cbc3 * opensm/osm_sa_node_record.c: In nr_rcv_create_nr, only set some variables when needed Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock 9acaba0d8350c479e9f12aeabd92df6c221938da * opensm/osm_helper.c: Add some missing fields to osm_dump_portinfo_record Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock 67949b9ca6d6c49bc49bb9f4c850a3dedacdeb7d * opensm: Cosmetic changes Tue Apr 5 18:56:01 2011 +0300 Hal Rosenstock 3c4932159524c53c174857e35118fdaf7d2c2906 * opensm/osm_sa_service_record.c: Cosmetic changes Mon Apr 4 14:45:44 2011 -0400 Hal Rosenstock f08479a87fe96482791114ef4ab613b86dcdde24 * opensm/osm_base.h: Fix a commentary typo Mon Apr 4 13:37:54 2011 +0300 Hal Rosenstock ae966f64fe9fa0e638480f9819ec65b0cbe2dfcc * osmtest/osmt_multicast.c: Fix some typos Mon Apr 4 13:35:42 2011 +0300 Hal Rosenstock 8a3b5b9bea58f6c08cd3cc40ec40e3e09bf07e42 * osmtest/osmt_multicast.c: Fixed some error codes in OSM_LOG messages Mon Apr 4 13:34:13 2011 +0300 Hal Rosenstock c90953d4ac308c6a80fafed250055737d54e7232 * osmtest/osmt_multicast.c: Fixed a couple of typos in OSM_LOG messages Mon Apr 4 13:32:36 2011 +0300 Hal Rosenstock 570715833b23f5343c06b43843ae5bf2f3dfe72a * opensm/osm_prtn.c: Cosmetic formatting change Mon Apr 4 13:31:42 2011 +0300 Hal Rosenstock e1b625e6c83c6c52eebe13bea77cd42c3e41a8b5 * opensm/osm_pkey.c: Cosmetic formatting change Mon Apr 4 13:30:52 2011 +0300 Hal Rosenstock f7f1ead1b4e9bba741a0d1312513839504cab1e3 * opensm/osm_sa_mcmember_record.c: Fix handling of invalid PKey Mon Apr 4 13:19:30 2011 +0300 Hal Rosenstock 0404e9edceb78c029ddb1e54881d1ef776b812ad * opensm/osm_sa_mcmember_record.c: Changed status in a couple of SA responses Mon Apr 4 13:15:22 2011 +0300 Hal Rosenstock 9d2bf0462397c47be672f96eeac5ebe512fbffef * opensm/osm_pkey.c: Minor change to comment Mon Apr 4 13:12:34 2011 +0300 Hal Rosenstock fb630f6bf6667b2452f08eee1281855128575e5d * opensm/include/opensm/osm_mcm_port.h: Cosmetic formatting changes Mon Apr 4 12:32:03 2011 +0300 Hal Rosenstock 62fb69dd222089f0b378d66081bede5286beb611 * opensm/osm_pkey_mgr.c: Move clearing of empty_block after any "early" returns Fri Apr 1 18:37:18 2011 +0000 Hal Rosenstock 65d3e4f2853dd1d0766e74e30eb2d833cd248d48 * opensm/osm_pkey_mgr.c: Fix commentary typo Tue Mar 29 10:46:49 2011 +0200 Eli Dorfman 8a43aeab9027e5f32c45d196c61bdd41e4b281db * Allow comma in plugin names parsing Wed Mar 9 16:28:23 2011 -0800 Ira Weiny 34d61cce6244046f0f616402351119169847957d * opensm/perfmgr: fix overflow processing Sun Mar 27 11:15:27 2011 +0200 Alex Netes c850d39c2a40ac3c03a199af6b0fe326b704b95b * opensm/osm_opensm.c: Conditionalize sa_db_file_dump on sa_db_dump option Sun Mar 27 14:04:15 2011 +0200 Alex Netes cdf227c224a42dadcbc8114767562b6546dc9028 * opensm: Proper mfttop initialization when starting/restarting Mon Mar 7 12:05:04 2011 +0000 Alex Netes 77d79b4069118ac844cc79e244a029f8f9c9cfdd * opensm: fixed potential null variable dereferencing in libvendor Mon Mar 7 10:03:59 2011 +0000 Alex Netes 350c6e49fe3ee492b397346633dee76d3cad9ade * opensm: fixed potential memory leak in osm_ucast_ftree() Mon Mar 7 09:57:39 2011 +0000 Alex Netes e2068722c9d115979964552fecb120bf94a74567 * opensm: Fixed debug message in osm_vendor_send() Mon Mar 7 11:24:23 2011 +0000 Alex Netes 1b3e93e3f5f27ea700027d34bca15d37cfc128db * opensm: fixed sizeof of pointer allocation in osm_ucast_lash() Mon Mar 7 15:25:32 2011 +0000 Yevgeny Kliteynik 2f56d1e2f6fc0737d5dd1e25017cc3197686c15d * pensm/osm_qos_parser: QOS parser doesn't work after syntax error Mon Mar 7 15:35:01 2011 +0000 Alex Netes 7f1970b1d030ac4e3544b053eff8851c0cc9b054 * opensm: removed unnecessary checks in main() Mon Mar 21 15:47:35 2011 +0200 Alex Netes f369aaf9cbd04e999f9c6c725fc5805b624f56f7 * Ignore command line option -timeout 0 Mon Mar 7 09:58:37 2011 +0200 Alex Netes 89c98f60eec9d8a5420c261a27a9390d629cec8b * opensm: packages versions update Mon Mar 7 09:57:38 2011 +0200 Alex Netes 9ca052eae7221dc5bb833e7162de7b4371805b63 * opensm_release_notes-3.3: update Mon Feb 14 16:15:32 2011 +0200 Alex Netes 358cea271541652d5d2e9913a7ce5509bb107afb * opensm: packages versions update Mon Feb 14 16:14:12 2011 +0200 Alex Netes f12289893ce7c14c7b793b3a9c6e52cd4f60da87 * opensm: update shared library versions Mon Feb 14 16:12:07 2011 +0200 Alex Netes 1bd83ed4bdfe39679dd85da3436223669669b325 * opensm_release_notes-3.3: update Thu Jan 6 18:39:05 2011 +0200 Eli Dorfman (Voltaire) 15989afbfbe55b2785acebf29a3db536d4910fec * configure multicast only once during sweep Tue Mar 1 17:29:41 2011 -0700 Jason Gunthorpe f0b915afb1b69868a15eb2010c7c0db150c008fd * Fix SANodeRecord.nodeInfo.localPortNum Thu Jun 17 18:16:29 2010 +0000 Hal Rosenstock c126ef166e2fddca71d5a28bfae3196cd4df5ecb * opensm/osm_console.c: Add dump and clear redir perfmgr command support Thu Jun 17 17:28:49 2010 +0000 Hal Rosenstock bff2d70d8d3e67738618fb1ee4f9aa2570613299 * opensm/PerfMgr: Better redirection support Wed Sep 1 21:47:02 2010 +0000 Hal Rosenstock fb4394e5fd88a29cc2d29d44d4e09c1c01f02d86 * osmtest/SA client: Only set attribute offset for RMPP operations Fri Mar 4 14:08:47 2011 +0200 Alex Netes 333265865d3929da33a37a75cd23ad42f06e25fe * opensm: fixed memory leak in multicast spanning tree calculation Mon Feb 28 18:27:08 2011 +0200 Alex Netes e4525b15f7b8c721a2e8bde57db2891c004a18b7 * opensm: fixed indentation and decreased verbosity of RMPP length message Fri Feb 11 15:12:06 2011 -0700 Jason Gunthorpe 827a386019ea64f6f47608573469788cafc19f0c * Decode the SAPKeyTableRecord block number properly, and don't segv Mon Feb 14 15:25:36 2011 -0800 Ira Weiny 10ac4c1bf127b13e38e17db49d28a4a4a94ac831 * Fix compile warning introduced by patch "fixed getline pointer allocation free in osm_console_io" Wed Feb 2 18:43:43 2011 +0200 Hal Rosenstock d69a82c2109a0d791a40d872c41ed721b84f6157 * opensm: Add support for SwitchInfo:MulticastFDBTop Thu Feb 10 12:53:50 2011 -0700 Hal Rosenstock 7b52bed05b721b84a2c5e33d3b6e89bde7b71e31 * opensm.spec.in: Add in man5 for torus-2QoS.conf Thu Feb 3 13:53:55 2011 +0200 Alex Netes bf23d7c172dc6e70fca8fb6f5ca4b1319c28e9e4 * opensm: fixed getline pointer allocation free in osm_console_io Thu Feb 3 18:21:48 2011 +0200 Alex Netes 54b1583138c3318bdb1a1715ca4a3dab476c0608 * Makefile: ChangeLog and version generation script path fix Tue Jan 25 17:09:04 2011 -0800 Ira Weiny 74867c78845b138364cecf58a024e4d7f54818ee * Add node/port/qos information to some error messages Thu Sep 9 14:12:21 2010 -0700 Stan C. Smith 9978b464537c9fe5f2cdab969b94fc6fa9e09e5f * replace (long*)(long) casting with transportable data type (uintptr_t) Mon Dec 6 15:55:11 2010 -0800 Stan C. Smith 31a617d46be4140fe4d70f1a23021feea6aa6fca * replace (long*)(long) casting with transportable data type (uintptr_t) Tue Sep 7 18:18:41 2010 +0300 Yevgeny Kliteynik 8da7521cc65d48b274cc0ca6624ece16b420522c * opensm/st.c: fix potential core dumps Tue Sep 7 22:30:09 2010 +0300 Yevgeny Kliteynik 6a309119556d39d841cb0beafd6a17ad00c5f5f2 * opensm/osm_console.c: fix memory and file descriptor leaks Tue Sep 7 18:17:54 2010 +0300 Yevgeny Kliteynik 696f12c3bbd2a64fb0dd32ca26bc1c44e1aea526 * opensm/osm_qos_parser_y.y: fixing bunch of memory leaks on invalid values Tue Sep 7 18:16:44 2010 +0300 Yevgeny Kliteynik 3a7b97c119e86541e33f94315f793f7ee0679e82 * opensm/osm_ucast_file.c: closing file descriptor in error path Tue Sep 7 18:15:58 2010 +0300 Yevgeny Kliteynik b4575c5fc9b42eab31980eaa34e51ce675511011 * opensm/osm_pkey_mgr.c: fixing small memory leak Tue Sep 7 18:15:09 2010 +0300 Yevgeny Kliteynik dc0695f08a8f24f9729830e1963a9b177475502b * opensm/osm_ucast_lash.c: small bug in calculating allocated size Tue Sep 7 18:11:55 2010 +0300 Yevgeny Kliteynik 3c9604b39ea05c1ae5d44bf309116955b989bf03 * opensm/osm_ucast_ftree.c: fixing another memory leak at error path Tue Sep 7 18:11:01 2010 +0300 Yevgeny Kliteynik 4460990f70601df548742719ee002aeb0d443434 * opensm/osm_ucast_ftree.c: fix small memory leak in error path Tue Sep 7 17:53:03 2010 +0300 Yevgeny Kliteynik 857cd6c7a38e0d87cfc3872608c2311c65d5a8d8 * opensm/osm_trap_rcv.c: fix possible core dump Thu Jun 17 11:38:45 2010 -0400 Hal Rosenstock b74bef560a657797e7ad685687715516bebe5bec * opensm/osm_trap_rcv.c: No need to check for sweep for trap 145 Mon Sep 27 09:32:14 2010 -0400 Hal Rosenstock 81dade3aeb1d5c80472a4f9fef55e9916bb38d3a * opensm/osm_ucast_ftree: When roots are not connected, update hop count but not lft Mon Sep 27 09:40:40 2010 -0400 Hal Rosenstock acf2337d4fe9fd159429e16884dacb4bb49c0892 * osmtest/osmt_service.c: In osmt_run_service_records_flow, add missing status Mon Sep 27 09:46:40 2010 -0400 Hal Rosenstock 0149b13f312843ba4225d8712b8b6b9891d505d8 * opensm: Fix some typos Fri Nov 12 15:11:22 2010 -0700 Jim Schutt 8c50364e6b69bea9f7e86c50a46ae0ce7bb182e5 * opensm/doc/current-routing.txt: Sync torus-2QoS information with new man pages. Fri Nov 12 15:11:21 2010 -0700 Jim Schutt 0b025100679c0824acdcabf1b97fd10846facffb * opensm: Add torus-2QoS man pages. Fri Nov 12 15:11:20 2010 -0700 Jim Schutt 2d1bae04b94ae278acfa55ac1c53e3c2ef7518d4 * opensm/man/opensm.8.in: Add references to torus-2QoS. Fri Nov 12 15:11:19 2010 -0700 Jim Schutt c18adbcecc485bb9299b94a2c8d4f30f9c2bd39b * opensm/main.c: Add description of "no_fallback" to "--routing_engine" option documentation. Fri Nov 12 15:11:18 2010 -0700 Jim Schutt cdd1efe6f3ac8e78a1fd1a0f4e8138ee42cb91f6 * opensm/osm_subnet.c: Add torus-2QoS config file option to those configurable via opensm config file. Fri Nov 12 15:11:17 2010 -0700 Jim Schutt f4b076701d304032b271e16da0e2d6c32f1639ad * opensm/osm_torus.c: Ignore multiple configurations of torus size. Fri Nov 12 15:11:16 2010 -0700 Jim Schutt eb8811bc666eddbde7c77156329de53ce6afca6c * opensm/osm_torus.c: Use PRIx64 for GUID printing. Fri Nov 12 15:11:15 2010 -0700 Jim Schutt 765a02d98c7f1314af897e77011e4c54d14b0503 * opensm/osm_torus.c: Also parse DOS line endings in torus-2QoS.conf. Fri Nov 12 15:11:14 2010 -0700 Jim Schutt 0270d56d99f05fab5f1ae3288ca02aae16cb0f6d * opensm: Cause torus-2QoS to warn if QoS configuration will cause issues. Fri Nov 12 15:11:13 2010 -0700 Jim Schutt cd9345e69595c96af95afb67a171dda10dc97342 * opensm: Fill in default QoS values at last possible moment. Fri Nov 12 15:11:12 2010 -0700 Jim Schutt 7a142a0183762f3da44a47af29fd73ea95f5e26d * opensm/osm_ucast_mgr.c: ensure osm_ucast_mgr_process() returns failure when no routing engine runs. Fri Nov 12 15:11:11 2010 -0700 Jim Schutt 2fe3eb8ca1f6920544b583139d42274ea091c77a * opensm: torus-2QoS requires that QoS be enabled. Fri Nov 12 15:11:10 2010 -0700 Jim Schutt 6bfca67baf3cfd39244ea29ca587ff60441e9c62 * Revert "opensm: Do not require -Q option for torus-2QoS routing engine." Fri Sep 17 11:03:14 2010 -0600 Jim Schutt d0b8c590d18929260d6c9783fb6c3f81ad8b0bd5 * opensm/osm_torus.c: Handle calloc() failure on routing engine context creation. Fri Sep 17 11:03:13 2010 -0600 Jim Schutt d2f55b87516fc32170c83f965f16c4e2541e2c24 * opensm/osm_torus.c: Add check for invalid topology discovery due to user misconfiguration. Thu Feb 4 19:43:18 2010 +0200 Eli Dorfman (Voltaire) 593547e891cb538c22ca4f38cadac862c3429c92 * Wrong handling of MC create and delete traps Mon Oct 4 09:16:44 2010 -0400 Hal Rosenstock 6db7f4ab45828b24d999ff02889e648418d3965d * opensm/osm_state_mgr.c: Don't signal DISCOVER to SM state machine when already DISCOVERING Thu Oct 7 16:33:01 2010 -0600 Jason Gunthorpe 28693c58e359d4d27388dc1fcac66102994974d4 * Fix autotools to include the necessary M4 files Mon Oct 11 13:04:22 2010 +0200 Yevgeny Kliteynik c1c87305f8a089286ba65ea0aa0df60b47c88295 * osm_vl15intf.c: fixing use-after-free coredump Sun Sep 12 11:56:55 2010 +0200 Yevgeny Kliteynik 3353f9b9db76bab15b13ba73f9d18cd53d8e432b * opensm/osm_helper.c: use ARR_SIZE macro instead of hardcoded values Tue Sep 7 18:07:13 2010 +0300 Yevgeny Kliteynik 2da9849b018245243d3d007b3e18e5a53ce531b5 * osmtest/osmt_slvl_vl_arb.c: handling fopen() failure Thu Sep 9 17:45:12 2010 +0300 Sasha Khapyorsky f48d5eaf80fef1bcf695c2839e9da2e32f8b2552 * opensm/osm_db_files.c: malloc() return value run-time check Tue Sep 7 18:05:36 2010 +0300 Yevgeny Kliteynik ea3ef8217d75f002c9b1e17f1a2ee19cc3047d8c * opensm/osm_db_files.c: fix small memory leak Tue Sep 7 18:04:38 2010 +0300 Yevgeny Kliteynik f4a5174aa7b8a461e80fa2d626b72fad69b4c108 * opensm/osm_subnet.c: fixing small bug in error path Tue Sep 7 18:00:30 2010 +0300 Yevgeny Kliteynik c18ef238811776dc796ceb61d43aa67b98608ac0 * opensm/osm_mesh.c: fixing a bug in compare_switches() Tue Sep 7 18:03:52 2010 +0300 Yevgeny Kliteynik 4da9aa67fe3dc5bc9be3ce6c0303e75fbf43a8fa * opensm/osm_helper.c: cosmetics - move define closer to the relevant code Tue Sep 7 18:02:49 2010 +0300 Yevgeny Kliteynik 83b74cd30f70df95f5a80231ce060138db039702 * opensm/osm_helper.c: fix potential overrun of the array Tue Sep 7 18:01:42 2010 +0300 Yevgeny Kliteynik 85c0ac9377d0acf881a9191ce2da7c758f148138 * osmtest/osmtest.c: handle timeouts in PR stress test Wed Sep 8 00:03:29 2010 +0300 Sasha Khapyorsky ebb2c841aedf4623c83d724e1185bc0662f46135 * opensm/osm_node_info_rcv.c: move p_physp declaration under code block Tue Sep 7 17:58:53 2010 +0300 Yevgeny Kliteynik 5c88113d51484076b0794f5aa9442ff8fc2e4f24 * opensm/osm_node_info_rcv.c: remove useless code line Tue Sep 7 17:59:34 2010 +0300 Yevgeny Kliteynik 866d939da2ffd174b2db2399767d47ede7ae60e2 * opensm/osm_sa_vlarb_record.c: removed unused variable Tue Sep 7 17:57:35 2010 +0300 Yevgeny Kliteynik 15a8770babfad831ec25898218cf1c5f35ad4b5c * opensm/osm_sa_pkey_record.c: removing unused variable Tue Sep 7 17:55:42 2010 +0300 Yevgeny Kliteynik 8f002b7fe00fa992497b9733086885afbd955249 * opensm/osm_pkey.c: removing unused function Tue Sep 7 17:56:35 2010 +0300 Yevgeny Kliteynik 9c0fa2fc4ec8dc712e2c1f870969d1cc9b7b01b2 * opensm/osm_sminfo_rcv.c: removing unused variable Tue Sep 7 17:53:54 2010 +0300 Yevgeny Kliteynik d3f060aafc68a463afd1e92f42a624a8257f0848 * opensm/osm_mtree.c: removing useless 'if' statement Tue Sep 7 22:34:52 2010 +0300 Yevgeny Kliteynik bbef64a79758199dd5d1e217e268f6b9453855bb * libvendor/osm_vendor_mlx_sa.c: remove useless "if" statement Tue Sep 7 18:13:52 2010 +0300 Yevgeny Kliteynik 2da02b58af7bdf183bd1467ac38c75b06a76d4f5 * libvendor/osm_vendor_ibumad_sa.c: remove useless "if" statement Tue Sep 7 21:17:47 2010 +0300 Sasha Khapyorsky 435dde076959c57169dbb95b4ffa597d1b44a6f2 * opensm/sa: simplify osm_mcmr_rcv_find_or_create_new_mgrp() function call Tue Sep 7 17:50:33 2010 +0300 Yevgeny Kliteynik 4c822b0379ac42441fa67e98733534f9ebc891e3 * opensm/osm_prtn.c: removing TopSpin hack Sun Sep 5 18:24:54 2010 +0300 Yevgeny Kliteynik e7a872d22e61514cf4e7c66bbd41d9cda2ded351 * opensm/osm_qos_policy.c: change a log message Fri Sep 3 10:43:14 2010 -0600 Jim Schutt ffbe7d0cd173b6b6e4ae9fbf623a773f92fd1c52 * opensm: Cause status of unicast routing attempt to propogate to callers of osm_ucast_mgr_process(). Fri Sep 3 10:43:13 2010 -0600 Jim Schutt 125f35c12a156e4504408607e6edd72bdb0450ca * opensm: Avoid havoc in dump_ucast_routes() caused by torus-2QoS persistent use of osm_port_t:priv. Fri Sep 3 10:43:12 2010 -0600 Jim Schutt 9ddcf3419eade13bdc0a54f93930c49fe67efd63 * opensm: Avoid havoc in minhop caused by torus-2QoS persistent use of osm_port_t:priv. Fri Sep 3 10:43:11 2010 -0600 Jim Schutt b74faf2b352b0ee5bbf10f12ee07378505c01d0f * opensm: Make it possible to configure no fallback routing engine. Fri Sep 3 10:43:10 2010 -0600 Jim Schutt 5a60f394b16b5354ed3b40c8d815dfa352e1044a * opensm: Do not require -Q option for torus-2QoS routing engine. Fri Sep 3 10:43:09 2010 -0600 Jim Schutt fedc08c87996487af211ace2898f018d005d4ca0 * opensm: Add opensm option to specify file name for extra torus-2QoS configuration information. Fri Sep 3 10:43:08 2010 -0600 Jim Schutt 3da7219bbe48f9d3a1c436a4522a869164d700c3 * opensm: Enable torus-2QoS routing engine. Fri Sep 3 10:43:07 2010 -0600 Jim Schutt 398f9865914f299bd968d72b9bac35bde75827c2 * opensm: Update documentation to describe torus-2QoS. Fri Sep 3 10:43:06 2010 -0600 Jim Schutt 126736cbef8a5704d21c873c8f792dfbdbae57a2 * opensm: Add torus-2QoS routing engine, part 4. Fri Sep 3 10:43:05 2010 -0600 Jim Schutt ced8f8b4f99e562d8991bf0befdccc51ba78261c * opensm: Add torus-2QoS routing engine, part 3. Fri Sep 3 10:43:04 2010 -0600 Jim Schutt 6f3f5b4a532815a6ee5c1b7e7808fefc96a0008b * opensm: Add torus-2QoS routing engine, part 2. Fri Sep 3 10:43:03 2010 -0600 Jim Schutt 3b8b1534fab2a47a4333052ee7b8208098a10892 * opensm: Add torus-2QoS routing engine, part 1. Fri Sep 3 10:43:02 2010 -0600 Jim Schutt 673877add5e92bc24c037d2a8a090175822472b9 * opensm: Make mcast_mgr_purge_tree() available outside osm_mcast_mgr.c. Fri Sep 3 10:43:01 2010 -0600 Jim Schutt 2b5ee5459cc1fc8f6e5567cdeba52e74336b6b0c * opensm: Add struct osm_routing_engine callback to build spanning trees for multicast. Fri Sep 3 10:43:00 2010 -0600 Jim Schutt b1356875542f14b71ca1afb7642b5c888e565fc2 * opensm: Track the minimum value in the fabric of data VLs supported. Fri Sep 3 10:42:59 2010 -0600 Jim Schutt d9d42dc0c8c27a971ab2adcfcdef5f6386301a87 * opensm: Allow the routing engine to participate in path SL calculations. Fri Sep 3 10:42:58 2010 -0600 Jim Schutt 1104942fb0f538772db9fa64c3566f8dbaff041d * opensm: Allow the routing engine to influence SL2VL calculations. Fri Sep 3 10:42:57 2010 -0600 Jim Schutt d7988c876fa11404e9a9349ef5b53c9842eb8422 * opensm: Prepare for routing engine input to path record SL lookup and SL2VL map setup. ** Version: opensm-3.3.7 Sat Sep 4 14:15:33 2010 +0300 Sasha Khapyorsky c9cd580b86d2ac2f5ea046dc9a02dd4a9c68bf07 * management: packages versions update Sat Sep 4 14:13:06 2010 +0300 Sasha Khapyorsky fec98892afe5fcb63276d4c4aea3b89cbd897e4f * management: update shared library versions Sat Sep 4 13:32:37 2010 +0300 Sasha Khapyorsky 8f47ad7414d2af60424e1c88c2392c80b0336f22 * opensm_release_notes-3.3: update Tue Aug 31 14:21:33 2010 -0400 Hal Rosenstock 9ef1fc893f3b2c1c5327264119b4f9c1cbfb65d6 * opensm/osm_pkey_mgr.c: Eliminate unneeded parameter from pkey_mgr_get_physp_max_blocks API Tue Aug 31 14:20:42 2010 -0400 Hal Rosenstock b4843c6f851ecee37d425c94feaaf177b0b99029 * opensm/include/osm_helper.h: Eliminate some duplicate declarations Sun Aug 1 12:36:20 2010 +0300 Eli Dorfman (Voltaire) 0dbe5ca6cd715d840c6deb34d5ba9f36a9aec9f5 * opensm: Fix sl2vl configuration Wed Aug 18 16:38:14 2010 +0300 Yevgeny Kliteynik cead6a579e77d1aca425f622c4d73d556929e290 * opensm/osm_opensm.c: no report when SM is exiting Wed Aug 25 19:36:54 2010 +0300 Sasha Khapyorsky 741b9959fdaa8bbff87c6eaac11fde194f7f1d55 * complib/cl_timer: remove not needed timeval initializations Tue Aug 24 16:21:33 2010 +0300 Yevgeny Kliteynik f53a9d7141f7b68660b52e059fe74fee40d50d6a * complib/cl_timer.c: fixing cl_timer calculation Fri Jul 9 10:27:05 2010 -0400 Hal Rosenstock dbdcf955addf946241a18d0985f960e32e36e6e7 * opensm/osm_helper.c: Add some missing message names to disp_msg_str Tue Jun 29 16:49:25 2010 +0300 Eli Dorfman (Voltaire) 01f40c4fe5d41e29fab5699818de202c4b6af0af * opensm/osm_lid_mgr.c: Allow switch lids to be non LMC aligned Wed Jun 30 13:00:38 2010 +0300 Yevgeny Kliteynik 2d5ad86117c1a9501a749f3693b1da55afcd4217 * opensm/osmeventplugin: added new events to monitor SM Tue Jun 29 17:38:54 2010 +0300 Eli Dorfman (Voltaire) 054fe32d59bfe703fef140fb82ae031d0ef0d807 * opensm: Modify OSM_LOG_SYS messages Sun Jun 20 12:31:55 2010 +0300 Eli Dorfman (Voltaire) 0bb5645d1350999c67082a84278caf5cabc43faf * opensm: Fix wrong messages in MC delete flow Tue Jun 22 10:13:41 2010 -0400 Hal Rosenstock 44f6f5071116761e5c8c7019944316e0baf1a3d5 * opensm/osm_req.c: In osm_send_trap144, eliminate redundant clear of m_key in smp Mon Jan 25 15:22:48 2010 -0500 Hal Rosenstock c1bd7a3b19623d9a3ad059d4d01cbbccb55033f4 * opensm/osm_qos.c: Eliminate unneeded endport SL to VL setup Thu Jun 10 16:49:19 2010 +0300 Yevgeny Kliteynik d4a46a9a57afe483d91368a53dff0e23eaf6c349 * opensm/osm_sa_path_record.c: adding wrapper for pr_rcv_get_path_parms() Thu Jun 10 15:00:50 2010 +0300 Yevgeny Kliteynik 582ec70de419c7af4964d8fcec74cd96dd863c5f * opensm/main.c: force stdout to be line-buffered Mon Jun 14 08:46:46 2010 -0400 Hal Rosenstock 9f9084b672b4df694af014048f1af0b5876a52ed * opensm/osm_mcast_mgr.c: Only route MLIDs with more than 1 member Mon Jun 14 07:11:49 2010 -0400 Hal Rosenstock 5bafefdc5ccc1c39d9285466654d3ae1ffc4b862 * opensm/osm_trap_rcv.c: No need for heavy sweep when just NodeDescription changes Tue Jun 15 11:33:41 2010 +0300 Yevgeny Kliteynik e8be8436133feffaa0c82a0bbcdfaf9aab442776 * opensm/osmtest.c: fix bug in getting attr offset Mon Jun 14 15:59:35 2010 +0300 Sasha Khapyorsky 2b63324d440bc59610cae45e08ee9fe246986fc9 * iba/ib_types.h: remove assertion in ib_get_attr_offset() Thu Jun 10 18:01:31 2010 +0300 Eli Dorfman (Voltaire) 82720e4e0902917827d030a4539a89997a7ab3d9 * return no path when path does not exist Wed Jun 9 14:29:11 2010 -0400 Hal Rosenstock 7bd8e26d0e1d32f68adb031fb4df3d3d53b334ad * opensm: Better handling of non responsive SMAs Mon Dec 22 11:03:59 2008 -0800 Ira Weiny 42fb6dc7f050d8a86b64db655e3731dd6893f040 * opensm/osm_perfmgr.c: Remove unnecessary lock reference from Performance Manager object Wed Mar 24 17:50:10 2010 +0200 Yevgeny Kliteynik 3d7d688a04fc994a18d8c4a44bc58dc83ab1f79f * opensm: fixing compilation issues in some header files Tue Jun 1 08:56:52 2010 -0600 Jim Schutt 8a1c61d58092074fa0b1609dd9e1ca23e130a8b4 * opensm/qos.c: Revert port ranges for calls to sl2vl_update_table(). Mon May 24 20:58:48 2010 -0700 Stan C. Smith 1e66124b80d0dcfd9d3a625078fc3ce6845ceaf6 * opensm - cleanup Tue May 25 08:32:46 2010 -0700 Stan C. Smith 458e59a484dff66f37aee9e89a7cfdcb4a408126 * opensm/libvendor Reduce stack consumption Tue May 25 09:03:16 2010 -0700 Stan C. Smith 6ec32d52bf36a97f744279ebd7bafc6df65d0f15 * opensm - address windows env issues Mon May 24 15:43:53 2010 -0400 Hal Rosenstock 36f80f6c7718254a797c493eb92038f4556a8d55 * opensm/osm_sa_multipath_record.c: livelock in mpr_rcv_get_path_parms Mon May 24 15:42:51 2010 -0400 Hal Rosenstock 8144ecf31c57c6c3dbe93ef54caec638bb9993cd * opensm/osm_sa_path_record.c: Add error code to newly added log message Tue May 25 09:53:30 2010 -0700 Arthur Kepner 6b23b71b331dd9a299ab2e9fef8b391fd2d0c109 * opensm: toggle sweeping V3 Fri May 21 10:49:27 2010 -0700 Smith, Stan f3aaa184bec981ea6afd75330137df957c25205a * ib_types.h add debug assert Fri May 21 10:23:26 2010 -0700 Smith, Stan b704f556d08cdede8a4ea523d971e0d0ca346347 * osmtest - use helper function Fri May 21 09:45:03 2010 -0700 Smith, Stan 40d2623c0cd256b01225639051bd3845175f93f7 * opensm/complib use portable macro syntax ** Version: opensm-3.3.6 Sat May 22 18:00:16 2010 +0300 Sasha Khapyorsky 19bd6f48ba95e341c36226fe9f316cb552fcd129 * management: packages versions update Sat May 22 17:52:50 2010 +0300 Sasha Khapyorsky b13986020b9828c40c96cbe37116f99567f4b697 * management: update shared library versions Sat May 22 16:04:10 2010 +0300 Sasha Khapyorsky c49f99fe3c110260243aff2c2f229c2a699b2c24 * opensm_release_notes-3.3: update Wed Apr 21 13:22:02 2010 +0200 Line Holen b949bdbca6eabaebb79aaa2cc886a9ad20b474ac * opensm/osm_sa_path_record.c: Lower max number of hops allowed Mon Apr 26 13:42:10 2010 +0300 Sasha Khapyorsky add0fc6456e6b151f2f88a9f404ae89bbe8fdf2b * opensm/osm_lid_mgr: revert 'coming_out_of_standby' replacement patch Mon May 17 10:22:04 2010 +0300 Yevgeny Kliteynik bd21679f98ff34812e714f9a9be5e630a2f006d6 * opensm/osm_log.c: add OSM_LOG_SYS to default flags Sun Apr 25 20:26:14 2010 +0300 Sasha Khapyorsky 6c9240f6f1ddacaab964347417d72831bb4af9e7 * opensm/osm_lid_mgr: fix couple of duplicate LIDs bugs Mon Apr 26 13:42:10 2010 +0300 Sasha Khapyorsky 9a0ed25b6226e1461e37555ae614987c28adf251 * opensm/osm_lid_mgr: use 'first_time_master_sweep' flag Sun Apr 25 16:44:17 2010 +0300 Sasha Khapyorsky de5df952916482e989feac59e873c4c64d3bee0b * opensm/osm_lid_mgr.c: some cleanups Thu Sep 24 04:40:03 2009 +0300 Sasha Khapyorsky 84e956710ad1eb9bbd2352576be61743305ed567 * opensm: conversion to osm_get_port_by_lid() Sun Apr 25 16:47:27 2010 +0300 Sasha Khapyorsky 7864d1c74762a35dbb6f6e15ed6913808c9aae67 * opensm/osm_lid_mgr.c: fix memory leak Mon Apr 19 19:00:44 2010 +0300 Dave Olson 4afbb61a4326ff118e90d0b512004e758d5f335e * opensm/opensm.init.in: fix install warning on SLES11 Mon Apr 19 11:15:43 2010 +0200 Line Holen 8aa7567d467f0c79d26dd8d6b2914ed8e22f3053 * opensm/osm_sa_path_record.c: livelock in pr_rcv_get_path_parms Thu Apr 15 16:27:45 2010 +0300 Sasha Khapyorsky 34de58d9588a175a3132aea3a17c6ab2adc655b0 * opensm/vendor: fix portguids array size Wed Apr 7 14:27:39 2010 -0500 Dale Purdy 19dacb07d5cad8608984aa984a086f58011d45e2 * Dimension port order file support Tue Apr 13 13:40:35 2010 +0300 Yevgeny Kliteynik 95fa2ebe1092c7abf1cc033e31fd74e6b4d69a07 * opensm/osm_subnet.c: fixing some options to not "hot-swappable" Tue Apr 13 13:43:14 2010 +0300 Yevgeny Kliteynik 6d7233fc27e5deb7f91655b7bfdd04172dc090b0 * opensm/osm_subnet.{c,h}: passing options to the event plugins Tue Apr 13 13:39:14 2010 +0300 Yevgeny Kliteynik 8dcd84d7184fbbae10e7acc1e980a738394662f4 * opensm/osm_subnet.h: cosmetics - fix description of event_plugin option Fri Feb 26 09:49:39 2010 +0100 Line Holen 825e80396ade24a079a68db9a1f126f6aae65608 * opensm/osm_pkey.h: Fix typo in comment Thu Feb 4 20:12:20 2010 +0200 Eli Dorfman (Voltaire) 8edd358f4675bae99a47aa451e5283b360b8a79f * Delete port only after GID OUT trap was sent Mon Feb 8 21:26:50 2010 -0800 Arputham Benjamin 163f19281a544edefaa4fc7825e541c24a40af46 * opensm: Add option to specify prefix to syslog messages Thu Feb 4 16:14:41 2010 +0200 Yevgeny Kliteynik fafe779c09a7c2d8905534e1a3230f33616ba8a2 * opensm/complib/cl_passivelock.h: remove unneeded casting Thu Feb 4 16:13:04 2010 +0200 Yevgeny Kliteynik 61269fbdfecebd2cbbf833f9513b724475bb56a2 * opensm/complib/cl_types.h: convert cl_status_t to int Fri Feb 5 00:16:46 2010 +0200 Sasha Khapyorsky 0c94b9147c0d969f5812e90edd599aacdf2e994a * opensm/osm_mcast_mgr.c: preserve root switch calculation functionality Thu Feb 4 16:33:33 2010 +0200 Sasha Khapyorsky 56750e16da2945319b80ea0e9628a696b68acd0e * opensm/osm_mcast_mgr.c: code simplifications Thu Feb 4 22:25:14 2010 +0200 Sasha Khapyorsky e69b84098f3add3ee3220c09653d24aa21a6802b * opensm/osm_mcast_mgr.c: fix bug in MC root switch calculation Thu Feb 4 15:27:12 2010 +0200 Sasha Khapyorsky 1d75bcbfb72f472a50c26317b78a0812a28df4b2 * opensm/osm_mcast_mgr.c: fix some indentation errors Thu Feb 4 15:21:09 2010 +0200 Sasha Khapyorsky a2057aec578eac44176aecca07295ea05512ea2e * opensm/osm_mcast_mgr.c: remove redundant casting Thu Feb 4 09:27:28 2010 -0500 Hal Rosenstock 56f55fa9137748a76cad7ddfb6f53014be2301ee * opensm/osm_mcast_mgr.c: Cosmetic changes Thu Dec 3 16:11:30 2009 +0200 Slava Strebkov 588ef347609688da118867e5d2f4d2158ee6fcca * opensm: Multicast root switch calculation Fri Jan 29 22:43:00 2010 +0200 Sasha Khapyorsky b89e760c404925445a0e6987e4a313c81405f30d * opensm/osm_sa_pkey_record.c: optimize port selection logic Fri Jan 29 17:55:42 2010 +0200 Sasha Khapyorsky 4549ab7bbc19b44b1517017fa739681d074be9b9 * opensm/osm_mcast_mgr.c: fix memory leak Tue Feb 2 15:29:26 2010 +0200 Yevgeny Kliteynik 812d3dc50a623b2209a5b6fb87f1bde388d039a3 * opensm/complib/cl_ptr_vector.c: fix bug/compiler warning Mon Feb 1 14:46:47 2010 +0200 Yevgeny Kliteynik 52919ae39f82e22d5cc49e87fa1758cb27e0cb79 * opensm/osm_subnet.h: remove redundant function definition Wed Jan 27 12:32:33 2010 +0200 Sasha Khapyorsky 8ba32f3ff3d10ff95d97ddbd72e800cd0b691a7a * opensm/osm_vl_arb_rcv.c: indentation improvement Wed Jan 27 10:45:29 2010 +0100 Line Holen 43f6d76d728fe47f4878aca52e66c06658b4907c * opensm/osm_vl_arb_rcv.c: fix double mutex release bug Tue Jan 26 18:10:54 2010 +0200 Yevgeny Kliteynik dbd50311ee173812cc765f9a4c2eaedd465f2e01 * opensm/osm_port_info_rcv.c: fix compilation warning Thu Jan 21 17:54:13 2010 +0200 Yevgeny Kliteynik ca22df7d1650fca4bc5de73ba1eabd6129c179d2 * opensm/osm_sa.{c,h}: osm_sa_db_file_dump() return values Mon Jan 25 08:30:23 2010 -0500 Hal Rosenstock 2a444cdfb5771407837b46388322d886e4c5a29f * opensm/osm_qos.c: Fix typo in OSM_LOG message Tue Jan 12 15:02:08 2010 +0200 Sasha Khapyorsky 8121bce55fc635f71c576366b4dc9b6be7e6f00e * opensm/osm_update_node_desc(): minor prototype improvement Wed Jan 13 17:34:13 2010 +0200 Eli Dorfman (Voltaire) 35f44212c9e1341c58ba1fb836daac1ae74de110 * opensm: Add update_desc command to opensm console Mon Jan 4 14:15:30 2010 -0500 Hal Rosenstock 86ad3e36fcc13cd302edc7a9d042fca6390802b6 * opensm/osm_vl_arb_rcv.c: Dump table after validating block number Mon Jan 11 10:47:47 2010 +0200 Yevgeny Kliteynik 1c4f5ef69e804cf9c56d82d87b5798e9a043e5af * opensm SA DB: dump only if modified Thu Jan 7 14:15:59 2010 +0200 Sasha Khapyorsky 59e30bc75a28dcc7fb276967eb36a130b0cbbccf * opensm/osm_sa_infrominfo.c: fixes and simplifications in lid range check Thu Jan 7 14:00:04 2010 +0200 Sasha Khapyorsky 0bf76142a09543c8eaf9c06a12106660c5b933ee * opensm/osm_sa_informinfo.c: minor simplifications and fixes Tue Dec 1 14:41:10 2009 -0500 Hal Rosenstock 368ccf6ed18eab81ee1fbc0543767b4c91b2ec41 * opensm: Add support for optimized SLtoVLMappingTable programming Mon Jan 4 21:06:19 2010 +0200 Sasha Khapyorsky f9f908f72fab77760e22d7a504e3d926f7cfd418 * opensm/osm_qos.c: split switch external and end ports setup Mon Jan 4 18:50:28 2010 +0200 Sasha Khapyorsky fbad47dbb02d7b6b6ca8ce21a8b8e6f94e10e0a5 * opensm/osm_qos.c: merge SL2VL mapping capability check Tue Dec 29 15:48:14 2009 +0200 Sasha Khapyorsky 123d874d2eed14192b279023590c10bbe52d5a54 * opensm/osm_slvl_map_rcv.c: verify port number values received from network Tue Dec 29 00:42:56 2009 +0200 Sasha Khapyorsky 640c2fc7c1fa27da38ea40592dfb3912c6dc71c7 * opensm/osm_slvl_map_rcv.c: fix mutex double release bug Mon Dec 28 13:58:28 2009 +0200 Sasha Khapyorsky 42781eb27aab588dfce4b12122095dd4d2274911 * opensm/osm_slvl_map_rcv.c: fix port parsing on BE machine Sun Dec 20 21:35:04 2009 +0200 Sasha Khapyorsky 020dda70404196d3b8abbfbd3646fa10e19836d0 * osm_sa_path_record.c: cleanups Sun Dec 20 22:29:50 2009 +0200 Sasha Khapyorsky 005982227890b1c7e74cbda4f1f1fe017b640ae4 * osm_sa_path_record.c: use PR DGID by reference Sun Dec 20 20:30:04 2009 +0200 Sasha Khapyorsky 11059a8c27608db0e439dfe2d01b9217e11ed242 * osm_sa_path_record.c: separate mutlicast processing code Mon Dec 21 12:39:57 2009 +0200 Sasha Khapyorsky 190fe5212a7811c72044c2a6b5dfe64f2180710a * opensm/osm_sa_path_record.c: MGID must be specified explicitly Thu Dec 24 16:22:01 2009 +0200 Sasha Khapyorsky 83ae138d3efaba06ac99261ea86ac3ff012a04c9 * opensm/osm_mcast_mgr.c: strip log-only variable ** Version: opensm-3.3.5 Thu Dec 24 15:14:41 2009 +0200 Sasha Khapyorsky 0fa0ea350a74ed0fe090c35350a1d78959d3357e * management: packages versions update Thu Dec 24 15:11:08 2009 +0200 Sasha Khapyorsky c21fe49dce61782d460ebf7f9f0c5ee5b9ef186e * opensm: update libraries version strings Thu Dec 24 15:06:43 2009 +0200 Sasha Khapyorsky 81ee98f58ba7b96b9e82e8a503c2f0243829d3e5 * opensm_release_notes-3.3: RN update Wed Dec 23 16:44:12 2009 +0200 Yevgeny Kliteynik a251743c4a3b7c4d19cf3f300b84c6aa6e1d0d0b * opensm/osm_mcast_mgr.c: fix osm_mcast_mgr_compute_max_hops for managed switch Thu Dec 24 14:19:11 2009 +0200 Sasha Khapyorsky 2faaf4f98d2917355912b0525db0838cc7bac357 * opensm: add Voltaire copyright notice Thu Dec 24 06:20:36 2009 -0500 Hal Rosenstock 2a424a7e4fab93aad4781c3abad39be3015fee56 * opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, revert setting of init failure on QoS initialization failures Sun Dec 20 11:51:34 2009 +0200 Yevgeny Kliteynik f4459c82303bc5488e30b5e0bc9b74cdf077c968 * opensm: copyright updates Sun Dec 20 12:15:48 2009 +0200 Sasha Khapyorsky 8ef66980591580b2903921189f4e218f0b21cffd * opensm: cosmetic cleanup Wed Dec 16 08:57:24 2009 -0500 Hal Rosenstock 6121265a284b19ac7b57dbc27e5e57a3b80e4f02 * opensm/osm_vendor_ibumad.c: Add transaction ID to osm_vendor_send log message Wed Dec 16 11:02:45 2009 +0200 Yevgeny Kliteynik c5270b4ef1b975c899a4753c8f54468e28d543e0 * opensm/osm_vl15intf.c: reverting commit 546399c3b983cdfe7adf4bd0b179358744603478 Tue Dec 15 21:18:36 2009 +0200 Sasha Khapyorsky 796ab79a2d1a28d5255d7e59f1b9a1bddb44f01c * opensm/osm_sa_path_record.c: don't set dgid pointer for local subnet ** Version: opensm-3.3.4 Sun Dec 13 19:39:11 2009 +0200 Sasha Khapyorsky 4693bba5c7845d2f7de7d5c48658da1152383a72 * management: package versions bump Sun Dec 13 19:36:19 2009 +0200 Sasha Khapyorsky 0cbe3e7c51e14eb1eb12e8088fcbe8f1d181182d * management: update library versions Sun Dec 13 19:22:55 2009 +0200 Sasha Khapyorsky 665e310da04f23314ca035a4d312507e7c797865 * opensm_release_notes-3.3.txt: updates for 3.3.4 version Sun Dec 13 18:35:49 2009 +0200 Sasha Khapyorsky 4a324ec6b11d648711da99eec28fca3a4c9993d8 * opensm/osm_vendor_ibumad.c: dump DR path at same log level as its error message Sun Dec 13 18:27:05 2009 +0200 Sasha Khapyorsky 525faa14a3c6953cc4aff02eb3fe90dc13600717 * opensm/osm_sa.c: check for SA DB file only if requested Sun Dec 6 16:52:08 2009 +0200 Yevgeny Kliteynik 1ff8fb0ae85aeb2a5ece22cc84867d4190176245 * opensm SA DB dump/restore: added option to dump SA DB on every sweep Sun Dec 6 16:40:40 2009 +0200 Yevgeny Kliteynik f1f19e9cf4958379e63a1c1b9ce4438483a97f31 * opensm SA DB dump/restore: load SA DB only once Sun Dec 6 11:19:51 2009 +0200 Yevgeny Kliteynik e8385c7d283a0ea7eab501cd7aad90d7a277db0a * opensm: implement 'connect_roots' option in fat-tree routing Fri Dec 4 15:26:17 2009 +0100 Line Holen 0a71c070359c822cf4459c32aa8a97accb8311bd * opensm: Added print_desc to various log messages Fri Dec 4 10:41:50 2009 +0100 Line Holen 4d26fea9404f4c61d1e347b11b06770f23738cff * opensm/osm_vendor_ibumad.c: Move error info into single message Fri Dec 4 10:41:50 2009 +0100 Line Holen 824e8e442c5cc8651632bbc496e7f64676750ad7 * opensm/osm_vendor_ibumad.c: Move error info into single message Wed Dec 9 10:48:20 2009 +0200 Yevgeny Kliteynik b587b83fad2320cea1e5edc649f28e4c45cb6079 * opensm/libvendor//osm_vendor_ibumad_sa.c: uninitialized fields Sun Dec 13 16:03:27 2009 +0200 Sasha Khapyorsky aa6477c5964e61e67d502d1b1c789f8c9a55e9b1 * opensm/osm_sm_mad_ctrl.c: minor optimizations Thu Dec 3 15:27:15 2009 +0100 Line Holen 6afcbcf612ed1625cfebd6c9def2573eaca53a41 * opensm/osm_sm_mad_ctrl.c Changes to some error messages Thu Dec 3 11:12:04 2009 -0500 Hal Rosenstock ea5a892c9093a026f69584202d290c61bc7564da * opensm/osm_sm_mad_ctrl.c: Add missing call to return mad to mad pool Mon Dec 7 12:26:20 2009 +0200 Yevgeny Kliteynik e585fca5dcf2ab32747aa12ac25608a95e37d66b * opensm/osm_sa_mcmember_record.c: trivial optimization Mon Dec 7 12:22:55 2009 +0200 Yevgeny Kliteynik 9563cd95cb8e09b464fbc6ccdc0674d10b44a2d1 * opensm/osm_sa_mcmember_record.c: print mcast join/create failures in VERBOSE instead of DEBUG level Tue Dec 1 11:15:48 2009 -0500 Hal Rosenstock ddca44b711e8238c670b9961cb79eda8a2499e97 * opensm/osm_sm_mad_ctrl.c: Make some minor simplifications Tue Dec 1 08:14:56 2009 -0500 Hal Rosenstock f67dd9ec56d325409a0490a2d717293113048a5e * opensm/osm_vendor_ibumad.c: Change LID format to decimal in log message Mon Nov 30 16:45:23 2009 +0200 Yevgeny Kliteynik da24f8ed75d0e3a5ac90c40a2d3b09251281de54 * opensm/osm_vendor_mlx: fix compilation error Mon Nov 30 16:41:51 2009 +0200 Yevgeny Kliteynik 760e225600e2b0097e22de3a203973cd28a45bfb * opensm/osm_vendor_mlx_txn.c: eliminate bunch of compilation warnings Fri Nov 27 14:45:40 2009 +0100 Line Holen 4d2d0e37ec0757efd1f6ca1642c5c3db0c839ca2 * opensm/osm_vl15intf.c Log change Fri Nov 27 14:27:13 2009 +0100 Line Holen 6f76ca466655aa0ae31dfb78cbb2a30b296e4ec3 * opensm/osm_helper.c Log format changes Fri Nov 27 14:16:56 2009 +0100 Line Holen 8f05ddcab7f7be7a1bbee8c3aec5a0eb8c0caa27 * opensm/osm_ucast_ftree.c Changed log level Tue Dec 1 05:31:09 2009 +0200 Sasha Khapyorsky 46737d7d045ea2d0998f661e464e231819b4bc2f * opensm/osm_state_mgr.c: cosmetic Fri Nov 27 14:14:48 2009 +0100 Line Holen 43e936eca4f4f4c1a4b488686fea62e0c4a06451 * opensm/osm_state_mgr.c Added more info to some error messages Sat Nov 28 17:24:00 2009 +0200 Sasha Khapyorsky 2f99e56655b42f642436e23560a13654df8600ae * opensm/osm_trap_rcv.c: some cleaning Tue Nov 3 10:29:32 2009 -0500 Hal Rosenstock ee15df9cd75b5ad5e87b54a648701f1f469f8fc6 * opensm/osm_trap_rcv.c: Eliminate heavy sweep on receipt of trap 145 Tue Oct 13 09:15:35 2009 -0700 Stan C. Smith e7897b99ef304a4256c49cd6d74c33421d4467dd * opensm - standardize on a single Windows #define - take #2 Fri Nov 27 18:33:16 2009 +0200 Sasha Khapyorsky 888c2dc78d22bec5e1e15e4c80ae3fd3bb7e0f0f * opensm/osm_db_files.c: kill useless malloc() castings Wed Oct 7 16:46:43 2009 -0700 Stan C. Smith 174a4d8d179b7da0f7ee56042af8facee7dc910e * remove unnecessary leading '/' from filename Fri Nov 27 17:54:20 2009 +0200 Sasha Khapyorsky 1e653d292038ef9f167cee0b3b729f8bdc1cb21a * opensm/osm_base.h: remove trailing '/' in OSM_DEFAULT_CACHE_DIR Fri Nov 27 17:28:46 2009 +0200 Sasha Khapyorsky 98ef01ea80a8f07f358ba2d71de17bab398352d2 * opensm/osm_db_files.c: add '/' path delimited Tue Nov 17 14:08:38 2009 -0500 Hal Rosenstock 0f35ea42ef8ff58bb6e5b923120f4d25496cb61c * opensm/osm_sm_mad_ctrl.c: Fix qp0_mads_accounting Thu Nov 26 18:34:53 2009 +0200 Sasha Khapyorsky b1518d6686b47b4ca8001e43edcca877c3c3adb7 * opensm: IPv6 SNM update for man page and usage Thu Nov 26 18:08:34 2009 +0200 Sasha Khapyorsky b0c2701b91bcc5a73b3ecd3bdd3f8c3fc4b8b10d * complib/cl_fleximap.h: fix comment typo Tue Nov 17 09:03:41 2009 -0500 Hal Rosenstock ccd95fbf789f91617a0611b89c6da4900ead571a * opensm/osm_vl15intf.c: Cosmetic commentary change Tue Nov 17 09:02:57 2009 -0500 Hal Rosenstock c83d2a8f86c229b8dba707dae96bd393bbfa41ab * opensm/complib/cl_event.c: Cosmetic changes Mon Nov 16 13:43:43 2009 -0500 Hal Rosenstock 431f1f0c8eac2dcd2fee76323636c58fd6184a61 * opensm/osm_vendor_api.h: Fix commentary typo Mon Nov 16 13:43:03 2009 -0500 Hal Rosenstock c91e5553fc7e313ef28af981ac5aca19817dd283 * opensm/libvendor/osm_vendor_ibumad.c: Cosmetic change to OSM_LOG message Mon Nov 16 13:42:22 2009 -0500 Hal Rosenstock 9da8ba7001972b2f3434054c8f7443c43935a12f * opensm/osm_ucast_ftree.c: Cosmetic commentary changes Thu Nov 19 13:54:43 2009 +0200 Yevgeny Kliteynik b302a2755d69d0b947882bd43a784fe863b5ad5c * opensm/osm_subnet.c: fixing bug in dumping options file Thu Nov 26 01:16:09 2009 +0200 Sasha Khapyorsky 2428078c229718d5582886e696317045f1e85d0c * opensm/osm_ucast_mgr.c: fix memory leak Fri Nov 13 19:57:53 2009 +0200 Sasha Khapyorsky 56e73a8af87b80b3757f952af425b479dacfa6f0 * opensm: osm_get_mgrp_by_mgid() helper Thu Nov 12 03:53:17 2009 +0200 Sasha Khapyorsky d003bd00f01ebfa649f43e9bf39a055c70143619 * opensm: compress IPV6 SNM groups to use a single MLID Thu Nov 12 03:50:40 2009 +0200 Sasha Khapyorsky d654e820ee897d4516077901c635e2926e88c7f5 * complib/cl_fleximap: add cl_fmap_match() function Wed Nov 11 22:00:52 2009 +0200 Sasha Khapyorsky b995b82c8e96165da53aa4ed5c7779de86c2a691 * osm_sa_mcmember_record.c: pass MCM Record data to mlid allocator Sat Sep 19 19:51:37 2009 +0300 Slava Strebkov d6f8f3b334fd5554614adea92c7792b7faf36461 * osm_mgrp_box: infrastructure for mgid compression Wed Nov 11 19:36:08 2009 +0200 Sasha Khapyorsky 0d1a77ab725e736683c5c2e7122ea1e154dc17c3 * opensm/osm_mcast_mgr.c: cosmetic fixes Wed Nov 11 21:38:55 2009 +0200 Sasha Khapyorsky 1362fa96a49e4d7e8a48ff559b1ef52650ecf915 * opensm/osm_sa_member_record.c: mlid independent MGID generator Wed Nov 11 21:49:20 2009 +0200 Sasha Khapyorsky 4bc9e979caa93a008d81881ecece6cbc971f3a3d * opensm/osm_sa_mcmember_record.c: move mgid allocation code Sun Oct 4 12:53:28 2009 +0200 Sasha Khapyorsky 8d587aef29ef5f6739ee6128a9a821620419cc03 * complib: replace intn_t types by C99 intptr_t Mon Nov 2 15:48:35 2009 +0200 Yevgeny Kliteynik d43a023cb1d5acaee5fd65febbebfaacfd7480b8 * opensm/include/iba/ib_types.h: adding Congestion Control definitions Fri Nov 13 11:37:21 2009 -0500 Hal Rosenstock c5e87164e2f8dba363ba670defe49ff11e38209d * opensm: Cosmetic changes Fri Nov 13 17:33:10 2009 +0200 Sasha Khapyorsky e9cf56c5f6bc5f351e99abff19bb2af03fac2b8d * osmtest/osmt_mtl_regular_qp.c: cleaning uintn_t use Fri Nov 13 08:41:48 2009 +0200 Sasha Khapyorsky 8ffec3bed9ec1304e2e7881ad6d3cb4c82350d05 * opensm: remove braces around value in return statements Fri Nov 13 08:48:02 2009 +0200 Sasha Khapyorsky c253ff452918bf28458f00bc5e6da6ad3582e5c1 * opensm/osm_perfmgr_db.c: remove casting Fri Nov 13 08:46:44 2009 +0200 Sasha Khapyorsky c2272f776f67f261e743a632fed02d6337dfe49b * opensm/osm_console.c: make const functions Sat Sep 19 01:23:01 2009 +0300 Sasha Khapyorsky 77c019d18b17e41bb06da87bc7116b02dcf80191 * opensm/osm_mgrp_new(): add subnet db insertion Thu Nov 12 22:03:42 2009 +0200 Sasha Khapyorsky abad3805179198a8e833fe35b863e58825de8ba0 * complib/fleximap: make compar callback to return int Thu Nov 12 21:57:57 2009 +0200 Sasha Khapyorsky 13f5f79cb9c09734f2875daae7d837e8c229fd56 * opensm: cleanup intn_t uses Fri Nov 13 04:58:02 2009 +0200 Sasha Khapyorsky 1f5d66a62a3cd0618b3f6b32ae6f744494578c74 * opensm/main.c: kill unneeded braces Fri Nov 6 12:41:47 2009 -0600 Michael Reed 11c711e77754e3cc7a358c979c243a6663753532 * opensm/main.c: opensm cannot be killed while asking for port guid Sun Nov 8 15:28:16 2009 +0200 Yevgeny Kliteynik 112c97a1d80372b71e0fd9cef1c6bb12f680c472 * opensm/complib: bug in cl_list_insert_array_head/tail functions Mon Nov 9 17:48:08 2009 -0800 Stan C. Smith 51d0b5b368921df7f1a104d4e48d3ddede3972da * opensm - use C99 transportable data type for pointer storage Tue Nov 10 11:37:38 2009 +0200 Yevgeny Kliteynik 7bed088d38cad441fc8d7bec3a8510eb17f45c17 * opensm/osm_state_mgr.c: do not probe remote side of port 0 Fri Nov 6 15:42:19 2009 -0500 Hal Rosenstock e315149943b196b822d75583a024b732a2dd4a7a * opensm/osm_link_mgr.c: Fix IBA reference for PortInfo attribute Mon Nov 9 15:07:29 2009 -0800 Stan C. Smith d4b4e04d4a4cb7b58548ac43d8ffc43e194dc024 * opensm - remove useless goto Wed Nov 11 19:38:13 2009 +0200 Sasha Khapyorsky 125fbf7a0c132de2ef1645d2fd6f5e469eeb3dd8 * opensm/osm_mcast_mgr.c: fix return value on alloc_mfts() failures Tue Nov 10 10:39:47 2009 -0800 Ira Weiny b5f4e6ae6c3958a596296b5e83fd609f33e27fc6 * OpenSM: Fix unused variable compiler warning. Sat Sep 19 16:38:36 2009 +0300 Sasha Khapyorsky 5a88e8f6d3fd4280657c2a2063551efe1cb473bf * opensm/partition: keep multicast group pointer Fri Nov 6 09:14:02 2009 -0500 Hal Rosenstock 48663a10d28ae2d0bb190333e381038288df6c52 * opensm: Only clear SMP beyond end of PortInfo attribute Fri Nov 6 09:08:08 2009 -0500 Hal Rosenstock 8ce83b183d41a9f88058d7482f149d9aa2b400a6 * opensm/osm_base.h: Update IBA reference to use 1.2.1 Fri Nov 6 09:06:24 2009 -0500 Hal Rosenstock 2eebf9a84e07180d78014d2dc69dfe4622088bb8 * opensm/ib_types.h: Fix some commentary typos Wed Nov 4 12:34:04 2009 -0800 Stan C. Smith cf5d838fe4034f72c54b760dbb8d9869c10e0d28 * osmtest - code cleanup: remove Windows specific items. Wed Nov 4 09:29:08 2009 -0500 Hal Rosenstock c5f699b9b2909e7260f5810484ba36f4a51a60ca * opensm/osm_switch.h: Remove dead osm_switch_get_physp_ptr routine Tue Nov 3 07:00:58 2009 -0500 Hal Rosenstock 4f9a6f2f53fda827f3f0a8d778879158346252e9 * opensm/osm_mcast_tbl.c: In osm_mcast_tbl_clear_mlid, use memset to clear port mask entry Tue Nov 3 03:46:54 2009 +0200 Sasha Khapyorsky 6ddfb1111a871e48c2d9f50651d41a847e42c0ab * opensm/osm_trap_rcv.c: some consolidation Tue Nov 3 09:56:30 2009 +0200 Yevgeny Kliteynik e11a7379d4c28c611f913b9049bf1a8e6b5b5a6d * opensm: copyright updates Tue Nov 3 09:56:30 2009 +0200 Yevgeny Kliteynik d02dc50ab6d8b364d44ff8544c826793c9e88e30 * opensm: copyright updates Thu Oct 29 12:22:06 2009 +0530 Keshetti Mahesh df14e4fb275d9cb62640e81ff931ba026fd57c32 * opensm/: Removed empty comments Tue Nov 3 02:59:24 2009 +0200 Sasha Khapyorsky dc2f149569102ca6e733ea93cce51e4f61a06e1f * opensm/osm_trap_rcv.c: use source_lid and port_num for logging Mon Nov 2 14:06:54 2009 -0500 Hal Rosenstock 548548eedc8c3cffc97e5b9b59a196fdf3965ec8 * opensm/osm_mcast_tbl: Fix size of port mask table array Mon Nov 2 21:36:41 2009 +0200 Sasha Khapyorsky 66dde1c4dc068f3175b381d0e090c55637d3efd6 * opensm/osm_trap_rcv.c: some simplification Mon Nov 2 11:43:19 2009 -0500 Hal Rosenstock f72e12ee14678531fe5a795473ecc286fc957f0d * opensm/main.c: Use strtoul rather than strtol for parsing transaction timeout Mon Nov 2 17:59:10 2009 +0200 elid e940f01aa7de1585a58dba3a2c27e4b4f55b6145 * opensm: Return single PathRecord for SubnAdmGet with DGID/SGID wild carded Mon Nov 2 17:32:57 2009 +0200 Sasha Khapyorsky 7eb584cfdfb4d6167d8a277060e90a5338ccb0c6 * opensm/osm_sa_path_record.c: flow simplification Mon Nov 2 00:38:19 2009 +0200 Yevgeny Kliteynik b3784d889749d483a3e7b121cb7054c8cb4faf28 * opensm/osm_sa_mcmember_record.c: fsmall code optimization ** Version: opensm-3.3.3 Sun Nov 1 21:55:47 2009 +0200 Sasha Khapyorsky eb95933f0dbd006da8053ea4da0b95a98bd7edea * management: bump package versions Sun Nov 1 21:42:56 2009 +0200 Sasha Khapyorsky b309b613b647d456ad6624575c586ed30870fd1a * management: update libraries version information Sun Nov 1 21:03:06 2009 +0200 Sasha Khapyorsky f851005abbd85b1d5c98b9679736976a9da696ef * opensm_release_notes-3.3: add newest features/fixes Sun Nov 1 20:38:11 2009 +0200 Sasha Khapyorsky 55774fa16b9a57301231043a139cbd8baeb4278b * opensm_release_notes-3.3: remove OFED dependency Sun Nov 1 20:05:57 2009 +0200 Sasha Khapyorsky cf7b7af5ef51ba904355afb6f25d6680a3edd8f2 * opensm_release_notes-3.3.txt: align formatting Mon Nov 2 02:09:14 2009 +0200 Sasha Khapyorsky 4db32df4d74b70c820caf20f6f58ad147632d8d8 * management: update/add Voltaire copyright Sun Nov 1 18:34:16 2009 +0200 Sasha Khapyorsky b5b70bcff4b022434dd8c13b3ef9889d98b7cde1 * opensm/osm_trap_rcv.c: Improvements in log_trap_info() Sat Oct 31 07:25:01 2009 -0500 Hal Rosenstock 1ef8a79d0745e4429e2bc94b5508a32e49b335b3 * opensm/osm_trap_rcv.c: Minor reorganization of trap_rcv_process_request Fri Oct 30 18:05:00 2009 -0500 Hal Rosenstock 007a62e9b15ce514ca3da02f9d12e774c86358b8 * opensm: Add configurable retries for transactions Sun Nov 1 11:37:04 2009 +0200 Yevgeny Kliteynik 07fb3293cbadd97ba4bf96ac376b0ca27c7ec4fb * opensm/osm_sa_mcmember_record.c: optimization in zero mgid comparison Mon Aug 10 09:13:20 2009 -0400 Hal Rosenstock 18118f2c7b915bdc95db077a5dbcf3e0a1f66903 * opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, set init failure on PKeyTable and QoS initialization failure Fri Oct 30 02:48:06 2009 +0200 Sasha Khapyorsky 37b6d5bf4508c0de765cf255c4e65764571a232d * opensm/link_mgr: verify port's lid Fri Oct 30 23:21:31 2009 +0200 Sasha Khapyorsky a77046282c9c5e7e32d99374e263d42030ff2321 * opensm/osm_mcast_tbl: fix mlid removal Thu Oct 22 09:43:00 2009 -0400 Hal Rosenstock 2d499ecaff756eec0fe9343c0d1f79e0dd775c2b * opensm/osm_vendor_ibumad: Use OSM_UMAD_MAX_AGENTS rather than UMAD_CA_MAX_AGENTS Fri Oct 30 01:28:43 2009 +0200 Sasha Khapyorsky 1bfc0155c1810206506c5edc1fd078d3b59ddbf3 * opensm/osm_mcast_tbl: fix max_mlid_ho setup Thu Oct 29 21:11:43 2009 +0200 Sasha Khapyorsky 9be521b8bc60c505ff69e6c524f6be4fd40c276d * opensm/mcast_tbl: set max_mlid_ho as actually configured mlid Thu Oct 29 21:04:00 2009 +0200 Sasha Khapyorsky edab92c5bd1a4db6157a73fe34d188d9c8025b9d * opensm/osm_mcast_tbl: remove redundant checks Thu Oct 29 20:40:15 2009 +0200 Sasha Khapyorsky aac22b697b9c9e6666f2552f1096966a203e5cdf * opensm/osm_mcast_mgr: simplify alloc_mfts() Fri Oct 23 19:48:56 2009 -0400 Hal Rosenstock c3873d7b6d044f78b70a1b507fac062dce7f5df1 * opensm: Reduce heap consumption by multicast routing tables (MFTs) Wed Oct 28 11:54:43 2009 +0200 Yevgeny Kliteynik 4899f856cb1f94dda4e82720e131e9ee318d2655 * opensm/osm_sa.c: don't ignore failure in osm_mgrp_add_port() Tue Oct 27 10:43:38 2009 -0700 Stan C. Smith 808a87715d6525cfac2ed5ce013e1f9dd2ba5ee4 * opemsm code cleanup Tue Oct 27 10:36:13 2009 -0700 Stan C. Smith 39c48e77e4a763e7c81bcb9b24ce85ad78a41efc * remove extraneous Windows include Thu Oct 22 13:20:09 2009 +0200 Sasha Khapyorsky 4e165b35c69c9cec180208112303921d4e19c446 * osmtest/osmt_multicast.c: fix strict aliasing breakage warning Fri Oct 23 23:52:23 2009 +0200 Sasha Khapyorsky 34b5d9eb09e32fd6340bbb0697c8b9254c5e31e6 * opensm: make subnet's max mlid update implementation independent Fri Oct 16 14:28:34 2009 -0400 Hal Rosenstock 2fcfcf3743999dd1e76c76fde941df44167ee909 * opensm/osm_mcast_tbl.(h c): Make max_mlid_ho be maximum MLID configured Thu Oct 22 17:33:03 2009 +0200 Yevgeny Kliteynik b899af94e9084429a1bd59ef57fabd693bbce19f * opensm/osm_ucast_updn.c: cosmetics - rename function Wed Oct 21 08:50:27 2009 -0400 Hal Rosenstock 94540f9838a8fd0ba272c3bb1bc77de8365674eb * opensm/osm_ucast_cache.c: Eliminate unneeded define Tue Oct 20 09:35:20 2009 -0400 Hal Rosenstock f329919cb981441fc5dae70fa4941752b3e0368e * opensm: Cosmetic changes Mon Oct 19 09:03:51 2009 -0400 Hal Rosenstock 7d47a1d41f840c5f9cf3917ea9ab1b0b43fc9c69 * opensm/osm_sm_state_mgr.c: Cosmetic formatting changes Mon Oct 19 09:02:11 2009 -0400 Hal Rosenstock 152efcee79f966eaeae7d9486583dda470b1c9db * opensm/osm_vendor_api.h: Fix some commentary typos Mon Oct 19 09:00:28 2009 -0400 Hal Rosenstock 0270fb0ad08a6469a9e6174b90bbdf8d72d0d7e4 * opensm: Add some additional HP vendor IDs/OUIs Fri Oct 16 11:03:05 2009 -0400 Hal Rosenstock 0ed107a81f56843483fa9e4175e1eaee855e5293 * opensm/osm_sa_mcmember_record.c: Make mcmr_rcv_create_new_mgrp static function Thu Oct 22 12:59:55 2009 +0200 Sasha Khapyorsky 348ae670f7cc9d62166cac64fdb67db0e17a610c * osmtest/osmt_multicast.c: cleanups Thu Oct 22 12:16:47 2009 +0200 Sasha Khapyorsky b41efcc3cf9778d0633b080c98e6f99c4125c5ed * osmtest/osmt_multicast: kill some duplications Fri Oct 16 15:40:36 2009 +0200 Line.Holen@Sun.COM 5f7bbced33ba69e54f724767435262aba815fa99 * osm_ucast_ftree.c missing reset of ca_ports Fri Oct 16 13:43:10 2009 +0200 Sasha Khapyorsky 098ec736eaca4ee2fc8f14933d253d134fa2a290 * opensm: fix LFT allocation size Thu Oct 15 23:50:46 2009 +0200 Sasha Khapyorsky 227226b30290abf9993554e5abeb349ee44c777f * opensm/osm_ucast_cache: reduce OSM_LOG_INFO debug printouts Thu Oct 15 16:00:29 2009 -0400 Hal Rosenstock 6b103e43f855bd03178f2176e0d3fad4e1552895 * opensm/osm_ucast_updn.c: Further reduction in cas_per_sw allocation Thu Oct 15 14:43:07 2009 -0400 Hal Rosenstock e2e12c65e2e6193f3aae9fccda7d1eb30498eb90 * opensm/osm_lid_mgr.c: Cosmetic commentary changes Wed Oct 14 17:05:53 2009 -0700 Ira Weiny 7835f7686425fc43d2230356819e4ae2737566db * opensm/opensm/osm_subnet.c: adjust buffer to ensure a '\n' is printed Wed Oct 14 16:01:24 2009 -0400 Hal Rosenstock 73b51709c3682111eaecdcabfb7dffc29fc4700f * opensm/osm_mcast_mgr.c: Cosmetic changes Wed Oct 14 15:51:50 2009 -0400 Hal Rosenstock 93f18a1cfd32b79a2e0c0c3d60d9a96750f3f9ce * opensm/osm_subnet.h: Add mgrp_mgid_tbl description Wed Oct 14 10:45:38 2009 -0400 Hal Rosenstock 2e17367f7625f9d76b7174f0c0f9b141774f8531 * opensm/osm_ucast_updn.c: Reduce temporary allocation of cas_per_sw Wed Oct 14 07:28:19 2009 -0400 Hal Rosenstock 19c639c04ac27059b05f1a32147a06a43c6df604 * opensm/release notes: Fix typo Tue Oct 13 14:59:48 2009 -0400 Hal Rosenstock 0646e8d1ad0cb5c5ac8b671838b233a6c278b0f1 * opensm/osm_mesh: Cosmetic changes Tue Oct 13 15:35:49 2009 -0400 Hal Rosenstock b806da3c20b4fd4a243f12b52ae67845d5ae513a * opensm/ib_types.h: Mask off client rereg bit in set_client_rereg Tue Oct 13 14:10:38 2009 -0400 Hal Rosenstock 4cba3b796ea89bc89e33bf54683d36d1f10b0978 * opensm: Add infrastructure support for PortInfo IsMulticastPkeyTrapSuppressionSupported Tue Oct 13 19:52:01 2009 +0200 Sasha Khapyorsky c5582e39e90e47cddec4519e5a348df22659d69c * opensm/osm_state_mgr.c: in cleanup_switch() check only relevant LFT part Tue Oct 13 09:00:03 2009 -0400 Hal Rosenstock df13ce5b3138775535c818da1da2588cb60b20c7 * opensm: Reduce heap consumption by unicast routing tables (LFTs) Tue Oct 13 00:05:53 2009 +0200 Sasha Khapyorsky 56edfe4d6087256c3e2175a8deed3541038d1a33 * osmtest/osmtest.c: remove strings.h inclusion Wed Oct 7 09:32:57 2009 -0700 Stan C. Smith 9ba167d4e49018604845d3effd3eec3fe8d91f53 * use transportable constant attributes Mon Oct 12 11:57:08 2009 -0700 Stan C. Smith d543efcbfdd81b0de04a459d17cfe4b19cf2de70 * osmtest - code cleanup Mon Oct 12 11:52:24 2009 -0700 Stan C. Smith 6cad6a3132f14fd34c0b645067ec8902d6b56ccc * osmtest -code cleanup - use strncasecmp() Mon Oct 12 23:34:01 2009 +0200 Sasha Khapyorsky 99151d403429085527b8fb442bb5e3dc92f1364e * osmtest: initialize attr_array[] on declaration Mon Oct 12 10:21:29 2009 -0700 Stan C. Smith acd46a3b0a20a9cdb0ea429c441acf0e3c1a03a1 * osmtest - fix signed unsigned comparisons Mon Oct 12 10:17:12 2009 -0700 Stan C. Smith 41e10da61a46de995f02d6ac9fdff8538937c484 * osmtest - clarify assignment operation Mon Oct 5 13:30:57 2009 -0400 Hal Rosenstock 3b8aed67149f2b38b7bd2c60af413a0d2b796b2c * opensm/osm_mcast_tbl.c: Cosmetic changes Mon Oct 5 09:36:32 2009 -0400 Hal Rosenstock 459c3a022740b0bfe8b6b7c571ecb844cf70ab94 * opensm/osm_mcast_mgr.c: In mcast_mgr_set_mft_block, fix node GUID in log message Sat Oct 3 17:58:17 2009 +0200 Sasha Khapyorsky 1c1c1880ceedbee48b9c56ac1f685790656738c3 * opensm/osm_sa_path_record.c: separate router guid resolution code Mon Oct 12 15:52:52 2009 +0200 Sasha Khapyorsky df346ecdc526a486555dcc12d1dcdcbd59ba1b99 * opensm/osm_helper.c: fix indentations Mon Oct 12 15:34:30 2009 +0200 Sasha Khapyorsky 2377c8e428593e508c8ef23cc3ce402ee1c0af32 * opensm: fix gcc-4.4.1 warnings Fri Oct 9 10:48:37 2009 -0400 Hal Rosenstock c435d87304da3e07c207dcc6a380326dbde43e20 * opensm/osm_pkey.c: Cosmetic changes Fri Oct 9 10:47:50 2009 -0400 Hal Rosenstock 917f1ed9d2d23179cf489c3052dbf525ddb93237 * opensm/osm_lid_mgr.c: Fix typo in OSM_LOG message Tue Sep 29 17:55:40 2009 -0400 Hal Rosenstock 10cf6ecf9fe30495e5a3018ed1cff008fac93e71 * opensm/osm_mesh.c: Add dump_mesh routine at OSM_LOG_DEBUG level Thu Oct 1 16:09:42 2009 -0700 Smith, Stan 3da27cfa26ee8c92fb7614380eb75f35d5dd7d24 * C++ style coding does not compile Thu Oct 1 22:13:14 2009 +0200 Sasha Khapyorsky be93c2cfda88208e78fc6300512494440b07eb3b * opensm: remove meanless 'const' keywords in APIs Sat Oct 3 03:06:39 2009 +0200 Sasha Khapyorsky fdaf0d5aecc4e45d2124d519f8c8a24d3d9b2a27 * opensm/osm_qos_parser_y.y: fix endless loop Sat Oct 3 02:19:49 2009 +0200 Sasha Khapyorsky 7733b40e13d22d99aaae6babf921b1279f94332e * opensm: fix endless looping in mcast_mgr Thu Oct 1 22:13:14 2009 +0200 Sasha Khapyorsky 067ffac2f307561b38d1ac9893f4eb5ca890e0d5 * opensm/osm_helper: remove meanless 'const' keywords Thu Oct 1 21:18:29 2009 +0200 Sasha Khapyorsky d9807d241f2488af46bfce911117b77af545aba4 * opensm: fix some obvious -Wsign-compare warnings Wed Sep 23 18:40:31 2009 +0300 Sasha Khapyorsky 1127cc33d5f2f5f30ffc005433f41c84018b0cdf * opensm/osm_get_port_by_lid(): don't bother with lmc Wed Sep 23 16:09:16 2009 +0300 Sasha Khapyorsky 7d54828e2e0ec5e3d1a6a7ea4a8e9a7c89cf0e1e * opensm/osm_get_port_by_lid(): speedup a port lookup Wed Sep 23 16:09:16 2009 +0300 Sasha Khapyorsky 2f79de17448c78cb91697de05e006af559211db2 * opensm/osm_get_port_by_lid(): use faster cl_ptr_vector_get() Thu Oct 1 18:34:11 2009 +0200 Sasha Khapyorsky e070411509d895446b15fe0fa9f14bfa28a6606d * opensm/osm_mesh.c: simplify compare_switches() function Thu Oct 1 19:13:38 2009 +0200 Sasha Khapyorsky a3f3352823f949864c4f296600d4bdb75227991e * opensm/osm_helper.c: fix compiler warning Wed Sep 30 13:34:44 2009 -0700 Stan C. Smith d962f5dfc3832f460d0fb36ab119f461c052b4df * cast to remove compiler warning. Thu Oct 1 17:50:04 2009 +0200 Sasha Khapyorsky f3cff048a69124bd286b7f40f34c3b13ef8e2a91 * opensm/osm_mesh.c: remove some castings Wed Sep 30 13:30:09 2009 -0700 Stan C. Smith c1ab20af0f82445e6b7a346938cd6a31fed4e8ba * cast to remove warnings about signed vs. unsigned comparisons Wed Sep 30 13:20:59 2009 -0700 Stan C. Smith 85549d770480287d940531d521b32d70a5234739 * osm_sa.c - void * arithmetic causes problems Tue Sep 29 09:44:16 2009 -0700 Stan C. Smith 7452e287a00bd162af8d2a2f30d1ac8fb523e7f8 * osm_helper.c use explicit value for struct init Mon Sep 28 16:50:53 2009 -0700 Stan C. Smith 4b371fbbb43b7cb68a6bac3d87d5eec1645f7978 * use standard varargs syntax in macro OSM_LOG() Mon Sep 28 15:52:41 2009 -0700 Stan C. Smith 3a9e0fb433d3c9699162047bf29eb33f5ccc31d4 * update functions to match .h prototypes Fri Sep 25 09:05:29 2009 -0700 Stan C. Smith 638dd6b945f897cd037bacd8bd9d2c50b64dc6bb * update osm_db_files.c & osm_pack.c functions to match .h prototypes Fri Sep 25 17:42:02 2009 +0300 Sasha Khapyorsky fcf2a9ef56d72614c2c35479530768de12aa97cd * opensm/osm_ucast_lash: fix use after free bug Sat Sep 19 15:34:02 2009 +0300 Sasha Khapyorsky 2fee1d78a8735a78a8cb8202ca099c929d7d6f09 * opensm: osm_get_port_by_lid() helper Sat Sep 19 14:21:34 2009 +0300 Sasha Khapyorsky e2302f8054016eab59328aeb6ad423e83cab3203 * opensm: discard multicast SA PR with wildcard DGID Sat Sep 19 12:58:58 2009 +0300 Sasha Khapyorsky 1b177141fc0d731f11ee7e7456bf7d7fda94b94b * opensm/osm_sa_path_record.c: validate multicast membership Sat Sep 19 01:13:34 2009 +0300 Sasha Khapyorsky 4d2bf5bbe6ae86dd54e08d4f7f1a16f529889505 * opensm/multicast: improve function prototypes Sat Sep 19 16:28:27 2009 +0300 Sasha Khapyorsky 067b8f62b08aab0bec1e95cf535de6c6e08b2109 * opensm/osm_prtn.c: cosmetic Mon Sep 21 09:41:51 2009 -0400 Hal Rosenstock d19a37707c78cc7f64c954881331d7a6204d14da * opensm/osm_mesh.c: Remove edges in lash matrix Tue Sep 22 18:31:13 2009 +0300 Sasha Khapyorsky a6470060c37591d77fd253b1fd40fe692ddecef7 * opensm/osm_sa_mcmember_record.c: clean uninitialized variable use Mon Sep 21 10:44:31 2009 -0400 Hal Rosenstock 56c9535ece2c59d35234e631b0c8cdfbb60f8c67 * opensm/osm_perfmgr_db.c: Fix memory leak of db nodes Mon Sep 21 09:18:25 2009 -0400 Hal Rosenstock ab6c86631b6bf9fbd23bb43369ea0889b66acd27 * osmtest: Add SA get PathRecord stress test Tue Sep 1 08:55:05 2009 -0400 Hal Rosenstock 79f54975b74ed2d537679def7a5db01d8dfd768c * opensm: Add infrastructure support for more newly allocated PortInfo CapabilityMask bits Sat Sep 19 22:36:42 2009 +0300 Sasha Khapyorsky 163202496e6d56c920ff3348f71b480b86602cd4 * opensm/osm_notice.c: move logging code to separate function Wed Sep 9 09:04:29 2009 -0400 Hal Rosenstock 779bb0effba2e086f0fadfe550c8130ad8aff3a1 * opensm/osm_inform.c: For traps 64-67, use GID from DataDetails in log message Mon Sep 14 11:42:37 2009 -0400 Hal Rosenstock 43e353ffc0d4def1bbf478e91664ebbae84bf4a1 * opensm/opensm.8.in: Indicate default rule for Default partition Fri Sep 18 20:56:50 2009 +0300 Sasha Khapyorsky 148bef3e23efc7f7c552cd2c5d06a3066184b66b * opensm/multicast: consolidate osm_mgrp_cleanup() calls Tue Sep 15 22:18:37 2009 +0300 Sasha Khapyorsky f8b18e0a3ccfa572998598382e758efd75024df9 * opensm: remove not used osm_mcm_info.[ch] files Fri Sep 18 18:15:45 2009 +0300 Sasha Khapyorsky a7fdac1947290bc0d91a1fc6933fad14d36fea68 * opensm/osm_sa_node_record.c: dump NodeInfo with debug verbosity Tue Sep 15 20:31:00 2009 +0300 Sasha Khapyorsky 4ea39cc987e801dce28d14354c5d63e0af0a7550 * opensm/multicast: merge mcm_port and mcm_info Tue Sep 8 22:24:59 2009 +0300 Sasha Khapyorsky 4894ade691564a37e798d1707c8abcf5a2205f2b * opensm/multicast: consolidate port addition/removing code Mon Sep 7 18:34:49 2009 +0300 Sasha Khapyorsky 5cfeae54cba00f20d73efea0ab556ddbcf4520b2 * opensm: port object reference in mcm ports list Thu Sep 17 20:57:36 2009 +0300 Sasha Khapyorsky ba866a71519076f97796eba52641a441aeb172b5 * opensm: fix uninitialized return value in osm_sm_mcgrp_leave() Tue Sep 15 14:35:48 2009 +0300 Sasha Khapyorsky 9723ab881b0a0dba57cc7744b893d2ffa60b7279 * opensm/osm_multicast: remove unused osm_mcast_mgr_ctxt_t Sun Sep 13 16:09:27 2009 +0300 Sasha Khapyorsky 144e31c74b1444eeab7a073a9c5366b9476ea978 * opensm/osm_prtn.c: minor improvements Tue Sep 8 22:37:28 2009 +0300 Sasha Khapyorsky 157721259ff872d19e359250a059675264f15dce * opensm/osm_multicast.[hc]: cosmetic changes Fri Sep 11 07:34:06 2009 -0400 Hal Rosenstock f70da14a067cdb40adb687b088ca97a397647c8f * opensm/opensm.8.in: Cosmetic formatting change Tue Sep 8 02:08:23 2009 +0300 Sasha Khapyorsky 444429c2c18660838394ad1fad1d5ff356971596 * opensm/osm_ucast_ftree.c: indentation fixes Wed Aug 19 20:51:15 2009 +0200 Nicolas Morey-Chaisemartin 74478064a88196ff6ca9b28901044a3557f05010 * osm_ucast_ftree.c: Applied osm_indent Wed Aug 19 20:50:23 2009 +0200 Nicolas Morey-Chaisemartin 0bfee7dcdb3566fc1903d565b3b6f81af6ae3e78 * osm_ucast_ftree.c: Cleaned up many comments Wed Aug 19 20:50:04 2009 +0200 Nicolas Morey-Chaisemartin 8a2e1df3cd0bf032b1eb4f30f2fb8fa90766cbab * osm_ucast_ftree.c: Removed reverse_hop parameters from fabric_route_upgoing_by_going_down Mon Sep 7 14:47:22 2009 +0300 Sasha Khapyorsky 3d0fdc8286127c75abec7de434d00cf4f4a02d2c * opensm/multicast: kill mc group to_be_deleted flag Mon Sep 7 05:08:15 2009 +0300 Sasha Khapyorsky 9f900fcb365ca66d92f1cbbf09b1798fb7d8fae3 * opensm/osm_sa_mcmember_record.c: cosmetic Mon Sep 7 04:59:20 2009 +0300 Sasha Khapyorsky 883f5de37f418c7835e381868b32c70d49872c3d * opensm/osm_mcast_mgr.c: almost cosmetic Fri Sep 4 12:03:44 2009 +0300 Sasha Khapyorsky f0cf5a6abea62c6950ea1e61ddc89981c0eea35b * opensm/osm_mcast_mgr.c: multicast routing by mlid - renaming Tue Mar 31 03:32:48 2009 +0300 Sasha Khapyorsky b8af033bf1ecc94986d7ece2c7811be6923b3975 * opensm/multicast: remove change id tracking Sun Dec 14 23:57:09 2008 +0200 Sasha Khapyorsky 64b91dd58982127b5a2fba5c09faab2dc5d771a4 * opensm: improve multicast re-routing requests processing Sun Sep 6 18:19:24 2009 +0300 Sasha Khapyorsky 2b4cebf9a094a105494a853eafd08e6c45148bbd * opensm: remove not used osm_mgrp_apply_func() function Fri Sep 4 12:03:44 2009 +0300 Sasha Khapyorsky b33f8654c00db6adb5c9a6d1728db7dde2f32fab * opensm: use mgrp pointer as osm_sm_mcgrp_join/leave() parameter Fri Sep 4 12:03:44 2009 +0300 Sasha Khapyorsky cecc3f94a42356af4c9b9c291055118c3537cc99 * opensm: use mgrp pointer in port mcm_info Thu Sep 3 09:00:36 2009 -0400 Hal Rosenstock f81886cd89c156c43ab3ba5119b4ac7a4fbcb4ed * opensm doc: Indicated limited (rather than partial) partition membership Tue Sep 1 10:42:30 2009 -0400 Hal Rosenstock a30bcbc18bf6c4fdd001a2728e706a86b816d16b * opensm/osm_base.h: Add new SA ClassPortInfo:CapabilityMask2 bit allocations Mon Aug 31 09:39:34 2009 -0400 Hal Rosenstock 38cf7042f889e53eefde37fc6930c151b0d19461 * opensm: Parallelize (Stripe) MFT sets across switches Sun Aug 30 08:51:50 2009 -0400 Hal Rosenstock cc348a25945064984b655d56a61328808b20887a * opensm: Add infrastructure support for MulticastFDBTop Wed Aug 26 11:54:47 2009 -0400 Hal Rosenstock de9cde064879a8a0479c08ec34426b8dd6ba6433 * opensm/ib_types.h: Add CounterSelect2 field to PortCounters attribute Thu Aug 6 14:23:15 2009 -0400 Hal Rosenstock df06fc3cc79b78d68c28651156927eb0fccaab09 * opensm/osm_ucast_lash.c: In lash_core, return status -1 for all errors Fri Aug 28 09:44:53 2009 -0400 Hal Rosenstock 2a85f1499639bb53f4b08c86acbea717f73bc936 * opensm/osm_helper.c: Add SM priority changed into trap 144 description Wed Aug 26 21:02:55 2009 +0300 Sasha Khapyorsky f38f34e04c9990e2f95ec60edc51d3cd4a15a7b7 * opensm/osm_ucast_mgr.c: move fwd tables setup function Wed Aug 26 20:56:32 2009 +0300 Sasha Khapyorsky 7c61bdffe101406b8268f34f12ce10dede195356 * opensm/osm_ucast_mgr.c: better function names Wed Aug 26 12:14:43 2009 +0300 Sasha Khapyorsky bd7317647c372c378572e5ad621562d58d7f2982 * opensm/osm_ucast_mgr: better lft setup Tue Aug 25 21:05:21 2009 +0300 Sasha Khapyorsky 832c98469b0d84974f1ea0e1f31fc61c99811c59 * opensm/osm_ucast_mgr.c: simplify fwd tables setup flow Tue Aug 25 19:20:24 2009 -0400 Hal Rosenstock 1b6f3baa20304af46e7bad5d7da0adae333a37b4 * opensm/osm_helper.c: Only change method when > rather than >= Fri Aug 7 07:08:11 2009 -0400 Hal Rosenstock 6e2efdce7196e986e6aab371f766af5e61f0fe44 * opensm: Parallelize (Stripe) LFT sets across switches Sun Aug 23 20:19:16 2009 +0300 Sasha Khapyorsky 27e0eb971905324d15f7b3b85cf19d725386b847 * complib: format comment blocks Sun Aug 23 20:13:05 2009 +0300 Sasha Khapyorsky eb032b9ede64a73189fef0c46802b4bfa451069b * complib: indentation fixes Sun Aug 23 18:01:42 2009 +0300 Sasha Khapyorsky 0844485e9f230607ae52d3d9b2aabd88827e7693 * complib/cl_event.c: change nanosec var type long Thu Aug 13 09:06:02 2009 -0700 Ira Weiny a7effc1d144c3c5dd72f424f02e9a4a2cc25db97 * opensm/complib: account for nsec overflow in timeout values Thu Aug 20 16:06:55 2009 +0300 Yevgeny Kliteynik 02b0659a40354a2cab44a44cf72081660d4bb6bb * opensm/osm_qos_policy.c: matching PR query to QoS level with pkey Thu Aug 20 16:07:16 2009 +0300 Yevgeny Kliteynik 1f9396f99f0177d1bcaad8e43ee37c2b730d88dc * opensm: fixing some data types in osm_req_get/set Fri Aug 14 10:11:32 2009 -0400 Hal Rosenstock 3106a99ff6bb1dcc197e25372a9268f66a979547 * opensm/libvendor/osm_vendor_ibumad.c: Handle umad_alloc failure in osm_vendor_get Fri Aug 14 07:58:23 2009 -0400 Hal Rosenstock 13fcaf8d8ecc5bc34dd67a03536e6f4e875c62bc * opensm/osm_helper.c: In osm_dump_dr_smp, fix endian of status Fri Aug 14 07:56:07 2009 -0400 Hal Rosenstock 64b69fa49933d17e57e922572b0c544572e729aa * opensm/osm_sm_mad_ctrl.c: Fix endian of status in error message Wed Aug 12 09:22:47 2009 -0400 Hal Rosenstock 42061d2328fd7490331fd04ce826c10ab879dd3d * opensm/osm_mcast_tbl.c: In osm_mcast_tbl_get_block, eliminate unneeded check Tue Aug 11 14:40:11 2009 -0400 Hal Rosenstock a55afc0ea0c3039fc5f575ba4405ff013a5fecad * opensm/osm_qos_policy.c: Some minor simplifications Wed Aug 5 15:03:44 2009 -0400 Hal Rosenstock 616a1c317d1a447ad2fa9bffe741a0fa646e76b6 * opensm/osm_mesh.h: Fix SFW copyright Wed Aug 5 14:48:22 2009 -0400 Hal Rosenstock c7654a359138d995320ba4fe4e548cf0d4427d53 * opensm/osm_mesh.c: Reorder switches for lash Wed Aug 5 15:19:41 2009 -0400 Hal Rosenstock 219bd237820ea68ed75d7c770f0acfef764ee7e0 * opensm/osm_trap_rcv.c: Validate trap is 144 before checking for NodeDescription changed Wed Aug 5 11:22:58 2009 -0400 Hal Rosenstock 4d163b4b2126b85562bd06cf044b359e91ca3877 * opensm/osm_ucast_lash.c: Handle calloc failure in generate_cdg_for_sp Wed Aug 5 14:20:53 2009 +0300 Yevgeny Kliteynik 6b2fc0349ac738abacd645748e39561f7920900a * opensm: fixing handling of opt.max_wire_smps Tue Aug 4 17:44:13 2009 -0400 Hal Rosenstock 15e7b015db8132a3481dc62b4177177dee48de4c * opensm/osm_lin_fwd_rcv.c: Commentary change Tue Aug 4 17:39:05 2009 -0400 Hal Rosenstock d9a36a595c2ee491cd53055ed5cd7db6e46bf55c * opensm/osm_ucast_lash.c: Directly call calloc/free rather than create/delete_cdg Tue Aug 4 11:13:37 2009 -0400 Hal Rosenstock f8634c236106438c9f23e93985b45bc375e21ef8 * opensm/osm_ucast_lash.c: Added error numbers to some error log messages Tue Aug 4 11:29:06 2009 +0300 Yevgeny Kliteynik ade94e0e889d1b114140036a9d34b85e51cdde5b * opensm/osm_helper.c: fix printing trap 258 details Mon Aug 3 16:04:29 2009 +0300 Yevgeny Kliteynik 08a759e1424e43f86a10f4603d85f88da18b7c00 * opensm: do not configure MFTs when mcast support is disabled Mon Aug 3 13:59:46 2009 -0400 Hal Rosenstock d48c68044258eb2d916f3128310ac5afdc151c08 * opensm/osm_trap_rcv.c: Use proper flag name in comment Sun Aug 2 20:14:45 2009 -0400 Hal Rosenstock 09853166ae1abd6ae88662327562472393bd468e * opensm/osm_sm_mad_ctrl.c: In sm_mad_ctrl_send_err_cb, indicate failed attribute Sun Aug 2 14:48:49 2009 -0400 Hal Rosenstock c7d1990318f2b2b4b375369c93f2bbd58a05a8ba * opensm/osm_helper.h: Fix some commentary typos Sun Aug 2 14:48:05 2009 -0400 Hal Rosenstock 38d68ab13f7010f9bff6fa1a15d2c953642f26f1 * opensm/osm_path.h: Fix osm_dr_path_extend return values comment Sun Aug 2 14:47:16 2009 -0400 Hal Rosenstock b84f9f463b060b8faed2a720a9cb8b4697548c42 * opensm/osm_ucast_lash.c: Remove osm_mesh_node_delete call from switch_delete Sun Aug 2 11:22:04 2009 -0400 Hal Rosenstock c0974c97b455046cee69225d66053cab875bc2eb * opensm/osm_path.h: In osm_dr_path_init, only copy needed part of path Sun Aug 2 11:31:33 2009 -0400 Hal Rosenstock 65d2ece76d92d0295385a656927a06e2d981d95d * opensm: osm_dr_path_extend can fail due to invalid hop count Sun Aug 2 11:16:12 2009 -0400 Hal Rosenstock 9317ecd187fc15fcdcf6098f82b0153d07ba74d9 * opensm/ib_types.h: Update ib_mad_is_response description Sun Aug 2 08:40:52 2009 -0400 Hal Rosenstock a3a715e7cd4d66648d5b099af6a64e188826d345 * opensm/osm_lash: Fix use after free problem in osm_mesh_node_delete Sat Aug 1 02:40:35 2009 +0300 Sasha Khapyorsky d0a35d53b5bb9a57054bbab6c4738c11276c008f * opensm/osm_req.c: indentation fixes Fri Jul 31 13:36:40 2009 -0400 Hal Rosenstock 9f241a87aa062c42135022a6a5b8258582cf9667 * opensm/osm_ucast_lash.c: Handle malloc failures better Tue Jul 28 18:55:10 2009 -0700 Ira Weiny 1d1e83d78305a1dd0114e02cdd11327b0c344cfa * opensm: remove extra "0x" from debug message. Mon Jul 27 16:22:59 2009 -0400 Hal Rosenstock 1f3bac4e1f00a8817ba789c58ef7c3ae1b1b8def * opensm/main.c: Display SMSL when specified Mon Jul 27 20:14:33 2009 +0300 Sasha Khapyorsky 4b25cfd7fcf6ee4be0fd4a52be72535cf7df7ecd * opensm/main.c: indentation fixes Thu Jul 23 09:05:29 2009 -0400 Hal Rosenstock d616c3c69bdeb73dd77a83d54bac4df779066108 * opensm: Add ability to configure SMSL Fri Jul 24 10:14:51 2009 -0400 Hal Rosenstock beeaaf68f4cbe9b424a68c3d52f7ec3d105c5102 * opensm/osm_ucast_lash.c: Minor cleanups Wed Jul 22 15:00:29 2009 -0400 Hal Rosenstock 99182e10aa74400f2a188217c7d95ba7048adb78 * opensm/osm_subnet.c: Format lash_start_vl consistent with other uint8 items Wed Jul 22 14:59:40 2009 -0400 Hal Rosenstock cd6ce8436f52dbdda8d7a6cf07f3a2aa3d547cc1 * opensm/main.c: Display LASH start VL when specified Tue Mar 31 03:49:17 2009 +0300 Sasha Khapyorsky 2874e4267793fc2b51a0b6c548546d86d38b2657 * opensm/osm_macst_mgr.c: merge functions Tue Mar 31 03:42:25 2009 +0300 Sasha Khapyorsky ab5ceb120ec9fed97ef36ed50c5368508d3095d2 * opensm/osm_mcst_mgr.c: check number of switches only once Mon Mar 30 18:37:07 2009 +0300 Sasha Khapyorsky 453962ade1febc40c416a54b43a520a9e21a47e7 * opensm/osm_sm.c: code consolidation Sun Dec 7 21:57:14 2008 +0200 Sasha Khapyorsky b65d390612e65a058b21a44caf8a216d32a94a18 * opensm: find MC group by MGID using fleximap Wed Jul 22 08:44:49 2009 -0400 Hal Rosenstock 14d1201e331b8798b8f7222e193364c4fc8433c9 * opensm/lash: Set minimum VL for LASH to use Mon Jul 20 11:19:00 2009 -0600 Jason Gunthorpe 6da59b4b26ba71866ca1a540463cc6bae70a9530 * Clarify the syntax of the hop_weights_file Fri Jul 3 09:34:41 2009 -0400 Hal Rosenstock fd9bc128a4c1bf2916ccb184e2ed4bdaffb5bd71 * opensm/osm_mesh.c: Improve VL utilization Wed Jul 15 13:37:17 2009 +0200 Line.Holen@Sun.COM 89dd72ed333a34bf76f2de69ec76a414be501371 * opensm/osm_ucast_ftree.c Fix assert comparing number of CAs to CN ports Mon Jul 13 16:41:13 2009 +0200 Nicolas Morey-Chaisemartin ee43c06788573719b34e6c17b8a2a32cf05ea5f7 * opensm/osm_ucast_ftree.cd: Added support for same level links Wed Jul 15 07:59:50 2009 -0400 Hal Rosenstock 74b65b55e7d720f2509e478e828f1d008575a945 * opensm/osm_qos_policy.c: Use calloc rather than malloc/memset Wed Jul 15 07:58:35 2009 -0400 Hal Rosenstock c30a45de8a7a19138692f410a994c3661c85136c * opensm/osm_qos_policy.c: Use proper size in malloc in osm_qos_policy_vlarb_scope_create Fri Jul 3 09:18:05 2009 -0400 Hal Rosenstock c4764d546626eb07c896bb3728ef8360c9c52589 * opensm/osm_ucast_ftree.c: Made error numbers unique in some log messages Mon Jun 29 14:44:57 2009 -0400 Hal Rosenstock a58a395c590d457d73d8662110db25213906ac1f * opensm/osm_switch.c: In osm_switch_prepare_path_rebuild, use realloc Tue Jul 7 16:07:52 2009 +0200 Line.Holen@Sun.COM 438f842f69008f2713bbdc4a50eed7ce7ea2928a * opensm: Add new Sun vendor ID Tue Jul 7 10:00:07 2009 -0400 Hal Rosenstock 0e09876b5d62a0a88a94c1ed4e04cb4addf7d461 * opensm/osm_mcast_tbl.c: In osm_mcast_tbl_init, use calloc Wed Jul 1 09:32:25 2009 +0200 Line.Holen@Sun.COM 9cd0fbbf7a360649c683c7b182e0638aeece345b * osm_ucast_ftree.c Count number of hops instead of calculating it Mon Jun 29 15:48:06 2009 +0200 Nicolas Morey-Chaisemartin b12ab3afc186fa798c26907fbdf02a4667a6ce29 * opensm/osm_ucast_ftree.c: Fixed issue with reverse_hops introduced by commit 1d7dd18b531c1d6370f80cc7303493d6f3e3e777. Thu Jul 2 23:23:54 2009 -0400 Hal Rosenstock 19eae83044b5a8a0d76f008f3212edfb417c983a * opensm/osm_sa_(path multipath)_record.c: Fix typo in a couple of log messages Thu Jul 2 15:48:40 2009 -0400 Hal Rosenstock 25ad2bcd5d47b123a22a4a2d3df85f572b7a780b * opensm/osm_ucast_mgr.c: Add error numbers to some error log messages Wed Jul 1 07:13:17 2009 -0400 Hal Rosenstock 9a1133bf82a2d3d9334ea1be176c54f24f424026 * opensm/osmtest: Fix some typos Mon Jun 29 13:51:28 2009 +0300 Sasha Khapyorsky d7b5e7001ffa823aabf3338105fd26abdaeac2fd * complib/Makefile.am: prevent file duplications Tue Jun 23 21:29:59 2009 +0300 Sasha Khapyorsky 94d14a43b36f193773f982460174a481c75ed982 * opensm/osm_sminfo_rcv.c: clean type of smi_rcv_process_get_sm() Mon Dec 15 01:36:30 2008 +0200 Sasha Khapyorsky 96b072928cdadfc3f7af34cca4a1e706f87f2da1 * opensm: sweep component processors return status value Thu Jun 25 08:54:08 2009 -0400 Hal Rosenstock 8f51e733012772c1c62e223a806a5db8e659c895 * opensm/man/osmtest.8: Update email address Thu Jun 25 08:53:16 2009 -0400 Hal Rosenstock c6469d495f40f19e335f8447813532371b8853a6 * opensm/libvendor/osm_vendor_(ibumad mlx)_sa.c: Handle malloc failure in __osmv_send_sa_req Thu Jun 18 09:04:32 2009 -0400 Hal Rosenstock 39ca4c03d16fc6e1891bac6a18e9c1eaf3f8e8a0 * opensm/osm_ucast_lash.c: Remove some unused code Thu Jun 18 16:45:57 2009 +0300 Sasha Khapyorsky 7e73d2208e3596803457ed926b88ef758f569248 * opensm/osm_ucast_ftree.c: indentation fixes Sat Jun 13 13:51:32 2009 +0200 Nicolas Morey-Chaisemartin 507706de02fdca65d150622ffe6db012252d4207 * opensm/osm_ucast_ftree.c: Enhanced Fat-Tree algorithm Sun Mar 15 09:42:07 2009 -0500 Dale Purdy 702f9cdc7dbaaf88253284a75c7849ea6f5fea50 * Add LMC support to DOR routing Thu Jun 18 07:31:25 2009 -0400 Hal Rosenstock ff5f0f64204c8d00383aba05de281ed5acd1bbbc * opensm/osm_ucast_lash.(h c): Replace memory allocation by array Wed Jun 17 20:37:45 2009 +0300 Sasha Khapyorsky 06cc00bfdd75c60ced08808531c4641a826a074c * opensm/osm_sa_node_record.c: simplify flows Fri May 22 07:43:46 2009 -0400 Hal Rosenstock 780efb3ada3ff746fc27da8166b0a60e3dc7bb12 * opensm/osm_ucast_lash.c: Use calloc rather than malloc/memset Fri May 22 07:42:34 2009 -0400 Hal Rosenstock 440fccfb8145d7a374e11e0a950da7fd8f207709 * opensm/osm_ucast_lash.c: Fix commentary typo Fri May 22 07:41:10 2009 -0400 Hal Rosenstock 79d8e0eb3c9a4a20f435b44111442177aaf18f7d * opensm/osm_mesh.c: Use define rather than hard coded constant Sun Jun 7 18:06:00 2009 +0300 Eli Dorfman (Voltaire) 1245517fa9283919d296cba88cd63e776e2bc636 * opensm/osm_sa_node_record.c use comp mask to match by LID or GUID Thu Jun 4 11:08:27 2009 -0700 Ira Weiny 9ee312a73af3320b8ea3cf9838f186b87e7e1b55 * Move _with_node_name_map rpm spec option from infiniband-diags to opensm. Thu Jun 4 15:30:34 2009 +0300 Eli Dorfman (Voltaire) 19e08e33fc86d48a719fa994585b39f81a0891b0 * opensm/osm_sa.c add attribute and component mask to error message Wed May 27 12:32:23 2009 +0200 Line.Holen@Sun.COM 21757e887d8d97dc1b8eec1e9dc0680e8bffefcb * osm_dump.c dump port if lft is set up Wed Jun 10 16:14:33 2009 +0200 Line.Holen@Sun.COM d8699b2e6bca409e49143ad06b70b533cbb19b58 * osm_sa_patch_record.c Remove unneeded break statement Sun May 10 11:17:11 2009 +0300 Doron Shoham 3f419701d5f521003495ce47945842b9197aab05 * osm_port.c: check if op_vls = 0 before max_op_vls comparison Tue May 12 14:32:33 2009 -0400 Hal Rosenstock 7132086d3b366e9857150da9879216867c830c69 * opensm/osm_port.c: Change log level of Invalid OP_VLS 0 message to VERBOSE Tue May 12 07:21:03 2009 -0400 Hal Rosenstock dcee32212e2fa114ab4b85c4f260ef1b3d01052d * opensm/PerfMgr: Reduce host name length Sat May 9 14:29:23 2009 +0300 Eli Dorfman (Voltaire) 7d4f8db4ba1dc0d70249f1c0e359a345105f70f8 * opensm/osm_lid_mgr.c bug in opensm LID assignment Thu May 7 10:33:46 2009 -0400 Hal Rosenstock 62aa728cd47e43186e4d5d27eea712a2f374d47c * opensm/osm_port.c: Remove error number from debug level log message Wed May 6 10:13:26 2009 -0400 Hal Rosenstock 4cab4a200c5f1de6acb3e530983428f3d12a0f54 * opensm/PerfMgr: Cosmetic changes Wed May 6 07:35:52 2009 -0400 Hal Rosenstock 9c67b4f3fb35b6221eb2b99f61d016ab859989c7 * opensm/osm_perfmgr_db.c: Remove unneeded initialization in perfmgr_db_print_by_name Tue May 5 15:25:19 2009 +0200 Line.Holen@Sun.COM 639b4cb906f2218312191d179475249c221ad09c * opensm/osm_ucast_ftree.c Increase the size of the hop table Mon May 4 16:00:18 2009 -0400 Hal Rosenstock c9393b70c92fa4dbd3381c8a1ce83a998c25c95b * opensm/PerfMgr DB: Remove leading underscores from internal names Fri May 1 17:47:24 2009 -0400 Hal Rosenstock c552ceb0c7a3eefb057fa7c4fc0df7de8f09f1b1 * opensm/PerfMgr: Remove some underbars from internal names Mon Apr 27 07:08:32 2009 -0400 Hal Rosenstock 6cedabc4c1f57a4b54f3b7668902d91691842299 * opensm: Changes to spec and make files for updated release notes Mon Apr 27 09:53:30 2009 -0400 Hal Rosenstock e5ecccd8962332609e15fc5018b4359bda2a9019 * opensm: Add SuperMicro to list of recognized vendors Mon Apr 27 14:46:40 2009 +0200 Nicolas Morey-Chaisemartin 4725ba81965e139a206272f5f454550767686604 * OpenSM: include/vendor/osm_vendor.h - Replaced #elif with no condition by #else Mon Apr 27 12:59:05 2009 +0200 Nicolas Morey-Chaisemartin 6aef81c850f23a2e5aa7ba8018f56bda9c0c6d20 * management: Fixed custom_release in SPEC files Sun Apr 26 08:30:09 2009 -0400 Hal Rosenstock 841991c49de2cd6e93082aed7e11191bafc96a6b * opensm/PerfMgr: Change redir_tbl_size to num_ports for better clarity ** Version: opensm-3.3.2 Sun Apr 26 17:05:13 2009 +0300 Sasha Khapyorsky 10f3f4502ad44b98022beded7308ce9866ad5105 * management: bump package versions Sun Apr 26 16:45:13 2009 +0300 Sasha Khapyorsky 7a9346798a3d4d3a091187aeb5e951886cd4c2b2 * opensm: Release Notes update Tue Apr 21 07:13:00 2009 -0400 Hal Rosenstock b6e83c9827ba8ed85b0b06b6698ea3d72281aef1 * opensm/doc/performance-manager-HOWTO.txt: Indicate (previously implied) master state Tue Apr 21 11:46:12 2009 -0400 Hal Rosenstock b686ef5f6f104c64df562ab6e4204c40b60b3c72 * opensm/osm_pkey_mgr.c: Fix pkey endian in log message Tue Apr 21 11:12:53 2009 -0400 Hal Rosenstock db552c7a86cdb1579aecaa948e0da11ec545a559 * opensm/include/opensm/osm_pkey.h: Fix commentary typo Tue Apr 21 10:47:36 2009 -0400 Hal Rosenstock 0ea77e20a26e04605c4b5f5100c241e35bf0c194 * opensm/man/opensm.8.in: Add mention of backing documentation for QoS policy file and performance manager Sun Apr 19 10:53:06 2009 -0400 Hal Rosenstock 1dadba17e5f319c2cb89b9c43cfae13c6b736a4b * opensm/osm_perfmgr.c: Eliminate duplicated error number Mon Apr 20 15:46:32 2009 +0300 Eli Dorfman (Voltaire) a6ea91ee02e1639176ae4b9059248fe48a981fc1 * ib_types.h: fix commit 103891092f5f6f0b2cf56555e19fdf008f164c41 Fri Apr 17 11:17:05 2009 -0400 Hal Rosenstock 942e4bb570f6ff56abc88852a6930aaa95a28431 * opensm: Some cosmetic formatting changes Fri Apr 17 11:11:39 2009 -0400 Hal Rosenstock 0e80561ce7421cc751f5246a82b3b650132a2e0c * opensm/osm_helper.c: Convert remaining helper routines for GID printing format Wed Apr 15 14:45:10 2009 -0400 Hal Rosenstock 61d38b161ea21412ecfad369b780756a06c18c82 * opensm/osm_helper.c: Add support for MaxCreditHint and LinkRoundTripLatency to osm_dump_port_info Wed Apr 15 14:44:00 2009 -0400 Hal Rosenstock 9bd928d4cc527308bb8a8433c8db9dae69adb187 * opensm/iba/ib_types.h: Add MaxCreditHint and LinkRoundTripLatency to PortInfo attribute Wed Apr 15 10:29:56 2009 -0400 Hal Rosenstock 37d67d06027a508e68c9efffe6b57a075ea0b037 * opensm: Improve some snprintf uses Tue Apr 14 14:53:19 2009 -0400 Hal Rosenstock e5df70fc847bf12ee300167dc6a8d35f672f6d43 * opensm: Add Dell to known vendor list Wed Apr 15 09:06:08 2009 -0400 Hal Rosenstock 66d075a5a09cc419400d8d0f0e261d398b5732c4 * opensm/osm_sa.c: Cosmetic change to a few log messages Tue Apr 14 21:11:36 2009 +0300 Sasha Khapyorsky 3e7a84cf774ba7291ee7a4655e8a6b03099afb1d * opensm/osm_helper.c: use single buffer in osm_dump_dr_smp() Tue Apr 14 20:39:26 2009 +0300 Sasha Khapyorsky e6850699a70e2f67695d6ffaf12bd0efe20b3ff7 * opensm/osm_helper.c: consolidate dr path printing code Tue Apr 14 19:25:50 2009 +0300 Sasha Khapyorsky 52fc5e6dc1766821e0e5b2a1b3c0b905efbc0825 * opensm/osm_helper.c: return then log is inactive Tue Apr 14 10:45:47 2009 -0400 Hal Rosenstock 9aa28b9e6b8582f7d1e662a95f7b88d8b8e62998 * opensm/osm_helper.c: Add more info for traps 144 and 256-259 in osm_dump_notice Thu Mar 26 11:39:57 2009 -0500 Hal Rosenstock de22ab75fb910150ac205cc2ed3f51b25457165d * opensm/osm_ucast_mgr.c: Cosmetic formatting change Wed Mar 25 10:22:46 2009 -0500 Hal Rosenstock 3f27a28ace108db5e1b5b54e5109d8cd3c670c6a * opensm/osm_link_mgr.c: Remove extraneous parentheses Wed Mar 25 10:21:53 2009 -0500 Hal Rosenstock 00337c96074d89b0225956851539eae971880ff4 * opensm/osm_slvl_map_rcv.c: Cosmetic formatting changes Wed Mar 25 10:21:03 2009 -0500 Hal Rosenstock 78508147ebf5f1c8686cd012991c67c07b76637f * opensm/osm_qos.c: Cosmetic formatting changes Tue Mar 24 17:16:55 2009 -0500 Hal Rosenstock d4f292b9cb9d2285ec9aa81c4fb758af847662df * opensm/osm_qos.c: Cosmetic formatting changes Tue Apr 14 10:48:17 2009 +0200 Nicolas Morey Chaisemartin 988ecd3f6b9ce8835edf4b08d45aba3ca7e47d8b * opensm/osm_ucat_ftree.c Enhance min hops counters usage Tue Mar 24 14:41:21 2009 -0500 Hal Rosenstock db79c99f8414b08958e8a4aebb752625847931a4 * opensm/include/ib_types.h: Add ib_switch_info_get_state_opt_sl2vlmapping routine Tue Apr 14 11:26:42 2009 +0300 Sasha Khapyorsky 1a753d1249812019d9aee5eb49d479d4c165dad3 * opensm: clean OSM_CDECL macro Mon Apr 13 14:30:26 2009 -0400 Hal Rosenstock b796aa3a319f35ff2b3e4d88fa2d81c24da0fef9 * opensm/partition-config.txt: Update for defmember feature Sun Apr 12 19:09:24 2009 +0300 Yevgeny Kliteynik 1ba13a4eaf72021a55434943375c402b8fec3469 * opensm/osm_ucast_ftree.c: lids are always handled in host order Sun Apr 12 18:28:38 2009 +0300 Yevgeny Kliteynik 9540628b6b5086ebcd23cc8a8229486f603f3f64 * opensm/osm_ucast_ftree.c: fixing bug in indexing Tue Apr 7 16:46:18 2009 -0700 Ira Weiny 8f481eaa99dab777b448fbf4ced48b1ff84b8c8f * Fix further bugs around console closure and clean up code. Tue Mar 24 13:44:48 2009 -0500 Hal Rosenstock 3edead95404d36d2c9e7fbc92f3616b292777637 * opensm: Remove some __ prefixes Tue Mar 24 11:15:01 2009 -0500 Hal Rosenstock a0695f2948abb7fde64e1e6a4be68587ff5fac7f * opensm/osm_sm_state_mgr.c: Remove unneeded return statement Tue Mar 24 11:14:13 2009 -0500 Hal Rosenstock 2ed4e4282426ac037636bf2a2687afbe3f7ff3a8 * opensm/osm_sminfo_rcv.c: Minor simplification Tue Mar 24 07:10:25 2009 -0500 Hal Rosenstock 4b362a60169a4266f4ca32fbbc2f6893fd982abd * opensm/iba/ib_types.h: Add PortXmit/RcvDataSL PerfMgt attributes Tue Mar 24 03:25:00 2009 +0200 Sasha Khapyorsky 20900def97aaea69c2be6aeec951472c1cd74b08 * opensm: fix indentations with osm_indent. Mon Mar 23 07:30:12 2009 -0500 Hal Rosenstock c0ec0a771c4653c36f5894967f1a4af466ce2a8c * opensm: Remove __osm_ prefixes Mon Mar 23 07:29:22 2009 -0500 Hal Rosenstock 936717553b5a32d9ea6dffe44ff07a50ec765528 * opensm: Some cosmetic changes Mon Mar 23 07:28:20 2009 -0500 Hal Rosenstock 1a4d0f0e29fd20adeb3d506d5a9f97afcef73bb0 * opensm/include/ib_types.h: Fix some typos Wed Mar 18 23:28:48 2009 +0200 Sasha Khapyorsky 8bbc46ae419348e2b16f972e71b50ba2cd331bf9 * opensm/osm_sw_info_rcv.c: consolidate flows Sat Feb 28 16:53:04 2009 +0200 Sasha Khapyorsky 6163a536bfaf9b7f19ba9be1caf408579ecbb4a4 * opensm: kill __osm_ prefixes in static functions Tue Mar 17 22:15:26 2009 +0200 Sasha Khapyorsky af075dae28a9e58a2adac8c80e9ea9e6b585546d * opensm/osm_sa_link_record.c: improve get_base_lid() Tue Mar 17 16:14:41 2009 +0200 Itai Baz 26681ba139b776475530bdfe47f5667b677f69db * ib_types.h: Adding BKEY violation trap (259) Sun Mar 15 14:22:58 2009 +0200 Sasha Khapyorsky 23ac73e957586e3bc648d2e66070fd66034597b2 * opensm: some init functions simplification Thu Mar 12 15:20:08 2009 -0500 Hal Rosenstock fb0a810c9d40b1a65b2280a75aa91022de3303c9 * opensm: Utilize ib_gid_is_notzero routine Thu Mar 12 15:19:18 2009 -0500 Hal Rosenstock 8b5921bd0ff224e1ce3caaf8a954d6570e447acc * opensm: Add common ib_gid_is_notzero routine Mon Mar 16 07:39:35 2009 -0500 Hal Rosenstock 4bf080aaac08416dd36cfe1b79a095742c59c536 * opensm/osm_req.c: Update send_trap144() log message Mon Mar 16 07:39:35 2009 -0500 Hal Rosenstock 090a3878d0b40ad96f425e133ffaff9c89d4df78 * opensm/osm_req.c: Update log message based on commit 3551389dcb7353ffd51c66e6ad518648bc1dd19e Mon Mar 16 13:17:20 2009 +0100 Line.Holen@Sun.COM 47ac864dd3d46a7f1fdb2a73a599a175d4ade5c1 * opensm/osm_link_mgr.c: indentation fixes Mon Mar 16 13:17:20 2009 +0100 Line.Holen@Sun.COM c9f89d6a345ee77c2eed7dad146db5662913edb5 * opensm/osm_link_mgr.c Remove __osm_ prefix Mon Mar 16 10:33:25 2009 +0200 Eli Dorfman (Voltaire) 5367fd481a53b8368ecc657c3ac5f3db2b828875 * opensm/osm_opensm.c: add newline to log message Sun Mar 15 11:22:17 2009 +0200 Yevgeny Kliteynik c682eb6ce2c0c455d973b3cb8d68d323531442c4 * opensm/osm_ucast_ftree.c: some refactoring Thu Mar 12 16:15:10 2009 +0200 Eli Dorfman (Voltaire) 04a68b3843902bcbf0fe07848f4c61f7902f4c45 * opensm: set IS_SM bit during opensm init Thu Mar 5 16:54:56 2009 +0200 Eli Dorfman (Voltaire) f4ca5e8fd375f65fcf593f004a51272db951102a * fix local port smlid Tue Mar 10 10:37:39 2009 +0100 Line.Holen@Sun.COM 0f479394d48ecbe8d287e0eefdf20cb0db5df43c * opensm/osm_link_mgr.c initialize SMSL Thu Mar 12 19:44:04 2009 +0200 Sasha Khapyorsky fda068daa2797645f2b83e1cfd637b562947fc21 * opensm/osm_ucast_ftree: indentation fixes Thu Mar 12 11:30:18 2009 +0200 Yevgeny Kliteynik 9327299687f42661e1f245ef9083778536751349 * opensm/osm_ucast_ftree.c: remove __osm_ftree prefix in static functions Thu Mar 5 16:43:53 2009 +0200 Eli Dorfman (Voltaire) d7865bc5d9152971f646106048e233ab13d72cda * send trap144 when local priority is higher than master priority Tue Mar 10 14:24:25 2009 -0500 Hal Rosenstock 060822a6d67e1ea270947cae168c31cdbf39ae07 * opensm/osm_trap_rcv.c: Remove extraneous comment Thu Mar 12 14:02:32 2009 +0200 Yevgeny Kliteynik c875f3beb9cdec1f7eee48f2d0e4abedc67fd053 * opensm/osm_subnet.c: fixing compiler warnings Fri Mar 6 13:20:53 2009 -0500 Hal Rosenstock f00832993058f52e7c542f15a76901434922bcd7 * libvendor/osm_vendor_mlx_dispatcher.c: Eliminate no longer needed osmv_mad_is_response Fri Mar 6 13:19:48 2009 -0500 Hal Rosenstock 9ff1ff5e41ec768193ca34fe188404d0183bbda2 * opensm: Handle trap repress on trap 144 generation Fri Mar 6 07:30:38 2009 -0500 Hal Rosenstock 4af4c60ee89444b2636c6178afa4d8b5828ffd23 * Add pkey table support to osm_get_all_port_attr Mon Mar 9 06:01:17 2009 -0500 Hal Rosenstock 0ae4f115fee131ad3938d0d277b93b790da83bac * opensm/osm_inform.c: In __osm_send_report, make sure p_report_madw valid before using Mon Mar 9 06:00:20 2009 -0500 Hal Rosenstock 2490de587450e2179ff07cda7c857f630d9edada * opensm/osm_req.c: Shouldn't reveal port's MKey on Trap method Fri Mar 6 10:25:54 2009 -0500 Hal Rosenstock 35b81e51e5e99c0569bb389c4b0a92e191731037 * opensm/PerfMgr: A few more esp0 changes Mon Mar 9 18:22:30 2009 +0200 Sasha Khapyorsky 18a8edcd702e59bac9df23af74083ef50a312c7a * opensm/osm_console_io.c: move cio_close() function Mon Mar 9 18:22:30 2009 +0200 Sasha Khapyorsky 20944afaae491fd7f5ce5a13331e06b722283149 * opensm/console: move cio_open() function Mon Mar 9 16:00:51 2009 +0200 Sasha Khapyorsky f98635eb68b782933816982a2e1649b898edadda * opensm: fix build warning with --disable-console-socket Mon Mar 9 11:30:36 2009 +0100 Nicolas Morey Chaisemartin dc0abaa899805951e5a03e649cd75c6144be31e4 * Fixed cio_close use when ENABLE_OSM_CONSOLE_SOCKET is not set Fri Feb 27 13:46:53 2009 -0500 Hal Rosenstock 47e243b87541975265b8fc53f1d4bb5a9cc5e817 * opensm/infiniband-diags: Changes for C rather than C++ style comments Fri Mar 6 13:25:25 2009 +0200 Sasha Khapyorsky eed01b4228c397e377e3a56d04c78d3934676716 * opensm/osm_console_io.c: remove 'osm_' prefix from static function names Fri Mar 6 10:28:38 2009 +0100 Nicolas Morey Chaisemartin ca68c64bc1cd42a29761da1dbb0482357e463fed * opensm/osm_console_io.h: Modify osm_console_exit so only the connection is killed, not the socket Fri Mar 6 10:17:42 2009 +0100 Nicolas Morey Chaisemartin 4292d9531a9bf01886743438a06e398e047d659a * opensm/console: Fixed osm_console poll to handle POLLHUP Wed Mar 4 10:12:28 2009 -0500 Hal Rosenstock f9e424fb512e00595b44d4e2797adac192f7533d * opensm/osm_req.c: In osm_send_trap144, set producer type according to node type Wed Mar 4 10:11:38 2009 -0500 Hal Rosenstock 74efcb0443acd42763263fcd150473afd5091183 * opensm/libvendor/osm_vendor_ibumad.c: In clear_madw, fix tid endian in message Wed Mar 4 09:58:53 2009 +0100 Nicolas Morey Chaisemartin 40437e1cb005bdcb6e2fe45e8d7b255824731aa8 * opensm/osm_switch.h : Fixed wrong comment about return value of osm_switch_set_hops Tue Mar 3 14:03:04 2009 -0500 Hal Rosenstock 7e18d9728b74790752aaf55e4baddfe21f123cab * opensm/libvendor/osm_vendor_ibumad.c: Commentary changes Tue Mar 3 16:52:28 2009 +0100 Nicolas Morey Chaisemartin e3f366d03855820330e886ea0da485edde8f9fbb * opensm/osm_ucast_ftree.c: Removed useless initialisation on switch indexes Tue Mar 3 10:25:08 2009 -0500 Hal Rosenstock 96fb22c305af551704744a76178ee3f7095dd0b4 * opensm/osm_trap_rcv.c: Cosmetic changes Mon Mar 2 16:02:29 2009 -0500 Hal Rosenstock 5c8d2b890078c3226a0f1f586c89b93937335106 * opensm/osm_state_mgr.c: Cosmetic commentary change Mon Mar 2 16:01:25 2009 -0500 Hal Rosenstock 73b4dd52ad26b5e3fcb5f060797fedfa5c6a552f * opensm/osm_port.h: Fix a commentary typo Mon Mar 2 07:03:57 2009 -0500 Hal Rosenstock f83b921a3e93b1e22570eb73521412bb259fff86 * opensm/ib_types.h: Add attribute ID for PortCountersExtended Mon Mar 2 07:03:06 2009 -0500 Hal Rosenstock 0f9164169d00ea9d7adc1d8b52fd2698b8a156fe * opensm: Return error status when cl_disp_register fails Fri Feb 27 16:18:51 2009 -0500 Hal Rosenstock ed0bd4d2969949ed49f39453fb9c964df564a1fc * opensm/osm_perfmgr.c: Improve assert in osm_pc_rcv_process Fri Feb 27 13:45:57 2009 -0500 Hal Rosenstock b3a1f6ef7d12923614aa90dccd961bec345796ff * opensm/osm_perfmgr.c: In osm_perfmgr_shutdown, add missing cl_disp_unregister Fri Mar 6 01:39:16 2009 +0200 Sasha Khapyorsky 00c94003f08719243e75d063718cb56ef2a5db38 * osmtest: remove useless prototypes Sat Feb 28 16:29:44 2009 +0200 Sasha Khapyorsky e3b00f183ad15417732f89b0ecccf9b9780952ac * opensm: remove casting of ib_smp_get_payload_ptr() Fri Feb 27 22:37:51 2009 +0200 Sasha Khapyorsky 0757f05624acaaf52a0bf7988b8cb73076e99c52 * opensm: PortInfo requests for discovered switches Fri Feb 27 21:02:07 2009 +0200 Sasha Khapyorsky e43645e4a85bb21f5bb3603f46c9f5b79cb8246e * opensm: remove unneeded anymore physp initializations Fri Feb 27 11:22:22 2009 +0200 Sasha Khapyorsky b3b68395b2846ba41d61e2255132b36587183302 * opensm: initialize all switch ports Thu Feb 26 06:40:25 2009 +0200 Sasha Khapyorsky 14c8101f7db3b766214175ea87a2589076452b57 * opensm/osm_lid_mgr: use single array for used_lids Sun Mar 1 23:24:57 2009 +0200 Sasha Khapyorsky 2b55e85d6def77f04ee0f87b62dc81ca132866de * opensm/osm_ucast_mgr.c: code simplifications Wed Feb 25 15:09:32 2009 -0600 Dale Purdy 4bdeb767b5cce5c2e970e9f64787107ae91ebf4a * opensm: Implement weighted routing Sat Feb 28 19:22:10 2009 +0200 Sasha Khapyorsky 2cd1dc194e297f750330759a5fad91a6777050b8 * opensm/osm_console.c: kill warning: defined but not used Fri Feb 27 20:39:31 2009 +0200 Sasha Khapyorsky 77bb9f7680fb5785ac8428b49bcf5b69fdb2b82f * opensm: indentation fixes Thu Feb 12 10:11:42 2009 +0100 Nicolas Morey Chaisemartin f82758a013c78dbbddc2a5e502df5956d0fec77b * Added documentation for io_guid_file and max_reverse_hop feature Thu Feb 12 10:11:38 2009 +0100 Nicolas Morey Chaisemartin d3af5aa1267e437741e0ec14f8bfcc6f1128a7e1 * opensm/osm_ucast_ftree.c: Added possible reverse hops for Ftree algorithm. Sat Feb 28 20:54:10 2009 +0200 Sasha Khapyorsky 77e48585d573e131f41fdf9fa48ba8f4ac81e399 * opensm/main.c: cosmetic Fri Feb 13 10:24:24 2009 +0100 Nicolas Morey Chaisemartin e4d904545a41cdc50ec021c667b53f2254cd0df6 * opensm: Added io_guid_file and max_reverse_hops options ** Version: opensm-3.3.1 Sat Feb 28 18:50:54 2009 +0200 Sasha Khapyorsky 8d6b3c808a6233f41e3d5a53e758de14b02fe68f * management: bump all package versions Sat Feb 28 18:48:45 2009 +0200 Sasha Khapyorsky db59b192187cfd4efca46ebbeb7d0649f0da5ac9 * opensm: OpenSM Release Notes for 3.3 Thu Feb 26 14:22:14 2009 +0200 Yevgeny Kliteynik d26c00df248cfe8abae1c02eb80131b31395a583 * opensm/osm_node_info_rcv.c: create physp for the newly discovered port of the known node Wed Feb 25 21:59:16 2009 +0200 Sasha Khapyorsky e87fc63721ce4fdc701fa578d56f2ca588ff565e * opensm/osm_lid_mgr.c: consolidate flows Tue Feb 24 20:59:43 2009 +0200 Sasha Khapyorsky ee2054519aa9bda76b823bfbdf72f113970902e7 * opensm/sweep: add log message before lid assignment Tue Feb 24 21:03:51 2009 +0200 Sasha Khapyorsky 4de6dc4496a65fd084149df8ad86ca193fc9f0ab * opensm/lid_mgr: simplify lmc_mask initialization Wed Feb 25 19:25:25 2009 +0200 Sasha Khapyorsky d4475fae9b1742c6e21ecf854b46e8cf6e31365d * opensm/lid_mgr: fix duplicated lid assignment Thu Feb 19 08:06:53 2009 -0500 Hal Rosenstock 3197a3e95a7969e70110ff6fe73ab5492a493579 * opensm/console: Enhance perfmgr print_counters for better nodenames Wed Feb 18 10:32:27 2009 -0500 Hal Rosenstock 67e12b64edac65d598af7a3edddcfa32a43fdfbe * opensm/osm_console.c: Improve perfmgr print_counters error message Thu Feb 19 13:44:15 2009 -0500 Hal Rosenstock cc899896b0cc21128b9e35f0bd4c3bce660c8882 * opensm/man/opensm.8.in: Indicate ROUTER_EXP obsoleted Wed Feb 18 10:10:15 2009 -0500 Hal Rosenstock 6d10e3acf64cb21ddcc4c95f77ef8989029e50a9 * opensm/osm_inform.c: Fix sense of zero GID compare in __match_inf_rec Sun Feb 15 09:05:00 2009 +0200 Sasha Khapyorsky ba797e690d517856e94cc00a45785068b092ae31 * opensm/Makefile.am: remove osm_build_id.h junk file generation Tue Feb 24 16:31:42 2009 +0200 Sasha Khapyorsky 50003a932835b912caf2a49b008e588b41c4131f * opensm/osm_qos.c: cosmetic: remove empty line Mon Feb 23 19:01:00 2009 +0200 Sasha Khapyorsky fa4b5d3f931670bed502abea28d76fbedf509f64 * opensm/main.c: remove enable_stack_dump() call Mon Feb 23 18:38:57 2009 +0200 Sasha Khapyorsky e75970c26ffe4d8c023cf52bb05d819d31e93baa * opensm/osm_subnet: fix crash in qos string config parameters reloading Tue Feb 17 14:57:10 2009 +0200 Sasha Khapyorsky 9623c29be8d1e0cad8e6f373a77f01ed0f881c98 * opensm: proper config file rescan Thu Feb 12 22:43:46 2009 +0200 Sasha Khapyorsky d464d2e131a29e78015f1a5a580a2aec79a59463 * opensm/osm_subnet.c: move parse and setup functions Sun Feb 15 11:23:42 2009 +0200 Sasha Khapyorsky 35308996a2d13161bac231f30e0a129d11565d15 * opensm: pre-scan command line for config file option Tue Feb 17 20:38:15 2009 +0200 Sasha Khapyorsky 91d317ca8bb62af4bac81aef732ed311eae6293f * opensm/console/dump_portguid: minor improvements Tue Feb 17 19:18:05 2009 +0200 Sasha Khapyorsky 010546cd6e1729a169bdf5983eb37c0348bc59c3 * opensm/console: dump_portguid - don't duplicate matched guids Tue Feb 17 19:13:28 2009 +0200 Sasha Khapyorsky b33baaacfe8b63fd9b168a38c2a356287038c054 * opensm/console: dump_portguid command fixes Sat Feb 14 08:55:50 2009 -0500 hnrose@comcast.net f1b7754f86835351cb87f19d2f3ee26bc0a16c51 * opensm/osm_console.c: Add missing command in help_perfmgr Sat Feb 14 08:55:04 2009 -0500 hnrose@comcast.net b075d0c3a36fff1c5dac54187d52e013fc69b421 * opensm/osm_console.c: Eliminate some extraneous parentheses Sat Feb 14 08:54:09 2009 -0500 hnrose@comcast.net 6b023f9de2b3f3f344973f93cb494ed8f376bf83 * opensm/osm_console.c: Add list of SMs to status command Sat Feb 14 08:53:08 2009 -0500 hnrose@comcast.net 94179b2759b1bae02dcf8aec70a849766cd33f49 * opensm/osm_helper.c: Add port counters to __osm_disp_msg_str Sat Feb 14 08:51:39 2009 -0500 hnrose@comcast.net 0fff93ccb764951174e8649999422d5ae8635517 * opensm/osm_ucast_mgr.c: Add error numbers for some OSM_LOG prin Fri Feb 13 11:31:02 2009 -0800 Ralph Campbell 440e24270f0a4eb9c77643f4a3e4ae7dac51ec7d * opensm: fix structure definition for trap 257-258 Thu Feb 12 17:01:22 2009 +0200 Yevgeny Kliteynik 26c456a0688690db7ccab7cae616fb13ada2a5ba * opensm/osm_state_mgr.c: small bug in scanning lid table Thu Feb 12 16:55:39 2009 +0200 Yevgeny Kliteynik da5b0e827f03e090e182471fb036a4bc1e95ae80 * opensm/osm_sa.c: fixing SA MAD dump Thu Feb 12 07:46:27 2009 +0100 Nicolas Morey Chaisemartin 70f8e86bc770cf328ddc254357045a13cc83e9e4 * opensm/osm_console.c : Added dump_portguid function to console to generate a list of port guids matching one or more regexps Wed Feb 11 02:09:10 2009 +0200 Sasha Khapyorsky c1914a050da71741ac75c4ba68bba0ee171142b6 * opensm/osm_helper.c: print port number as decimal Wed Feb 11 16:02:25 2009 +0200 Sasha Khapyorsky aaf96c7e70580747216afcbb20cff64a13be6ee4 * opensm/ftree: make unsigned sw->down_port_groups_idx Tue Feb 10 10:53:21 2009 +0100 Nicolas Morey Chaisemartin 7a7fd843f95830921eac3fc792b1d2de516c3298 * opensm/osm_ucast_ftree.c Fixed bad init value for down port index Sat Feb 7 22:54:09 2009 +0200 Sasha Khapyorsky d759edd66210de9e30da99559a167e096e3f56d3 * opensm/ftree: simplify root guids setup. Sat Feb 7 22:30:21 2009 +0200 Sasha Khapyorsky c129b209e311b3816c891bcf4464f52bdfef6e03 * opensm/ftree: cleanup ftree_sw_tbl_element_t use Tue Jun 24 23:25:03 2008 +0300 Sasha Khapyorsky e6fedcf8aaa416f9dc570f745e2d0ab59896f1eb * opensm: sort port order for routing by switch loads Sun Feb 8 16:43:47 2009 +0200 Sasha Khapyorsky 067ed0bb2bba402fbf0bacf1457d8ca8a77fd201 * opensm/qos_config: no invalid option message on default values Sat Feb 7 11:13:49 2009 +0200 Sasha Khapyorsky bc9974a8351f1f6721f865d108d780b70a6221d8 * opensm: avoid memory leaks on config parameters reloading Mon Feb 9 21:40:56 2009 +0200 Sasha Khapyorsky 09d6f1fc4671885ce61dd07e0b2f2cececa527cc * opensm/osm_ucast_ftree.c: cosmetic improvements Mon Feb 9 16:55:46 2009 +0100 Nicolas Morey Chaisemartin 16fbeca1b04e50b7e1407c36cab55e8ee4ab50e7 * opensm/osm_ucast_ftree.c: Fixed bug on index port incrementation Sat Feb 7 11:25:37 2009 +0200 Sasha Khapyorsky e9da67614a231feb3d5344568271bcca1dbc1ff3 * opensm/osm_subnet.c: break matching when config parameter already found Sat Feb 7 11:10:45 2009 +0200 Sasha Khapyorsky f19d6774e1f06e3d9700739150bef11d8854ceab * opensm/osm_subnet.c: clean_val() remove trailing quotation Thu Feb 5 21:36:20 2009 +0200 Sasha Khapyorsky 007a9a9802527d56c4df404b41183967aeedb4ac * opensm/osm_subnet.c: indentation fixes Thu Feb 5 21:06:30 2009 +0200 Sasha Khapyorsky 5d307883ed94eac8570c7a66a8f7a452597a7c9b * opensm/ib_types.h: cosmetic Tue Feb 3 16:11:46 2009 +0200 Sasha Khapyorsky 9deb852381e686385c595909db81fd070b166596 * opensm: rescan config file even in standby Thu Feb 5 16:42:23 2009 -0700 Hal Rosenstock c5a768a4f61c64089568b7f86933e6888a630d48 * opensm/PerfMgr: Add copyrights Thu Feb 5 16:41:39 2009 -0700 Hal Rosenstock 757c575b3ec2788ddfdd745c26b4fa61c96c5869 * opensm/doc/perf-manager-arch.txt: Fix some commentary typos Thu Feb 5 17:19:41 2009 +0200 Eli Dorfman (Voltaire) 647b4dc4c5feea2b76b6c4b3f1eeadc42cb02497 * opensm/osm_subnet.c fix parse functions for big endian machines Thu Feb 5 17:00:19 2009 +0200 Eli Dorfman (Voltaire) cdd3e99fb4351a001f743140a3261cc6a9bac55f * opensm/osm_subnet.c enable log_max_size opt update Thu Feb 5 02:27:02 2009 +0200 Sasha Khapyorsky 3dabcba672a1e9f6a826195c1abdc77e590f271f * opensm/osm_perfmgr.c: kill some redundant tests Wed Feb 4 15:06:06 2009 -0700 Hal Rosenstock d3b2048dc8c7e3086bafdc635af0defcc6260714 * opensm/PerfMgr: Primarily fix enhanced switch port 0 perf manager operation Thu Feb 5 02:13:15 2009 +0200 Sasha Khapyorsky eaf050cc4f2283990ef2f5dd705b96aa277a182a * opensm/osm_sw_info_rcv.c: cosmetic changes Wed Feb 4 14:26:08 2009 -0700 Hal Rosenstock ac3458136c300650afa27eb3b183cdaa8ccc545f * opensm/osm_node.h: Fix osm_node_get_num_physp description Wed Feb 4 09:15:10 2009 -0700 Hal Rosenstock 9ff29b35b215f98bc74a754ef1b83afc9ac0a576 * opensm/PerfMgr: Mainly cosmetic changes Wed Feb 4 09:14:48 2009 -0700 Hal Rosenstock c390c99b0d36fe8d1ece1d17c6042826a06dd636 * opensm/include/iba/ib_types.h: Add xmit_wait for PortCounters Wed Feb 4 19:39:11 2009 +0200 Sasha Khapyorsky ea66d7bcbcaa5e8f2d339806d3a8315134b6139c * opensm/main.c: indentation fixes in get_port_guid() Wed Feb 4 19:33:43 2009 +0200 Sasha Khapyorsky 4b3e45f4ae6e7fdb231b10361463659b366b37b7 * opensm: fix port chooser Wed Feb 4 17:39:25 2009 +0200 Sasha Khapyorsky e3b8ffddbf2525a35685821a7c4ffd76dba594e7 * opensm/osm_subnet.c: fix compile warnings Mon Feb 2 13:35:40 2009 -0500 Hal Rosenstock 8994f42cea596026ddd8dedb2d942b37c5f36dac * opensm/osm_perfmgr.c: In osm_perfmgr_init, eliminate memory leak on error Mon Feb 2 12:06:50 2009 -0700 Hal Rosenstock 731ee768e39dc77b20d862c6d8fe698251445cce * opensm/osm_perfmgr_db.h: Remove unused typedef Mon Jan 26 16:34:36 2009 +0200 Eli Dorfman (Voltaire) b7e8b4909d883b153040e8c17fa8cff0412398a1 * opensm/osm_subnet.c support subnet configuration rescan and update Mon Jan 26 16:33:26 2009 +0200 Eli Dorfman (Voltaire) 0bf7016b5b80daa951204c209e5dc26ebefe7fe9 * opensm/osm_log.c save log_max_size in subnet opt in MB Thu Jan 29 17:35:42 2009 +0200 Yevgeny Kliteynik 183f8529a4b5330e0cf750a282ed2b21010aa49f * opensm/osm_ucast_ftree.c: fix full topology dump Tue Jan 20 13:01:29 2009 +0200 Sasha Khapyorsky bddee2f475eed1d03f6f69324efdfade137b7b17 * opensm/osm_subnet.c: fix warnings in subn_free_qos_options() Sun Jan 11 22:39:52 2009 +0200 Sasha Khapyorsky 6a2d48cb93bf354adf8ac362f4ee2e172c893727 * opensm: invalidate routing cache when entering master state Tue Jan 13 18:01:19 2009 +0200 Eli Dorfman (Voltaire) 776392dd306413cb836be76e0196f51fe02fe761 * docs update documenatation about new partition keywords Tue Jan 13 18:00:17 2009 +0200 Eli Dorfman (Voltaire) 51ebd3f2d9ab3bbacf0c55d52d5bdf9cf4cee9f8 * opensm: Add new partition keyword for all hca, switches and routers Sun Jan 11 22:51:41 2009 +0200 Sasha Khapyorsky 4de079bd1667e91ae71d87cda5151ca9017ac826 * opensm/osm_subnet.c: drop some unneeded braces Sun Jan 11 22:39:52 2009 +0200 Sasha Khapyorsky 49cd60e6c02fd2db564482eeac1360542aef4ad3 * opensm: update LFTs when entering master Thu Jan 1 10:57:26 2009 +0200 Yevgeny Kliteynik 323fe46af58fec5715ecef51837b77c411f02925 * opensm/osm_port_info_rcv.c: don't clear sw->need_update if port 0 is active Sun Dec 21 13:54:02 2008 +0200 Eli Dorfman (Voltaire) 4074969cb4461d9e19ff69b335787ae2c091074a * opensm/osm_subnet.c Fix memory leak for QOS string parameters. Mon Dec 22 00:32:25 2008 +0200 Sasha Khapyorsky 5c9bf9d224b493394178b72462c7eab1ee2f09c9 * opensm: remove libibcommon build dependencies Thu Dec 25 17:14:37 2008 +0200 Sasha Khapyorsky b6219f5e4b2b9ca8d624c8217aa202f9108410d4 * opensm/opensm.spec: fix event plugin config options Mon Dec 22 05:05:46 2008 +0200 Sasha Khapyorsky 0776abe145ebeca7875ed4c9710829720c5767d9 * opensm/lash: simplify some memory allocations Mon Dec 22 05:05:46 2008 +0200 Sasha Khapyorsky fcde1c3b14723d47e0cfeef60b540f55ffa64a3e * opensm/osm_mesh: simplify mesh node links and ports allocation Mon Dec 22 04:54:48 2008 +0200 Sasha Khapyorsky 00c27383f473cf7185d3f9e1fa757e155d7c3175 * opensm/osm_mesh: make mesh_info static and const Thu Dec 18 16:48:13 2008 -0800 Ira Weiny ba3bb388f8a468650772b3e9d1f92acb96e44d69 * OpenSM: update osmeventplugin example for the new TRAP event. Sat Dec 20 21:50:01 2008 +0200 Sasha Khapyorsky 6cd48d727523a2fc2f6ffc3c5c4a7ff630961f42 * opensm/lash: fix memory leaks Mon Dec 15 15:55:50 2008 -0600 Robert Pearson 84ca9fefcdd5acd4e5f339ed9848b4334ad3c30b * mesh analysis - integrate into lash core Wed Dec 10 12:49:45 2008 -0600 Robert Pearson e3cbaf369ccebef5a9d7a625947d8c36776557b3 * mesh analysis - lash preparation Sat Dec 20 21:26:58 2008 +0200 Sasha Khapyorsky 6d8782c5b31790d0f938c425d2b1c5805c766e88 * opensm/mesh: fix memory leaks Wed Dec 10 12:44:41 2008 -0600 Robert Pearson 5887f5fa794f7be8d005abcbff3ae97c678065ce * mesh analysis - reorder links Wed Dec 10 12:40:33 2008 -0600 Robert Pearson f51baee74861a1654d5c586514a4193eb3ee75a2 * mesh analysis - induce global geometry Wed Dec 10 12:36:20 2008 -0600 Robert Pearson d31ced4c5deb0448954db5214bc9dd194a698d01 * mesh analysis - mesh info table Mon Dec 15 15:55:30 2008 -0600 Robert Pearson b41e3a08fe76cb9603b4720594f106e9de6a4212 * mesh analysis - local geometry Wed Dec 10 12:18:26 2008 -0600 Robert Pearson f9332ca40d638c0fffd39b5870627a9323674142 * mesh analysis - matrix/polynomial routines Mon Dec 15 15:29:12 2008 -0600 Robert Pearson 250cd623361320bc0d145c9b4cbd745f423ca4c2 * mesh analysis - node and link structures Wed Dec 10 12:00:21 2008 -0600 Robert Pearson 15f52ea545ab5db97190480f6a992dcb027f212b * mesh analysis - mesh_t data structure Fri Dec 19 17:30:52 2008 +0200 Sasha Khapyorsky 631ad07f1366db5603303c923b7c316b9ac1ca45 * opensm: add do_mesh_analysis configuration parameter Fri Dec 19 17:07:01 2008 +0200 Sasha Khapyorsky 3c8697856fd8008271077a880c57e029f6f1831c * opensm/man/opensm.8.in: add descrition for --do_mesh_analysis option Wed Dec 10 11:49:34 2008 -0600 Robert Pearson 76022d3329b5a3e1d1ea98b4168ea90415ac3323 * mesh analysis - skeleton Fri Dec 19 17:28:27 2008 +0200 Sasha Khapyorsky fc80293ab6c18a3d37baa32a911a3741138cb921 * opensm/osm_subnet.c: indentation fixes Tue Dec 16 09:56:44 2008 +0200 Sasha Khapyorsky c38896bde819e1aa30a3d6293ea8bdb492533199 * opensm/vendor: save some stack memory Thu Dec 18 14:03:47 2008 -0600 Mike Heinz 85bf1aeb88b6ad0e8342e744b3061a4c000cc321 * opensm/osm_vendor_*_sa: fix incompatibility with QLogic SM Wed Dec 17 17:00:54 2008 +0200 Yevgeny Kliteynik ee3953d86cf15edba3563c767e9108d0b84254dd * opensm/osm_ucast_ftree.c: fixing errors in comments Wed Dec 17 13:44:36 2008 +0100 Nicolas Morey Chaisemartin 29252ba700bae77cc151deefa3ca90f0f265fd29 * Corrected incoherency in __osm_ftree_fabric_route_to_non_cns comments Wed Dec 17 09:57:43 2008 +0200 Sasha Khapyorsky e4d7d6d44b8fbee6e1e9ac13a562fc6c38b3456e * opensm/event_plugin: link opensm with -rdynamic flag Tue Dec 16 10:44:20 2008 -0700 Hal Rosenstock 6c5191a6e626b7d452c2335eaebb368db669d00d * opensm/osm_inform.c: Eliminate compile warning Wed Dec 10 03:02:38 2008 +0200 Sasha Khapyorsky b554626457e943de29e469d4be0f00c20bfda4b1 * opensm/osm_subnet: consolidate some duplicated code Tue Dec 9 16:11:29 2008 +0200 Sasha Khapyorsky e572a441ffad8e93ad8634aa2b2e42f8eedadcdf * opensm/multicast: remove some unused parameters. Tue Dec 16 14:10:59 2008 +0200 Eli Dorfman fcde862e8c5705ced3d88d4fff70321aa794384b * opensm/osm_inform.c report IB traps to plugin Mon Dec 15 11:22:11 2008 -0700 Hal Rosenstock 77065358e4c068be727430662a8edf0b62b1f295 * opensm/libvendor/osm_vendor_sa_api.h: Fix commentary typo Sun Dec 7 15:51:13 2008 +0200 Sasha Khapyorsky 0981c61f423ff668f90ef502f5735ff19730ddf0 * opensm/osm_sa_mcmember_record: improve __cleanup_mgrp() Sun Dec 7 15:46:55 2008 +0200 Sasha Khapyorsky b2485f60a6597ccefe30c327037da7c38709b9e4 * opensm/osm_sm.c: fix MC group creation in race condition Mon Dec 15 00:42:28 2008 +0200 Sasha Khapyorsky ed9d2b7a9625445b213bde4fc109083075704c12 * opensm: remove unused header osm_pkey_mgr.h Wed Dec 10 02:27:59 2008 +0200 Sasha Khapyorsky 4560b5c56232585153213d2cb751158ee8de0e07 * opensm/osm_ucast_mgr: indentation fix Wed Dec 10 02:21:09 2008 +0200 Sasha Khapyorsky d4824ea819dd4b2e51272afa176f249c437055d8 * opensm: remove some unused variables and funcs Fri Dec 12 16:57:12 2008 -0800 Ira Weiny e5ac1e0b6b8d1d7e95aa247888a6231c06e8a046 * opensm/opensm/osm_console.c: move reporting of plugins to "status" command. ** Version: opensm-3.3.0 Sat Dec 13 19:46:15 2008 +0200 Sasha Khapyorsky a2e562802f3852e4bbab8ee00a80393b44a6a438 * management: bump all package versions ** Version: opensm-3.2.5 Sun Dec 7 00:16:36 2008 +0200 Sasha Khapyorsky 47411f0d2a132ba27840a92c741593b1a16fc5a6 * management: update package versions Sun Dec 7 00:12:59 2008 +0200 Sasha Khapyorsky 30538d838ae1c9695aa8747a28ff2babd193cad0 * opensm: Release Notes update for next version (3.2.5) Sat Dec 6 14:00:49 2008 +0200 Sasha Khapyorsky f740b7557effa5b9f8926420027901a7c1fc3cee * opensm: add RN to distributed docs list Thu Dec 4 20:40:58 2008 +0200 Sasha Khapyorsky e7b586d7998be4040dd7176a75c8fbb7dfb96e20 * opensm: fix race in main OpenSM flow. Wed Dec 3 15:47:15 2008 +0100 Nicolas Morey Chaisemartin 05a22c3efaee765a5d2cc9fb723aab538b03070d * OpenSM: Fixed GUID check against cn_guid_file usinf Ftree. Thu Dec 4 07:01:24 2008 -0700 Hal Rosenstock 22f42a98cd1179e543ab72f84daa386030a3203c * opensm/osm_lid_mgr.c: Commentary fix Thu Dec 4 18:18:32 2008 +0200 Sasha Khapyorsky 56d1d4a9cd8bd31f0595a162b15e739a4141023b * opensm: more 3.2.4 related things for RN Thu Dec 4 14:58:17 2008 +0200 Yevgeny Kliteynik c80e7482bb9361d739ef3c752fc74b3501bf7461 * opensm: release notes for OSM 3.2.4 Mon Dec 1 11:43:47 2008 -0700 Hal Rosenstock 4ce5d42aea6e3888e9415ee7977d087e81be5638 * opensm/osm_prefix_route.h: prefix and guid are in network rather than host endian order Mon Dec 1 22:48:35 2008 +0200 Sasha Khapyorsky 48d8d72c72001b115e1b7712858fc740afb3e80c * opensm/osm_sa_path_record.c: minor indentation fix Mon Nov 24 12:06:59 2008 -0700 Hal Rosenstock 447461926bdcef898f2b5a99e0bce353e2097f8e * opensm.8.in: Update email address Mon Nov 24 20:26:20 2008 +0200 Sasha Khapyorsky 2acb3cee52d2a59c82ad795ab62060eb42544780 * opensm/man/opensm.8: add some missing stuff Sun Nov 23 13:05:37 2008 +0200 Sasha Khapyorsky 2aa3c4f5eb6286b05286c3e2b33ace71a5f4ac15 * opensm/ftree: save lft_buf memory allocations Mon Nov 24 10:08:10 2008 +0200 Sasha Khapyorsky c6bbf7c22411a5bc653c3b73dbb10218f6361286 * opensm: fix possible crash when disabling babbling port Sun Nov 23 19:52:54 2008 +0200 Sasha Khapyorsky 4ea0a2bdb6beade085d65f720a6f2f2c75ac41e8 * opensm: rename switch lft_buf to new_lft Sun Nov 23 13:00:13 2008 +0200 Sasha Khapyorsky dea17e8fe89ed5544672597f0c569d4325caca0e * opensm: free lft_buf right after use Wed Nov 19 22:56:19 2008 +0200 Sasha Khapyorsky 1300e4f4c10768531cf728d8aa7a0294849d7c61 * opensm: remove osm_node_get_any_physp_ptr() function Wed Nov 19 22:56:19 2008 +0200 Sasha Khapyorsky 1d6024cabc84230d929e729ee8f1f758967fbca9 * opensm: remove osm_node_get_any_dr_part_ptr() function Wed Nov 19 22:56:19 2008 +0200 Sasha Khapyorsky db21a1a0bc9dfb96eb59d689d503abb141d0ac5b * opensm/osm_sw_info_rcv: eliminate osm_node_get_any_physp_ptr() use Sat Nov 22 13:32:29 2008 +0200 Sasha Khapyorsky 056a9af2ef9b5ef95af43f1f428456bfe1173f63 * opensm/osm_sa_link_record: prevent potential endless recursion Sat Nov 22 14:31:59 2008 +0200 Sasha Khapyorsky a6a40d04f20191863834562898c742821134e849 * opensm: remove function names in OSM_LOG() string Thu Nov 20 10:00:38 2008 +0200 Eli Dorfman daddf54023d15685d29bff1248945d99046a482e * opensm/osm_trap_rcv.c disable the port with the least hop count Thu Nov 20 10:33:19 2008 +0200 Yevgeny Kliteynik 9ff8d110c85c35e0ba23b1c5599b3a6090b523a7 * opensm/osm_state_mgr.c: bug fix in unicast cache Wed Nov 19 11:55:07 2008 -0700 Hal Rosenstock f86976d1a6fd7a2c75cda4f9a9b5426b4075da3b * opensm/osm_port_info_rcv.c: Remove SM from sm_guid_tbl when IsSM is not Wed Nov 19 11:43:14 2008 +0200 Yevgeny Kliteynik c54550360c28f5be6307cb6858551c6949e112e3 * opensm/osm_lid_mgr.c: cosmetics in log message Tue Nov 18 14:36:15 2008 +0200 Sasha Khapyorsky bce431e8ca5eb5c91825b9984607e1d526062ee3 * opensm: disable switch ports only Sun Nov 16 19:15:37 2008 +0200 Sasha Khapyorsky b7dcbfdcce3d1672fff6f5ddd6a7ee057aed3ec4 * opensm/osm_trap_rcv.c: separate port disabling code Wed Nov 19 19:45:30 2008 +0200 Sasha Khapyorsky 50541a20e1d351e414fa24ae577634500e604e7f * opensm: fix QoS config bug Tue Nov 18 12:31:28 2008 +0200 Sasha Khapyorsky 1bc50be78358e9ccb495622f8f5c943488c2aa12 * opensm/osm_subnet: don't reassign zeroed config params Tue Nov 18 12:26:43 2008 +0200 Sasha Khapyorsky 958329e2aaaeb0040489182c3dcb20ab1b7d28fa * opensm/osm_subnet.c: fix high_limit sign when printing Tue Nov 18 11:47:23 2008 +0200 Sasha Khapyorsky d6df89bfa70e3c37d4345aa3e2acea647f48de6b * opensm/osm_sa_sminfo_record: remove unused variable ** Version: opensm-3.2.4 Tue Nov 18 06:20:46 2008 +0200 Sasha Khapyorsky 3517a206b6cd732724f7d077f8394c64fc61001a * management: update versions Sun Nov 16 18:43:40 2008 +0200 Sasha Khapyorsky 5861b191566140ee08636a6e6cc4db9f503cf98f * opensm/osm_trap_rcv.c: kill some empty lines Mon Nov 17 14:58:10 2008 +0200 Yevgeny Kliteynik 67d784bb61b722d09ed258a3f0948c043b09e83d * opensm/osmtest: fixing some comments in mcast flow of osmtest Mon Nov 17 14:56:28 2008 +0200 Yevgeny Kliteynik 66add2b091274925929868ef6a14c9a55a089170 * opensm/osm_sa_mcmember_record.c: bad return state when leaving mcast Sun Nov 16 11:37:34 2008 -0700 Hal Rosenstock 6d1d2c205112ec13c923b98a1085898a476e0613 * opensm/osm_trap_rcv.c: Fix typo Fri Nov 14 14:28:48 2008 -0800 Ira Weiny 07a8768bad6b829e712c24f8ac6ece97dd6940a3 * opensm: Add check for previous versions of plugins. Mon Nov 10 13:41:04 2008 -0800 Al Chu 8c892da68b1a38ad42f793390aa588c75ee18c9d * fix qos config parsing bugs Fri Nov 14 00:22:35 2008 +0200 Yevgeny Kliteynik 8308f09496c6bfa35fb72cc98c02a95ef8441db0 * opensm/osm_lid_mgr.c: ignore and overwrite guid2lid (windows) Sun Nov 16 13:08:04 2008 +0200 Eli Dorfman 5de254a517852659daf9711a8e2f4a35e110083f * opensm/osm_sa_mcmember_record.c print multicast lid in error message Sun Nov 16 13:06:17 2008 +0200 Eli Dorfman ef86ebcda1d16ab79b24bcbe1e19596bc5baf38f * opensm/osm_mcast_tbl.c wrong max mcast lid cause the sm to set invalid MFT block. Thu Nov 13 16:23:25 2008 +0200 Yevgeny Kliteynik 760d12d5b735324428475c2ae2c069eadfbc3c68 * osmtest/osmt_multicast.c: some refinements to the multicast flow Thu Nov 13 11:18:07 2008 +0200 Eli Dorfman 140c9583668188961c24211dfc74c6e680520a6c * opensm/osm_sa_path_record.c print port guids in error message Thu Nov 13 07:36:19 2008 +0200 Sasha Khapyorsky f9829101bd58e44e1e159818752d7550485fadf4 * opensm/osm_sa_mcmember_record: simplify query code Thu Nov 13 04:02:18 2008 +0200 Sasha Khapyorsky cd14f542644f2c201bc0ab09332e75c350ec828e * opensm/osm_sa_mcmember_record: return a real port JoinState on update Thu Nov 13 02:08:58 2008 +0200 Sasha Khapyorsky 6adaa1d914d7d8c6d5cb0933f2bdb2f65999c890 * opensm/osm_subnet.c: move osm_subn_rescan_conf_files() function Thu Nov 13 01:22:57 2008 +0200 Sasha Khapyorsky d41516bdb2ba98fcf19d239c66ae6cb1e6bc47ef * opensm/osm_subnet.c: consolidate qos parameters verification code Thu Nov 13 01:20:07 2008 +0200 Sasha Khapyorsky 43e260a2755fd9ff1899746ec9ca7c6b4dc9ec44 * opensm/osm_subnet.c: use strdup() function Thu Nov 13 00:57:23 2008 +0200 Sasha Khapyorsky b304ddb2276cd145d1b5c1d05956b6a9a3e79d05 * opensm/osm_subnet.c: consolidate logging code Mon Nov 10 13:13:55 2008 -0800 Albert Chu f18f1a4036be5f224cb0d7f316f9e8ca5a41764e * support dump_conf console command Mon Nov 10 13:41:13 2008 -0800 Al Chu 7dbb294abe5f2afe5c25bc88cf16022d80519e89 * opensm: verify config inputs when config file is rescanned Tue Nov 11 07:23:34 2008 -0700 Hal Rosenstock a3823783cbf9c0eafe5f9fdf4f8e4d5124047b29 * OpenSM/osm_subnet.c: Fix log_max_size conversion to MB Tue Nov 11 14:08:22 2008 +0200 Yevgeny Kliteynik fca153c3bebe1cbde8f257c37155d7bb26740f5d * opensm/Makefile.am: install QoS_management_in_OpenSM.txt Thu Nov 6 14:57:56 2008 +0200 Or Gerlitz 46011fcc35efa315317587e361db9c5a81f9f6ac * opensm: fix iser service-id used for SL assignment Tue Nov 4 09:57:44 2008 -0800 Ira Weiny 83b664deca5238ca1d2f63b897d5b75ec1f9b4df * opensm/opensm/osm_state_mgr.c: Add check for valid physical port before using pointer. Thu Nov 6 13:59:44 2008 +0200 Doron Shoham d01d9f8a0e40d5c5ebf0c0cc1d5a6b90dbc0dc8b * export osm_log_max in MB Tue Nov 4 11:59:59 2008 +0200 Doron Shoham fe8e9908ce32178ab3bf88b83e7711ac88493bff * change log_max_size to MB Mon Nov 10 16:36:54 2008 +0200 Yevgeny Kliteynik 407593fe3b509bfcb72186d70c6cd8657df141ba * opensm/osm_multicast.c: bug with joining/leaving mcast group Mon Nov 10 09:48:55 2008 -0800 Tim Meier fab169c9592a7ee412b26ae3d1fafb7229566c57 * opensm: osm_opensm.c added a method to remove plugins Mon Nov 10 16:25:09 2008 +0200 Yevgeny Kliteynik 75161145c38ecab58156d96bd6fe4a4c6aa2be0d * opensm/ib_types.h: rename IB_MC_REC_STATE_SEND_ONLY_MEMBER Mon Nov 10 16:19:17 2008 +0200 Yevgeny Kliteynik 67d891403c5244ee75070837242365d52c800da6 * opensm/osm_pkey.c: cosmetics in some log message Thu Nov 6 11:49:31 2008 +0200 Doron Shoham d951ea5c5446d7fbed17787c9813f042e7f85ea5 * install QoS_management_in_OpenSM.txt Mon Nov 3 17:07:27 2008 +0200 Yevgeny Kliteynik 87b240afd28a99071f5eba56e8cb4cce8445cf21 * opensm/osm_sa.c: adding missing include Mon Nov 3 17:05:56 2008 +0200 Yevgeny Kliteynik e7a3e9c33fffd98bd03139badb73c6afe2286b2f * opensm/osm_ucast_cache: fixing coredump Sun Nov 2 20:02:37 2008 +0200 Sasha Khapyorsky a48bf0acfd6d13bee848875634b2c3c73452fb38 * opensm/osm_ucase_cache: simplify cached links allocation code Thu Oct 30 23:37:45 2008 +0200 Sasha Khapyorsky 878191244218e59a8b6850f7fbe47fdc3f855116 * opensm/osm_ucast_cache.[ch]: indentation fixes Thu Oct 30 23:26:55 2008 +0200 Sasha Khapyorsky 8aac1ce1d48f06a6859e1ffae4a597e8e61873ae * opensm/osm_switch.c: minor: shorter flow Thu Oct 30 18:03:20 2008 +0200 Yevgeny Kliteynik fc7f24dad3a6838e3bb871f124430041aab1cfc9 * opensm: free lft_buf if it matches switch's lft Thu Oct 30 16:05:09 2008 +0200 Yevgeny Kliteynik ad7b555ea0a4a952766649d7b2f306224337e844 * opensm/osm_ucast_ftree.c: some simplification in LFT handling Wed Oct 29 15:01:58 2008 +0200 Yevgeny Kliteynik c124e46d4e8fb75a2476418b63d4f6a3984398f5 * opensm: replace switch's fwd_tbl with simple LFT - remove obsolete files Thu Oct 30 21:46:22 2008 +0200 Sasha Khapyorsky 9e3b4371f30357f957b1bcc88630340c2f69fa6e * opensm/include/opensm/osm_switch.h: minor simplifications Wed Oct 29 15:01:48 2008 +0200 Yevgeny Kliteynik 3362436e4b722d4b20c2f725b0e5c0779619c553 * opensm: replace switch's fwd_tbl with simple LFT Sat Oct 25 22:18:00 2008 +0200 Sasha Khapyorsky 5596796913e4f980c8903195a7f6740a22a31a07 * opensm: sweep on SIGCONT Sat Oct 25 21:33:03 2008 +0200 Sasha Khapyorsky 6d13f290c82103d4f81dd0ecd9d79fba8179e406 * opensm: rename sm signal Sat Oct 25 21:03:36 2008 +0200 Sasha Khapyorsky b65c436562d5249d111d6e204819f7b5104dad81 * opensm: hide function name with OSM_LOG_MSG_BOX() macro Sat Oct 25 21:24:07 2008 +0200 Sasha Khapyorsky 7ea6ab503e6543f0981a1db58c1c5f3a6901ff1d * opensm: notify master SM with trap 144 Sat Oct 25 20:08:11 2008 +0200 Sasha Khapyorsky befc5038cdf41cd4415391df9a1b0c84f4bd934c * opensm: send trap144 to master SM when priority is raised Sat Oct 25 18:29:40 2008 +0200 Sasha Khapyorsky 30c0ce624723ed4c3b17ba4419b44c482c840ca1 * opensm: osm_send_trap144() function Sat Oct 25 16:37:50 2008 -0400 Al Chu e3ee21005b9b9df97377d34e906acd971ac7f72b * fix documentation typos Fri Oct 24 22:12:58 2008 +0200 Sasha Khapyorsky 63b4b4be18c2b47daa0d3e37224202206ea312cc * opensm: support more PortInfo:CapabilityMask bits Fri Oct 24 18:33:36 2008 +0200 Sasha Khapyorsky 6bd333daaf19131df4fb80af21bea78b644a97f8 * opensm: remove update_master_sm_base_lid field in PortInfo madw context Fri Oct 24 17:08:28 2008 -0700 Al Chu c725c6326901b6126556d7748f555466a7c99e7e * opensm: fix manpage typos Thu Oct 23 14:11:19 2008 +0200 Sasha Khapyorsky 031ae33dee418872d0674c894a931ebb3ee279a3 * opensm/opens.spec: add -D option for logrotate file install command Wed Oct 22 21:09:32 2008 +0200 Sasha Khapyorsky 110fd01218cc666e12438757c03389d76c2dd441 * opens/osm_inform.c: cosmetic changes Wed Oct 22 20:56:37 2008 +0200 Sasha Khapyorsky 28ad891fe5159426bacaff048e477981796dcbd5 * opensm/scripts: unify scripts' config Wed Oct 22 16:45:19 2008 +0200 Yevgeny Kliteynik 181ef8b8945d5306bcf5a9809d9e9122882efad1 * opensm/opensm/Makefile.am: allow 'make dist' from non-source directory Wed Oct 22 16:41:12 2008 +0200 Yevgeny Kliteynik 55c539d53c86ffe6b32937de7947175d8055945b * opensm/scripts/opensm.conf: remove obsolete config file Wed Oct 22 00:45:13 2008 +0200 Sasha Khapyorsky 9072c8637834801e46bc5af732d231663d23fff8 * opensm/osm_ucast_lash: simplify get_phys_connection() prototype Wed Oct 22 00:39:12 2008 +0200 Sasha Khapyorsky 7e3449365472738630767c6fe45b00491d64d2d8 * opensm/osm_ucast_lash: fix extra memory allocations ** Version: opensm-3.2.3 Sun Oct 19 20:53:23 2008 +0200 Sasha Khapyorsky 9e87aac2eb7dbffaff44fc6e82bbedd0cca7a97d * management/*/configure.in: bump all versions Sun Oct 19 20:48:42 2008 +0200 Sasha Khapyorsky d23a02f9d93586f4f09305fdb74bb3780336583d * opensm/release notes: add recent changes Sun Oct 19 20:32:34 2008 +0200 Sasha Khapyorsky 86b03133c81adae58f5f0fc038a692bbc997c4a2 * opensm/libopensm.ver: advance libopensm library version Wed Oct 8 12:28:44 2008 +0200 Sasha Khapyorsky 245f455765a2e329a1b21c8b31169d73b2da0d3b * management: update Voltaire copyright Sun Oct 19 19:59:08 2008 +0200 Sasha Khapyorsky ba51e8642a4aad05606b7a715fe9679715d9ad58 * opensm/osm_mcast_mgr.c: cosmetic Sun Oct 19 19:56:25 2008 +0200 Sasha Khapyorsky 56e0c1effc09c5c4ac4527fd5db784fa75f38cf4 * opensm/osm_mcast_mgr: fix memory leak Sun Oct 19 17:11:11 2008 +0200 Sasha Khapyorsky aa31e80c5e41b6d19001620f2cedda973afbaea5 * opensm/osm_sa: fix memory leak in SA responder Sun Oct 19 01:22:37 2008 +0200 Sasha Khapyorsky fb1cb54ea7ab245df48fd7a28655b4b83e371f00 * opensm/osm_sa_lft_record.c: fix block number encoding byte order Thu Oct 16 13:42:59 2008 +0200 Yevgeny Kliteynik 5e269ff3021973dafa32a4d95acc67b88a72b256 * opensm/doc/current-routing.txt: added ucast cache info Wed Oct 15 08:23:04 2008 -0600 Hal Rosenstock efb1469ec6d00890b8feca082152daa088ac046c * OpenSM release notes: Indicate InfiniScale-IV support Wed Oct 8 21:28:45 2008 +0200 Sasha Khapyorsky b8950cc5775810c3131221aa925e90f2de276315 * opensm/osm_ucast_lash.c: indentation fixes Sat Oct 18 11:09:57 2008 +0200 Sasha Khapyorsky 9e2e45c7c551b694457ff5df465dc727039e31e9 * opensm/osm_ucast_cache: trivial comment fix Thu Oct 16 00:21:20 2008 +0200 Yevgeny Kliteynik e6547897de0f2b438b5d14e649a95b16ef3bc61c * opensm/Unicast Routing Cache: manpage entry Thu Oct 16 00:19:43 2008 +0200 Yevgeny Kliteynik 4334878b379d1a19cc120711e4088d6f3febcb11 * opensm/Unicast Routing Cache: integrate cache into opensm Thu Oct 16 00:02:00 2008 +0200 Yevgeny Kliteynik 33fff8530e1499bb7dc2c02d4a35031f477f1815 * opensm/Unicast Routing Cache: compile cache files Thu Oct 16 00:00:34 2008 +0200 Yevgeny Kliteynik 8b46e11938659d4100813e7da01bbcc073a624fc * opensm/Unicast Routing Cache: add osm_ucast_cache.{c,h} files Wed Oct 15 23:35:09 2008 +0200 Yevgeny Kliteynik cd6ce9bb802e9b1e11d1b4c3369677e607fa5031 * opensm/Unicast Routing Cache: add -A / --ucast_cache option Wed Oct 15 23:34:58 2008 +0200 Yevgeny Kliteynik 14ed20a32e39212579e73e7b0c56d74eb740bbd2 * opensm/Unicast Routing Cache: move lft_buf from ucast_mgr to osm_switch Tue Oct 14 14:11:02 2008 -0600 Hal Rosenstock 4b758222d5aae44aeb0d32cf49b03132caff6348 * OpenSM release notes: Clarify OpenSM compatibility due to change in default SM/SA keys Tue Oct 14 11:30:01 2008 +0200 Sasha Khapyorsky 36d2c35c159a6e6fa62d297902cda2a781f07f93 * opensm: 3.2 release notes update Tue Oct 14 11:01:57 2008 +0200 Sasha Khapyorsky a3d633baf86d43395b0967a3840866443360d313 * opensm/osm_event_plugin.c: include config.h Sun Oct 12 01:25:40 2008 +0200 Sasha Khapyorsky 7206f39ddce5e23a8885d4b9393d8a612906a156 * opensm: Unify options listing in usage() message Sat Oct 11 19:36:24 2008 +0200 Sasha Khapyorsky a96f3f0491cda584b2c70f2bf1c3c9c0db651ea0 * opensm/vendor: replace osm_vendor_select.h by osm_config.h Wed Oct 8 12:28:44 2008 +0200 Sasha Khapyorsky f0d46840c0b90c56592372743994bc0afa5a864b * management: add Voltaire copyright Wed Oct 8 12:27:12 2008 +0200 Sasha Khapyorsky d367b4f360ce151f52e32de0f82d49948b8b2d47 * management/*/COPYING: update Voltaire copyright years Sat Oct 11 23:40:35 2008 +0200 Sasha Khapyorsky b56d4c332a3bea4f5a2570256e4cf2ed6c6739b6 * opensm: update Release Notes for OpenSM version 3.2 Sat Oct 11 13:14:38 2008 +0200 Sasha Khapyorsky a9a1c98d061eac556a22314e56a4fcf85636399b * opensm/osm_config.h: generated OSM_DEBUG macro Sat Oct 11 13:09:35 2008 +0200 Sasha Khapyorsky b3491b9cfa8daf0144b8fad8ac49f30053c15220 * opensm/opensm/Makefile.am: merge CFLAGS Fri Oct 10 22:51:41 2008 +0200 Sasha Khapyorsky 3103aeb82f0e8ffd570265a851ea8e77018217e2 * opensm/vendor: remove osm_pkt_randomizer from ibumad vendor build Fri Oct 10 11:25:37 2008 +0200 Sasha Khapyorsky a34c2fdddfc3b29d7dc51a7a74984fe6df7feb81 * opensm/config/osmvsel.m4: fix indentations Thu Oct 9 14:59:44 2008 -0700 Ira Weiny 50d61031ffee8aead089d08778f210a0e81b24ce * opensm: Add osm_config.h file Fri Oct 10 10:10:39 2008 +0200 Sasha Khapyorsky dd05344bacf539ca077b01333c49256e7f38fa1b * opensm: fix broken IPv6 SNM consolidation code Thu Oct 9 21:09:09 2008 +0200 Sasha Khapyorsky fed2316598460d122a24370c8aca9f9e8d5b4798 * opensm/osm_ucast_lash.c: minor code optimization Wed Oct 8 01:19:05 2008 +0200 Sasha Khapyorsky 1ba9acd4ff365bec39c6e39c84d067fd721965c1 * opensm/osm_ucast_lash: fix buffer overflow Tue Oct 7 11:09:45 2008 +0200 Sasha Khapyorsky 17ce519ec56b97f2e20ed145ac45d71ca188f9e7 * opensm/main.c: trivial usage message formatting fix Fri Oct 3 14:07:13 2008 -0600 Hal Rosenstock 313de09ce16bf17864ecc05486b8b0ce8fb9a153 * OpenSM: Display port number in decimal in log messages Fri Oct 3 12:54:42 2008 -0600 Hal Rosenstock cd404357c5269f83100b3672bbc928cd49af2aab * OpenSM: Display port number in decimal in log messages Mon Sep 29 15:51:25 2008 +0300 Sasha Khapyorsky 282b65c316e5646c53ee10f78f2eb853ef48a47c * opensm/osm_ucast_mgr: remove any_change tracking Mon Sep 29 15:41:53 2008 +0300 Sasha Khapyorsky 7ca99dacc8fb2a36ef5d816b76daa49a4082840e * opensm/osm_ucast_updn: cosmetic Sun Sep 21 19:38:23 2008 +0300 Albert Chu f05fa4cbd6e8adc9d5cd067cefa827e31e0d3c25 * opensm: routing chaining Wed Oct 1 04:00:34 2008 +0300 Sasha Khapyorsky 47b931d34f79d126a3a22a964fd3535510306535 * opensm/osm_sa_mcmember_record.c: cosmetic - remove empty line Tue Sep 30 07:08:25 2008 -0600 Hal Rosenstock c19e5cb7f7c6d5d253bc4924a5e43caea537018a * OpenSM: More man and doc changes for opensm.conf Fri Sep 26 22:35:39 2008 +0300 Sasha Khapyorsky 92d3ae09a8184988e72fb6d7ba74bba355f6a64d * opensm/man: remove any opensm.opts mentions from opensm man page Sat Sep 20 13:10:22 2008 +0300 Sasha Khapyorsky 46d374596a5d3798cbf1c0791a73ff2efd773ac8 * opensm/osm_log.c: provide useful error message when file opening fails Sat Sep 20 12:55:52 2008 +0300 Sasha Khapyorsky d42f6c5844b4f9ce625069fbb2562f3ff14876ab * opensm/osm_opensm.c: cosmetic formatting Wed Sep 17 21:52:47 2008 +0300 Sasha Khapyorsky d3d938d18cc9b4c43885375222937691e6f7d7b0 * opensm: consolidate mgrp_send_notice calls Mon Sep 15 14:00:51 2008 +0300 Sasha Khapyorsky 4d6e504bd0a4f90af21a3fa7d068451869cf3c06 * opensm: multicast group create/delete notification fix Fri Sep 5 18:19:43 2008 +0300 Sasha Khapyorsky 3941653cc473947fb52bbcdb850d3f8ade54d47c * opensm/osm_sa_mcmember_record.c: cleanup code, simplify flows Fri Sep 5 17:34:19 2008 +0300 Sasha Khapyorsky c8b1cdc5d0b850277dff0f17a3068b868b4693d5 * opensm: simplify osm_get_mgrp_by_mgid() search function Fri Sep 5 19:32:22 2008 +0300 Sasha Khapyorsky 6739e532dda64043f192fd8f77b9904a3e8d1ff9 * opensm/osm_multicast.[ch]: simplify flows, remove unused functions Fri Sep 5 17:30:59 2008 +0300 Sasha Khapyorsky 62b1a5d48e4d8fd89bc4fce61eff840bb0114037 * opensm/osm_sm.c: cosmetic Fri Sep 5 17:28:01 2008 +0300 Sasha Khapyorsky 2309f3a64f8188524d630279d2fc479c44ceb621 * opensm/osm_mcm_port.c: remove osm_mcm_port_init() Sat Sep 13 21:21:34 2008 +0300 Sasha Khapyorsky 1b9ae223c6ce6c6b22b5bcb134d9c0972d85c01c * opensm/opensm.spec.in: don't install old format conf file Sat Sep 13 21:19:02 2008 +0300 Sasha Khapyorsky 478e7735f77b5e92795e1b2d28044ac31d126ae7 * opensm/redhat-opensm.init.in: make config file optional Sat Sep 13 00:10:43 2008 -0700 Sasha Khapyorsky 337fb58affec85769d63670484289abf4001fd37 * opensm: do not start opensm on boot automatically Sat Sep 13 00:10:43 2008 -0700 Albert Chu b9ab56b896aa0c9fb3f6ebd5162d2f8bec746cff * opensm/opensm.init: do not specify run levels on SuSE Fri Sep 12 09:59:50 2008 -0700 Al Chu 9d8836bf9dccaf17f6cb76fdf5aa8f4b3a932214 * opensm: fix routing algorithm description Thu Sep 11 21:28:25 2008 +0300 Sasha Khapyorsky e68e54182d2bf4846b7a6d7c780139d0dc41c42e * opensm: fix in usage message Wed Sep 10 07:19:20 2008 -0600 Hal Rosenstock c10c52283529a0d0961a9f178e26e43496b70507 * osm_(helper trap_rcv).c: Change output format of notice type to unsigned decimal Tue Sep 9 13:46:44 2008 -0700 Al Chu 3c8179da5683ab6f9ca26dc72fac816b33b252c1 * opensm: remove old comment Tue Sep 9 10:01:43 2008 -0700 Al Chu efb95f912b1b3b39e036cd15e85e69890cec7856 * opensm: fix comment typo Wed Sep 3 11:21:22 2008 -0700 Al Chu 02e1c949e8cf18944b9ddeb57c741159c39d940a * opensm/console: close console socket on cleanup path Fri Sep 5 04:14:03 2008 +0300 Sasha Khapyorsky 33180695647818bcd39504c509601a23e5ab0a0b * opensm: fix strict-aliasing rules warnings Thu Sep 4 10:00:58 2008 -0700 Al Chu 7af67fa626af25deff0b466f72c9f079a33354ac * opensm: fix segfault corner case when osm_console_init fails Tue Sep 2 19:18:19 2008 +0300 Sasha Khapyorsky 8a22af3bf6a75ede3f8cacf32bcf561d2717bd24 * opensm/*/Makefile.am: remove -Wno-deprecated-declarations C flags Tue Sep 2 19:08:14 2008 +0300 Sasha Khapyorsky d2ffd562759d67992aecfed9477960c1c07521a2 * opensm/Makefile.am: remove -fno-strict-aliasing flag from *CFLAGS Tue Sep 2 18:55:59 2008 +0300 Sasha Khapyorsky 2a60f1fcd3f1954c52c1ea912dcd03a35eefedd8 * opensm/config: remove unused variables Tue Sep 2 17:57:50 2008 +0300 Sasha Khapyorsky 7ddec2e27092f1a740b1801c782419401ab2f2d9 * opensm: opensm_release_notes-3.2.txt template Mon Aug 25 10:16:38 2008 -0700 Ira Weiny f81f7636ef9b1ceace78475792dd84a87532839f * opensm: move vendor specific compilation flags to config.h Mon Sep 1 18:03:28 2008 +0300 Yevgeny Kliteynik 5b7305e772d0a7b37e10b5f295322446c4f134c9 * opensm/Makefile.am: adding yacc-generated .h file as dependency Thu Aug 28 15:10:35 2008 -0700 Tim Meier c9a13a83940a4fdecbf5fcbac35e16ed829dced6 * opensm: osm_opensm.c - changed load_plugins() arg to const Thu Aug 21 17:29:54 2008 +0300 Yevgeny Kliteynik a36ecbfc2c5e25e123a5a70fa7486158eac44f40 * opensm/osm_qos_policy.c: log matched qos criteria Sun Aug 31 15:57:36 2008 +0300 Sasha Khapyorsky 025b1b7c9d1b38e501ec2bc5f5c531fd31a38456 * opensm/osm_qos_policy.c: cosmetic simplification Thu Aug 21 17:25:15 2008 +0300 Yevgeny Kliteynik bd302214877c2b3086beae0f43e6eeeabd94c78f * opensm/osm_qos_policy.c: removing some log messages Wed Aug 20 17:58:42 2008 +0300 Yevgeny Kliteynik ce4a49f2d92fa1f09c1a85f205caf1b6c444ed42 * opensm/osm_state_mgr.c: fixing some typos Mon Aug 18 14:43:06 2008 -0700 Ira Weiny c3a6b874ba76340def43800990ab891a7e632d0d * opensm: Add a Node Description check on light sweep. Mon Aug 18 02:11:11 2008 +0300 Sasha Khapyorsky 7c4ea06b00a6a06e010a254e2f246aed33d0164a * opensm: remove USEGPPLINK hack Mon Aug 18 02:09:41 2008 +0300 Sasha Khapyorsky 61fc0d803e53b87e0c7e8eac2a0f898199093c38 * opensm/config/osmvsel.m4: remove unused osmv_save_ldflags variable Mon Aug 18 02:06:31 2008 +0300 Sasha Khapyorsky 07b5b4b5b4e2752a33e3c255f0abe1217c1a7cbf * opensm/osm_version.h.in: remove 'extern "C"' braces Mon Aug 18 22:48:48 2008 +0300 Hal Rosenstock 4a6744b765c02f1529cadb35fc7512b293f49513 * osmtest/osmtest.8: Fix log_file option description in man page Sun Aug 17 18:12:18 2008 +0300 Yevgeny Kliteynik d4906128449dc3f321f2f9cb654d82827b37c14d * opensm/libvendor/osm_vendor_mlx_sa.c: handling attribute offset of 0 Wed Aug 13 17:35:04 2008 +0300 Yevgeny Kliteynik f3a7f9922c589b3ada0b766ed486e8caafbe68ac * opensm/osm_ucast_mgr.c: cleaning port_order_list Thu Aug 7 21:00:21 2008 +0300 Sasha Khapyorsky f9df155bedb4b215ae277b03a348528b44a3e035 * opensm/osm_sa_informinfo.c: consolidate flows Thu Aug 7 20:50:01 2008 +0300 Sasha Khapyorsky c8e6ff60449a7afdcb2ecc60d48e5fc59bdbd005 * osm_vendor_ibumad_sa: in a log print mad_status in host byte order Thu Aug 7 20:39:30 2008 +0300 Sasha Khapyorsky 263f63a222258c3fd8f21fe8faf1f850ebda16b3 * osmtest: fix qpn encoding in osmtest_informinfo_request() Thu Jul 31 10:43:38 2008 +0300 Sasha Khapyorsky 2376844a65c24dbaed1ec81235fa2d0d2db46c87 * opensm: query remote SMs during light sweep Wed Aug 6 22:31:16 2008 +0300 Sasha Khapyorsky c55f1d7e4cfdb5e4a5c7c840f1fcf6d3082e6c97 * opensm: redo lex and yacc files generation Mon Jun 16 03:27:40 2008 +0300 Sasha Khapyorsky b34e991b4656bdc84bb2e795c4b62817b8ab09ad * opensm: add OSM_EVENT_ID_SUBNET_UP event Wed Aug 6 16:15:28 2008 +0300 Yevgeny Kliteynik 55de8dc780c6f2aad06fa417c9a31ea0256e1c26 * opensm/Makefile.am: add dependency rule Tue Aug 5 18:41:41 2008 +0300 Yevgeny Kliteynik a5c7134500108ad737b090c7688b667fc85fcc6c * opensm/Makefile.am: Fix dependency for 'make -j2' Mon Aug 4 17:38:08 2008 +0300 Sasha Khapyorsky a007f6ab4accc49876aa9e6f73a1aab4e4b22813 * opensm/osm_sm.h: fix comment Mon Aug 4 17:37:03 2008 +0300 Sasha Khapyorsky 89cb495607894625fd9223a9b18527fae54b4999 * opensm: remove osm_sweep_fail_ctrl.[ch] files Mon Aug 4 17:33:32 2008 +0300 Sasha Khapyorsky bb46072037f5df7b2f3e9d8488f7edbcba03c0a1 * opensm: cleanup osm_sweep_fail_ctrl Mon Aug 4 17:34:58 2008 +0300 Yevgeny Kliteynik 5451749fddbb6c7a1625def438ec4496462cb3ed * opensm/Makefile.am: fixing compilation error with osm_version.h Thu Jul 31 20:57:43 2008 +0300 Sasha Khapyorsky a635bd9d3aefdcd79de2005c0cef0364088d148f * opensm/osm_ucast_lash.c: A couple more conversions to (unsigned) decimal lid format Mon Aug 4 11:45:38 2008 +0300 Yevgeny Kliteynik 10b8a31f95880c8006ee5ed42fb4a0f43975c1eb * opensm/osm_qos_parser.l: add 'noinput' lexer option to remove compiler warning Mon Aug 4 10:46:37 2008 +0300 Sasha Khapyorsky de07e8f4d251c38ef42a2fd4adc2e865e47bdc0d * osmtest/osmt_service.c: fix over bound array access Mon Aug 4 10:46:37 2008 +0300 Sasha Khapyorsky e1a3a1634f6b10f4f591ff63f69adbbed0b97361 * opensm/osm_sa_class_port_info.c: fix over bound array access Mon Aug 4 10:38:42 2008 +0300 Sasha Khapyorsky beb5d02c0e31adc3b1503b155ee46584edf53c1d * opensm/osm_mtree.c: mask unused static function __osm_mtree_dump() Thu Jul 31 10:39:52 2008 +0300 Sasha Khapyorsky 2eef15af2c523f699bc9d349e7d18b519ee5b419 * opensm/osm_sminfo_rcv.c: improve locking Sun Jun 15 11:49:17 2008 +0300 Sasha Khapyorsky a588e513a98dff20ec8d785c1a428d52c9cabaca * opensm/event_plugin: plugin API version 2 Wed Jul 30 04:00:40 2008 +0300 Sasha Khapyorsky 0f64ff244d1f3bc3b5ea0c54cf088dd183f69949 * opensm: install all OpenSM header files Wed Jul 30 03:14:43 2008 +0300 Sasha Khapyorsky 1a36885eaf039eeeea56b3169eb53914754dc56e * opensm/include/Makefile.am: don't duplicate header files in EXTRA_DIST Wed Jul 30 16:08:44 2008 +0300 Sasha Khapyorsky 7ed529416a49adcbadce179b02ee5812a27e2bca * opensm/osm_sminfo_rcv.c: cosmetic Wed Jul 30 15:30:09 2008 +0300 Sasha Khapyorsky f70fdf2121836f086659cab6b18f8aefbc9b183b * opensm/osm_state_mgr: trivial changes Wed Jul 30 15:18:32 2008 +0300 Sasha Khapyorsky 55c8ad92c32412becbdef830d0c58ca95f2bb12f * opensm/osm_state_mgr: fix ERR code in __osm_state_mgr_light_sweep_start() Wed Jul 30 03:21:27 2008 +0300 Sasha Khapyorsky 417ac5b0754a6f04dfd56df7c1007ed86a41da1e * opensm/*/Makefile.am: sort header file list by name Wed Jul 30 02:21:23 2008 +0300 Hal Rosenstock 9d91feed0a81a220afae9a9975eece097de6d705 * OpenSM: More conversion to (unsiged) decimal lid format Wed Jul 30 02:17:06 2008 +0300 Sasha Khapyorsky 101e38593f754219c97dcc7b9795a3262b23c2d6 * opensm/osm_helper: remove some empty lines Wed Jul 30 02:12:10 2008 +0300 Hal Rosenstock 8d0928ef9e3df292725f9886d6ba8d9a27f24a98 * opensm/osm_helper.c: Change lids_per_port to decimal Wed Jul 30 02:07:36 2008 +0300 Hal Rosenstock ca3a2bc3f78cbb901a2eff8e02d12667649978a5 * opensm/include/opensm/osm_subnet.h: Update some comments Tue Jul 29 10:48:21 2008 -0700 Al Chu c1b35fe853b01411ccb3d99266f655c320e4ebda * opensm: fix instruction typo in config file Tue Jul 29 10:47:13 2008 -0700 Al Chu f7ff0228b5fba1d57372c23ffa089d3ffc52ca73 * opensm: rename ucast_file and ucast_dump_file to lfts_file Sat Jun 21 18:01:46 2008 +0300 Sasha Khapyorsky 4d90267e42df0f36dcba2f55cee924cfd060749f * opensm: add osm_version field to osm_opensm_t object Mon Jul 28 15:54:59 2008 -0400 Hal Rosenstock 186177be1cb58584cdce57cccb2ea9d712d3a337 * opensm/osm_lid_mgr.c: Cosmetic format change Mon Jul 28 09:54:16 2008 -0400 Hal Rosenstock fe3f6ac345cea4265aaa5663cb3d02dd3593690a * opensm/osm_lid_mgr.c: Convert lid range prints to decimal Mon Jul 28 09:54:07 2008 -0400 Hal Rosenstock 1b4f2e6a907fa95c5d442f4b4a2a326ca5814d67 * complib/cl_event_wheel.c: Fix some printf typos Mon Jul 28 19:38:12 2008 +0300 Sasha Khapyorsky f806574c497838481c839c4f6da8e95782d321a7 * opensm: simplify flow in __osm_state_mgr_light_sweep_start() Tue Jul 15 14:15:53 2008 +0300 Sasha Khapyorsky b4bd8e1b426f4a8fb41d3374150142fe2d722050 * opensm/libvendor: convert osm_log() to OSM_LOG() macro Tue Jul 15 14:15:53 2008 +0300 Sasha Khapyorsky 3133de86834328b800f5aa8cac277b82e4d6d660 * opensm/osmtest: convert osm_log() to OSM_LOG() macro Sun Jul 13 12:18:11 2008 +0300 Sasha Khapyorsky 038edff11935b4a288a6b6bb4d5599904bd1ce25 * opensm: remove osm_log_is_active() check Mon Jun 30 08:01:53 2008 +0300 Sasha Khapyorsky afd980fc04bb45545dcaf3d3b8ada8b4069cfb24 * opensm/OSM_LOG(): wrap osm_log call with log level check Sun Jul 27 21:39:29 2008 +0300 Sasha Khapyorsky dd8b38394aea0c1fc6fbfd9e30c3b88047dcef5a * opensm/*/Makefile.am: remove explicit -lpthread and -ldl flags from Makefile.am Sun Jul 27 15:55:51 2008 +0300 Doug Ledford 7fa10a08642684e6c64b2d0a5bda5c61e7a3f19a * opensm: remove -rpath from LDFLAGS Sun Jul 27 07:43:07 2008 -0400 Hal Rosenstock a08c24572c12c90ebe3e1aead904a44d13c97df6 * opensm/osm_inform.c: Fix compile warning Sat Jul 26 20:05:22 2008 +0300 Keshetti Mahesh 19887d3b3a32b11d09637194e5c14bf9b8a70aa4 * opensm/osm_ucast_lash: find_port_from_lid() function is not used Sun Jul 27 09:52:21 2008 +0300 Sasha Khapyorsky 6b29a015feb01bd2f7c62171f638e14f624f3554 * opensm/osm_ucast_updn: move and rename __osm_updn_find_root_nodes_by_min_hop() Sun Jul 27 09:47:58 2008 +0300 Sasha Khapyorsky 9988c48e08f763aad65f9e9a95c033eed0afd288 * opensm/osm_ucast_updn: remove some debug logging Sat Jul 26 19:55:09 2008 +0300 Sasha Khapyorsky a7687e763f2e0701e52021d7fa1fc175ea4eaefb * opensm/osm_ucast_lash: remove an invalid error log Sat Jul 26 19:32:39 2008 +0300 Keshetti Mahesh 061046c10ff4dba208eda51ad98b8958a9d51bb3 * opensm/osm_ucast_lash.c: remove unused variables Sat Jul 26 21:44:39 2008 +0300 Sasha Khapyorsky f44c8e177325a23d4b84725acfaf894ba9138e9d * opensm/osm_sa_mcmember_record: fix uninitilized variable use Sat Jul 26 18:40:44 2008 +0300 Sasha Khapyorsky b5f2f37faeb5889aafa25b0b305944e3595a4fc2 * opensm/configure.in: don't touch CFLAGS directly Thu Jul 24 10:11:13 2008 -0700 Ira Weiny ededbebbbc90d85b524eb437ca4281ac482dfe7b * opensm: Add ib_trap_str function Wed Jul 9 04:27:28 2008 +0300 Sasha Khapyorsky 7564b226d529e0a13d2d80d06ca8c0b2e3c93d14 * opensm/osm_helper.c: trivial simplifications Mon Jun 30 04:51:26 2008 +0300 Sasha Khapyorsky eaa765437573b4ce25738522fc956a98c33fef05 * opensm/osm_log: osl_log() speedup Mon Jun 30 04:46:07 2008 +0300 Sasha Khapyorsky 89cbb9f5db90cb6882bceb83d269fd731ff9f90b * opensm/osm_log: reverse log level check flow Wed Jul 9 01:11:51 2008 +0300 Doug Ledford 6c5b135ae5efeabeae5278b7b268142b82634bf2 * opensm/*/Makefile.am: remove install-exec-hook Thu Jul 24 12:54:10 2008 -0400 Hal Rosenstock a46a4d1053c41b97ffb4af4f1345b538230f8b6c * opensm/osm_qos_parser.y: Eliminate bison warning Thu Jul 24 12:54:02 2008 -0400 Hal Rosenstock 02afd38a4e25a6c9b5c89a64b97240aba234150d * opensm/osm_console_io.c: Eliminate compile warnings Thu Jul 24 19:41:54 2008 +0300 Sasha Khapyorsky f496bb2258903ec21d4ef5682f90eee83c2caa91 * opensm: minor: move GID print buffer definitions under nearest condition Thu Jul 10 17:44:10 2008 -0700 Ira Weiny 88d412ba22fa2f7797288e318fa1fcae59d6da81 * OpenSM: convert GID prints to use inet_ntop Thu Jul 10 06:17:24 2008 -0700 Hal Rosenstock 97a5666560be128ecdb69b888cecc6010300bc62 * opensm/osm_rand_fwd_tbl.h: Cosmetic changes Thu Jul 10 06:05:18 2008 -0700 Hal Rosenstock ab049bc9e0b76a57b37c87f52025b03ba007f6a8 * opensm/osm_lin_fwd_tbl.h: Cosmetic changes Tue Jul 24 15:27:10 2035 +0300 Keshetti Mahesh c25c6661c33af4fe16be609569ef6ace8f546058 * complib: trivial change in description of cl_list_insert_tail function Sat Jun 28 04:24:32 2008 +0300 Sasha Khapyorsky 64f1f55b2d490010bbdc86e7715efd8c6ec4521f * opensm: improve port_prof_ignore handling Thu Jun 26 11:12:55 2008 +0300 Sasha Khapyorsky d063e941079cc8d9519dafc5e5a06bda6bc12cdc * opensm: speedup and improve ipv6 snm handling Mon Jun 30 03:59:30 2008 +0300 Sasha Khapyorsky 322e1e8cc0f5210f6866b893b78de10dd799b1e8 * opensm/osm_sa_lft_record: pass block parameter in host byte order Mon Jun 30 03:57:37 2008 +0300 Sasha Khapyorsky c0b4d48d45f01e8467c540a2fe51be1446fbf3a7 * opensm/sa: remove local *get_port_by_guid() wrappers Mon Jun 30 02:33:02 2008 +0300 Sasha Khapyorsky 63788715e6417ea2a46b3083076eb1b41425ae9b * opensm/osm_sa_lft_record: validate LFT block number Mon Jul 7 14:25:52 2008 -0700 Al Chu fdcb387cbdcf6c2f6f66553c8d8c0dbab71083b4 * opensm: reroute console option ** Version: opensm-3.2.2 Tue Jul 8 07:22:02 2008 +0300 Sasha Khapyorsky a129c1c979721b7299cb6ad64859a71a9af171a4 * management: bump management versions Tue Jul 8 17:04:52 2008 -0700 Tim Meier 612088635ce78fb58b2b8cfcd5983105c6ad4c19 * opensm: osm_subnet.c - added console loopback mode to opts file & parser Sun Jul 6 23:07:38 2008 +0300 Sasha Khapyorsky 32d3390d755a6226ac4a4f1cd340c6eae0f22244 * management: revert configure.in update configure.in on 'make dist' Tue Jul 1 11:46:51 2008 -0700 Al Chu c9bcb1056be9a394935af5a090775e5bb5a35109 * Fix comment typo Tue Jul 1 10:54:01 2008 -0700 Al Chu 7587ea37b512a9ba2322f563ac4cf2f848a7e0ac * fix true/false usage Mon Jun 30 11:52:01 2008 +0300 Yevgeny Kliteynik d5f9093f8dc0fabc46c50928db5513c4f965a0ab * opensm/osm_state_mgr.c: fixing log message Mon Jun 30 04:44:22 2008 +0300 Sasha Khapyorsky 58b57ae3eb061158be0387328f8e5f1da8106da7 * opensm/osm_log: formatting changes Mon Jun 30 03:44:26 2008 +0300 Sasha Khapyorsky 99aaca081528c9b954f1fecb24d42e9e81847ffe * opensm: trivial formatting fixes Mon Jun 30 02:26:47 2008 +0300 Sasha Khapyorsky 2f75562c0b6b0bf376fddc4dd7f423d96f699909 * opensm/osm_sa_lft_record: trivial formatting fixes Sun Jun 29 04:43:57 2008 +0300 Sasha Khapyorsky 8d0cef24efd4e9d00eb1b189947d035a7e1bdc69 * opensm: fix snprintf() usage Sun Jun 29 04:43:06 2008 +0300 Sasha Khapyorsky 7ff6e3753bb3f334575b26e1228631e701b55d00 * opensm: minor snprintf() usage improvements Sat Jun 28 16:17:08 2008 +0300 Sasha Khapyorsky 2f00875166ce24b3fb2039b052a274b2d95c428d * opensm/osm_log.h: trivial formatting in comments Fri Jun 27 10:48:58 2008 -0700 Hal Rosenstock 2a79a99b198b5f0d943aeb1f7d8e7dd508130bd2 * opensm/osm_port_profile: Handle all possible ports Fri Jun 27 08:14:46 2008 -0700 Hal Rosenstock 3a4c95bda09328ebc75ecd1fc1efffa3e1842251 * opensm: Convert unicast LIDs in long messages from hex to decimal Thu Jun 26 14:36:43 2008 -0700 Hal Rosenstock d058d95f3a0ff2b8b6790d973e12980761bda597 * opensm/osm_mcast_mgr.c: Only send MCG delete notice if not previously done Thu Jun 26 11:00:14 2008 -0700 Hal Rosenstock 9a48e495e8737e3d5c9c2d98f3b260299ca39fe2 * opensm/man/opensm.8.in: Clarify ignore-guids file format Thu Jun 26 07:07:51 2008 -0700 Hal Rosenstock afb00e0a51493e8bfc944a1a3a6f96f54bb1f1b7 * osm_port_profile: Change some variable names for consistency Thu Jun 26 07:08:25 2008 -0700 Hal Rosenstock fa1de7242f46c48d808ebf0e394d50ecc6e0c87b * opensm/include/opensm/osm_port.h: Commentary change Wed Jun 25 08:16:59 2008 -0700 Hal Rosenstock 56a3fbbcac0623ca92be1b1399ff6baf27ce967d * opensm/include/opensm/osm_port_profile.h: Cosmetic formatting changes Wed Jun 25 13:04:38 2008 +0300 Sasha Khapyorsky dbc62923cc09561a137fd6303c0ef839b84e243c * opensm: workaround CL_ASSERT() failure with port_order_list qlist Wed Jun 25 23:45:19 2008 +0300 Sasha Khapyorsky a7aeebd9c731fa0be3945f9806e90ab4170f303c * opensm/man: add -F. --config option to OpenSM man page Wed Jun 25 23:08:11 2008 +0300 Sasha Khapyorsky bfac93e5b88847cfe5444e81ed5b74b7f0a6faf7 * opensm: --create-config command line option Wed Jun 25 23:30:56 2008 +0300 Sasha Khapyorsky 2aa72ca5a203c727446ec5080cc73b67f75bcf97 * opensm/configure.in: fix HAVE_DEFAULT_OPENSM_CONFIG_FILE define generation Wed Jun 25 16:17:10 2008 +0300 Sasha Khapyorsky 1f184cf466583e106546b7283e7e7e92df415a1d * opensm: add --version command line option Wed Jun 25 16:51:04 2008 +0300 Vincent Ficet 585b6019ab0a44390bd3bb6ab0cb4f44788d133a * opensm: fix wrong port_guid initialization Wed Jun 25 06:03:06 2008 +0300 Sasha Khapyorsky 5863032fc15ce12c8bf91232946c34119e36d020 * opensm/osm_subnet.h: comments formatting Mon Jun 23 13:24:28 2008 +0300 Sasha Khapyorsky d8e75668e726c0277492b90276a37625c933b992 * opensm/osm_ucast_mgr: some code consolidation and cleanup Mon Jun 23 13:20:26 2008 +0300 Sasha Khapyorsky d1ce91659c4cb4f44af763e00ed3709cb84c33a0 * opensm/complib: cl_item_obj macro Wed Jun 25 04:46:13 2008 +0300 Sasha Khapyorsky df681bdf54f2d836af871d037c192b6111ffae0c * opensm: trivial rename max_unicast_lid_ho and max_multicast_lid_ho Wed Jun 25 04:29:32 2008 +0300 Sasha Khapyorsky 56072cc82a6789dd9ab366203678b577f7380087 * opensm: merge all __get_mgrp_by_mlid() instances Wed Jun 25 03:54:48 2008 +0300 Sasha Khapyorsky 33b6746282ff91dfd9282c93cd0dc1b6a5dc6082 * opensm/osm_sa_mcmember_record: cleanup __get_new_mlid() function Wed Jun 25 03:43:30 2008 +0300 Sasha Khapyorsky 36f1d593c1cfabb562ef77a4ebde0fc517b3e565 * opensm/osm_subnet: rename field mgrp_mlid_tbl to mgroups Tue Jun 24 16:28:48 2008 -0700 Hal Rosenstock 654ca595ad4a92065c7489a6ab7413c2a15a916a * opensm: Convert mgrp_mlid_tbl into array Sun Jun 22 04:50:06 2008 -0700 Hal Rosenstock 6dd053a4fe06079c397b6e450383c6a4eb74f081 * opensm/osm_sw_info_rcv.c: Cosmetic formatting change Tue Jun 24 11:12:38 2008 -0700 Hal Rosenstock 8d57aa6a49379d4358275b695776ce6f529301b9 * opensm/include/opensm/osm_port_profile.h: Cosmetic formatting changes Tue Jun 24 07:27:13 2008 -0700 Hal Rosenstock 26abbb9291aa787de975dddcb100b36aa33977a7 * opensm/include/complib/cl_fleximap.h: Improve cl_pfn_fmap_cmp_t PARAMETERS comments Tue Jun 24 16:04:04 2008 +0300 Sasha Khapyorsky 3dc9d1cd185bf177acafa294764b1d5d00e3f6ca * opensm_ucast_mgr: add node name and port number to the logging Mon Jun 23 13:25:08 2008 -0700 Al Chu 77a3d0390d9ec515c18647008e7cf6b762d97314 * implement guid_routing_order_file Mon Jun 23 13:25:06 2008 -0700 Al Chu 6e9c5054da2305508b7f0da07106f721562d51c0 * rearch __osm_ucast_mgr_process_tbl() usage Mon Jun 23 13:25:02 2008 -0700 Al Chu 08a945131dd0b089f57e07b79f69191a568cb7a1 * add guid_routing_order_file option Sun Jun 22 15:13:44 2008 +0300 Sasha Khapyorsky 7679c46cca2c40ea4a5d0f370908b5f086a56dae * cmoplib/*.h: trivial: remove empty lines in structure definitions Tue Jun 24 06:04:43 2008 +0300 Sasha Khapyorsky a729795f2db3c0230d08d4d7b62d64d76d7dcb8a * opensm: fix compilation error with --enable-debug Fri Jun 13 23:34:40 2008 +0300 Sasha Khapyorsky 48702f1a681df7886e98e03a4c2d50239f447110 * opensm: support for multiple event plugins Fri Jun 13 23:21:23 2008 +0300 Sasha Khapyorsky a777763fecef2cc3ab5164bd5b348fb5fcaefe7f * opensm: move event_plugin from perfmgr to opensm Fri Jun 13 15:03:46 2008 +0300 Sasha Khapyorsky bc73030982eac9570e5c2bce0350060b48bdd861 * opensm/config: allow space separated strings as values Sat Jun 14 15:39:58 2008 +0300 Sasha Khapyorsky 13e1827031cfcf3b5d84daf0a798729a2900a21c * opensm/perfmgr: move event_db_dump_file to common OpenSM dump dir Fri Jun 20 15:21:37 2008 -0700 Hal Rosenstock d24951e2370ff0b1fb3e5300a4f68c1c56db30b5 * opensm/osm_lid_mgr.c: Fix off by 1 issue with max_lid Fri Jun 20 11:59:09 2008 -0700 Hal Rosenstock 3174bbdedce692351c96d3f7a385c6e279815e4d * opensm/osm_sw_info_rcv.c: Cosmetic formatting changes Fri Jun 20 11:57:39 2008 -0700 Hal Rosenstock 52eb3ecf33693db87c1b55c317f3d12b44929789 * opensm/osm_sa_mcmember_record.c: Fix some off by 1 issues related to max_multicast_lid_ho Fri Jun 20 07:34:38 2008 -0700 Hal Rosenstock 10a9c0df0d131cebb86e7e52b30789a209b39d48 * opensm/osm_subnet.h: Cosmetic formatting changes Fri Jun 20 07:24:43 2008 -0700 Hal Rosenstock 68a2fdbd61f18c5a95d0c0d59ef1548baebe79d3 * opensm/osm_switch: Cosmetic formatting changes Fri Jun 20 06:56:53 2008 -0700 Hal Rosenstock af46480439c0587078fc10d059c629a8558aee61 * opensm/osm_port.c: Cosmetic commentary changes Wed Jun 18 07:09:40 2008 -0700 Hal Rosenstock 69c51f220f181a3e4a413a7031f0e2f1f806672b * opensm/include/osm_mtree.h: Eliminate unneeded include Wed Jun 18 07:04:20 2008 -0700 Hal Rosenstock 9cc5ce7774a483243131f8556db9b7bdaa0d69dc * opensm/include/osm_prefix_route.h: Support C++ inclusion Wed Jun 18 06:44:54 2008 -0700 Hal Rosenstock f8753846fba326d3573e710021892c4a995f4608 * opensm/include/osm_db.h: Fix some typos Wed Jun 18 06:44:50 2008 -0700 Hal Rosenstock 7792c20d46bfe73e6763b23eb0c72c826e2aa88b * opensm/include/osm_port.h: Eliminate some unneeded includes Wed Jun 18 13:56:56 2008 +0300 Sasha Khapyorsky 6e38b2175f79ff6208e9868d4db061f9cb708676 * opensm/osm_ucast_ftree.c: trivial: remove OSM_LOG_EXIT Sun Jun 15 16:49:00 2008 +0300 Sasha Khapyorsky 4a2b95c8d62bc2e68d936234a2214124ff54b62d * opensm: make osm_perfmgr_db.* content dependent on PerfMgr availability Mon Jun 16 12:28:41 2008 +0300 Sasha Khapyorsky 21adbd886bb063b7e0480c1c596d34115ba4f1e5 * opensm: replace inclusion of osm_vendor.h by osm_vendor_api.h Sun Jun 15 11:26:26 2008 +0300 Sasha Khapyorsky 370fee787f0e64c4148e43eccb4e1431ab5d5288 * opensm: rename 'struct _osm_*_t' to 'struct osm_*' Sun Jun 15 21:31:26 2008 +0300 Sasha Khapyorsky 7deb52591c66598597b97dff8c9691745a305d7f * osm_vendor_select.h: make OSM_VENDOR_INTF_OPENIB to be default Tue Jun 17 14:09:29 2008 +0300 Yevgeny Kliteynik 07fefc066b20b813942636cc251d5969a7ccb52c * opensm/man/opensm.8.in: TRIVIAL addition in fat-tree description Tue Jun 17 06:42:56 2008 -0700 Hal Rosenstock f6ac0ee5d671a987752ff70c3ade23078da4515b * opensm/osm_lid_mgr.c: Cosmetic formatting changes Tue Jun 17 06:02:59 2008 -0700 Hal Rosenstock 2cc1097661f8930f21bc206c0a0f684a82b8452a * opensm/osm_mcast_mgr.c: Cosmetic comment format change Tue Jun 17 05:58:01 2008 -0700 Hal Rosenstock a930f708ba6444f0557951764f72778bcff1941b * opensm/osm_sa_mcmember_record.c: Cosmetic changes Tue Jun 17 05:06:44 2008 -0700 Hal Rosenstock 6add4d28cfa4a1abb45df781f57523eebddd2922 * opensm/include/opensm/osm_multicast.h: Cosmetic changes Mon Jun 16 16:14:00 2008 +0300 Yevgeny Kliteynik 39de5fe7c8f086e50d0377e8f7da8680a21b03a4 * opensm/osm_qos_parser.y: TRIVIAL addition in log message Mon Jun 16 06:07:51 2008 -0700 Hal Rosenstock fa9b337759e0ecf4a19a0e214683a77fced81dfd * opensm/osm_sa_mcmember_record.c: Some error message improvements Mon Jun 16 08:55:48 2008 +0300 Sasha Khapyorsky caee6497151bf48d8b575d690f7b6f776f7f2221 * opensm/osm_subnet.h: remove some not used typedefs Mon Jun 16 08:30:05 2008 +0300 Sasha Khapyorsky 065cdf639e7b80eef73c6d7ff4b734061b03b6d1 * opensm/osm_console: use osm_get_switch_by_guid() Sun Jun 15 11:35:40 2008 +0300 Sasha Khapyorsky 2e3724584de962d7ecc99d55a3ddf6fdc9d33e43 * opensm/inculde/*.h: remove empty lines in type definitions Sun Jun 15 14:45:02 2008 +0300 Sasha Khapyorsky fcaf815088f6546fcb316f20c62f6b3fc7d7603f * opensm/osm_console.c: fix guid parsing Sun Jun 15 14:43:54 2008 +0300 Sasha Khapyorsky feaa068bad8ef7d8cf0515ed8ff8e320287302d7 * opensm/osm_concole.c: trivial: break comment long lines Fri Jun 13 16:04:56 2008 +0300 Sasha Khapyorsky 3b7ac019b2325bab47a74fcf9ba0c02892d51d88 * opensm: consolidate config parser logging code Sat Jun 7 20:38:22 2008 +0300 Sasha Khapyorsky f33836775c444f5df72b19aa713588ab64841898 * opensm: preserve base lid routes Sat Jun 7 02:09:19 2008 +0300 Sasha Khapyorsky d1b71f0aee61e661321732284af151f3ae2e8077 * opensm: move remote guids counting to ucast_mgr Sat Jun 14 06:01:26 2008 -0700 Hal Rosenstock 95fdcf7a6876f7f5378b2e01a9a5c7a4e63bbee8 * opensm/osm_subnet.c: Fix typo Fri Jun 13 10:35:55 2008 -0700 Hal Rosenstock 393b0a09da13261e58d62d84165aa184cb82b253 * opensm/man/opensm.8.in: Update consolidate_ipv6_snm_req description Fri Jun 13 10:28:29 2008 -0700 Hal Rosenstock 5bc6f560067f23a923184a3c133755d0b66f2627 * opensm/osm_sa_mcmember_record.c: When consolidating SNM, need separate group per PKey Sat Jun 14 15:28:18 2008 +0300 Sasha Khapyorsky 514299808345a1a905f1275b891e2a7401b8ddfc * opensm: replace "(null)" string with null_str variable Thu Jun 12 11:02:48 2008 -0700 Hal Rosenstock fa01d03cf2869cf2adc6efca9bf75858f33bea01 * opensm/osm_sa_mcmember_record.c: Breakup some long lines Thu Jun 12 06:35:58 2008 -0700 Hal Rosenstock cdb458874db4cc8918aeffb0605971aedeede48c * opensm/osm_trap_rcv.c: Break up some long comment lines Thu Jun 12 06:35:56 2008 -0700 Hal Rosenstock e449f3d83079b5bdd1123f934ccd3fe30400339e * opensm/osm_sa_path_record.c: Break up some long OSM_LOG lines Tue Jun 10 15:59:22 2008 +0300 Sasha Khapyorsky 84bcf9a5efb98a212375daf89ec5596beda82bdc * opensm: state default SM_Key value change in usage and man Thu May 22 17:15:45 2008 +0300 Sasha Khapyorsky 93052f92fcecfa18fdf7befb2079b2e5dc80755b * opensm: fix OSM_DEFAULT_SM_KEY byte order Wed Jun 11 08:55:39 2008 -0700 Hal Rosenstock fd8b3281f6c039e4bd4bd9cc165f73969e7512e0 * opensm/osm_lin_fwd_tbl.c: Minor change to __osm_lin_tbl_compute_obj_size Wed Jun 11 10:54:29 2008 -0700 Hal Rosenstock ebc70a60a1409e77d2e14d7ca09ca1bfea8b400a * OpenSM/libvendor/osm_vendor_ibumad_sa.c: Eliminate unneeded define Wed Jun 11 12:47:34 2008 -0700 Hal Rosenstock 427d9b313d1865271bdc87623068ae9058f5f4a4 * OpenSM/include/osm_port_profile.h: Fix some typos Wed Jun 11 11:27:17 2008 -0700 Hal Rosenstock 295e3faed70514f6d6d145a1458442df3862c529 * OpenSM/include/opensm: Fix some commentary typos Tue Jun 10 07:25:59 2008 -0700 Hal Rosenstock cdab26ab42e395ec6c4fe942a5aec9c4c5f10afe * opensm/include/iba/ib_types.h: Fix comment Sun Jun 8 18:56:04 2008 +0300 Sasha Khapyorsky 804b032b71807e58f9b9d0253f30bf95f614e39e * opensm/configure.in: remove AM_MAINTAINER_MODE Mon Jun 9 09:20:17 2008 -0700 Hal Rosenstock 6f22d6fb26b84c470183c5519e873580eab5c2d0 * OpenSM/osm_sa_path_record.c: Add some information to some error log messages Mon Jun 9 07:44:27 2008 -0700 Hal Rosenstock baebc2f4f4b895451667dd18d719c017587981ec * OpenSM/osm_sa_mcmember_record.c: Cosmetic change to error log message Mon Jun 9 06:24:26 2008 -0700 Hal Rosenstock 1f250b65171a505219c16311218449ca9ec1d9a5 * OpenSM/osm_sa_portinfo_record.c: Cosmetic comment change Mon Jun 9 06:24:20 2008 -0700 Hal Rosenstock e5bb8d4ddc86ade07c5b29f482d3c8a414692f58 * opensm/libvendor/osm_vendor_ibumad_sa.c: Cosmetic changes Sat Jun 7 23:24:57 2008 +0300 Sasha Khapyorsky f5598b4e7aa86ab9ebf4ff7e2e9cd3889ea2117a * opensm: improve log messages in __osm_state_mgr_check_tbl_consistency() Sun Jun 8 06:16:14 2008 +0300 Sasha Khapyorsky d69c5e8f18821a0e48ffbf03526927c54d06ac3f * opensm: remove some vestigial comments and RCS keywords Sat Jun 7 10:30:46 2008 -0700 Hal Rosenstock a1e596a471e3fca5676f4c09529af9434b96583a * OpenSM: Remove some vestigial comments Sat Jun 7 06:03:28 2008 -0700 Hal Rosenstock cd1569106d154ef754dd1621aef676c09be0e9ae * OpenSM/osm_sa_mcmember_record.c: Comment reformatting Wed Jun 4 05:44:27 2008 -0700 Hal Rosenstock 9b36a7e64dd267d33603793c5ca8bd7cc3d6a0e8 * opensm/osm_port.c: Eliminate potential NULL pointer dereferences Wed Jun 4 04:37:57 2008 -0700 Hal Rosenstock 574f7984de8f22a8f1c0bc5098bf7c67b0d57ca1 * opensm/osm_pkey.c: Eliminate potential NULL pointer dereference Wed Jun 4 04:37:16 2008 -0700 Hal Rosenstock 2aa1adc9755594f1466d78468c4c7ecef37fa49e * opensm/osm_ucast_ftree.c: Eliminate unnecessary check in __osm_ftree_sw_tbl_element_create Wed Jun 4 04:37:00 2008 -0700 Hal Rosenstock 27ed4e2e33af32a9ef78e584eb8ec5b0ad78f84e * opensm/osm_sa_mcmember_record.c: Minor logic change in __get_new_mlid Sun Jun 1 01:08:05 2008 +0300 Sasha Khapyorsky e17972e1bb94a603ea14c9c434ad023ea64f14a0 * opensm: remove osm_log reference from osm_mad_pool object Mon Jun 2 07:00:39 2008 -0700 Hal Rosenstock 474dd65172d917a0b3e0ede8d3ce8bde8846a8b5 * OpenSM/osm_sa_mcmember_record.c: Validate some more MGID bits for IPv6 SNM Mon Jun 2 10:05:17 2008 -0700 Hal Rosenstock 457cd4ba18bbedb3929a4b54cad7c4037b16a1fc * opensm/osm_lin_fwd_tbl.c: Eliminate potential NULL pointer dereference Mon Jun 2 23:30:36 2008 +0300 Sasha Khapyorsky 3a1b21808d40a3501c26f9154e5c731db16dbc52 * opensm/osm_lid_mgr.c: indentation fixes Mon Jun 2 07:25:29 2008 -0700 Hal Rosenstock 48ddf2c309023d1a253bf740593a8af33411f19c * opensm/osm_lid_mgr.c: Eliminate some potential NULL pointer dereferences Mon Jun 2 07:00:29 2008 -0700 Hal Rosenstock 120ef0f5123f028a59b142edfbd9987f40ba9896 * OpenSM release notes: Update to 3.1.11 Sat May 31 10:31:57 2008 -0700 Hal Rosenstock 7300de84f208492286fbc13be7ede192899a8959 * OpenSM/osm_sa_mcmember_record.c: Collapse all scopes when consolidating IPv6 SNM Fri May 30 11:07:15 2008 -0700 Hal Rosenstock 915c5a3946d1b84f59d0c6d6ea53051ca7e8b873 * opensm/osm_subnet.c: Change comment for IPv6 SNM in options file Fri May 30 04:07:57 2008 -0700 Hal Rosenstock aafc2fc467339597ed95f5cbb4bdfb1aa484dc43 * OpenSM: Add another HP OUI to recognized vendor IDs Thu May 29 12:25:10 2008 -0700 Hal Rosenstock e5bae1558c940fb0c07e5b2d61c01b5d35da4e02 * opensm/main.c: Minor change to long option for consolidate_ipv6_snm_req Thu May 29 12:25:07 2008 -0700 Hal Rosenstock 3fe1bd0367ddc8788823b8c26a2bdea9ce46465a * opensm/osm_sa_mcmember_record.c: Improve log message and some comments relating to SNM Thu May 29 06:22:52 2008 -0700 Hal Rosenstock cdb772bb0ad611f2351f0eec8b32203d014876b1 * management: Support separate SA and SM keys as clarified in IBA 1.2.1 Mon Mar 31 00:59:12 2008 +0300 Sasha Khapyorsky 2f7273110bc5df3920e5746e817d3a81b8597c93 * opensm: use OSM_DEFAULT_CONFIG_FILE as config file Sun Mar 30 21:46:09 2008 +0300 Sasha Khapyorsky e61ccf5407114b28bc674af108d478f9e7580513 * opensm: option to specify config file Sun Mar 30 20:47:34 2008 +0300 Sasha Khapyorsky 6ab6746b091b9e1d829a3a52c338bcca7b226b49 * opensm: config file functions return int Sun Mar 30 20:27:25 2008 +0300 Sasha Khapyorsky 1dde03e8f7b09f6f6a72fa7822175ace422870a1 * opensm: pass file name as parameter to config parser funcs Fri May 23 11:40:54 2008 +0300 Sasha Khapyorsky 17d618f13481d39032e6c95d6d9fda0c4b5c905a * opensm/scripts: remove opensm.conf usage Fri May 23 11:09:39 2008 +0300 Sasha Khapyorsky 3ccb3a6904dc7194eca0bbae6e455edbd57f437b * opensm/scripts: remove not used opensmd template Thu May 22 17:43:34 2008 +0300 Sasha Khapyorsky 3620842af3e3a1ee499d3a83edbc5d009ef698b2 * opensm/scripts/opensm.init.in: fix status command Mon May 19 17:00:58 2008 +0300 Sasha Khapyorsky 650811e201158d0f54da915305276e430f5b7d96 * opensm: write all OpenSM options to cache file Mon May 19 15:37:03 2008 +0300 Sasha Khapyorsky cb0759cef0bb09309f3400c433fd5c497b7a4f39 * opensm: port_prof_ignore_file option Mon May 19 15:12:45 2008 +0300 Sasha Khapyorsky 1a175cf98150bd7930c2e89f5b7c11f65ef735f7 * opensm: remove unused pfn_ui_* callback options Mon May 19 15:00:57 2008 +0300 Sasha Khapyorsky c5e29b6f137dfbe28b042c5bef6a4720f9a0d301 * opensm: merge disable_multicast and no_multicast_option options Fri May 16 13:16:16 2008 -0700 Hal Rosenstock b6c3408be7d63620f9d1f9c8ce7d3908b64eb52f * OpenSM/doc/QoS_management_in_OpenSM.txt: Remove mention of OFED Fri May 16 13:13:52 2008 -0700 Hal Rosenstock ae3f62857417537b4f4b860fa901aca93a3a079c * OpenSM/doc/modular_routing.txt: Fix typo Thu May 15 13:27:23 2008 -0700 Ira Weiny 3f270054602fed5c54e3f80d9563177568926464 * OpenSM: Add a Performance Manager HOWTO to the docs and the dist Thu May 15 13:27:21 2008 -0700 Ira Weiny 4f39aa9c52b19e87f49749bfdff6d2e9e9d4015f * OpenSM: Fix rpm build, /opensm/opensm.conf failed to install Thu May 15 12:08:30 2008 +0300 Yevgeny Kliteynik 890d890861fe4f4780cdf43c62ab9e8faffed903 * opensm/ib_types.h: fixing some wrong comments Thu May 15 10:03:02 2008 +0300 Yevgeny Kliteynik 0474af218256510d073cbda5be7df1a0193e1c31 * opensm/ib_types.h: cosmetics - µsec t o usec Thu May 15 09:04:33 2008 +0300 Sasha Khapyorsky 1b134db8c1c84c2cf6d67bee11d9835b1d2d7b28 * opensm/doc/current-routing.txt: add DOR algorithm reference Tue May 6 07:33:26 2008 -0700 Hal Rosenstock 58808bd39feedc341b8b2affdecae9f5e119c35c * OpenSM: Add QoS_management_in_OpenSM.txt to opensm/doc directory Tue May 13 23:59:44 2008 +0000 Sasha Khapyorsky 1e0b9a5d85cfc78d96669450bd3857ca8717239d * opensm/osm_lid_mgr.c: cosmetic Thu Apr 24 18:16:57 2008 -0700 Ira Weiny d26423dcdaf0b2ad20047a92f517b0c8a1ca2959 * opensm/opensm/osm_lid_mgr.c: set "send_set" when setting rereg bit Tue May 13 14:15:22 2008 +0300 Yevgeny Kliteynik d445680ceb555d58245d01c5f1574630e056a512 * opensm/osm_state_mgr.c: fix segmentation fault Tue Apr 22 14:06:01 2008 -0700 Ira Weiny 3a8d399a9031ad2818b6ce94625ed373732cc566 * opensm/configure.in: Fix the QOS and prefix routes config file default locations Tue Apr 15 15:05:53 2008 -0700 Al Chu a77ad37dc85ddb0cf00a6c0c14376e234d9cf109 * ids_guid_file manpage entry Sat Apr 5 04:48:34 2008 +0300 Sasha Khapyorsky 0557a149d6b77f0a11c48ef2a3c9ae8f517f1e59 * opensm/osm_base.h: fix typo Thu Apr 3 14:30:54 2008 -0700 Ira Weiny 05c9b995a8582daf67413cc2189f43b0919538fb * opensm/opensm/osm_perfmgr.c: change log level of counter overflow message ** Version: opensm-3.2.1 Thu Apr 3 22:52:03 2008 +0300 Sasha Khapyorsky 3b7a07a8d2b00bac60678a6fc199d09fd682fb2f * opensm: add osm_console_io.h to EXTRA_DIST list Thu Apr 3 20:07:55 2008 +0300 Sasha Khapyorsky 9938c95a9676d2f653f52593d126d5e2df68ceb0 * management: bump all versions Tue Apr 1 17:51:22 2008 +0300 Sasha Khapyorsky 0f79b8f67811008e6f92222e395d0c1bb49eca95 * opensm/osm_base.h: use OPENSM_COFNIG_DIR in config files paths definitions Tue Apr 1 17:42:05 2008 +0300 Sasha Khapyorsky 90d71686512bea43ef649498328d351b3528ce05 * opensm/configure.in: make prefix routes config file configurable Tue Apr 1 16:48:21 2008 +0300 Sasha Khapyorsky 6514759806eb87357959bc48f7027459dc40d0f1 * opensm/configure.in: replace CONF_DIR config var by OSM_CONFIG_DIR Mon Mar 31 01:54:02 2008 +0300 Sasha Khapyorsky 3d58bd6c063c77fd579c4bda772e23d18921dabf * opensm/configure.in: improve readability of configured config files Sun Mar 30 17:07:52 2008 +0300 Sasha Khapyorsky e7f7443d5f487ba1c25f03c8ced4857db0032aa1 * complib/nodenamemap: merge file parsers Sun Mar 30 15:53:39 2008 +0300 Sasha Khapyorsky 5811a4e20c82d76102203b73e6939481977cf565 * opensm: make formats of node map names and up/down guid ids files identical Tue Apr 1 15:45:50 2008 +0300 Sasha Khapyorsky 443901c5d8f160d71cb0ee64f21c3150d1768f0b * opensm/scripts/opensmd.in: fix typo Sun Mar 30 21:58:39 2008 +0300 Sasha Khapyorsky 8687f60d0248bd08c3794fa64009d40a73d1250d * opensm/configure.in: fix typo Sun Mar 30 18:48:53 2008 +0300 Sasha Khapyorsky 7ec7f4c0970778918c3f6c0a2bda5918fda1d85f * opensm: remove duplicated osm_subn_set_default_opt() prototype Wed Mar 26 01:32:13 2008 +0200 Sasha Khapyorsky cf99e2513845ccbd0c244f004d65f155f093fc68 * opensm/updn: --ids_guid_file - node guids to ids map Tue Mar 25 17:56:57 2008 +0200 Sasha Khapyorsky 606c40cd5c5060f55fafa8d5861964a13ee2b4bb * opensm: remove unused osm_ucast_mgr_read_guid_file() Tue Mar 25 17:50:25 2008 +0200 Sasha Khapyorsky ebd918711a6f2ccf1f9e12b570f6885a24673e26 * opensm/ftree: use parse_node_map() for guids file processing Tue Mar 25 17:05:58 2008 +0200 Sasha Khapyorsky ab05e7d319bd73f0c4a104d49f70321b8bb6112e * opensm/updn: update root nodes at each run Tue Mar 25 04:44:19 2008 +0200 Sasha Khapyorsky 7a7aadb4932a649891c39db01f806db33d850564 * opensm/updn: use parse_node_map() for root node guids file processing Tue Mar 25 04:37:11 2008 +0200 Sasha Khapyorsky 1d575fbf26f4c3456d7bc955fc93c39c58a47302 * complib/nodenamemap: add generic parse_node_map() function Wed Mar 26 19:05:22 2008 +0200 Sasha Khapyorsky 599a343543698ef13c21be590a0ccc79f3107a9b * opensm: update copyright dates after recent changes Wed Mar 26 17:50:40 2008 +0200 Sasha Khapyorsky 7add9df3cc2a0cd670f4316925a7a1c78ec18247 * opensm: remove not used osm_log_printf() function Wed Mar 26 17:45:45 2008 +0200 Sasha Khapyorsky 1041fae3b9863b35467032583bcf65700b1b420a * opensm: unify dumpers, use fprintf() every there Wed Mar 26 16:19:01 2008 +0200 Sasha Khapyorsky ba7a93fe8638dc7692165c42e84700f8c0695369 * opensm/updn: dump used root nodes guid Wed Mar 26 16:14:06 2008 +0200 Sasha Khapyorsky 5e09f6cf60ff6f7e137eb703bfb9297624819b1d * opensm: osm_dump_qmap_to_file() function Wed Mar 5 13:28:37 2008 +0200 Sasha Khapyorsky 0f736f61e19f0c103b17ae38799e06e01dc40177 * opensm: send trap 64 only after new ports are in ACTIVE state. Wed Mar 26 18:41:37 2008 +0200 Sasha Khapyorsky f2fff7aec0a3cd5063b8b2cdf461c3f14b795bf0 * opensm: switch LFTs incremental update fix Wed Mar 26 17:31:21 2008 -0700 Al Chu 7080cb08e65047f94f671f85dcd434fdc00ebf5a * opens: fix trivial ftree comments Wed Mar 26 16:09:07 2008 +0200 Sasha Khapyorsky dd4f0bc1fa025b6e801a7206fe543007cbb4de55 * opensm: trivial: fix in commented functions Mon Mar 24 16:49:12 2008 +0200 Yevgeny Kliteynik 80d6087746ee327e78a7516ed0e823c23ae92232 * opensm/QoS: setting SL in the IPoIB MCast groups Tue Mar 25 13:54:48 2008 +0200 Dotan Barak d6ef804689fc9643de8e99ed67a4b3c96c7bb17f * management: Remove extraneous semicolon from several files Tue Mar 25 02:08:14 2008 +0000 Sasha Khapyorsky d81d7dd6850df0a6450e471b84e8d172fe418cb2 * opensm/osm_trap_rcv: remove unused variable Mon Mar 17 23:16:51 2008 +0200 Sasha Khapyorsky 88fdab25281bb4f541af0eabb5df4dc4122359b8 * opensm: minor memory leak fix Mon Mar 24 09:37:09 2008 +0000 Sasha Khapyorsky c3674c177cce552a8e73ef203ac5004fc75b6c09 * opensm/osm_mcast_mgr: limit spanning tree creation recursion to max hops (64) Mon Mar 24 09:13:44 2008 +0000 Sasha Khapyorsky 89218d4b3bc5f7d6442d13db685673573e205644 * opensm: updn/connect_roots: preserve connectivity to root nodes Mon Mar 24 01:38:05 2008 +0200 Yevgeny Kliteynik 6dce14a1f6ff50488ab6de2a597b299e38b66b00 * OpenSM release notes Mon Mar 24 01:01:01 2008 +0200 Yevgeny Kliteynik 1d7eaaab39f28cbd29b81faa8eb25b5df9e04271 * opensm/osm_partition.h: trivial - fixing pkey order in struct Sat Mar 22 07:35:52 2008 -0700 Hal Rosenstock 4a35d296faaf8f3a073d8d576ad0216df1ec036b * OpenSM release notes: Add in new QLogic HCAs Fri Mar 21 15:51:22 2008 -0700 Ira Weiny c4642e95b33117a5a71d5d838dd39c02ebf541a9 * opensm/opensm/osm_trap_rcv.c: respond to new trap 144 node description update flag Thu Mar 20 07:39:01 2008 -0700 Hal Rosenstock cd72cdee7009e7018337f0d5f3430b29fdd040f6 * opensm/doc/partition-config.txt: Update default file name Thu Mar 20 07:34:55 2008 -0700 Hal Rosenstock 4cabe307eafd581144b0359cb0e6902b29aabf8d * OpenSM release notes: Add byacc as alternative to bison for qos parser Wed Mar 19 09:36:49 2008 -0700 Ira Weiny 04ee3fb8a5e0ed753d63860ceea0fbe4188779e1 * Ensure ownership of the /etc/opensm directory Wed Mar 19 07:35:04 2008 -0700 Hal Rosenstock 78eb38812c656f20307d24aefef11f17dc135682 * OpenSM/osm_subnet.c: Cosmetic changes to options file Tue Mar 18 07:19:24 2008 -0700 Hal Rosenstock 0359bbdd77d7096e373c8c1db66e389a2d384464 * OpenSM release notes: Clarify QoS firmware support Fri Mar 14 07:13:58 2008 -0700 Hal Rosenstock 3911d455b630fa3f2b903be71ea05c1bdccf7f1d * opensm/osm_sw_info_rcv.c: Clarify LinearFDBTop correction log message Thu Mar 13 14:55:30 2008 -0700 Al Chu 32ce561346be104a39344648fd2c91d5a3a3252d * opensm: add lidbalance command to console Wed Mar 12 10:23:35 2008 -0700 Ira Weiny 0683ab8d65574871ec7cbb852cb432bbda47125e * opensm/include/iba/ib_types.h: update Notice DataDetails for Trap 144 to 1.2.1 Wed Mar 12 14:10:15 2008 -0700 Ira Weiny 9c92d792af370221a2e8f80ce52238fe88c057d6 * opensm/include/iba/ib_types.h: fix DataDetails definitions based on 1.2 and 1.2.1 specification Thu Mar 13 14:32:30 2008 -0700 Albert L. Chu 5be29d3cde9f8b577b7d5567e7d635af76709cef * handle routers in switchbalance console command Wed Mar 12 15:37:23 2008 -0700 Al Chu 9a569ca574608f18dd419f9f3d2f520b1770416b * Opensm: switchbalance console option Mon Mar 10 17:18:59 2008 -0700 Al Chu b21206ce6918de31a4d32c716831409df9eb1694 * Opensm: minor code cleanup Mon Mar 10 17:01:16 2008 +0200 Yevgeny Kliteynik 5fa2bccc61c053ede23972423094d876d4fdf178 * opensm/configure.in: make lex/yacc presence mandatory Mon Mar 10 16:56:23 2008 +0200 Yevgeny Kliteynik ce46870d307bc780cf51296d8728376a5ad2729e * opensm/osm_qos_parser: fixed compilation on byacc Sun Mar 9 14:27:19 2008 +0200 Yevgeny Kliteynik 941345e44c82990286df7bf05797680a3aa14926 * opensm/osm_subnet.{c,h}: osm_get_port_by_guid takes guid in network order Sat Mar 8 04:05:11 2008 +0200 Sasha Khapyorsky 30bec4816ce7f9f8a9e40c492c73cafe7c319604 * opensm: in UP/DOWN algo compare GUID values in host byte order Sat Mar 8 04:01:50 2008 +0200 Sasha Khapyorsky c07cd5bf0e8163728e3ff332bdae6849d65b7880 * opensm/osm_ucast_updn.c: decrease noisy ranking debug prints Sat Mar 8 03:57:55 2008 +0200 Sasha Khapyorsky dec9303a8e5dc4298e33a0e439668e0611ea1300 * opensm/osm_dump: dump fixes Sun Mar 9 16:51:27 2008 +0200 Sasha Khapyorsky ff615dafb2f6384ec0902e8dfa4817d0044015da * opensm/osm_switch.h: use tab instead of space charaters Sun Mar 9 16:50:46 2008 +0200 Sasha Khapyorsky bbf4b01826970385db3d558f9e156ea466688311 * opensm/osm_ucast_mgr: make error code uniq Mon Mar 3 15:08:44 2008 -0800 Al Chu fe13902f7f1d11c8a64214188d7665493236c89b * opensm: multi lid routing balancing for updn/minhop Wed Mar 5 16:24:23 2008 +0000 Sasha Khapyorsky 75f3f457f6a5dc98fd8af6171ef349a8d803e269 * opensm: release notes update Thu Mar 6 03:49:13 2008 +0200 Sasha Khapyorsky 4e5986fcb13f4f7ee454e65f695e90cc91b82a31 * opensm/osm_sw_info_rcv.c: cosmetic formatting fix Sun Mar 2 07:46:59 2008 -0800 Albert Chu 998679a3f0b3c1622eb04e72ccbd367ae4960789 * opensm: enforce routing paths rebalancing on switch reconnection (part 2) Sat Mar 1 17:49:55 2008 +0200 Sasha Khapyorsky c75d5f2f6d98b1833eb2c9cb71d02bb325935eed * opensm: enforce routing paths rebalancing on switch reconnection Sun Mar 2 19:47:56 2008 +0000 Sasha Khapyorsky a1ff38ebbcc617eaf61cece06a4196fb665bae8a * opensm: set SA attribute offset to 0 when no records are returned Sun Mar 2 19:37:03 2008 +0000 Sasha Khapyorsky 70bdee883a224cb6f2f040429f2b15e8bb85c9c8 * opensm: rename osm_sa_vendor_send() to osm_sa_send() Sun Mar 2 18:45:37 2008 +0000 Sasha Khapyorsky 3ce42a513f99949b88009f0feae85c399c39b5b2 * opensm: consolidate SA response sending code over SA processors Mon Mar 3 06:11:57 2008 -0800 Hal Rosenstock 45ccdf2031b3f0268a5d3dbd88dee3799ba8b02e * OpenSM: Set packet life time to subnet timeout option rather than default Sun Mar 2 19:23:40 2008 +0000 Sasha Khapyorsky 000025adefcf53cc7bad6cc14b9208b5b7150777 * libvendor/osm_vendor_ibumad_sa.c: cosmetic Sun Mar 2 04:36:34 2008 +0200 Sasha Khapyorsky 43c20ee5bc2cbdf723d09fb004d176545ec4c609 * opensm/osm_sa_service_record.c: remove unneeded braces Sun Mar 2 00:33:37 2008 +0200 Sasha Khapyorsky 3172d112d17ce73f1d82a05499d28eb30435af66 * opensm: cosmetic code clean in SA area Sat Mar 1 22:21:09 2008 +0200 Sasha Khapyorsky 3daabe950db11615cd9e9690df3fc2de2bd8b3ef * opensm: move osm_sa_send_error() to osm_sa.c file Sat Mar 1 22:13:54 2008 +0200 Sasha Khapyorsky 7700897bb4bea8305ca014fab16ebf0050cb4dd2 * opensm: consolidate osm_sa_vendor_send() status check Wed Feb 20 14:27:01 2008 -0800 Timothy A. Meier eb08a2d4a0b31bc4a77e0bc214db2a70e555281f * opensm: console split console into two modules Mon Feb 25 10:31:43 2008 -0800 Ira Weiny d0a68616f83a83e550e903a9cca103e40de37266 * opensm/libvendor/osm_vendor_ibumad.c: Add environment variable control for OSM_UMAD_MAX_PENDING Wed Feb 27 17:13:52 2008 +0200 Yevgeny Kliteynik aea844aa85665026b4242fd7fc54d4dabafec9ee * opensm/man: added -Y/--qos_policy_file option to OSM man Tue Feb 26 00:11:02 2008 +0200 Yevgeny Kliteynik 7014e530eb25c5e0be497a32b45040c9a4978876 * opensm/doc: fixing version in release notes Mon Feb 25 10:38:57 2008 +0200 Yevgeny Kliteynik 6cbff6ad57a310fab0f799de22e43613b7e4a83e * opensm/scripts: Fixing location of generated opensm.init script Sun Feb 24 20:45:02 2008 +0200 Sasha Khapyorsky 3c1a127181bcbf8ad98fd61af5c40505cf11beec * opensm/doc: rename OpenSM Release notes to 3.1.10 Sun Feb 24 20:05:26 2008 +0200 Sasha Khapyorsky 0046b5fe89ba519c6f20e4142a59c714e025aa56 * opensm/scripts: make configurable scripts Sun Feb 24 19:30:48 2008 +0200 Sasha Khapyorsky 4620cf6216030f0b07e6524e7e2768f69ba552a3 * opensm/scripts: rename all opensm scripts as *.in Sun Feb 24 14:11:12 2008 +0000 Sasha Khapyorsky 22ca16aa77c79548e2823e1c6783beb6a52cbc4f * opensm: rename OpenSM startup script to opensmd Sun Feb 24 14:10:51 2008 +0200 Sasha Khapyorsky 4875cae9e38189c4a2e6e91995375eee108fb17f * opensm/osm_switch.c: comment typo fixing Fri Feb 22 21:14:20 2008 +0200 Sasha Khapyorsky cdf2c50a6217108e811d3cb85226ab6347154c2f * opensm/osm_vendor_ibumad: simplify put_madw() prototype Fri Feb 22 21:07:50 2008 +0200 Sasha Khapyorsky 764d6b080140ccf8a8d2dcb47c117354f48efa53 * opensm/libvendor: use CL_HTON64() macro for constant conversion Fri Feb 22 20:32:49 2008 +0200 Sasha Khapyorsky e509b0e896f964c0b5cf78d97d8528f7958f14d6 * opensm/osm_sa_slvl_record.c: fix typo in log print Wed Feb 20 17:39:21 2008 -0800 Al Chu 2ba60380284c982f9b4a252742233b200f51328e * note cbb means constant bisection bandwidth Thu Feb 21 23:27:10 2008 +0200 Sasha Khapyorsky 666543ad83b973daa571a682e2dbc73588204ffd * opensm: check p_physp for null before using Thu Feb 21 23:10:13 2008 +0200 Sasha Khapyorsky c6943052b12e1969f5b824adad37eaee6de76ce4 * opensm: fix potential core dumps Thu Feb 21 22:30:29 2008 +0200 Sasha Khapyorsky 1851f2d1fa7761044cacacad4b2466354840cc7b * opensm/osm_sa_pkey_record: fix typo Wed Feb 20 14:02:47 2008 -0800 Ira Weiny 2ab7f1e2d5dd2f5c49f4610319502f1d4bcbce7b * opensm/libvendor/osm_vendor_ibumad.c: add transaction ID printing to error messages Thu Feb 21 07:07:45 2008 +0000 Sasha Khapyorsky c310ba438dd88d3889d74ed1efbb0db115cd0023 * opensm/osm_node: trivial code consolidation Wed Feb 20 14:02:45 2008 -0800 Ira Weiny acab6ac8bda3dcd9cd8827d3584186caf206140f * Fix 2 potential core dumps now that osm_node_get_physp_ptr can return NULL Wed Feb 20 14:02:44 2008 -0800 Ira Weiny 392468227a49a11b4659f38feed9847316faa414 * opensm/libvendor/osm_vendor_ibumad.c: Fix print of Transaction ID Wed Feb 20 14:07:21 2008 +0200 Sasha Khapyorsky a9b4fbb879dd1a4bdf13b29ec40516072ba5b1dc * opensm/doc: Remove list of ofed-1.2 bug fixes from OpenSM Release notes. Wed Feb 20 03:02:02 2008 +0200 Sasha Khapyorsky 82e0b4967ce46f21dbc9154be22a81c353b5c3f5 * opensm: Release Notes for 3.1.9 Sat Feb 16 19:33:18 2008 +0200 Sasha Khapyorsky c1390230e439ed6ad9092bb2d23a8b920c390017 * opensm: convert to OSM_LOG() macro Fri Feb 15 19:26:09 2008 +0200 Sasha Khapyorsky f799077875c771b6547fc4fc023b165a16efd7d6 * opensm/osm_log: OSM_LOG() macro Mon Feb 4 13:55:53 2008 +0200 Sasha Khapyorsky e8a68348f046592d0a8b5eeabec8fe8cc1f79171 * opensm: drop unused parameter in OSM_LOG_ENTER macro Fri Feb 15 15:25:02 2008 +0000 Sasha Khapyorsky 4dfdd7aa1263d232f786d11c0db6879c3f105f1e * opensm/osm_console.c: fix unused func warning Fri Feb 15 15:18:06 2008 +0000 Sasha Khapyorsky b766a7fa009605654e9fbd99fffd9e88102a2081 * opensm/osm_console.c: indentation fixes Thu Feb 14 16:15:20 2008 -0800 Timothy A. Meier 0cbef8f7f9a73af9fc80e5af4d9bda1ec3e76006 * opensm:osm_console cleanup, rename, reorg, no new functionality Thu Feb 14 11:29:19 2008 +0200 Sasha Khapyorsky ed903c867de36491e0959056a1de2d91f964b726 * opensm: label indentation fixes Thu Feb 14 11:20:36 2008 +0200 Sasha Khapyorsky ceaf836ef5bde84de4a0813d48d77211e62106e5 * opensm: indentation fixes Thu Feb 14 10:56:14 2008 +0200 Sasha Khapyorsky 3500bf9649e227548474f4c2fc989fda5ea7e2e4 * opensm/osm_sm_state_mgr: remove unused function Wed Feb 13 11:59:12 2008 +0200 Sasha Khapyorsky 966ff70dc46fb96b260a929494f8830deab2fafe * opensm/osm_helper.c: make some static Sat Feb 9 20:10:03 2008 +0200 Sasha Khapyorsky fbab9ac91a93a3303dd2c5b7598f20c636cd14b7 * opensm/osm_sminfo_rcv.c: comments fixing Mon Feb 4 10:03:24 2008 +0200 Sasha Khapyorsky d1494edf2629688a67ffe4985bc81a5114e077ec * opensm: indentation fixes Mon Feb 4 09:58:44 2008 +0200 Sasha Khapyorsky d2b4367e4b7586778576939dc2d9dedf5c7c90cb * opensm: remove unused header files Mon Feb 4 09:56:05 2008 +0200 Sasha Khapyorsky 914583d6fd32031b30de26486e94def815fc1270 * opensm: kill drop_mgr, link_mgr and mcast_mgr SM sub-objects Mon Feb 4 09:25:08 2008 +0200 Sasha Khapyorsky 891987b639202cc410e787020c91c61e13a0fcbd * opensm: remove redundant moving_to_master flag ** Version: opensm-3.2.0 Mon Feb 11 20:17:54 2008 +0200 Sasha Khapyorsky a90c4a13f6beadeef9962cc8275a48db6d512ddf * management: bump versions in master branch Mon Feb 4 07:56:36 2008 +0200 Sasha Khapyorsky 7744c8a699480ea11e003b4f8952e53cb157e066 * opensm: cleanup sm->state field Sun Feb 3 17:16:15 2008 +0200 Sasha Khapyorsky 2e30cadc854b90e6f7a7c93477cb8e6ee367f690 * opensm: remove unused header files Sun Feb 3 16:47:58 2008 +0200 Sasha Khapyorsky bbf219143be000da8c82110d437edd75dd785472 * opensm: kill osm_sm_state_mgr sub-object Sun Feb 3 15:22:12 2008 +0200 Sasha Khapyorsky 99462cc880879bf849f1e7d79a4da2e898212c0f * opensm: consolidate SM state logging code Sun Feb 3 15:00:18 2008 +0200 Sasha Khapyorsky e6b118dc06c5459fbd73ed400ce48cc4bad6d3df * opensm/osm_log: add STRICT_OSM_LOG_FORMAT attr for osm_log_printf() Sat Feb 2 16:52:39 2008 +0200 Sasha Khapyorsky 7ca2609fe7601da321148962b20f81065d5902c4 * opensm: cleanup IB_SMINFO_STATE_INIT Sat Feb 2 16:01:44 2008 +0200 Sasha Khapyorsky 55508a10200e7274e249242f21b63f7cce9f4e95 * opensm/osm_state_mgr: use osm_log_msg_box() Fri Feb 1 19:11:29 2008 +0200 Sasha Khapyorsky 1c12c01017ca08f3cb6e4a3e07724735e7e3e310 * opensm: consolidate message "box" logging code Wed Jan 30 20:26:56 2008 +0000 Sasha Khapyorsky 9dd5abf4be4386a52d952ac3232e5187a746b33e * opensm: kill osm_state_mgr object Wed Jan 30 19:38:15 2008 +0000 Sasha Khapyorsky 0b2277702fc31effe640c9d76514135ffc719318 * opensm/osm_mcast_mgr: OSM_SIGNAL_NONE is not in use anymore Fri Feb 8 13:44:13 2008 -0800 Ira Weiny f72cb9b92997f3e803a96d718bd5e44a4dfefbd1 * opensm/opensm/osm_console.c: fix seg fault when running "portstatus ca" in the console Wed Jan 30 19:42:38 2008 +0000 Sasha Khapyorsky 55f1595d2822206839c1dd401ddcaf2121747867 * opensm: fix comment Wed Jan 30 18:09:53 2008 +0000 Sasha Khapyorsky cbcc355c227d980e08a16262df36178e363aa1dd * opensm: OpenSM state machine rework Mon Jan 28 03:10:18 2008 +0200 Sasha Khapyorsky 230068a7d9c7febea5f5f8c734b5c90618f57520 * opensm: wait_for_pending_transaction() generalization Sun Feb 3 16:11:35 2008 +0200 Sasha Khapyorsky 5c607bb2b29b3da95c44d1620e706ac3eb88c8de * opensm/osm_trap_rcv.c: SM object reference cleanup Thu Feb 7 23:49:31 2008 +0000 Sasha Khapyorsky f48e9dcd895edf22f0dc021ddd6877e243b0ca75 * opensm: fix indentation in main.c and osm_console.c Mon Feb 4 14:49:34 2008 -0800 Tim Meier 2ca6cc29e174e2de0b567309d648f54c4bf40659 * opensm: osm_console - cleanup in preparation for adding OpenSSL option Fri Feb 1 16:43:47 2008 -0800 Tim Meier d0a7ccd9748df05b7870f3620970175d0cb543bb * opensm: separated current loop in main into its own function Wed Feb 6 12:57:40 2008 +0000 Sasha Khapyorsky cb5d3dee79a9feb748a3acee5a1078c9f89903bb * opensm: scripts/opensmd - fix opensm path. Mon Feb 4 13:22:27 2008 -0800 Ira Weiny dff5dd48f634c69d6874ce1d64d30e5494331616 * Add node name map, partition config, and QOS policy config files to the "FILES" section of man page. Mon Feb 4 14:19:02 2008 -0800 Ira K. Weiny 2429047dfd1b3ffa97da43115d8db53f2ca513c6 * Update man page for configurable partition and prefix-routes file Mon Feb 4 14:14:23 2008 -0800 Ira K. Weiny 889a6aa7dcf10c7f5ba056d8204cdcbf3e05f848 * Move opensm.8 man page in prep for making config file changes. Sun Feb 3 11:49:31 2008 +0200 Yevgeny Kliteynik 950c47d3715faf3cf97bab65a96f3a132394e968 * opensm/osm_ucast_ftree.c: cosmetics Sun Feb 3 11:16:33 2008 +0200 Yevgeny Kliteynik b95121cac76eb3ff5adc641e1e2b2a1fdb4a9c07 * opensm/osm_ucast_ftree.c: do load-leveling of non-CN routes Tue Jan 29 09:24:40 2008 -0600 Dale Purdy 9c62c0f591fc30a25cbdbd0a38c6e0b1080df231 * error in osm_ucast_ftree.c Sat Dec 1 22:05:12 2007 +0200 Sasha Khapyorsky 4a31e57f7e8794fd5d2310be6505ca074f6d8122 * opensm/perfmgr: add support for non-pthread systems Mon Jan 28 02:35:43 2008 +0200 Sasha Khapyorsky 6587a5bd96cb22768009e6671ec10b65fdc25e2c * opensm/perfmgr: break perfmgr discovery if osm_exit_flag is on Mon Jan 28 02:31:47 2008 +0200 Sasha Khapyorsky 0a99e7ea15f23052d601a0ac0ec252fba2562779 * opensm/perfmgr: wakeup perfmgr discover only after NO_PENDING_TRANSACTION was signaled Mon Jan 28 20:26:32 2008 +0000 Sasha Khapyorsky 80b67c1a278bf563b7ed720ff24f931f023f319c * opensm/perfmgr: remove unused label - fix compilation warning Mon Jan 28 10:13:42 2008 -0800 Hal Rosenstock 12c6042c6e886e2815708be823dfbc2574565a6a * opensm/osm_perfmgr.c: If redirection requested but disabled, don't rerequest Mon Jan 28 10:13:35 2008 -0800 Hal Rosenstock b8fd0554a2686f32b421d03fa17f574d08be39db * opensm/osm_perfmgr.c: Fix duplicated error code Mon Jan 28 10:13:28 2008 -0800 Hal Rosenstock dda403be21c4e2e6e132a295544b1bab0583ac94 * opensm/osm_subnet.c: Better clarity in opensm.opts file for perfmgr_redir Mon Jan 28 20:02:34 2008 +0000 Sasha Khapyorsky f6bb381474c4fa3eaee8874310fa6ab20af074bb * opensm: --consolidate_ipv6_snm_req usage formatting fix Sun Jan 27 23:45:59 2008 +0200 Sasha Khapyorsky 05ec8878a89a745da8daa650d5dec5aca2684057 * opensm: remove unused states and sm signals Mon Jan 28 13:47:06 2008 +0200 Yevgeny Kliteynik 1dab45377650166623b559443113576b3b0c197a * opensm: osm_version.h not found Mon Jan 28 01:07:09 2008 +0200 Yevgeny Kliteynik ae2b6d4ddc13b5fa616ec82cf71649c0ef7717bf * opensm/osm_ucast_ftree.c: ignore port 0 and loopbacks on swithces Wed Dec 5 17:08:38 2007 +0200 Sasha Khapyorsky 2629766f7592ffc4573db3be7e769d682f3a1887 * opensm: merge force_immediate/delayed_heavy_sweep flags Sun Jan 27 18:05:07 2008 +0200 Sasha Khapyorsky e6d745597a21e82cc5a8cb4a67676680642d512c * opensm: remove osm_physp_get_mod_pkey_tbl() Sun Dec 16 00:46:59 2007 +0200 Sasha Khapyorsky 19f511799ef2f070033fc78dbc0416f70edc6600 * opensm: cleanup osm_physp_is_valid() use Sat Dec 15 15:35:35 2007 +0200 Sasha Khapyorsky a5ffe1b95f601cc8687f8ee35f91c04f2d6c9dac * opensm: remove some unneeded assertions Sat Dec 15 15:26:43 2007 +0200 Sasha Khapyorsky c8cc316d1e47a3815a97f7e8c9010ee35d576813 * opensm: simplify osm_port_t setup procedure Wed Jan 16 04:41:10 2008 +0200 Sasha Khapyorsky cfaa52ecbcef769632d9da4be8d2f26e65956fdc * opensm: rename field pkey to pkey_ix in gsi part of mad address Sun Jan 27 08:01:40 2008 -0800 Hal Rosenstock 8548607164844669d3ec836fe1ef822b4e3ce45a * management: Update License: field in management spec files Sun Jan 27 12:29:23 2008 +0200 Yevgeny Kliteynik 9f8d93ab9af17ae6f31fe108f594f0632cfd0825 * opensm/QoS: fixing RDS handling in QoS policy Sat Jan 26 22:40:41 2008 +0200 Sasha Khapyorsky a96df9545fe5d490ac118961e14a6a0e403ecd5d * opensm: remove trailing whitespaces Thu Jan 24 14:01:29 2008 -0800 Ira Weiny c56d31f369f7edfc97814a20198a2fd0f69be384 * opensm/opensm/osm_subnet.c: update valid force_link_speed values to v1.2.1 of the spec Thu Jan 24 12:28:46 2008 -0800 Timothy A. Meier 9a8b231011b0a7a2ab9e5f3ac6c87b32b2777914 * opensm: osm_subnet.c log and print the path of the cached option file Thu Jan 24 10:59:19 2008 -0800 Ira Weiny b62326e7f0672f79bae859b2eaffdaba17d9d434 * opensm/scripts/redhat-opensm.init: fix starting opensm when using daemon mode Thu Jan 24 17:35:27 2008 +0000 Sasha Khapyorsky d54fc5adbf10dc9a18f9f568ac8e358742958695 * opensm/opensm.spec: install scripts/sldd.sh Thu Jan 24 17:34:17 2008 +0000 Sasha Khapyorsky f4e3c8d138f1f3aed76081183b911d8d9b9315a3 * opensm/scripts: fix sldd.sh paths Wed Jan 23 12:40:28 2008 -0800 Ira Weiny 64fe35094397136a18a9fc943623225c9c784ff3 * opensm/opensm/osm_subnet.c: add a comment of valid "force_link_speed" values Sat Jan 19 20:37:58 2008 +0200 Sasha Khapyorsky 17044c0e092601aa9bed25bae2e1eec5ac35dbd5 * opensm/lash: fix possible segfault in osm_get_lash_sl() Wed Jan 16 21:16:25 2008 +0000 Sasha Khapyorsky eb2ba35601b022743231539514cdb9e79e0c4cb6 * opensm/opensm.spec.in: add Obsoletes rule Wed Jan 16 16:01:50 2008 +0200 Yevgeny Kliteynik 5b6d59d5f78615018d2e5d8d8c12242c027b442c * opensm/scripts: fixing MAXSMPS values to the right default Wed Jan 16 15:57:26 2008 +0200 Yevgeny Kliteynik d8d0d7fbfacf56c2cf3ac9336cb5d4553f3dabbb * opensm/scripts: removing trailing blanks Tue Jan 15 15:34:46 2008 -0800 Ira Weiny 60106698e368b86fac77cb930310abaf8eb470ee * Fix spelling of "consolidate" Tue Jan 15 14:49:05 2008 -0800 Ira Weiny 88f4f7eea9286326acc89c2d5123dfc36ae3c916 * Fix logic '{' around consolidate_ipv6_snm_req introduced by "patch cleanup" Tue Jan 15 18:15:36 2008 +0000 Sasha Khapyorsky 30f008f56f9373a6d58355ffd6d9d68a2bd9893c * opensm/perfmgr: use pkey at index 0 Tue Jan 15 15:10:26 2008 +0200 Yevgeny Kliteynik b99bdc2a6570f11e88fb11579f4331f8d0080bcb * opensm/osm_ucast_ftree.c: cosmetics in log messages Tue Jan 15 15:04:40 2008 +0200 Yevgeny Kliteynik a77194e66a7271bb5e71eb2c20fadc9b0bf7ac0b * opensm/osm_ucast_ftree.c: fixing coredump in fat-tree routing Tue Jan 15 00:06:49 2008 +0000 Sasha Khapyorsky 8d0352cecb244ff452566fb4dab47dd1d2a462f4 * opensm/osm_sa_mcmember_record.c: cosmetic changes Mon Jan 14 11:45:30 2008 -0800 Ira Weiny c7f14d074e3d95528e55a2dc173d49ae67e0d1cf * Add option to Special Case the IPv6 Solicited Node Multicast address into a single Mcast Group Mon Jan 14 11:45:28 2008 -0800 Ira Weiny 9f46c6a606a398ce98059d4275ccfdf0201182b3 * Removed unused and commented out var. Mon Jan 14 23:44:57 2008 +0000 Sasha Khapyorsky 362e9039a67a7683ba2ae629aaecef3ae6b596c0 * opensm/osm_sa.h: indentation fixes Mon Jan 14 23:43:22 2008 +0000 Sasha Khapyorsky 13e57f7a2d215e76d5d02479466490d4bbb12f5b * opensm/osm_sa_mcmember_record.c: unique error code Mon Jan 14 11:45:27 2008 -0800 Ira Weiny c9fca773473e3bc466c95b68661e448c33ef1f7a * Consolidate the 2 __get_mgrp_by_mgid functions into one global function which actually takes a mgid and returns a mgrp. Sun Jan 13 19:28:34 2008 +0000 Sasha Khapyorsky 3505432bdc47f3b999e6a8fe310785f0d552f898 * opensm/vendor: use valid pkey index value for gsi mads Wed Jan 9 21:54:25 2008 +0200 Sasha Khapyorsky de8c1e89ed6851350609f78c798ed3ebb918ecc7 * opensm/osm_sa_slvl_record: fix overflow crash Wed Jan 9 20:01:15 2008 +0200 Sasha Khapyorsky d691b90cfbbfcfd7dfc9ea2c9de09d9d42d1e7ef * opensm/osm_sa_slvl_record: remove unused variable Tue Jan 8 22:52:32 2008 +0200 Sasha Khapyorsky 3e1ec845d4cbb7a2d46d0e58d68c965742c0256f * opensm/vendor: filter out non-IB devices in osm_vendor_get_all_port_attr() Wed Jan 9 10:35:01 2008 -0800 Ira Weiny 4fc09aee1b1a2654f77b760a9aa2bf0849a94ae2 * Fix perfmgr enable in spec file. Wed Jan 9 15:18:19 2008 +0200 Yevgeny Kliteynik 0af00a7b36b0f7a9319185e9a348569be31f2dc1 * opensm/osm_mcast_mgr.c: fixing a seg. fault in processing mcast groups Mon Jan 7 17:13:56 2008 +0200 Yevgeny Kliteynik 51c1313bb3ffd9ce38c453b94733c74614cfed8d * opensm/osm_qos_policy.c: trivial fix in passing wrong pointer Mon Jan 7 02:25:17 2008 +0200 Sasha Khapyorsky 5bd0cdee79d9ce2c954f17ea0c2de674b9d2764c * osmtest: remove unused error.h file Sat Dec 1 04:13:45 2007 +0200 Sasha Khapyorsky 536ddff426a187bc0214293c06a2d944b88d2778 * opensm: remove unused header files Sat Dec 1 04:10:25 2007 +0200 Sasha Khapyorsky a9ca2db5aa4a7f1161dc930e19caaf2857c33024 * opensm: cleanup dummy SM req and resp objects Sat Dec 1 03:21:22 2007 +0200 Sasha Khapyorsky 53c2caf02d4262447845f8c584100e8669278e8b * opensm: unify SM managers initializers Mon Jan 7 04:49:52 2008 +0200 Sasha Khapyorsky a5cdb2affabeff22513056d64d8b79af7bb58bd7 * opensm/opensm/Makefile.am: fix version update rule Mon Jan 7 01:40:19 2008 +0200 Sasha Khapyorsky 19c4eaec7b49e28088810791be8c5ab7ae5dd917 * opensm/Makefile.am: update configure.in version on 'make dist' Mon Jan 7 01:23:16 2008 +0200 Sasha Khapyorsky 15e25f39126e88208f7b65f353e20e7d202756a9 * opensm: update OpenSM version according to the tree state Sun Jan 6 21:33:44 2008 +0200 Sasha Khapyorsky c44889dc9190ac0ec7ce6852c2b64e15c01c388b * management/*/Makefile.am: fix ChangeLog generation rule Sat Dec 1 00:14:46 2007 +0200 Sasha Khapyorsky 819c91f84f4242eb6ead13d79800c43255f663f6 * opensm: remove not used osm_sa_*.h header files Sat Dec 1 00:06:02 2007 +0200 Sasha Khapyorsky 45b95f959983d18eeb5dc3c94db7bb32453ba7b6 * opensm: cleanup SA related osm_*_rcv_t objects Tue Nov 13 05:48:17 2007 +0200 Sasha Khapyorsky 05b142661686a2eb5ef8df587276026f42af355d * opensm: remove unneeded *_rcv.h header files Tue Nov 13 05:45:37 2007 +0200 Sasha Khapyorsky 7d88bba73abb9a730e4717353a2524c4300b7f11 * opensm: cleanup SM related _rcv_t objects Sat Dec 1 00:43:50 2007 +0200 Sasha Khapyorsky 84ff47789da981c17eaf73a126d3336ccfde1395 * complib: clean unused cl_qlockpool primitives Tue Nov 27 19:58:19 2007 +0200 Sasha Khapyorsky 604d7300f713908d3d0332ca514b58f950ecdebf * opensm: use malloc instead of cl_qlock_pool in osm_mad_pool.c Tue Nov 27 17:34:02 2007 +0200 Sasha Khapyorsky af88550c1de0c91735fb0b87adc09587bbafacd9 * opensm: use malloc instead of cl_qlock_pool in SA processors Thu Jan 3 04:03:59 2008 -0800 Hal Rosenstock 383bb4fe9523d107c21a73b81f2abd43464d6dc4 * opensm/osm_subnet.(h c): Cosmetic changes to some options descriptions Thu Jan 3 09:44:46 2008 +0200 Sasha Khapyorsky ffbd1a76737a2cf39c890bddbfd1bacd607a22ba * management: bump versions Mon Dec 17 15:44:59 2007 +0200 Yevgeny Kliteynik fbd482e3a5b9cac9400145e00ae13cefef264bd9 * opensm: osm_state_mgr.c - stop idle queue processing if heavy sweep requested Wed Dec 26 21:23:11 2007 +0200 Sasha Khapyorsky 8e3ce475a32bb218a0e70cd3da32597011d5c31d * opensm: mcast mgr improvements Sat Dec 29 21:02:49 2007 +0200 Sasha Khapyorsky 0ace8a836b32d6b9a3eb654566f7c83cce79b54d * opensm: Revert "opensm/osm_pkey_mgr.c: setting only outbound partition enforcement on switch" Tue Dec 25 14:29:47 2007 +0200 Yevgeny Kliteynik 1230d7011a98a11585b5425014f5801a08ea10b9 * opensm/osm_pkey_mgr.c: setting only outbound partition enforcement on switch Sat Dec 22 16:15:50 2007 +0200 Sasha Khapyorsky d60473e8491f8e453bdd185c80b9ac3ffa6e42b6 * opensm/updn: rename __osm_subn_calc_up_down_min_hop_table() Sat Dec 22 15:57:13 2007 +0200 Sasha Khapyorsky 4ffa499513d51e2151c422f459559a5e4a7e18b2 * opensm/updn: report fallback properly Sat Dec 22 15:44:47 2007 +0200 Sasha Khapyorsky 3b38909dda72d10d2911346c8003f5f5dffaef0b * opensm: some micro-optimizations Sat Dec 15 01:30:18 2007 +0200 Sasha Khapyorsky 4798aa30892e39c1101f4f854bb35948d02ce1e2 * opensm: make some functions statics Sat Dec 15 01:09:42 2007 +0200 Sasha Khapyorsky 5674ae09729f2c8bc29cb9511f2de7ced91f1dad * opensm/osm_helper: make some functions static Fri Dec 14 23:27:02 2007 +0200 Sasha Khapyorsky 0ebb39c4a9b7628698dc0552cda8996fca5f7e53 * opensm: make some functions static Sat Dec 15 00:57:09 2007 +0200 Sasha Khapyorsky 0cbddac8eefecded3130e106e82d3ffe78e5e86c * complib: make __cl_thread_wrapper() static Fri Dec 21 18:32:28 2007 +0200 Sasha Khapyorsky 583e55bd41eebe151c12fbfd5aa412a34db73ea5 * manangement: kill __WORDSIZE macro checks Sat Dec 22 15:31:46 2007 +0200 Sasha Khapyorsky 0158cb8a7eeefdd353772a9fcabde690d78db0ef * opensm: indentation fixes Tue Dec 18 16:41:38 2007 -0800 Al Chu cad5ac438a4d5be21235befd899995141fc07fc9 * OpenSM: Fix incorrect identification of routing engine used Tue Dec 18 16:41:34 2007 -0800 Al Chu d3160df8a77ab52e57e0844345573b7c22ebb370 * OpenSM: Fix incorrect reporting of routing engine used Tue Dec 18 16:41:32 2007 -0800 Al Chu 1145b539627718c37c5843efbf5bb3f6ab83ba30 * OpenSM: osm routing engine type Mon Dec 17 17:30:14 2007 -0800 Ira Weiny 2a88f63bb9c93b1829851828942033bbeb846769 * opensm: Add "perfmgr print_counters node" to the console to print individual values Sun Dec 16 00:25:43 2007 +0200 Sasha Khapyorsky 335b090aa0d40c90ae636ba9d63fea4fddc7ab96 * opensm: remove useless osm_node_get_remote_type() Thu Dec 13 16:35:41 2007 +0200 Sasha Khapyorsky 61a7c1276c4e5d6e9a8367aca9d45ce19f0edb84 * opensm/osm_event_plugin.h: add names to structures Thu Dec 13 15:10:12 2007 +0200 Sasha Khapyorsky 060a0750d30e9689a08c6572a96c3444c18244cb * opensm: rename __osm_epi_plugin_t to osm_event_plugin_t Mon Dec 17 15:20:43 2007 -0800 Al Chu 91459f2c7bf8bc1f63c0e854e93652239f48d198 * OpenSM: Fix comment typo. Tue Dec 18 15:12:15 2007 +0200 Yevgeny Kliteynik 39a80efbfd69896dd8bf2c8fed6d7b5f2d64c8dc * opensm/osm_pkey_mgr.c: trivial fix in log message Sat Dec 15 15:22:10 2007 +0200 Sasha Khapyorsky 53d64b8d3879c1bd14672eff2164f0cf7a38fc46 * opensm/osm_node_new: move p_node->print_desc setup Sat Dec 15 14:23:56 2007 +0200 Sasha Khapyorsky c9503fd17a9f91d3e99d50c319d71c93f6681c12 * opensm/osm_port_info_rcv: node instead of port as parameter for osm_pi_rcv_process_set() Thu Dec 13 03:47:48 2007 +0200 Sasha Khapyorsky c4d3618654367c7241e12a9de344fa93b054080b * opensm: recover only for base LID values >= 0xc000 Thu Dec 13 04:35:53 2007 +0200 Sasha Khapyorsky badcb22f46f4c3407c621e4b4242f90a6d453004 * opensm/Makefile: remove opensm_CXXFLAGS Thu Dec 13 04:25:45 2007 +0200 Sasha Khapyorsky a10dc4ca3dbffeb867c2cb07eacc813503a140ed * opensm: remove old style code formatters Thu Dec 13 03:47:48 2007 +0200 Sasha Khapyorsky 1c84f1a30e884972dcf059cf43f6f86a7eb5a1e9 * opensm: don't zero base LID when invalid value is received Thu Dec 13 00:44:09 2007 +0200 Sasha Khapyorsky 750ebce76363684374123c030e41cb89fa51a8e8 * opensm/config/osmvsel.m4: update LDADD variable, not LDFLAGS Tue Dec 11 17:39:24 2007 +0200 Yevgeny Kliteynik 37b9529da7cdc12e836102a04a0541da744703e1 * opensm: QoS policy - fixing pkey range implementation Tue Dec 11 17:36:43 2007 +0200 Yevgeny Kliteynik 6f8847091fafb0fecf1856a2d23e8ba9115774ed * opensm: fixing coredump in QoS policy pkey validation Wed Dec 12 17:52:04 2007 +0200 Yevgeny Kliteynik 61d10e99588a9ab93873584a62ea6b6356eed759 * opensm: trivial change of log message Tue Dec 11 15:11:57 2007 +0000 Sasha Khapyorsky f46d276436176752b4371f11fc53b3b24f4f0638 * opensm/libvendor: indentation fixes Mon Dec 10 04:23:40 2007 -0800 Hal Rosenstock ed71838c16c346119bff2a2879e02e1f9ef3b2f3 * opensm/libvendor/osm_vendor_ibumad_sa.c: In __osmv_sa_mad_rcv_cb, handle attribute offset of 0 Tue Dec 11 14:40:01 2007 +0000 Sasha Khapyorsky 305f4c9964cbd13c521f10235c8190a3b499f659 * opensm/osm_ucast_updn.c: indentation fixes Mon Dec 10 16:39:37 2007 -0800 Al Chu cb567d37538e1700ab5906a8766903f2e7c464b3 * OpenSM: Fix error return corner case Sat Dec 8 00:46:58 2007 +0200 Sasha Khapyorsky 12d0c6d12b918d7956ec6af673fa52c897436119 * opensm/lash: cosmetic Sat Dec 8 00:29:41 2007 +0200 Sasha Khapyorsky 45667a27f528814d1ac01d4f052d93f452c6c477 * opensm/lash: fix wrong allocation size Wed Dec 5 21:24:42 2007 +0200 Sasha Khapyorsky 4d0056bd723f796bbc79944044f50a1afd714045 * opensm: minor cleaning Wed Dec 5 00:31:43 2007 +0200 Sasha Khapyorsky d7e150a5c56e95c4bd2c3e01745adef98f2daee3 * opensm: remove unused osm_port_lid_category_t enum Wed Dec 5 21:28:40 2007 +0200 Sasha Khapyorsky 49ed32bcb2776d1c1b420379486b5899ab97a81a * opensm: don't break name_map using when routing_engine was not found. Tue Dec 4 12:55:27 2007 -0800 Albert L. Chu 06b000174e5817e4f6c1b7fd11c4adf001cdbbb5 * change 'min-hop' to 'minhop' for consistency with routing engine input Tue Dec 4 09:36:45 2007 -0800 Albert L. Chu 3f0557a9eb6700d2ed023db48898f8ca5d9f76e0 * support minhop as a routing engine input Wed Dec 5 17:28:40 2007 +0200 Yevgeny Kliteynik cc1f8f244f4ec2dd8c20c00096e0b16fbbe27c7c * opensm: printing to stderr note about error in QoS policy file Tue Dec 4 17:04:11 2007 +0200 Yevgeny Kliteynik c7a1985bc7fd3f108b4e35bced8f571d1038214d * opensm: Fixing broken logic in 'process world' part of LinkRecord processing Tue Dec 4 01:37:57 2007 +0000 Sasha Khapyorsky f10ca384acd5f3dd1331747e4cf8e7346154d9e2 * opensm: fix lmc_mask bit order in osm_sa_link_record.c Mon Dec 3 17:16:55 2007 +0200 Yevgeny Kliteynik bca723ec62e9add9bc4bfd1536abfb50490e0a29 * opensm: adding missing comparison by to_lid/from_lid in LinkRecord processing Sun Dec 2 14:13:47 2007 +0200 Yevgeny Kliteynik 937b1f3b46bb83be535d8df99c502bd0fad209c0 * opensm: Remove unnecessary ntoh and hton conversions in LinkRecord processing Sat Dec 1 04:32:00 2007 +0200 Sasha Khapyorsky 4aeec893700c49d7151cd3581fe8f62f53a485bf * opensm: remove testability_mode option Sat Dec 1 01:14:34 2007 +0200 Sasha Khapyorsky df114deb158b7247096431c487efe640f51f77ec * opensm: make osm_pkey_get_tables static Sat Dec 1 00:30:11 2007 +0200 Sasha Khapyorsky 4e31bbee1e6646efe91ccbd5c19a72a84d43d06a * opensm: cosmetic fixes Fri Nov 30 17:59:55 2007 +0200 Sasha Khapyorsky d5f97ed5561364595797ec41e720a040858d67cb * opensm: move OpenSM constants from osm_sa_mcmember-record.h to osm_base.h Fri Nov 30 17:52:46 2007 +0200 Sasha Khapyorsky fe24980a16fc734e55088e4645b0ddc75a0f29c2 * opensm: move IBA constants from osm_sa_mcmember_record.h to ib_types.h Fri Nov 30 05:33:29 2007 +0200 Sasha Khapyorsky 603af282f66e39dc6e33796690fc342f98f9d973 * opensm: remove unused flag Tue Nov 27 20:16:24 2007 +0200 Sasha Khapyorsky 3d7c943f30c150729874deede83e76f5b14650f9 * opensm: move vendor specific header files to include/vendor Thu Nov 29 19:37:20 2007 -0800 Ira Weiny 18768044cea24b1d31930b3db92978ded86e2054 * opensm/opensm/osm_perfmgr_db.c: fix clearing previous count when "out of band" Thu Nov 29 19:36:34 2007 -0800 Ira Weiny 6e2d2e83d4737cb20a9931c2ca899b62f02a54ed * opensm/opensm/osm_event_plugin.c: remove duplicate header include Thu Nov 29 19:36:06 2007 -0800 Ira Weiny 01b44439845acecb715e244ac2a7d532165b7986 * opensm/opensm/osm_event_plugin.c: clean up version check error message a bit Thu Nov 29 19:35:40 2007 -0800 Ira Weiny aca7277cc34713e4d4a2d5522255697350d3c872 * opensm/include/opensm/osm_event_plugin.h: fix comment Thu Nov 29 10:58:46 2007 -0700 Rolf Manderscheid 10b81992808baae41721b2ef1e68e7d3cce5d933 * opensm: allow multiple scopes in a partition Mon Nov 26 08:12:10 2007 -0800 Hal Rosenstock 13960715e866ca91ffe830045b6b0d735f6b4daf * OpenSM/libvendor/osm_vendor_ibumad.c: Make error code in osm_log message unique Mon Nov 26 11:15:56 2007 -0800 Al Chu 9766332b1b2e2b83bf5e24b862349acfa575bc82 * osm cache file extra info patch Tue Nov 20 00:03:05 2007 +0200 Sasha Khapyorsky 0af1270dbd7669791962bc9962197dcc0f74710e * opensm: version 3.1.7 Mon Nov 19 20:12:07 2007 +0000 Sasha Khapyorsky fb43984b37ae6c804e5ddee97089239a9751049a * opensm: use OPENSM_CONFIG_DIR for prefix-routes file definition Mon Nov 19 20:07:05 2007 +0000 Sasha Khapyorsky 0315adbd0a00ec3ef44afe6394f1532dabbe7b5c * opensm/configure: add OPENSM_CONFIG_DIR variable Fri Nov 16 01:08:40 2007 -0700 Rolf Manderscheid 6f1cf3968db1e3a5ca5a55e3f71957bfc02ed004 * opensm: support multiple routers in a subnet Mon Nov 19 15:04:42 2007 +0200 Yevgeny Kliteynik e9d0a507fe996bf883f33b5c740418cc7b7a91f7 * osm: QoS - adding simplified syntax for policy definition Mon Nov 19 15:02:23 2007 +0200 Yevgeny Kliteynik 720dc51ccb693f4c4ce2ddde5855e1081a81ba98 * osm: Using new format of QoS parser error function Mon Nov 19 14:44:14 2007 +0200 Yevgeny Kliteynik 2c8e3d89ca94164d97abae30698f0074f2d8983c * osm: broken logic when scanning subnet for PIR request Mon Nov 19 14:34:27 2007 +0200 Yevgeny Kliteynik f4146a45615b0ce91683ca32ed0f99482d50143a * osm: improving error reporting function of the QoS parser Sun Nov 18 18:47:44 2007 +0000 Sasha Khapyorsky 1ee037f8da1340614838182543a506d832d367dc * opensm/vendor: be sure that node has IB type Sun Nov 18 15:04:00 2007 +0200 Yevgeny Kliteynik 7cf8db205505875a1eb7cc14ee614a6928d95123 * osm: cosmetics - removing obsolete comment Sun Nov 18 14:02:47 2007 +0200 Yevgeny Kliteynik c575341a89e484b93504a7fbe71740ee6be75889 * osm: moving call to QoS policy file parser to osm_qos_setup() Sun Nov 18 13:59:01 2007 +0200 Yevgeny Kliteynik 5a68c447fbed0d07cbe42cf825484d65c034a5ea * osm: use OSM_DEFAULT_PARTITION_CONFIG_FILE instead of hard-coded string Thu Nov 15 22:11:52 2007 +0200 Sasha Khapyorsky a0fa413a77260768422a8187c055092d343c326c * opensm/libvendor: remove __osmv_get_lid_and_sm_lid_by_port_guid() Thu Nov 15 21:59:52 2007 +0200 Sasha Khapyorsky 561cab95b6533143ef0b7ba81f43083b6401216b * opensm/osmtest: update port chooser Thu Nov 15 12:20:11 2007 +0200 Sasha Khapyorsky d15e855c82cf5ca3ffcf6c3fb9f58c1628890ecb * opensm: no interactive games in daemon mode Thu Nov 15 11:16:56 2007 +0200 Sasha Khapyorsky 4ac22018ca47184711c4f89b18513a530f91a5f2 * opensm/osmtest: adopt to osm_vendor_get_all_port_attr() changes Thu Nov 15 11:14:52 2007 +0200 Sasha Khapyorsky c3bbc694a8fd8bbabdc529a7cb792dd88ebf8ee1 * opensm/main: merge gen2 code in get_port_guid() Thu Nov 15 08:59:56 2007 +0200 Sasha Khapyorsky c63cbdf2505e86064bd42f90f7928802675e96ae * libvendor: osm_vendor_get_all_port_attr() rework Thu Nov 15 19:32:34 2007 +0200 Sasha Khapyorsky f00cbf5d498fc214dc2a238acf842523300575d5 * opensm/libvendor: make statics Thu Nov 15 10:49:23 2007 +0200 Sasha Khapyorsky 5afd8ae28a7aeb3d5899bce5d80fb9b0310dfb2b * opensm/vendor: handle guid = 0 with osm_vendor_bind() Thu Nov 15 10:31:44 2007 +0200 Sasha Khapyorsky dccd95dd10aa14866fc5f228d08275512d7ea3f7 * opensm/libvendor: fix umad_port leak Thu Nov 15 10:23:32 2007 +0200 Sasha Khapyorsky 88dded78acb415457ea2740d7942cfd20c423e03 * opensm/libvendor: remove not used umad_ca field Thu Nov 15 16:58:27 2007 +0200 Yevgeny Kliteynik e9e176ec822a0e1c9acbaf2e35e640f8a1f5d1d2 * osm: remove unused 'is_ipoib' parameter when adding mcast group Thu Nov 15 15:22:29 2007 +0200 Yevgeny Kliteynik 10d79899ce7b7cadf126a4451159a70a56ca7265 * osm: fixing memory leak in node description Thu Nov 15 13:58:46 2007 +0200 Yevgeny Kliteynik 6b9ce86feda959a12bd916355b72510894cc3179 * osm: fixing memory leak in QoS policy Thu Nov 15 00:33:37 2007 +0200 Sasha Khapyorsky 9ca9d6636e3fd82dc2c82f504781568f533b7853 * opensm/man/opensm.8: remove utf-8 characters Thu Nov 15 00:16:39 2007 +0200 Sasha Khapyorsky 4e30d60d8bec88096989d2aa5f60ed260df2ff79 * opensm/doc: remove utf-8 characters from text files Thu Nov 15 00:16:03 2007 +0200 Sasha Khapyorsky 99f18dab9f295d78fd5d1f352025e3e87a269de9 * opensm/man: break long lines, remove utf-8 characters Wed Nov 14 23:30:00 2007 +0200 Sasha Khapyorsky 44daedb551e631450719800b044f7cc4d66d0ebf * opensm/main.c: trivial cosmetic improvements Wed Nov 14 23:01:56 2007 +0200 Sasha Khapyorsky b30ce679d59e0c28dae9f8b678219f0901c88e22 * opensm: merge redhat-opensm.conf and opensm.conf Wed Nov 14 23:00:34 2007 +0200 Sasha Khapyorsky 2f7c31dfc6d1849e26c051d4275885ee23ba963a * opensm/scripts/opensm.conf: fix log file name in comment Wed Nov 14 20:28:12 2007 +0200 Sasha Khapyorsky a41b06837fb50628a929050ceabc6b442271f7fd * opensm: update default config names in man pages and doc Tue Nov 13 16:09:08 2007 -0800 Ira Weiny ee18b398c637a01f3ce5db6d84c71a6cd0fe3dbb * opensm/config/osmvsel.m4: Convert help strings to AC_HELP_STRING Tue Nov 13 16:09:00 2007 -0800 Ira Weiny 8fbb38a1e3a754bbaeadd1b96c6bc5acb4eac429 * Add --with-partitions-conf to configure Tue Nov 13 16:08:48 2007 -0800 Ira Weiny f16b5064f935f54aaf2c555ed2a380029f684d25 * Add --with-qos-policy-conf to configure Tue Nov 13 16:08:44 2007 -0800 Ira Weiny e82fba1b494e076fe4c37e54102d5ad9b5eaf3a0 * opensm/configure.in: remove unecessary comment Tue Nov 13 16:08:41 2007 -0800 Ira Weiny c72cbbe797019757f8c56ebcfdb7a1efcb82e1ac * Add the default in the with-node-name-map help string Tue Nov 13 16:08:36 2007 -0800 Ira Weiny 33922b7f02218b46d342b12c61f17daca1b6b685 * Add option to change the default "opensm" dir under sysconfdir as the config dir Tue Nov 13 16:08:04 2007 -0800 Ira Weiny 790c31018f12f9c3621a3438287427ade85ded2e * Break out a "CONF_DIR" variable in configure to base other config files on. Sun Nov 11 17:49:36 2007 +0200 Sasha Khapyorsky 3a0b5d563f45242471de550c3000bd2ee2d83eeb * opensm/osm_link_mgr: use return status when PortInfo is updated Sun Nov 11 13:15:09 2007 +0200 Sasha Khapyorsky ea9f147482148292bc69096458658ed681921b0a * opensm: eliminate some unneeded PortInfo Set requests Sun Nov 11 12:36:50 2007 +0200 Sasha Khapyorsky f2d8a83157764f7a389602f2fe34c1bbd9d7a3ae * opensm: fix PortInfo update issues. Tue Nov 13 04:41:11 2007 -0800 Hal Rosenstock cf31aa25739d05f693fdff4fbd8203f122fda861 * OpenSM/osm_subnet.c: Cosmetic format changes to opensm.opts file Tue Nov 13 04:14:26 2007 +0200 Sasha Khapyorsky 5bc2a38ffa20fa3c9d358555aa1debf23c37a0ba * opensmd script: fix opensm path Tue Nov 13 04:13:53 2007 +0200 Sasha Khapyorsky 85814ffe0ff5eb543920ec9970664610ce95f4e2 * opensm.init: startup script fixes Tue Nov 13 01:40:07 2007 +0200 Sasha Khapyorsky 20015cd364b4417b036d9ef038fb0b2d2faed533 * opensm/Makefile: add libopensm -> opensm dependency Sun Nov 11 19:10:57 2007 +0200 Sasha Khapyorsky d9c5eae93ec49e7c1202d9b3f562b3c0efc8437e * opensm/osm_sa_portinfo_record: cosmetic Sun Nov 11 17:43:51 2007 +0200 Sasha Khapyorsky 825689e141883d0b18bb7180c615e13418efc008 * opensm/osm_lid_mgr: cosmetic Sat Nov 10 16:49:26 2007 +0200 Sasha Khapyorsky feac52d7329b48bc403ddcf4b4e45b58c9f4b215 * opensm: PortInfo set decision flow simplification Sat Nov 10 15:14:55 2007 +0200 Sasha Khapyorsky f8aae603ba716242761e8cbed1c610c1fe91616e * opensm: simplify PortInfo.LinkSpeed setup flow Sun Nov 11 09:38:32 2007 +0200 Sasha Khapyorsky 458de3213429a13178415524d7567c9860b309ef * opensm: remove prototypes of non-existing *_is_inited() funcs Fri Nov 9 14:01:33 2007 +0200 Sasha Khapyorsky 97acc0ff1fe6edbb449a09d43eedb7c2c7fe8e22 * opensm/osm_log.h: fix indentation, update copyrights Thu Nov 8 16:18:41 2007 -0800 Tim Meier 2d1b6398821d4d6d777ded1a062af5dede172fb6 * opensm: osm_log - added the log message type to the message Wed Nov 7 19:16:03 2007 -0800 Ira Weiny fd9edb9f4e151f8b98b06fc765f70743edd666d1 * Specify a default node-name-map of /ib-node-name-map Wed Nov 7 18:58:23 2007 -0800 Ira Weiny 3e3db06bad6ba8cea955c670ec8490b723d388fd * opensm/opensm/osm_state_mgr.c: update log messages with node names Wed Nov 7 18:58:22 2007 -0800 Ira Weiny ea71eabb0ac1f0db36f6936cf223263ce7ca99b2 * use the monitored node's redirect information for this get_lid call because it is now available Wed Nov 7 18:58:21 2007 -0800 Ira Weiny 6eb4528a0c0e7f70b34a38a825875b8eb9fcbee9 * Use monitored map lookup to get the name of the node for recieved mad processing in perfmgr Wed Nov 7 18:58:20 2007 -0800 Ira Weiny 55fc794b529c4f9f00fef1f634d7e999dca6164b * Maintain a name of the node in the monitored node structure for log messages. Fri Nov 9 12:54:26 2007 +0200 Sasha Khapyorsky 79d5202860fb72bcb80c8889bc60ca963d63756e * opensm/osm_perfmgr: more log name fixes Wed Nov 7 18:58:19 2007 -0800 Ira Weiny faadf93a02ab9cb11fe82dae97323835cbd21764 * Fix log messages in perfmgr to use "perfmgr" in name, _not_ "pm" Thu Nov 8 15:47:22 2007 +0200 Sasha Khapyorsky 8b2c166d75b10a8fc9fe1b51ba2e7880c9520113 * opensm: print error details when OpenSM opt cache file open fails Tue Nov 6 19:08:38 2007 +0200 Sasha Khapyorsky 4c9d30176ee2f2d83e2ad4f789a6800510fadb44 * opensm: version 3.1.6 Tue Nov 6 19:03:53 2007 +0200 Sasha Khapyorsky 677a3f5185c0c1c0c023bbea63e3e177599ebf33 * opensm/complib: bump library version Thu Nov 1 20:15:31 2007 -0700 Ira Weiny 043bfd4d27fa13032205f36ae333162be7cd20c2 * Add node_name_map_name to opts file. Thu Nov 1 19:41:37 2007 -0700 Ira K. Weiny 24c9a7d08b7c5c95e72d108a4fb6b8cefe6c0bf8 * Add node-name-map support to OpenSM; using the "default" map. Thu Nov 1 19:29:02 2007 -0700 Ira K. Weiny e2d0f2f8cfd63e1ac6b994a98ee67aa08626c8ff * Change node name map implementation to use qmap in memory storage Thu Nov 1 20:15:08 2007 -0700 Ira Weiny a2f8073f501f981bb93bd68b8eb0d2779dae176a * Move nodenamemap out of infiniband-diags into libosmcomp Thu Nov 1 08:06:37 2007 +0200 Sasha Khapyorsky 10ade3a818d8ee8d73a61514931d67d00e07a837 * opensm/osm_vendor_ibumad: fix set_bit() func Mon Oct 15 20:41:33 2007 +0200 Sasha Khapyorsky 1e96371673564df6bcec86fbf8b28485c52cf012 * management: changed method_mask type in user_mad interface Thu Nov 1 11:01:04 2007 +0200 Sasha Khapyorsky 1f48ada263e5fcc69a3924e49c966f5dead6427b * opensm/osm_indent: add indentation for labels Sun Oct 28 12:50:30 2007 +0200 Yevgeny Kliteynik 61c015bdbf1da61ecd095cdd2b958d362c35ec3b * osm: adding missing dependency in the makefile Thu Oct 25 11:43:46 2007 -0700 Ira Weiny 0ca9a4c4d7c2043fa462ebc80e5cd31ae356a228 * Allow for a special value of "(null)" in the opts file. Tue Oct 23 11:03:32 2007 +0200 Yevgeny Kliteynik 7af86c730d093878aa1dd34da05d092abf502530 * osm: QoS - adding CPI:CapabilityMask2 and turning on QOS_SUPPORTED bit Mon Oct 22 13:05:08 2007 +0200 Sasha Khapyorsky 13e40daaaad7914d8f75fd796395b622c0ad5e87 * opensm/osm_ucast_mgr: trivial improvements Mon Oct 22 12:58:22 2007 +0200 Sasha Khapyorsky fb192ba10fd4639ca65c7a5bdc83754ff23c3f27 * opensm/osm_switch.c: indentation fixes Sun Oct 21 16:40:21 2007 +0200 Dale Purdy ab54783898b7b92d817d64439c93970cb529a018 * opensm: DOR (Dimension Order Routing) routing engine Mon Oct 22 17:11:39 2007 +0200 Sasha Khapyorsky 225f853f28a24ae3774ffc3c542bc7a0e47161e3 * opensm/osm_ucast_lash: remove unused function Sun Oct 21 10:04:22 2007 +0200 Yevgeny Kliteynik 42f12cae033565e6ed64b3243ffd470fbdec7229 * osm: QoS - parsing port names Thu Oct 18 19:11:21 2007 +0200 Sasha Khapyorsky c8737b80a10cce3704b605c192570ffee34d8fca * opensm/lash: remove debug printfs - speed-up algorithm Thu Oct 18 16:06:06 2007 +0200 Sasha Khapyorsky 72146186b4bb24616077eaeb1311616162dba36c * opensm/vendor: use umad_get_issm_path() in osm_vendor_set_sm() Tue Oct 16 08:57:31 2007 +0200 Yevgeny Kliteynik 1c4ecb188ac8191c171d3eb65243ba7b6303a927 * osm: Adding two SA MAD class-specific status values Tue Oct 16 00:44:52 2007 +0200 Yevgeny Kliteynik 499135949af7f9a27d9ff4b510f30dd473673201 * osm: QoS parser - adding support for quoted string Mon Oct 15 15:19:18 2007 +0200 Sasha Khapyorsky 25ea06fdee53a3451e800caf2c5a697a0c6a8db1 * opensm: only warning if no lid matrix or lft file given Wed Oct 3 14:05:03 2007 -0700 Tim Meier 7600b47d665db779d9a157d821dcb36ccab0acd4 * opensm: osm_console.h replaced string literals with macro definitions Sun Oct 14 11:03:29 2007 +0200 Yevgeny Kliteynik 28291a41bcf834560403eef61639cc1b0087e368 * osm: QoS - bug in opening policy file Tue Oct 9 01:05:03 2007 +0200 Sasha Khapyorsky 3832b414f8ac07155e1a7e325cbd958c8e050d0b * opensm: move osm_state_mgr dumpers to osm_dump.c Mon Oct 8 15:24:31 2007 +0200 Sasha Khapyorsky be25f8586bd4deeb6606f701364e8806129e903d * opensm/osm_state_mgr_report: trivial simplifications Mon Oct 8 15:02:54 2007 +0200 Sasha Khapyorsky 02016535a485bac3510cddce862172d59357ab03 * opensm: report message fix Tue Oct 9 11:00:38 2007 +0200 Yevgeny Kliteynik 10781fded34e90040aa56049ee279a2494803ccd * osm: QoS - fixing memory leaks Tue Oct 2 20:48:18 2007 +0200 Sasha Khapyorsky 755d42596839f4c39b2c3f83a7dd03f3a74ce452 * opensm/osm_console.c: indentation fixes Mon Oct 1 15:56:02 2007 -0700 Tim Meier 42c6acfe137e8c659c9ba3613ec97abbbffec4e2 * opensm: osm_console.c added a version command Mon Oct 1 15:13:42 2007 -0700 Ira Weiny 5c00fd7b7ed2721593e77917a9df773119ddfc0f * opensm/include/opensm/osm_perfmgr.h: fix the signaling of a sweep when the perfmgr is enabled. Mon Oct 1 15:13:41 2007 -0700 Ira Weiny 25249da409ab616ef68aac102688de1d0d4ab532 * opensm/include/opensm/osm_perfmgr.h: fix the signaling of a sweep when the sweep time is changed in the console. Mon Oct 1 15:13:39 2007 -0700 Ira Weiny dc29bd78deca455e7c7e052a61054c8f1a8167b5 * opensm/opensm/osm_perfmgr.c: fix memory leak Mon Oct 1 15:13:37 2007 -0700 Ira Weiny 377983f1771f41453b571a8aaabd5b49c99bbb97 * Add the event plugin name to the console output if a plugin is loaded. Mon Oct 1 19:42:25 2007 +0200 Sasha Khapyorsky ac279ad1c07a46721b84368183abc7d5585249e6 * opensm/opensm.spec.in: fix chkconfig command in %preun scriptlet Tue Sep 25 00:30:00 2007 +0200 Yevgeny Kliteynik 69139fe1ebda1b6358564d43d61e05fca6d25c62 * osm: QoS parser - adding pkey in port groups Tue Sep 25 00:23:39 2007 +0200 Yevgeny Kliteynik a6b397ac549ce2f6e960106655fb69a2fc8a4868 * osm/osm_sa_path_record: trivial cosmetic chage Fri Sep 21 17:40:10 2007 +0200 Sasha Khapyorsky 96cd11ab2db9bdfb354aae510ec1b23155f0947d * opensm: osm_version.h is generated by ./configure Thu Sep 20 19:40:13 2007 +0200 Sasha Khapyorsky 244f8d962cd0eb32e8fa79e2527387c781a2bc1d * opensm: update version to 3.1.5 Thu Sep 20 18:04:12 2007 +0200 Sasha Khapyorsky 86b1fc2f5af59719d7abb3664dfe7c7bf3cca009 * management/*/*.spec.in: change Source field to OFA paths Wed Sep 19 21:29:08 2007 +0200 Sasha Khapyorsky 31c976c710f1e20ce98bd5b9beb3bdf5b8c2513a * opensm/osm_sa_(multi)path_record: various fixes Wed Sep 19 21:01:52 2007 +0200 Sasha Khapyorsky 19c25ed32bc86c90e6be27ef224d00f8e541a354 * opensm/osm_sa_mcmember_record.c: fix uninitilized proxy_join usage Wed Sep 19 20:32:37 2007 +0200 Sasha Khapyorsky 9f119b94a0913c6f48911154c2c2c903db2e7436 * opensm/osm_vl15intf.c: uninitialized var usage fix Wed Sep 19 20:32:37 2007 +0200 Sasha Khapyorsky 1387ce47d4118afca9fc31b0d6af752308bc1ee6 * opensm/osm_ucast_ftree.c: potentially uninitialized vars usage fix Wed Sep 19 06:00:55 2007 -0700 Hal Rosenstock 67fe50b6f2fde7b0cc88709ca18d91cfd6d721c7 * OpenSM/osm_ucast_ftree.c: Possible NULL ptr seg fault Wed Sep 19 06:00:46 2007 -0700 Hal Rosenstock 030dc172eeb67a564152a3d8487e879c1e4b4c3b * OpenSM/osm_mcast_mgr.c: Possible NULL ptr seg fault Wed Sep 19 03:37:03 2007 +0200 Sasha Khapyorsky 953ad27c97a90695bce2a4aeebd610f6e8573787 * management/*/configure: RELEASE and TARBALL for spec files Wed Sep 19 03:28:43 2007 +0200 Sasha Khapyorsky 72ecd0ffca527bd242338ec88f797ffd44157ef4 * management/*/Makefile.am: clean dist-hook target Wed Sep 19 03:03:17 2007 +0200 Sasha Khapyorsky 77a787f1c5c08f5cf94238d05d134ef0a59f064a * opensm/Makefile.am: generate ChangeLog on 'make dist' Wed Sep 19 02:00:08 2007 +0200 Sasha Khapyorsky f43eb75bd116fa0187ef0abf23fa80a8acfd3249 * management/*/*.spec.in: don't run autogen.sh Wed Sep 19 01:29:39 2007 +0200 Sasha Khapyorsky ffc358af5c6d1fde296dde42078b0e2c34a4c922 * opensm/Makefile.am: more 'make dist' fixes Tue Sep 18 08:32:25 2007 -0700 Hal Rosenstock ade0224e3d2661a2bd9ca538d900192b484a5010 * OpenSM: Trivial comment changes and other cleanup Tue Sep 18 04:34:41 2007 -0700 Hal Rosenstock 1f7685afc64c6ed758b774c671aaac421520d548 * OpenSM/man: Update email contact info Tue Sep 18 16:03:14 2007 +0200 Sasha Khapyorsky a47a98074561cd5f41ca5bdae383a8c1fb54f3ae * opensm: recent indentation fixes Tue Sep 11 11:04:16 2007 -0700 Hal Rosenstock 31f72bc1ff4447c2b97de10351a67ded3876020f * OpenSM: Improve QP0 and QP1 counter accounting Mon Sep 17 16:59:58 2007 -0700 Hal Rosenstock 5344f09f1656f221dfbea1a297396a0fc5318b68 * OpenSM/main.c: Fix compile error Tue Sep 11 11:03:58 2007 -0700 Hal Rosenstock 160870b527ef5b5c5a3c484259a2852aa0a43eee * OpenSM/console: Support loopback in -console option Tue Sep 18 00:23:44 2007 +0200 Yevgeny Kliteynik c4d3d828663100264362e23b9c8bdfb46399a02b * osm: QoS parser - checking allocation status Mon Sep 17 21:23:27 2007 +0200 Yevgeny Kliteynik 0d67bbd511f1fd4b62d3066799c9befdb9c65336 * osm: QoS - reworked node types in port group Mon Sep 17 21:22:26 2007 +0200 Yevgeny Kliteynik 0e35a31b28c595f89a022e4fc8b802b68d755876 * osm: QoS - replace guid ranges and partition list by port map Mon Sep 17 21:09:55 2007 +0200 Yevgeny Kliteynik 6f8f70e8b84b0041ac92511fc45b2afe23e707e8 * osm: TrapRepress was failing for mkey != 0 Mon Sep 17 21:06:06 2007 +0200 Yevgeny Kliteynik 84d4a2bb6f848cae7eceb0d37938f33b9e4c52c2 * osm: mkey lease period description in options file Mon Sep 17 20:53:30 2007 +0200 Sasha Khapyorsky 1454292a6b45c0324bce3b5720e545361931e915 * opensm and all: fix Source field in spec.in files. Mon Sep 17 20:43:26 2007 +0200 Sasha Khapyorsky d2d357334026d4d7c579a2e44d257105a7a0646c * opensm: fix iba/*.h installation path Sun Sep 16 18:47:46 2007 +0200 Sasha Khapyorsky b07df69cf286bff64d785fede009812c2dc5daa4 * opensm/ptrn_config: decrease verbosity for SL overwrite log message Tue Sep 11 16:01:29 2007 +0300 Yevgeny Kliteynik 9d56daf8248345d1d8ba0b42e773c1282c99a3be * osm: QoS - changing 'no_qos' option to 'qos' Sun Sep 9 18:01:20 2007 +0300 Yevgeny Kliteynik 84c2cd6a507a0edad1b8355db3b4d07d517d781b * osm: QoS - MultiPathRecord selection according to QoS level Fri Sep 14 14:29:59 2007 +0300 Sasha Khapyorsky a136bc4f93daaa9a3717381bac1f954935de4bcc * opensm: build improvements Sat Sep 15 14:41:27 2007 +0300 Sasha Khapyorsky 30b1b76a63859f6edf1cc96e5ae5699052a425f6 * opensm: fix broken make dist Fri Sep 14 18:56:31 2007 +0300 Sasha Khapyorsky 04817d2a1e3189e728931e72f7bf22415fb4787f * opensm: remove obsolete configure.in and spec.in files Fri Sep 14 18:51:55 2007 +0300 Sasha Khapyorsky 413e968d89ca038c5d589fc58d8adb42c99d7f80 * opensm: configure scripts merge Tue Sep 4 20:52:49 2007 +0300 Sasha Khapyorsky a1c565ebf5ed95deef8fa8f52ad63c31385fd610 * opensm/autogen.sh: remove autogen.sh from opensm subdirectories Sun Sep 9 15:57:42 2007 +0300 Yevgeny Kliteynik 8033ccf86f7bb224806566fb58860e3b17709158 * osm: bugfix - IB_PR_COMPMASK was used in MPR Fri Sep 7 03:38:41 2007 +0300 Yevgeny Kliteynik c36f4dfad3576c94d87f061eb64b8a67accb195e * osm: QoS: selecting PathRecord according to QoS policy Fri Sep 7 03:38:04 2007 +0300 Yevgeny Kliteynik 7309fa5540e65da32c936031b37a40b008b33112 * osm: QoS - support for MPR in qos policy Fri Sep 7 03:36:15 2007 +0300 Yevgeny Kliteynik 84d6f9c950d50be657676b9b5ac4e5fb601604b6 * osm: QoS - adding subnet to qos policy and adding wrapper that returns qos level Tue Sep 4 23:18:18 2007 +0300 Yevgeny Kliteynik 7b37c1aab95defaf49a25fd14ae00a73e15960ce * osm: QoS - fixing access to ServiceID field of MultiPathRecord Tue Sep 4 18:17:07 2007 +0300 Yevgeny Kliteynik c56ac22000e6951154d8f3cd5db952fc9a63d56c * osm: QoS - adding new QoS fields to MultiPathRecord Tue Sep 4 18:16:58 2007 +0300 Sasha Khapyorsky a6f833ea3cbe7367494d4475e0db61e1fc544c27 * include/complib: cosmetic formatting changes Fri Aug 31 13:14:02 2007 +0300 Sasha Khapyorsky 591e397957da2d938c14c6ab15e60fad36dfbdc5 * opensm/complib: cl_event cosmetic cleanup Thu Aug 23 18:37:00 2007 +0300 Sasha Khapyorsky a0d7a0ff18ce1794ea60495762761fc88ddc5bed * opensm/perfmgr: PerfMgr for SM standby and inactive states Wed Aug 29 00:44:52 2007 +0300 Sasha Khapyorsky 8296399baa083e58171cf96ceb1a2e82ebae8fe6 * opensm: timer driven periodic sweep Tue Sep 4 15:49:36 2007 +0300 Yevgeny Kliteynik 1829aa61ee3a2bd47df935cc984d68139a110d94 * osm: QoS - fixing ServiceID and PKey bug in match rules Fri Aug 31 15:09:23 2007 -0700 Ira Weiny ced6b8225789d1940e07cdf4588abbcfec7f9765 * opensm/opensm/Makefile.am : add osm_event_plugin.h to the installed Sun Sep 2 02:45:56 2007 +0300 Sasha Khapyorsky 426fa29f74fc1bca7cac3265ed070fff54e20911 * opensm/osm_prtn.c: indentation fixes Fri Aug 31 10:13:59 2007 -0600 Rolf Manderscheid f03b42281a4fca17271e0baeb0817eebd725bce9 * opensm: set hop limit when creating ipoib multicast groups Fri Aug 31 16:16:46 2007 -0700 Ira Weiny 631e583e2df453416f348b2380d2a9556da5e405 * osm: QoS parser - fixing yacc command Wed Aug 29 15:34:03 2007 +0300 Sasha Khapyorsky cc45c4b810a4de06ef03bdff400767aa6394bf28 * opensm/osm_vendor_ibumad.c: send error callback only when reponse is expected Thu Aug 30 11:55:42 2007 -0600 Rolf Manderscheid d623f9d6c8ecf51bd729cf514dccfa506432e073 * opensm: set scope according to configuration for ipoib multicast groups Thu Aug 30 18:39:47 2007 +0300 Yevgeny Kliteynik 8afea7d9f26fe182d26684314ff80a84bdde54cb * osm: QoS parser - fixing yacc command Wed Aug 29 09:07:45 2007 -0400 Hal Rosenstock 8f831d177db1d61da4739bbdfffc9247f18f6dfd * Opensm/Makefile.am: Change for flex version 2.5.4 Wed Aug 29 14:18:06 2007 +0300 Sasha Khapyorsky 517990ec8708b3d389e89232e12df6cb556fbb5a * opensm: drop CL_ASSERT() for non-existing var Sun Aug 26 19:25:47 2007 +0300 Sasha Khapyorsky 0b7ee4609aa4ae16ea8031c8fb5086156f09060b * opensm: serialize osm_state_mgr_process() Tue Aug 28 18:11:35 2007 +0300 Yevgeny Kliteynik 8f14ab01f3f7bc2889b219e1dc5b1e846f8e35e5 * osm: QoS - destroy qos_policy when destroying subnet Tue Aug 28 17:49:46 2007 +0300 Yevgeny Kliteynik 5fde4be5dfeec4f43ef63986bb4c7d0455166a74 * osm: QoS - remove 'yyunput' compilation warning Tue Aug 28 20:21:46 2007 +0300 Sasha Khapyorsky 7733a95f4e110ac97a7c1dc3ba02ddf17c65c913 * opensm: cleanup signal.h inclusions Tue Aug 28 19:25:47 2007 +0300 Sasha Khapyorsky 20bea55b8c51f429c675339926270bdc83adefe2 * opensm/osm_base.h: trivial formatting improvements Wed Aug 29 03:35:39 2007 +0300 Sasha Khapyorsky 1ef7712bbf28650786e333734063dbcac89706ae * opensm/osm_vendor_mlx_txn.c: update cl_event_wheel_init() usage Tue Aug 28 15:54:20 2007 +0300 Sasha Khapyorsky e2659541597c781e8c929448f7c3fae91e9893c7 * opensm/configure.in: return lex and yacc deps back. Tue Aug 28 15:54:20 2007 +0300 Sasha Khapyorsky 11225ce93cc03b27a12549799260ae1cee961e32 * opensm/configure.in: drop lex and yacc. Tue Aug 28 02:11:46 2007 +0300 Yevgeny Kliteynik ec6e028e058f827f214af355fce945f5cd87ae5f * osm: QoS - reading policy file Tue Aug 28 02:11:28 2007 +0300 Yevgeny Kliteynik e4d52f5991bf9b3b73b691d86fc436f4cfe8d0e1 * osm: QoS - compiling policy file parser Tue Aug 28 02:10:59 2007 +0300 Yevgeny Kliteynik 212c495cfbdcf078c6096ccf9abd30ab60b319f3 * osm: QoS - adding QoS policy options Tue Aug 28 02:10:36 2007 +0300 Yevgeny Kliteynik f2d248cc3f7adb1dc543275ca88695a6d9538005 * osm: QoS - rename static find_prtn_by_name() to non-static Tue Aug 28 02:09:50 2007 +0300 Yevgeny Kliteynik 8c0b9457e28ba41cdf020399954febffda7098c4 * osm: QoS policy C & H files Tue Aug 28 02:09:06 2007 +0300 Yevgeny Kliteynik 0c975371046a53d06e5dfd34b1861e9269ae2c94 * osm: QoS - policy file parser Lex & Yacc Sun Aug 26 09:38:40 2007 +0300 Sasha Khapyorsky dcbb165a191c03494b3d83e2f3381ccc3d31462b * opensm/complib: remove osm_log usage from complib's API Fri Aug 24 19:44:17 2007 +0300 Sasha Khapyorsky 4384959eb8d87e779f7d43a51681441871f73807 * complib: remove osm_log() calls Thu Aug 23 18:36:15 2007 +0300 Sasha Khapyorsky 84fb1417e5666a6932c2055cdfe49f04586e53e9 * opensm/libvendor: add complib to the linker line Thu Aug 23 15:29:02 2007 +0300 Sasha Khapyorsky 687e04428373b3f5cd8b454cedd7b37bc79d00b7 * opensm: add --perfmgr to usage Thu Aug 23 09:51:13 2007 +0300 Sasha Khapyorsky dd68aa6263b6e080f28554860450cabe76c7baef * opensm/include/iba/ib_types.h: trivial formatting changes Sun Aug 19 09:42:15 2007 +0300 Sasha Khapyorsky 929eab21fb3a6aa79feb4140302419feba63a98d * opensm/perfmgr: trivial changes Wed Aug 22 17:09:47 2007 -0700 Ira Weiny 86b37bbbc6e127de0413e29f36ec0d262510715e * opensm configure: add perf-mgr-profile option and clean up "#if 0" debug code Wed Aug 22 16:55:35 2007 -0700 Ira Weiny 61c721a18aec85dbe25d630fd61c10a5e9bb5148 * opensm/opensm/osm_perfmgr.c: remove unused status variable. Tue Aug 21 14:44:58 2007 +0300 Yevgeny Kliteynik 7004b249b0daef22f5a496c52e84f636f2ee8530 * osm: QoS - adding new PathRecord fields Sun Aug 19 01:45:21 2007 +0300 Sasha Khapyorsky 94f2fb569d029fc9060493df5189dfec35ff0398 * opensm: fix outstanding mad counters tracking Mon Aug 20 12:20:05 2007 +0300 Sasha Khapyorsky b5608b629085fd462b41739e659d6f9ef1ffa7a2 * opensm/osm_vendor_ibumad.c: indent fixes Mon Aug 20 12:17:02 2007 +0300 Sasha Khapyorsky 6e567ad8c5247554271d83732b55d86f1e12938d * opensm/osm_vendor_ibumad.c: typo fix Sun Aug 19 01:11:40 2007 +0300 Sasha Khapyorsky 076352268c3ddcbb42bb745d102d8b95b4c6e7b8 * opensm/osm_ucast_ftree.c: remove unused funcs Sun Aug 19 01:10:24 2007 +0300 Sasha Khapyorsky e00f1dfe4c45d12b5a9362d305f17d76bf82267c * opensm/osm_sm_mad_ctrl.c: cosmetic Sat Aug 18 21:59:42 2007 +0300 Sasha Khapyorsky 37dfddc2a234fe21629e185a38432a93b5fd51d0 * opensm/osm_ucast_ftree.c: make some func static Sat Aug 18 21:54:47 2007 +0300 Sasha Khapyorsky 43d52f31765cc33cc616af5c326e93cd0376e882 * opensm: indentation changes Sat Aug 18 21:02:50 2007 +0300 Sasha Khapyorsky 6686890c9c56847ac74835da3bcfdb31998f0b99 * opensm/osm_ucast_lash.c: minor changes Fri Aug 17 07:14:40 2007 +0300 Sasha Khapyorsky 47460486d9f302ff202e0184b0805f76b3c7e113 * osmtest: indentation changes Fri Aug 17 06:58:45 2007 +0300 Sasha Khapyorsky acfb60d546fa81e4af7c46749b7569f00a648244 * opensm/osmeventplugin: indentation changes Fri Aug 17 06:48:59 2007 +0300 Sasha Khapyorsky 04b003be6dabbd3a21279c41ead0fcf70782e3a9 * opensm: make some funcs static Fri Aug 17 06:24:12 2007 +0300 Sasha Khapyorsky 49e89b7e0433fd408fb8a939bece8347c004592e * opensm/osm_sa_patch_record.c: trivial changes Fri Aug 17 06:15:47 2007 +0300 Sasha Khapyorsky 246ab27cd22b40036512ae75ffbd31ad4f68fd8b * opensm: indentation changes Fri Aug 17 06:00:14 2007 +0300 Sasha Khapyorsky 0a2b712e9c042962d6b245c1f518487be685bcd8 * opensm: cosmetic changes Fri Aug 17 04:52:40 2007 +0300 Sasha Khapyorsky 3e7cd649d2a8f3ec792a1ead4717f6ee4ddeb088 * opensm: indentation changes Fri Aug 17 04:40:05 2007 +0300 Sasha Khapyorsky 34e19259803489e93bd366ec20c684129f907445 * opensm/osm_link_mgr.c: cosmetic changes Fri Aug 17 04:09:27 2007 +0300 Sasha Khapyorsky bf341f927b12edce0ec3c22ed0031617e71d5ef0 * opensm: cosmetic changes Fri Aug 17 03:03:22 2007 +0300 Sasha Khapyorsky 0dd8a24400f91eb7a7fb0ac2d2ad237836c36b8d * opensm: indentation changes Fri Aug 17 02:49:27 2007 +0300 Sasha Khapyorsky c11329a3c0593cbb0ec6943e671dce4c132ba3a1 * opensm/osm_trap_rcv.c: cosmetic changes Fri Aug 17 02:33:47 2007 +0300 Sasha Khapyorsky 88fd5fbb7469b433e1f0b50bd54c059f93a62420 * opensm: cosmetic changes Thu Aug 16 23:30:22 2007 +0300 Sasha Khapyorsky bec4279e7012dee59b55339076c1da084b48cb01 * opensm/osm_vl15intf.c: trivial code reordering Thu Aug 16 23:14:05 2007 +0300 Sasha Khapyorsky 2b73f5c0c8ae8b1a6d42f131fea6c548d469ac7c * opensm/osm_vl15intf.c: indentation changes Thu Aug 16 22:51:46 2007 +0300 Sasha Khapyorsky 51fdc2b72e64374a4d39cd390a194ae78f94e10d * opensm/osm_vl15intf.c: trivial changes Thu Aug 16 22:23:30 2007 +0300 Sasha Khapyorsky 8dfbf5e21066d6a94bcf71dac7b44fee499e1e0c * opensm/osm_sm_mad_ctrl.c: trivial changes Thu Aug 16 20:58:42 2007 +0300 Sasha Khapyorsky c49937022e085be7265bd346c310011804c3cc47 * opensm/osm_subnet.c: trivial naming changes Thu Aug 16 20:46:32 2007 +0300 Sasha Khapyorsky abd298104b347226bb0138f5002daac83e92a7ca * opensm/osm_subnet.c: indentation changes Thu Aug 16 19:23:32 2007 +0300 Sasha Khapyorsky 88708bc7a579bd0634217f96c500d790042e4bd1 * opensm/opensm: indentation changes Thu Aug 16 15:00:02 2007 -0700 Ira Weiny 953e099699fcdfe96f94ba553c05351d3093b9c7 * osm_perfmgr.c: Fix extra port being added to num_ports Tue Aug 14 19:41:02 2007 +0300 Sasha Khapyorsky e6b7142f66a74e7f29343df96baee5d8477686f9 * opensm/include/opensm: indentation changes Tue Aug 14 19:41:02 2007 +0300 Sasha Khapyorsky 7785e3d03340b5bdfa61cb415c8d8bc387a21d97 * opensm/libvendor: indentation changes Wed Aug 15 23:44:31 2007 +0300 Sasha Khapyorsky a393c46e663f8600c2e73fabef5bb8b05d5ee088 * opensm/include/vendor: indentation fixes Wed Aug 15 23:49:17 2007 +0300 Sasha Khapyorsky f814d3a9da17b3029672760030bcc82e040bcb74 * opensm/libvendor: syntax fixes Tue Aug 14 19:41:02 2007 +0300 Sasha Khapyorsky c6beb05c86f39742f81c69a7b21c22318878dac0 * complib: indentation changes Tue Aug 14 18:23:36 2007 +0300 Sasha Khapyorsky 50403cf2bf37900ff4940b1d2f551587626ef516 * opensm/include/ida: indentation changes Tue Aug 14 17:53:08 2007 +0300 Sasha Khapyorsky 0732bf4a07c071641e2a706eda686f049fc23bca * opensm: remove light_sweep_physp_list list Tue Aug 14 16:21:48 2007 -0700 Ira Weiny eedad68940cadfd0d3c8ca8788b95a6d9094d7b2 * Fix the osm_epi_node_id_t structure name. Mon Aug 13 00:33:19 2007 +0300 Sasha Khapyorsky 188a349b2021ce4b22900b287f6657dbf574e175 * complib: indentation changes in header files Sun Aug 12 19:17:03 2007 +0300 Sasha Khapyorsky 1918519f197e2a59116e068dd4868ffcc3f2de3f * opensm: cleanup in report_duplicated_guid() Sun Aug 12 18:36:55 2007 +0300 Sasha Khapyorsky 57ca74a717a288e4ecfb61ebd74456bebccdd452 * opensm: resweep instead of exit when duplicated guid suspected Sun Aug 12 03:38:12 2007 +0300 Sasha Khapyorsky 3c33465c298cd642ee89de4e153123bc7747665d * opensm: duplicated GUID/moved port detection improvements Sat Aug 11 01:53:19 2007 +0300 Sasha Khapyorsky 1ac40cbbd9ebb76e1665134e73950c8388e0300a * opensm: move duplicated guid reporting to separate function. Sat Aug 11 22:20:30 2007 +0300 Sasha Khapyorsky 444d31e29d48b86a92351bbbfc51acf11eb80756 * opensm: discovery if new sweep was requested Sun Aug 12 23:28:44 2007 +0300 Sasha Khapyorsky 059157b873b5e0cf1aa2d3548a483418ed00696c * opensm: is_new osm_port_t field instead of new_ports_list Sun Aug 12 14:22:45 2007 +0300 Sasha Khapyorsky e3cb6e1385f41d166adad5dda373887a08dfd392 * opensm/osm_node_info: fix in printing Tue Aug 7 19:43:41 2007 +0300 Sasha Khapyorsky 71038ff99b76698264cc0df4a87315315721ec17 * opensm: descrease default HoQLife value for leaf ports. Tue Aug 7 00:05:08 2007 +0300 Yevgeny Kliteynik 793216e6eba4cbc76c3996c4ab414cd1a802f76e * osm: default leaf vl_stall and head_of_queue_life counters Sun Aug 5 18:57:58 2007 +0300 Sasha Khapyorsky 290885564b99e6bf74290210429bb3ed448bdfc0 * opensm: remove unused variable Sun Aug 5 18:56:46 2007 +0300 Sasha Khapyorsky 6c24dbb4a28b04cd52a809f7f3ecfd991d585bfd * opensm: wrong variable memset() Sat Aug 4 19:52:12 2007 +0300 Sasha Khapyorsky 251a77ed4ec1750641ee4bbd3b892623bfc0400e * opensm/osm_port.c: make some func static Fri Aug 3 19:37:54 2007 +0300 Sasha Khapyorsky becba138569cf6cfdd0ff85f53273008dc06ffad * opensm/osm_node_info_rcv.c: sprintf usage improvements Wed Aug 1 17:18:17 2007 +0300 Sasha Khapyorsky 806fc043ace242126d5fb21d5ec503b933067cc7 * opensm/osm_node_info_rcv.c: cosmetic formatting stuff Wed Aug 1 15:24:59 2007 +0300 Sasha Khapyorsky d71fbd9ffee2a8069e518ad1fdc4c5df97477da8 * opensm: loopback connection handling Thu Aug 2 16:10:19 2007 +0300 Yevgeny Kliteynik 3d171f0c8cc5e6843ae80245174fbdfef531d285 * osm: cosmetics - removing trailing blanks Tue Jul 31 14:27:42 2007 +0300 Sasha Khapyorsky 519383edad1493ccb5875554e01601da7975007e * opensm: report new ports before handover mastership Tue Jul 31 18:04:14 2007 +0300 Sasha Khapyorsky 7a19bcc1bce8a6b1b11b3fd5a94456f24c33b6aa * opensm: remove lft setup hack Tue Jul 31 18:16:01 2007 +0300 Sasha Khapyorsky 31df60de58150c71ead16ddd73cd35f18b8b035f * opensm: remove some CL_ASSERT() in __osm_ni_set_links() Mon Jul 30 15:54:11 2007 -0400 Hal Rosenstock 0feb6a98d049dbf14615b5d9d34ef8116caef5d5 * OpenSM/include/iba/ib_types.h: Some comment fixes Fri Jul 27 07:38:19 2007 +0300 Sasha Khapyorsky 03d742ea26eeb9ddb1909195886ae58bab47cb3c * opensm: cosmetic and formatting changes Fri Jul 27 07:11:29 2007 +0300 Sasha Khapyorsky e499c345c3a4152b9c0b0e8485472dc0e2c36ca9 * opensm: router creation code consolidation Fri Jul 27 00:59:42 2007 +0300 Sasha Khapyorsky c0ba7125010710a746a95a55297826bb7a53ee98 * opensm: dumpers improvements Thu Jul 26 06:28:47 2007 +0300 Sasha Khapyorsky dfedfd06331a734269d136d60da417e3fef16291 * opensm: remove static __some_hop_count_set var Thu Jul 26 03:49:40 2007 +0300 Sasha Khapyorsky d67b047690cbc744e543c0ee90ada96110b2bf25 * opensm: don't fetch LFTs initially Thu Jul 26 03:39:28 2007 +0300 Sasha Khapyorsky 85148f4c1044618225f7d5aa33919680f7bc75be * opensm: remove reassign_lfts configuration parameter Wed Jul 25 02:46:48 2007 +0300 Sasha Khapyorsky 113974ce47c872698a6ee2e5b54d57f663f0072b * opensm: handle port and switch tables update over handover Sun Jul 22 21:01:32 2007 +0300 Sasha Khapyorsky eb130c0d9f0cf7ea6dc45a23eba51524f03d69e9 * opensm: detect port external reset and flush cached tables Sun Jul 22 21:01:32 2007 +0300 Sasha Khapyorsky 48f585922974d2ac92bb3e7c4ceb06fa37800c46 * opensm: detect fast switch reset and force LFT update Thu Jul 26 13:53:07 2007 -0400 Hal Rosenstock 7d83ab401b1995dd7479bf0e9fcd65c748ec3b98 * OpenSM: More changes from osm.log to opensm.log Thu Jul 26 10:25:30 2007 -0400 Hal Rosenstock e06e70d6c3e12372f275c7f3840379f94e2dabbe * OpenSM/osm_port.c: Fix opvls and neighbormtu when remote port invalid Fri Jul 27 02:03:13 2007 +0300 Hal Rosenstock 901e6bddc93db018a44931b973c21ce9dcc6a0df * OpenSM/include/iba/ib_types.h: Fix comment Tue Jul 24 09:41:51 2007 -0700 Ira K. Weiny 766b596ec3494af9f1ec3a548e00e74ffba841d3 * Supress trying to load the "NONE" plugin if the default is not configured in Tue Jul 24 20:33:16 2007 +0300 Sasha Khapyorsky 0398b9de9157218f8340fbe384bf114eead2c377 * opensm: trivial formatting changes in osm_port.h Fri Jun 22 02:16:44 2007 +0300 Sasha Khapyorsky 56fe7d5cfbb7bbb7448b281322171181a2dce740 * opensm/osm_indent: go closer to opensm-coding-style.txt Sun Jul 22 01:05:02 2007 +0300 Sasha Khapyorsky e8e8c67367a597f7a2cb44fca94f52f9799dc079 * opensm: set PortInfo:LinkSpeed in link_mgr only Thu Jul 19 16:03:55 2007 +0300 Sasha Khapyorsky 4404d1a61cd6a85a4e8b1e1b6b0c174d2d8a60f7 * opensm: VLHighLimit update during initial (in sweep) link_mgr call Wed Jul 18 19:31:49 2007 +0300 Eitan Zahavi 54e76617617f0017535d66a8e93c64626a337620 * opensm: Bug in coding trying to set vl_arb_high_limit Thu Jul 19 07:26:20 2007 +0300 Sasha Khapyorsky 6aa232f182d1d4d72c8f92752a67fd166fb768d1 * opensm: remove trailing whitespaces Thu Jul 19 07:23:39 2007 +0300 Sasha Khapyorsky e8a4cdb93eee63ef28c51b920a803ebeea8d2d89 * opensm/osmtest: remove trailing whitespaces Thu Jul 19 07:21:30 2007 +0300 Sasha Khapyorsky 87b5f91de6a363dcbb6d6c1dbc91dd5e45c22ede * opensm/vendor: clean trailing whitespaces Thu Jul 19 07:18:02 2007 +0300 Sasha Khapyorsky b6db389a0ec61b5791066f4427fbc8abdf79e976 * opensm/include/iba: clean trailing whitespaces Thu Jul 19 07:15:50 2007 +0300 Sasha Khapyorsky 30806d1ea5d11b420c5366a216282abfb1314293 * opensm/complib: clean trailing whitespaces Sun Jul 15 06:43:20 2007 -0400 Hal Rosenstock 093d19214b670227e216def94875981407b9d951 * OpenSM: Change force_link_speed to allow for local policy and more flexibility Sun Jul 15 14:56:32 2007 +0300 Yevgeny Kliteynik 6bd3d1844ad096aac36bfeb8fc0826e77c2670d1 * osm: some improvements to fat-tree routing Thu Jul 12 11:56:08 2007 -0400 Sasha Khapyorsky 5764e8a528a7d6bbfe41c42e9ddcb4e09bb45e50 * OpenSM/osm_ucast_updn.c: Root detector function simplification Thu Jul 12 09:37:50 2007 -0400 Hal Rosenstock 8f9c8281777d211f319acaa0a938b10da6612362 * OpenSM/include/opensm/osm_version.h: Bump version to 3.1.4 to distinguish from version used for opensm-3.1.1 release Wed Jul 11 09:27:27 2007 -0400 Hal Rosenstock f01f03212091aa20c21b205d5aa5440d45bbfc0b * OpenSM/configure.in: Updated to version 3.1.1 Wed Jul 11 09:26:22 2007 -0400 Hal Rosenstock ce402cc75418a534fc6ae640d4c1b3d8ef10b68d * OpenSM/libvendor: Updated to version 2.2.1 Wed Jul 11 09:25:41 2007 -0400 Hal Rosenstock 4cc79dc92b8e0774a2e74d211d0f4a108579221f * OpenSM/opensm: Updated to version 2.2.1 Wed Jul 11 09:24:46 2007 -0400 Hal Rosenstock 0957e9b19f68d4741d60db2600c776f68e630aa5 * OpenSM/complib: Updated to version 2.2.1 Wed Jul 11 09:23:32 2007 -0400 Hal Rosenstock 039580ea8892c31c7f5ca39a06f732b56a24968b * OpenSM/include/configure.in: Updated to version 2.2.1 Tue Jul 10 15:06:48 2007 -0400 Hal Rosenstock b992499f2849643b8076fd9fa75add6a741c792e * OpenSM/osm_ucast_updn.c: Cosmetic change to osm_log message Tue Jul 10 15:03:27 2007 -0400 Sasha Khapyorsky 8be9b909e3029a3c2c3fe48a5f530d1ec791ca3e * OpenSM/osm_ucast_updn.c: up/down root switches detector fix Tue Jul 10 11:59:57 2007 -0400 Hal Rosenstock 211d4674acc834de14751eab5c5d021cb384e4c7 * OpenSM/osm_port.c: Cosmetic change to osm_log message Tue Jul 10 11:54:36 2007 -0400 Hal Rosenstock 76ddc0393538079f45b4d6b78d176d58f5b6c5ff * OpenSM: Cosmetic changes to some osm_log messages Tue Jul 10 10:17:05 2007 -0400 Hal Rosenstock 67b0ea3719e442cfa6c9b6f23189b1fa435f65a9 * OpenSM/osm_port_info_rcv.c: Fix commentary typo Tue Jul 10 09:43:53 2007 -0400 Hal Rosenstock b458d7b58c7ed44f7dc53d5fd7b114af7e02cef0 * libvendor/ChangeLog: Add log entry for Sean'c osm_vendor_ibumad.c change to umad_set_pkey call to use pkey_index 0 rather than pkey Tue Jul 10 09:40:57 2007 -0400 Sean Hefty 54681126de42a641f80900aff9ac609efca18ffc * OpenSM/libvendor/osm_vendor_ibumad.c: Use pkey index, rather than pkey with libibumad Tue Jul 10 09:08:16 2007 -0400 Hal Rosenstock 70d3c90c7b2f2344061dc69dcf9890657ed7ba11 * PerfMgr: Add option to disable redirection information saving Tue Jul 10 08:18:31 2007 -0400 Hal Rosenstock 0115e00b4f62851aa6a017e4e71bf807551b7b63 * PerfMgr: Clear redirection on send timeout Tue Jul 10 07:19:38 2007 -0400 Hal Rosenstock d60b552d1c08e9684975285f384cdddc17274dae * OpenSM/osm_trap_rcv.c: Commentary change Tue Jul 10 06:24:13 2007 -0400 Hal Rosenstock 938d1cb01680dc4b736f156fe6c62b267054da4d * PerfMgr: Cosmetic change to osm_log message Mon Jul 9 19:13:18 2007 -0400 Hal Rosenstock a8744daaaf3b16a8827eda9684eeefe24b97af9d * OpenSM/include/iba/ib_types.h: Add define for IB_PORT_PHYS_STATE_NO_CHANGE Mon Jul 9 16:42:20 2007 -0400 Ira K. Weiny d6092e760bf89d55f1d37a3a3183f93e1281acd4 * PerfMgr: Remove notice report hooks Mon Jul 9 15:35:20 2007 -0400 Hal Rosenstock 76e98ec9c7ab671697667a98a05b1492ef6b14dc * OpenSM/osm_port.c: Cosmetic changes Mon Jul 9 14:46:19 2007 -0400 Hal Rosenstock 389e609aca70ad8b3c660a7f9877577e16fe6178 * OpenSM/osm_trap_rcv.c: Commentary change Mon Jul 9 14:43:11 2007 -0400 Hal Rosenstock 48cd717061232b425a4ef6753ce9e4c3ebf178b8 * OpenSM/osm_trap_rcv.c: Commentary change Mon Jul 9 14:37:55 2007 -0400 Hal Rosenstock b13b21462a9679f8e619855c4c5e0fd4af654966 * PerfMgr: Query enhanced switch port 0 for PortCounters Mon Jul 9 13:15:42 2007 -0400 Hal Rosenstock 05b8baf921b830ff8210dc54411d027ddefba1b7 * OpenSM/osm_perfmgr.c: Commentary change Mon Jul 9 09:28:17 2007 -0400 Hal Rosenstock 1b7a816e5f4536e0060a2b35451413e42f34f6c5 * OpenSM/include/configure.in: Bump version to 2.2.0 Mon Jul 9 09:04:46 2007 -0400 Hal Rosenstock 872e62eba997b54804b23730486a4fde5c2678c3 * OpenSM/include/opensm/osm_version.h: Bump version to 3.1.3 for initial release off master Mon Jul 9 06:58:34 2007 -0400 Yevgeny Kliteynik a54fbec431a561e5f9c196b1cf69d4b8ef538a47 * OpenSM: Update doc with root and compute nodes options for fat-tree Mon Jul 9 06:54:56 2007 -0400 Yevgeny Kliteynik 72c1876c2f49ed9cce851ab97e1471bac4330337 * OpenSM: Remove trailing blanks in doc/current-routing.txt and man/opensm.8 Sun Jul 8 18:14:26 2007 -0400 Yevgeny Kliteynik 5226841443915f52362ff0bbe76fd5b757005045 * OpenSM/osm_ucast_ftree.c: Enhance fat tree routing for non pure trees Sun Jul 8 05:03:51 2007 -0400 Yevgeny Kliteynik 99f2d5c26f6f0a1f7c70ee736d723751eb9b9b3f * OpenSM/osm_ucast_ftree.c: Cosmetic change to remove trailing blanks Sat Jul 7 06:48:37 2007 -0400 Hal Rosenstock 2a96be86c722847b408343408dc9557f17e2455d * PerfMgr: Handle LID redirection by PMA Fri Jul 6 12:38:42 2007 -0400 Ira K. Weiny 341a97cab021d5d2284a7bc2d2233cc91cda0a13 * OpenSM/osmeventplugin/configure.in: Remove unneeded check for thread library Fri Jul 6 09:59:07 2007 -0400 Hal Rosenstock c2034a01b061c25d0407e2f370d04762eb8289f2 * OpenSM/osm_perfmgr.c: Add dest_qp parameter to osm_perfmgr_send_pc_mad and in osm_perfmgr_check_overflow, check status and issue osm_log error message if osm_perfmgr_send_pc_mad fails Fri Jul 6 08:55:25 2007 -0400 Hal Rosenstock 6574fb7006ce569fc5202cff7fb41ab0632fda88 * OpenSM/osm_perfmgr.c: Cosmetic changes Fri Jul 6 07:22:28 2007 -0400 Hal Rosenstock 2a40478ed4542d4159e2c842e6dfd8dd6548bc19 * OpenSM: Handle "babbling" ports Fri Jul 6 07:19:16 2007 -0400 Hal Rosenstock 69acd5cce022e66fa3a8ef6e24007d29ee1da4e8 * OpenSM/osm_perfmgr.c: Cosmetic changes Thu Jul 5 14:33:34 2007 -0400 Hal Rosenstock ec03590aecd214550c75b7daaf2e3afe7174bfda * OpenSM/include/opensm/osm_madw.h: Comment out query_start in osm_perfmgr_context_t as not currently used in PerfMgr Thu Jul 5 13:55:23 2007 -0400 Hal Rosenstock ea3248ae29ee38517bc5b20d4d43b73cee449ccb * OpenSM/osm_port.c: Commentary change Thu Jul 5 12:51:17 2007 -0400 Hal Rosenstock 79b98f0d4a00c638bc9a37de7ab8310e654a3989 * OpenSM/osm_node.c: Commentary change Thu Jul 5 08:38:15 2007 -0400 Yevgeny Kliteynik 8a4e47542eac22ef767f7ab8a2b3164d663e4776 * OpenSM/osm_ucast_mgr.c: Fix bug in dumping opensm.fdbs Wed Jul 4 07:48:44 2007 -0400 Hal Rosenstock 6c45f0b8c6e960220fda8161781e4c7a4e072b66 * OpenSM/osm_perfmgr.c: Cosmetic changes Wed Jul 4 07:33:16 2007 -0400 Hal Rosenstock 7d1fed5dd1a655022779087abca7d145ef6c71da * OpenSM/osm_perfmgr.c: Cosmetic formatting changes Wed Jul 4 07:26:09 2007 -0400 Hal Rosenstock f0fc5fe5f61dbbd48a1cf7393b97e5ea739ff7c5 * OpenSM/osm_perfmgr.c: Cosmetic changes Wed Jul 4 07:18:45 2007 -0400 Hal Rosenstock 2cae2f20280215a70a3e91a4f730bc0bc0b83605 * OpenSM/include/opensm/osm_perfmgr.h: Cosmetic changes Tue Jul 3 17:27:48 2007 -0400 Hal Rosenstock 768ac8bfa744b38c66168dfc4aed7c50b73af05d * OpenSM/osm_perfmgr.c: In osm_pc_rcv_process, convert endian of redirection parameters in osm_log message Tue Jul 3 17:20:37 2007 -0400 Hal Rosenstock 0db3a2a77614043906b7b4cc5f7ba621d339a9f3 * OpenSM/osm_perfmgr.c: Add RedirectQP into redirection osm_log message in osm_pc_rcv_process Tue Jul 3 15:17:27 2007 -0400 Hal Rosenstock df023de6f47f5849aeeb7c6fadf74ff302bc33b7 * OpenSM/osm_perfmgr.c: In osm_pc_rcv_process, indicate redirect LID and GID when redirection received. Also, prepare for redirect LID implementation. Tue Jul 3 10:50:30 2007 -0400 Hal Rosenstock 4c61d29e2eb367bb46814ff56254ae22f7f1d68a * OpenSM/PerfMgr: Rename ib_perfmgr_mad_t to ib_perfmgt_mad_t Tue Jul 3 10:43:47 2007 -0400 Hal Rosenstock 1e8e105c89e68c610a80cc11d58ea446865544f6 * OpenSM/include/opensm/osm_madw.h: Fix commentary typo Tue Jul 3 10:42:43 2007 -0400 Hal Rosenstock c644d8dc005222a452696a619642cc72e3c2d93b * OpenSM/include/iba/ib_types.h: Fix commentary typo Tue Jul 3 10:27:56 2007 -0400 Hal Rosenstock ea5b036f06ef6a4465db0022d5549334ab2f19a5 * OpenSM/osm_perfmgr.c: In osm_pc_rcv_process, some comments and minor change to osm_log message around redirection Tue Jul 3 10:20:52 2007 -0400 Hal Rosenstock a46c3db38fed731122cf0eb37c8ba5eab8404367 * OpenSM/osm_perfmgr.c: In osm_pc_rcv_process, add MAD status to osm_log message Tue Jul 3 09:38:58 2007 -0400 Hal Rosenstock 1883d2610bb5614b77a32155cdb426c94167ca9e * OpenSM/osm_perfmgr.c: Cosmetic commentary changes Tue Jul 3 09:30:29 2007 -0400 Hal Rosenstock 1ca113b57a3eb8c0ccb793b886bc67f415e232d8 * OpenSM/osm_perfmgr.c: Cosmetic formatting changes Tue Jul 3 09:00:06 2007 -0400 Hal Rosenstock e25a113eeda077b187ea407e6c71d685b681cf88 * OpenSM/osm_perfmgr.c: Cosmetic changes Tue Jul 3 08:54:24 2007 -0400 Hal Rosenstock 9d70d2ca2bc725f76772ea6a8fe621a05a4defd0 * OpenSM/osm_perfmgr.c: Cosmetic commentary changes Tue Jul 3 08:47:40 2007 -0400 Hal Rosenstock 16328dcef34ea08aa91e4237c469888f756b6831 * PerfMgr: Eliminate unneeded num_ports Tue Jul 3 07:15:21 2007 -0400 Hal Rosenstock ecedf928b80070a6eb3f0389508ee8afa0d17ac0 * OpenSM/osm_perfmgr.c: Cosmetic formatting changes Tue Jul 3 07:03:45 2007 -0400 Hal Rosenstock 873ab84946ccbc8744010867313eb915c08dc162 * OpenSM/osm_perfmgr.c: Cosmetic changes Mon Jul 2 09:09:59 2007 -0400 Sasha Khapyorsky 91485898e6431889c5e79a0f7d6995f7780df333 * OpenSM: Use osm_get_node/port_by_guid() functions Sun Jul 1 07:39:41 2007 -0400 Hal Rosenstock 735bb724d577006dcabaf2ce6c6e240669d3e847 * OpenSM/osm_subnet.c: Cosmetic change Mon Jun 25 12:44:09 2007 -0400 Hal Rosenstock 0760168f7cbdb56071dba6bac7155f3997e94210 * OpenSM/include/opensm/osm_req.h: Cosmetic changes Mon Jun 25 12:43:40 2007 -0400 Hal Rosenstock b0cb8e867ad5cad8473d0eb7752b156710dae2f4 * OpenSM/include/opensm/osm_resp.h: Cosmetic changes Mon Jun 25 12:34:46 2007 -0400 Hal Rosenstock 2dcb2629b839bdd239a28b1120f4007f393dbabd * OpenSM/include/opensm/osm_lid_mgr.h: Added comment for missing field Mon Jun 25 12:34:12 2007 -0400 Hal Rosenstock 9d67be9da2334285da105b10468de40c6730db11 * OpenSM/include/opensm/osm_link_mgr.h: Cosmetic changes Mon Jun 25 10:56:58 2007 -0400 Hal Rosenstock b0a47943cbeedbe0e114738278d7f3ee4e281734 * OpenSM/osm_link_mgr.c: Cosmetic commentary changes Mon Jun 25 10:56:41 2007 -0400 Hal Rosenstock 7502a466c6d363782e22393a08cd6dd37ef34d69 * OpenSM/osm_lid_mgr.c: Cosmetic commentary changes Mon Jun 25 10:12:14 2007 -0400 Hal Rosenstock 6e3571a8b1e492958873f43b437f68c1f5bf7178 * OpenSM/osm_trap_rcv.c: Cosmetic change to currently commented out osm_log message Mon Jun 25 09:44:24 2007 -0400 Hal Rosenstock 15fcd5ae0700b90c3f44e20b25cd9a01fecd6815 * OpenSM/osm_subnet.c: Fix comment in opensm.opts file relative to excessive buffer overrun trap number Mon Jun 25 08:44:43 2007 -0400 Hal Rosenstock 999b2a82f5038a3ade621af1dc175800abf22b31 * OpenSM/complib/cl_event_wheel.c: Fix some typos in printfs when __CL_EVENT_WHEEL_TEST__ defined Mon Jun 25 08:41:37 2007 -0400 Hal Rosenstock bec6b363ef407ed96ebcc4665905511dc8fb2892 * OpenSM/osm_trap_rcv.c: Various cosmetic changes including to some osm_log messages Mon Jun 25 08:40:32 2007 -0400 Hal Rosenstock f7a86524d9b81e94ecf183212c78ec67174a2d89 * OpenSM/osm_switch.c: Cosmetic formatting change Mon Jun 25 08:40:07 2007 -0400 Hal Rosenstock 7d311049fe50563b2675bc727bc4f62a624deb33 * OpenSM/osm_state_mgr.c: Cosmetic formatting change Mon Jun 25 07:25:54 2007 -0400 Hal Rosenstock 610adc778b7f76830283438bfc2c0f63c0154a49 * OpenSM/osm_port.c: Cosmetic formatting change Mon Jun 25 07:25:06 2007 -0400 Hal Rosenstock 7b005408257ed6ce51e48ea9b2d1fd78c6de2adf * OpenSM/include/opensm/osm_base.h: Commentary change Fri Jun 22 07:04:08 2007 -0400 Sasha Khapyorsky 83cb1688c7af377943edcc2a93c97e38244678bd * OpenSM/updn: --conect_roots option Thu Jun 21 13:26:54 2007 -0400 Hal Rosenstock fc49da4d61ef7ba3c9d18f511be6b320a1026ef9 * OpenSM/man/opensm.8: Updated man page for --root_guid_file (rather than --add_guid_file) and -u/--cn_guid_file options from Yevgeny Thu Jun 21 12:43:31 2007 -0400 Yevgeny Kliteynik 407e8c26031d29c6bef4dac4898fd72a16d23a4f * OpenSM: Add root_guid_file and cn_guid_file OpenSM options Wed Jun 20 13:50:14 2007 -0400 Hal Rosenstock 7650bede7ce16cc2c12b67384556396a876da24a * OpenSM/osm_helper.c: Add 3LeafNetworks and Xsigo to osm_get_manufacturer_str Wed Jun 20 12:09:28 2007 -0400 Hal Rosenstock 04ce63272ea7e4fa8e3a4dda760fe10986183ee3 * OpenSM/complib/libosmcomp.map: Add get_next map functions as global Wed Jun 20 11:41:08 2007 -0400 Hal Rosenstock f4df3bc28bf546043d6b9153cd6a3134b60a677c * OpenSM/complib/ChangeLog: Add log entry for Todd's change to add get_next functions to the various maps Wed Jun 20 11:38:37 2007 -0400 Todd Rimmer 99acdc8a81fddb4d1c841df80e96837b5ddc186c * OpenSM/complib/cl_*map: Add get_next functions to the various maps Wed Jun 20 11:25:39 2007 -0400 Hal Rosenstock 2b06f72a6bcab55d765e3fe1b1645c61a8e8ae1e * OpenSM/osm_lid_mgr.c: In __osm_lid_mgr_set_physp_pi, add GUID and port number into some debug osm_log messages Wed Jun 20 10:38:29 2007 -0400 Hal Rosenstock a62d0a4d08afd0d83af4897b71fe650e6b18435b * OpenSM/osm_sminfo_rcv.c: In __osm_sminfo_rcv_process_set_response, decode SMInfo attribute for additional debug information Wed Jun 20 10:07:12 2007 -0400 Hal Rosenstock 860e80e5bcb7f3bea4113faa74fda8328b41baa3 * OpenSM/osm_sminfo_rcv.c: Commentary change Wed Jun 20 09:27:33 2007 -0400 Todd Rimmer a6ec7209bf0279b329d897d64264fdcc465cfebb * OpenSM/include/complib/cl_fleximap.h: In cl_fmap_remove_all, make sure the count field is properly maintained     Signed-off-by: Todd Rimmer Signed-off-by: Hal Rosenstock Wed Jun 20 06:35:31 2007 -0400 Hal Rosenstock 2e93de50aae7162a748f3262b8355a685fa54866 * OpenSM/osm_perfmgr_db.c: Cosmetic formatting changes Wed Jun 20 06:18:21 2007 -0400 Hal Rosenstock 95ad48c0d54bf2f154f20eadfd31f835742758a1 * OpenSM/include/complib/cl_(map qmap fleximap).h: Cosmetic changes Tue Jun 19 17:58:56 2007 -0400 Todd Rimmer 0d35ee64b7892b6092d8d0724b1cc5559e6556b9 * OpenSM/include/complib/cl_qmap.h: In cl_qmap_remove_all, make sure the count field is properly maintained Tue Jun 19 16:41:29 2007 -0400 Hal Rosenstock 20e76d4af93821c1502b8cfda8faba640463324b * OpenSM/osm_perfmgr.c: In osm_perfmgr_check_overflow, reset previous reading so set doesn't cause erroneous out of band clear indication Tue Jun 19 15:51:38 2007 -0400 Hal Rosenstock af6526d3780d1d1356adb559687f97643b383cf7 * OpenSM/osm_perfmgr.c: Cosmetic changes Tue Jun 19 15:18:41 2007 -0400 Hal Rosenstock dae8028bacec01056cb2b3eb9385ce07fe4de55e * OpenSM/osm_perfmgr.c: Cosmetic formatting change Tue Jun 19 15:15:53 2007 -0400 Hal Rosenstock cff628a92e5932eb0d914c833cda3536b427d5c9 * PerfMgr: Cosmetic changes to some osm_log messages Tue Jun 19 14:20:05 2007 -0400 Ira K. Weiny 373efa7a05910321041a44020637f3b88555a149 * PerfMgr: Removed no longer needed eventdb Tue Jun 19 14:02:18 2007 -0400 Ira K. Weiny c7641f8afe994f3d8efd5aa21850706585bb6748 * PerfMgr: Convert "eventdb" to be a default event plugin which is optional. Tue Jun 19 13:20:39 2007 -0400 Hal Rosenstock 3cf6b2ac2ce88f4d761c19f0eba8a50e90ce570a * OpenSM/include/complib/cl_threadpool.h: Eliminate compile warning with cl_threadpool.c introduced by previous change Tue Jun 19 10:44:36 2007 -0400 Ira K. Weiny 111dd52d1da75ea802888e8424d59ff1459e4319 * PerfMgr: Move database of port counter data into new PerfMgr DB object. Tue Jun 19 10:05:18 2007 -0400 Ira K. Weiny 61353c444fee3acb52e2350c03cbce22d70d9402 * PerfMgr: Change prefix of perfmgr_edb (event db) functions to perfmgr_db Tue Jun 19 09:57:45 2007 -0400 Ira K. Weiny d63d426746213fe5fbc3a187612bc28de0025261 * OpenSM/PerfMgr: Remove no longer needed osm_event_db.c and osm_event_db.h as they are renamed to osm_perfmgr_db.c and osm_perfmgr_db.h Tue Jun 19 09:55:25 2007 -0400 Ira K. Weiny 8f81e72a3b57e0efdba816e774130dfcbf616572 * OpenSM/include/Makefile.am: PerfMgr header file name change to go along with previous commit Tue Jun 19 09:53:54 2007 -0400 Ira K. Weiny 6a472fbe9048edce8cb8388b977db9b78ba58c03 * OpenSM/PerfMgr: Rename osm_event_db.* to osm_perfmgr_db.* in preparation for plugin change Sat Jun 16 10:49:13 2007 -0400 Hal Rosenstock f7000edf9fe109991fdb53f419e63e3e33212127 * OpenSM/osm_lid_mgr.c: Cosmetic commentary change Sat Jun 16 10:15:12 2007 -0400 Hal Rosenstock 04f3e90ad0bf5217a4046e96804b0a1b2ed28755 * OpenSM/include/opensm/osm_base.h: Cosmetic change Fri Jun 15 13:21:57 2007 -0400 Yevgeny Kliteynik 767914efd21e78137d08daacc81e7c31fbd645d7 * OpenSM/osm_ucast_ftree.c: If fat-tree failed, osm should fall back to default routing Fri Jun 15 13:07:43 2007 -0400 Hal Rosenstock c9525e7ecd20c56eab17ec59ea5f6d1528597112 * OpenSM/complib/ChangeLog: Add log entry for Sasha's thread pool rework Fri Jun 15 13:07:05 2007 -0400 Sasha Khapyorsky 530f4996dbc35ab2fffe808c86fa4434b65769bc * OpenSM/complib: thread_pool rework Fri Jun 15 12:35:31 2007 -0400 Hal Rosenstock cbd3c9dca2aa7e23f93127e503604125cc8ef440 * OpenSM/opensm/ChangeLog: Add log entry for Sasha's previous fix to osm_helper.c for PortInfo:CapMask printing when CapMask is 0 Fri Jun 15 12:33:54 2007 -0400 Sasha Khapyorsky 441c0dc08533a2c9fc72bf9c29d7a495e67cb28d * OpenSM/osm_helper.c: Fix PortInfo:CapMask printing when CapMask is 0 Wed Jun 13 14:16:50 2007 -0400 Sasha Khapyorsky e073df42c09b6a1bfdc5f1b4d0c3d1546f308e8e * OpenSM/osmtest/osmt_multicast.c: Add missing include file Wed Jun 13 13:25:29 2007 -0400 Hal Rosenstock 468dc2a2501c0d49453e94207a882582f9e412a5 * OpenSM/complib/ChangeLog: Updated log entry for Sasha's previous change to modify include/Makefile.am for header files removed Wed Jun 13 13:23:48 2007 -0400 Sasha Khapyorsky 6aed0c6eba942276210d5c75315021033a96a3a6 * OpenSM/complib: Additional changes for removal of unused complib stuff Wed Jun 13 12:22:32 2007 -0400 Ira K. Weiny e9f6dd2356ef1b0d794c3533df6cecc6e6433a52 * OpenSM/osm_console.c: Clear up the dump_counters option of the perfmgr. Wed Jun 13 11:16:37 2007 -0400 Hal Rosenstock e46aa2b4a33a07e4fa794ef02c1d748cd47fcbab * OpenSM/osm_perfmgr.c: Minor change to move osm_log message prior to obtaining lock so locked time is less Wed Jun 13 10:11:07 2007 -0400 Hal Rosenstock f7b0b7177c50f0b15264205f65301526383a8810 * OpenSM/complib: Remove unneeded (previously deprecated) cl_mem* files Wed Jun 13 10:04:50 2007 -0400 Hal Rosenstock 947d15eafeeab83ccf5a879fd7da9c8a78c692da * OpenSM/complib: Remove deprecated memory allocation routines Wed Jun 13 09:17:11 2007 -0400 Hal Rosenstock 72fb44d408d581d322cd4b2bc68d24d7e98c2509 * OpenSM/complib: Update version info fori previous API removals Wed Jun 13 08:32:09 2007 -0400 Hal Rosenstock e070d441b0de7ec8cd236ba14a9ba04d84051654 * OpenSM/complib/ChangeLog: Add log entry from Yevgeny's change to remove unused cl_perf and cl_async_proc Wed Jun 13 08:29:32 2007 -0400 Yevgeny Kliteynik 1cbb6e3b74ab0468a8aedcb0dbaf7ed072a1495e * OpenSM/complib: Remove unused cl_perf and cl_async_proc Tue Jun 12 11:34:57 2007 -0400 Hal Rosenstock b43a63773336a79c277f8d992ecef4fa352341ef * OpenSM/osm_perfmgr.c: Cosmetic changes Tue Jun 12 11:26:42 2007 -0400 Hal Rosenstock c1a4c5f89e4df5c8b19dfe437f528e005ae2edc5 * OpenSM/osm_sminfo_rcv.c: Commentary changes Tue Jun 12 11:25:26 2007 -0400 Hal Rosenstock cb16e8a1195f9f491264b89eab455dfc4952208e * OpenSM/osm_sa_mcmember_record.c: Commentary change Tue Jun 12 09:48:19 2007 -0400 Hal Rosenstock 00262062a50aa21bfe6624f0cf1180142b9f035f * OpenSM/osm_perfmgr.c: Start to handle redirection Tue Jun 12 08:37:41 2007 -0400 Hal Rosenstock 4a33f09a4e90a2c79832cdcb8bee9f3efec94132 * OpenSM/osm_sa_class_port_info.c: Commentary change Tue Jun 12 07:40:33 2007 -0400 Hal Rosenstock 3d524ab28891758afdf8558cd793318d4e2e13d2 * OpenSM/osm_perfmgr.c: Cosmetic changes to some osm_log messages Tue Jun 12 07:28:22 2007 -0400 Hal Rosenstock f8af24b0be6ba504d89611ec6038c7b37a0c7cc9 * OpenSM/osm_sa_class_port_info.c: Eliminate unneeded assignment and variable Tue Jun 12 07:01:48 2007 -0400 Hal Rosenstock 65d643da8d8a8d68e443ebd5782830725c0ca16c * OpenSM/include/opensm/osm_madw.h: Commentary change Tue Jun 12 06:55:18 2007 -0400 Hal Rosenstock db51ae0d00f3d01ac4903b8357b903fe0ea9d23b * OpenSM/include/iba/ib_types.h: Cosmetic formatting change Tue Jun 12 06:38:21 2007 -0400 Hal Rosenstock 52fd3169669f786c4bef5e69518236c3196e6f5d * OpenSM/osm_perfmgr.c: Cosmetic formatting change Mon Jun 11 18:57:47 2007 -0400 Yevgeny Kliteynik 70ad4a2f8f89257a8f4c56271a2a9b9ad06d05d2 * OpenSM/osm_ucast_updn.c: Make up/dn ranking code more intuitive Mon Jun 11 11:22:33 2007 -0400 Sasha Khapyorsky 4ace1d9466d5ec124df76f278b610866dd43a36a * OpenSM: Remove no longer used state_step_mode Mon Jun 11 11:17:23 2007 -0400 Hal Rosenstock 9af500c7e2399e37c32d9559e33e6b0391a42c69 * OpenSM/opensm/ChangeLog: Add log entry for Sasha's previous change to remove OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTEDi from __osm_sm_mgr_signal_str Mon Jun 11 11:08:39 2007 -0400 Sasha Khapyorsky 33bdc41214064c7aac1ec3aa5140126e0c3d0215 * OpenSM: Clean unused OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED Mon Jun 11 10:56:12 2007 -0400 Yevgeny Kliteynik 6b5d79d82a370d234c796631da2d41afd214afb4 * OpenSM/osm_ucast_mgr.c: Trivial bug fix in osm_ucast_mgr_read_guid_file Mon Jun 11 09:20:20 2007 -0400 Yevgeny Kliteynik b41e23e60f4c95af861161847055acf16ef9f4c9 * OpenSM: Generalize reading of guids from file in ucast_mgr Mon Jun 11 09:16:11 2007 -0400 Hal Rosenstock b9edfbc5360b7c2a0b3e245dfd6c0eb8e7ccaf19 * OpenSM/man/opensm.8: Cosmetic formatting change Mon Jun 11 08:49:25 2007 -0400 Hal Rosenstock 08d180a04a5a58f0aad8b344e7069c0b33db0790 * OpenSM/main.c: Cosmetic formatting change Mon Jun 11 06:44:07 2007 -0400 Hal Rosenstock b117621ac6e1162d2a528bafde0e0f4923655eed * OpenSM/man/opensm.8: Add reference for up/down algorithm Mon Jun 11 06:36:50 2007 -0400 Hal Rosenstock a441979c20b426babfccb91eab4d45a71710cf45 * OpenSM/man/opensm.8: Cosmetic formatting change Fri Jun 8 11:27:49 2007 -0400 Hal Rosenstock 828b4c89a44227f6679cb9fe8d347114e1ae346b * OpenSM/osm_(port_info_rcv opensm).c: Restore changes to set PortInfo:CapabilityMask IsSM when sm_inactive as it does respond to SubnGet/Sets of SMInfo (so this is better) Fri Jun 8 10:58:55 2007 -0400 Hal Rosenstock 874c2e28180ff91a88ff742de600e33622051f96 * OpenSM/man/opensm.8: More tweaks to inactive option Fri Jun 8 10:51:51 2007 -0400 Hal Rosenstock 6a36fc232cb5fdb4b4659813d0bafbea89b5b051 * libvendor/ChangeLog: Cosmetic change Fri Jun 8 05:48:48 2007 -0400 Hal Rosenstock 4c62451c9a5d85ffa252baa31b4dde5a47a6c1cb * OpenSM/osm_opensm.c: In osm_opensm_destroy, only clear the issm bit in PortInfo:CapabilityMask if it were previously set (e.g. sm_inactive is not invoked) Fri Jun 8 05:47:28 2007 -0400 Hal Rosenstock f7105fba6dde4810cc2f96ecea7dd5562dd6f5d9 * OpenSM/osm_port_info_rcv.c: Cosmetic change to previous change Fri Jun 8 05:40:42 2007 -0400 Hal Rosenstock 79df208c49c887938b6cf750929d162af80fe4cf * OpenSM/osm_port_info_rcv.c: In __osm_pi_rcv_process_endport, don't set issm bit in PortInfo:CapabilityMask if sm_inactive Thu Jun 7 16:29:47 2007 -0400 Hal Rosenstock e3d2b4568678a262b6060b7a8d551f4fc00cf70b * OpenSM/osm_perfmgr.c: Cosmetic changes to some osm_log messages Also, fixed some typos, comments, and other cosmetic changes Thu Jun 7 11:52:15 2007 -0400 Hal Rosenstock 50937204c0a480a1aab0b1b7008989a87a2a4545 * OpenSM/man/opensm.8: Indicate inactive is not yet supported by performance manager Thu Jun 7 11:42:25 2007 -0400 Hal Rosenstock 9128f1f9dc51f362e417db57918a0accebcaee59 * OpenSM/osm_perfmgr.c: Cosmetic changes Thu Jun 7 11:39:27 2007 -0400 Hal Rosenstock a673bf39b06e42b72799515f8aa1dc25a2fef7a1 * OpenSM/man/opensm.8: Cosmetic change to --inactive description Thu Jun 7 10:39:46 2007 -0400 Hal Rosenstock d69599a93d985b4156ec0c179f9b2743565363c4 * OpenSM/osm_perfmgr.c: Cosmetic change to osm_log message Thu Jun 7 10:27:44 2007 -0400 Hal Rosenstock df23d39ba7b5c1aed44749b50c0e46e60f1f6423 * OpenSM/man/opensm.8: Add more explanation on use of --inactive Wed Jun 6 12:41:48 2007 -0400 Sasha Khapyorsky adb664ad87285e4a1b71b1e8a41554e12b26dc45 * OpenSM/osm_(helper state_mgr).c: More optimally define manufacturer strings so as not to put extra space in .text Wed Jun 6 10:32:45 2007 -0400 Hal Rosenstock 12a3ed278f0e4f121970cfd63331d1ceedc2bb82 * OpenSM/osm_helper.c: Add Sun to osm_get_manufacturer_str Wed Jun 6 08:58:06 2007 -0400 Yevgeny Kliteynik b71117f501aa4b8a1d20a600c2d8c684eaa9d74f * OpenSM/osm_vendor_mlx.h: Fix broken compilation when osm_vendor is Mellanox simulator Wed Jun 6 07:12:48 2007 -0400 Hal Rosenstock 0febff17365fead912125f5615681b3780aff9be * OpenSM/osm_state_mgr.c: Updated one compliance identifier for IBA 1.2 Wed Jun 6 06:52:03 2007 -0400 Hal Rosenstock a509fa5815d89b52508541bd5fe17d36e693ac0c * OpenSM/osm_state_mgr.c: Cosmetic changes (osm_log messages, comments, etc.) Wed Jun 6 06:51:17 2007 -0400 Hal Rosenstock 1d5f30629e17b10b944a746b8c9c640b3ef87348 * OpenSM/osm_sm_state_mgr.c: Fixed typo in osm_log message Wed Jun 6 06:50:46 2007 -0400 Hal Rosenstock 48c61babe98e7fde875398b91aaa5f3e2975738b * OpenSM/osm_sminfo_rcv.c: Updated a couple of IBA 1.2 vol 1 references Tue Jun 5 13:24:54 2007 -0400 Sasha Khapyorsky ff1870747ff5083f53bd976dc9540584a0ee58da * OpenSM: Protect SMInfo response Mon Jun 4 11:53:18 2007 -0400 Hal Rosenstock 59f02c2ad325b25a9869fe179935af9c5ae35a3c * OpenSM/opensm/ChangeLog: Add log entry for previous change to add 8x to __osm_lwa_str_fixed_width Mon Jun 4 09:20:14 2007 -0400 Hal Rosenstock 38bf0b4a108b8f2578546dd23496622390fddd4a * OpenSM/osm_helper.c: Add 8x to __osm_lwa_str_fixed_width Sat Jun 2 09:16:40 2007 -0400 Hal Rosenstock c1cd6dff299f121a40605cb821dbb2ea7dbc320e * OpenSM/complib/configure.in: Bumped version to 2.1.3 (in sync with ofed_1_2) Sat Jun 2 09:03:11 2007 -0400 Hal Rosenstock 245e44150e0b4e5b9a04a81c63c78f255cee6e17 * OpenSM/doc/opensm_release_notes_openib-3.0.13.txt: Updated for 3.0.13 with SMInfo self check fix Sat Jun 2 08:56:35 2007 -0400 Hal Rosenstock b6f502e88a9d112776a85af4e2ff40ac99a82fb9 * OpenSM/doc: Renamed opensm_release_notes_openib-3.0.12.txt to opensm_release_notes_openib-3.0.13.txt for version change Thu May 31 19:05:14 2007 -0400 Sasha Khapyorsky 16966658bf3120ef967728686350aae76e275b9c * OpenSM/osm_sminfo_rcv.c: Mutex cleanup fix Thu May 31 18:24:06 2007 -0400 Sasha Khapyorsky d55c104ebd0d9993276259d5d31a0cffdd9ca626 * OpenSM/osm_sminfo_rcv.c: Add SMInfo self query check Thu May 31 18:14:10 2007 -0400 Sasha Khapyorsky 20d69e689844d835f1f958ce2f565d6c030cb66d * OpenSM/osm_link_mgr.c: Fewer iterations in osm_link_mgr_process() loop Thu May 31 17:42:16 2007 -0400 Sasha Khapyorsky 597d08b6d72f79f21daf3cb0a2ddc4bf51fb5bf9 * OpenSM: Cleanup discovery count functions Thu May 31 12:33:39 2007 -0400 Hal Rosenstock 98727475be36e49d130081f46242a567adb5ac72 * management/*.spec: Remove *.spec files from management git repo as committed files. They are generated files. Thu May 31 11:41:16 2007 -0400 Hal Rosenstock 4c3855711c1a35ab29ae22f26afee5f9e7f38175 * management/*.spec: Latest daily versions of .spec files (prior to removing these due to build changes) Thu May 31 09:58:54 2007 -0400 Hal Rosenstock f93ee06884f8130ef04cf07a6fca2d6c8653da21 * OpenSM/(complib/libosmcomp eventdb/libibeventdb libvendor/libosmvendor).spec.in: Change Source and Url to openfabrics rather than openib Thu May 31 08:43:01 2007 -0400 Hal Rosenstock 9344460e473333cc332260a6f9b073bcd89664fa * OpenSM/osm_perfmgr.c: Added error numbers to OSM_LOG_ERROR osm_log messages Thu May 31 08:34:11 2007 -0400 Hal Rosenstock 0955d88825752cc22715f1a4c7487935f890ad30 * OpenSM/osm_console.c: Added error numbers to OSM_LOG_ERROR osm_log messages Thu May 31 06:47:43 2007 -0400 Hal Rosenstock 8c1e82f23bc6528a7456649d7287afdae3fb7aca * OpenSM/README: Changed for move from bin to sbin Wed May 30 23:58:24 2007 -0400 Sasha Khapyorsky db0c46436df0fead42da65c920126ef994e1006a * OpenSM: osm_node_get_physp_ptr() usage fixes Wed May 30 21:00:41 2007 -0400 Ira K. Weiny 8fb2c2095f16c2e8ac833f62dc9d374df24dca05 * OpenSM/osm_console.c: Add outstanding queries and the set max to the perfmgr console command Wed May 30 20:57:00 2007 -0400 Ira K. Weiny 1f87b83cdbffae755d177394bff53eaea78240d2 * OpenSM: Make PerfMgr's max outstanding queries configurable Wed May 30 18:53:08 2007 -0400 Sasha Khapyorsky 4d2c2bf7e6d4d6023113dace243b2b7662acc8d6 * OpenSM/man/opensm.8: Indicate default priority Wed May 30 18:47:30 2007 -0400 Ira K. Weiny 869cfd87c9a94a917f7f3a705620c6d18200ba61 * OpenSM/man/opensm.8: Add perfmgr command line options to opensm man page Wed May 30 18:46:05 2007 -0400 Ira K. Weiny 24c150a04a952c7175de257829abdba82a324024 * OpenSM/main.c: Add perfmgr command line options Wed May 30 16:55:58 2007 -0400 Ira K. Weiny b22b70ab5ec38e118c83f18bba4fba288a75450e * OpenSM/main.c: Fix short options so they do not conflict with long options Wed May 30 16:45:24 2007 -0400 Ira K. Weiny 9e3daf3876cc591bd5c2a8443bf1be7994ed6ec3 * OpenSM/include/opensm/osm_perfmgr.h: Signal an immediate sweep when the user enables the perfmgr Wed May 30 15:50:42 2007 -0400 Hal Rosenstock cd5b815b943635b15d71a0aeda76e2639eda543a * OpenSM/osm_drop_mgr.c: Cosmetic change to osm_log message Wed May 30 15:44:48 2007 -0400 Hal Rosenstock 2e60ed70395b84c40eb5a83272a7d52026683e9e * OpenSM/osm_drop_mgr.c: Cosmetic changes Wed May 30 15:42:15 2007 -0400 Sasha Khapyorsky 778765694333ec8bcf65bb9d87a7a8e44dd217a6 * OpenSM/osm_drop_mgr.c: Clean only associated with port physical obj Wed May 30 13:57:06 2007 -0400 Ira K. Weiny 2f10c0858fac921a8d8b5770f4a18537d1cdd8c5 * OpenSM/include/iba/ib_types.h: Fix NOTICE macros to convert from host to network byte order. Wed May 30 13:46:49 2007 -0400 Ira K. Weiny fdc2ea226ea4a21843c6341b283069140b9a2cf0 * OpenSM/include/iba/ib_types.h: Change macros to convert from "host" byte order to "network" byte order rather than the other way around Wed May 30 07:30:09 2007 -0400 Hal Rosenstock 5764880000e9dd77a9bb378e9fa02ebdfb8759a1 * OpenSM/osm_console.c: Cosmetic change to perfmgr help Wed May 30 07:22:00 2007 -0400 Ira K. Weiny 2f5a0b53bea7dd9d9afeb278890e1bcb20423372 * OpenSM/osm_console.c: Add PerfMgr status to status command Wed May 30 07:13:16 2007 -0400 Ira K. Weiny 42ab38b7fdc12d70706d55a4df651efff198a634 * OpenSM/osm_perfmgr.c: Pause PerfMgr thread indefinitely if the max number of outstanding PerfMgr queries exceeds the threshold Wed May 30 07:09:04 2007 -0400 Ira K. Weiny 7d3bd6fb9f2efff8083f3787396a2630c1eae136 * OpenSM/include/opensm/osm_perfmgr.h: Clean up formatting of perfmgr object Wed May 30 07:05:13 2007 -0400 Ira K. Weiny c3a9ae030376906f0180dff2d8bbd8b651db4be1 * OpenSM/PerfMgr: Add sweep state to the perfmgr object Wed May 30 06:34:06 2007 -0400 Sasha Khapyorsky e24d9fcf933086f4ac0767cd213ae27a12f88ca8 * OpenSM/osm_console.c: portstatus command is only for initialized ports Tue May 29 17:15:04 2007 -0400 Hal Rosenstock 7af01643caaecc9ecfc01d371c5a860709048b71 * OpenSM/osm_sa_informinfo.c: Cosmetic formatting changes Tue May 29 08:24:21 2007 -0400 Hal Rosenstock 275d8f49b915568f5b5adc7419e54ff31375561e * OpenSM/man/opensm.8: Add mention of performance manager (as experimental) Tue May 29 08:01:56 2007 -0400 Hal Rosenstock 51466ceb785c786cc1d7d76232d6f2cf8f50c317 * OpenSM/include/opensm/osm_perfmgr.h: Change OSM_PERFMGR_DEFAULT_DUMP_FILE from osm_port_counters.log to opensm_port_counters.log Sun May 27 08:08:38 2007 -0400 Sasha Khapyorsky 660fea26361b316bf97cf30dc8f9553ad945b15e * OpenSM/osm_perfmgr.c: In __osm_perfmgr_query_counters, check for physp valid prior to obtaining LID (and handle this) to prevent assertion Sat May 26 13:44:28 2007 -0400 Hal Rosenstock 71d3f3b4dc55f24fbab4b4c2bfdea9b4ae6f3911 * OpenSM/osm_subnet.(h c): Cosmetic changes Sat May 26 13:27:03 2007 -0400 Hal Rosenstock 7c96ef20fe980f5d57b7f91b5e3adbe4c3efa0c2 * OpenSM: Change qp1_ stats to sa_ stats Sat May 26 13:25:12 2007 -0400 Hal Rosenstock b4f89b27e4d46b9022a8b773ade1e525dfcf4bea * OpenSM/osm_perfmgr.c: Cosmetic changes Sat May 26 11:52:03 2007 -0400 Hal Rosenstock f947306378174b300a9da79fbe9e21cdd7be7a22 * OpenSM/osm_perfmgr.c: In __collect_guids, handle malloc failure Sat May 26 11:32:44 2007 -0400 Ira K. Weiny cff35777fbf1e5f285d0f2d2d20c92e2dfde2041 * OpenSM: Initial Perf Manager Sat May 26 10:29:11 2007 -0400 Hal Rosenstock 2d0f7df1ef0e231a124c8e28099275dcc02349ef * OpenSM: Cosmetic formatting changes to osm_vl15intf.c and osm_sa.c Wed May 23 21:09:13 2007 -0400 Ira K. Weiny 8a7b6397220c86737655f9562ec9739f301088ef * OpenSM/opensm.spec.in: Move osmtest from bin to sbin Wed May 23 17:00:24 2007 -0400 Hal Rosenstock cb3fa582b33239d93b011c27e865b5c851e25838 * OpenSM/osm_pkey*.c: Cosmetic formatting changes Tue May 22 14:53:34 2007 -0400 Ira K. Weiny 5fe7eede3f9430f7fb4ab4bf2b799deb1fb005e4 * OpenSM/osm_console.c: Add locking around the subnet port_lid_tbl in the querylid console command Tue May 22 07:05:51 2007 -0400 Hal Rosenstock c563c929da173d6c46694f9afde907b80b4088d7 * OpenSM/doc/opensm_release_notes_openib-3.0.12.txt: Remove isSMdisabled change Mon May 21 14:13:55 2007 -0400 Yevgeny Kliteynik 573e65ff47a0b008cebd09d973c96073b61efe7a * OpenSM/osm_ucast_updn.c: Up/down optimization - improved ranking Mon May 21 13:59:05 2007 -0400 Yevgeny Kliteynik efeaa1329523207dcca54c68d0fcea9b83e077f1 * OpenSM/osm_drop_mgr.c: Fix core dump in drop manager Mon May 21 13:03:18 2007 -0400 Ira K. Weiny eb52f7d50575b0f16cfbdc352c1510cb26c44897 * OpenSM/osm_console.c: Add portstatus command to the console Mon May 21 12:43:42 2007 -0400 Ira K. Weiny bbca13d23ed15a148230fb6d90d4fd1501cab20f * OpenSM/osm_console.c: Add querylid command to the console Wed May 16 14:26:08 2007 -0400 Hal Rosenstock 1524f0ce2319020fada1b562b08fd121abbea3a4 * OpenSM/include/Makefile.am: Changes for new ib_cm_types.h header file Wed May 16 14:25:24 2007 -0400 Hal Rosenstock e1314cfd3a557b88ba645b6c3e62d1d2b6a41c7b * OpenSM/ib_types.h: Remove CM definitions as now in ib_cm_types.h Wed May 16 14:24:40 2007 -0400 Hal Rosenstock 46d94f9a9d05d9f2a90d166f4f0c570eb1b22320 * OpenSM/ib_cm_types.h: Move CM definitions from ib_types.h Wed May 16 07:09:21 2007 -0400 Philippe Gregoire 01eddebbe1fdeb1b6528b27a7219417df88f9a51 * OpenSM/man/opensm.8: Add defmember partition feature description to man page. Wed May 16 07:08:16 2007 -0400 Philippe Gregoire 0b93504f5a192bf5e2cf09b3080fb93c40871f43 * OpenSM/osm_prtn_config.c: Add default membership (limited or full) to partition syntax. Wed May 16 06:58:01 2007 -0400 Hal Rosenstock 4cafe406680ff3085ac46bc721e064da5842a8f8 * OpenSM/doc/opensm_release_notes_openib-3.0.12.txt: Updated for 3.0.12 with up/down fix Tue May 15 12:56:25 2007 -0400 Hal Rosenstock dcf8e3381470f1e391607419f30a610c0c46e329 * OpenSM/doc/opensm_release_notes_openib-3.0.12.txt: Updated for 3.0.12 with up/down fix Tue May 15 12:44:49 2007 -0400 Philippe Gregoire 89f0b2bfafc56774ca4f00d8616804a69ce0cd6b * OpenSM/man/opensm.8: Improve man page readability. Tue May 15 11:52:25 2007 -0400 Hal Rosenstock 61fe1e15899e9774f8f361e2d60e47980eb5a81e * osmtest/Makefile.am: Move osmtest from bin to sbin (like opensm) Tue May 15 11:51:30 2007 -0400 Albert L. Chu 9d745ce74564aeceff336010bb220e1bc5fcedb3 * OpenSM/osm_subnet.c: Add QoS verification checks Tue May 15 11:37:37 2007 -0400 Albert L. Chu d4f8e2a7cf95517b9e476cff34cf7cbd774557e6 * OpenSM: Use macros for QoS defaults Tue May 15 11:28:19 2007 -0400 Yevgeny Kliteynik a1bb7d1d3ef95a5bb149b2e73cfd667ab2558616 * OpenSM/osm_subnet.c: Fix error message when failed opening cached options file Tue May 15 11:18:04 2007 -0400 Hal Rosenstock 4e5e724f7d6af9d1418eb9cefa7c6b8e16ebe178 * OpenSM/man/opensm.8: Updated date on OpenSM man page Tue May 15 10:57:58 2007 -0400 Hal Rosenstock bc5708f0e6254083ce56fe3ddda5e19475ff7a7b * OpenSM/include/opensm/osm_version.h: Bump version to 3.1.1 to signify reorganization of management/opensm Tue May 15 10:07:35 2007 -0400 Hal Rosenstock 9f02ef4c97b21093415196dfdebdf64f725a4711 * opensm/doc/opensm_release_notes_openib-3.0.9.txt: Removed as this is superceeded by opensm_release_notes_openib-3.0.11.txt and is an artifact of the merge which didn't handle this well Tue May 15 09:26:48 2007 -0400 Hal Rosenstock 37691eaa3fa18f753408d57d418730ba9d771888 * Merge branch 'master' of git://staging.openfabrics.org/~halr/management Thu Apr 12 16:52:49 2007 -0400 Hal Rosenstock b60ac60a2033f3a514d5e57823e455dd156c01c2 * Diags: Renamed openib-diags to infiniband-diags Also, some other changes based on this (openib-diags.spec.in moved to infiniband-diags.spec.in, openib-diags.spec moved to infiniband-diags.spec, and Makefile.am changed for this) Thu Apr 5 09:13:47 2007 -0400 Hal Rosenstock a65068c56fdc888259bdcb7f66cc43d171904196 * Merge git://git.openfabrics.org/~dledford/management into doug/rpm Wed Apr 4 16:48:21 2007 -0400 Doug Ledford 43ebb5238885b217f50f98bf248a9c9238bfd1ff * Merge branch 'master' of git://git.openfabrics.org/~halr/management into rpm_cleanups Wed Apr 4 16:05:55 2007 -0400 Doug Ledford 8342f1962b538fb2d49898e7cf5981a4ff8d5bf7 * opensm only looks in /etc/ofa for config files now, so don't conditionalize confdir. Also, make the Red Hat test work on versions prior to RHEL5 by testing /etc/redhat-release (which is a file on RHEL and a symlink to fedora-release on Fedora). Wed Apr 4 15:29:25 2007 -0400 Doug Ledford 071bab887b6783f8e86c0f57f0d40e8852beefd3 * Update all opensm created files to use the name opensm instead of osm Wed Apr 4 14:49:55 2007 -0400 Doug Ledford e3e9d5ceb71af574302c6af756ca5fd45884a9c2 * Fix a bug related to condrestart...need to NULL out pid before testing against in start() Wed Apr 4 14:10:49 2007 -0400 Doug Ledford 2f28a34e150b38c7d852bbb5f42cf979e9112fa0 * Start swithing the names of log files and dump files to opensm* Wed Apr 4 13:10:53 2007 -0400 Doug Ledford 5944928c5a91c29469875ba51bb30f5c88a937f2 * Oops, need to install opensm.conf as opensm.conf or else init script exits Wed Apr 4 12:47:18 2007 -0400 Doug Ledford 964d58c213ab9d9fd8a4bce15274e2d73b26aea9 * Move opensm to /usr/sbin, create /var/cache/opensm during install so rpm can track it Wed Apr 4 12:09:27 2007 -0400 Doug Ledford 5d913e5a843f8609d6a5cdbf5440ebfd05f27481 * RPM doesn't like variables with dots in their name Wed Apr 4 11:20:46 2007 -0400 Doug Ledford 9511dafccaaf507e1675b8b5ece30a2ba8fff2ba * Change all references of /var/cache/osm to /var/cache/opensm Wed Apr 4 10:58:40 2007 -0400 Doug Ledford 42517cdfa9fb2a69ef95ee160e9db38f6e1b0a7b * Add Red Hat specific config files and use the right one based upon rpm tags Wed Apr 4 10:55:16 2007 -0400 Doug Ledford beb873e7bab6196bb9dcdbfae20c397a475cf0ab * Make file name match convention of others in this directory Wed Apr 4 10:43:14 2007 -0400 Doug Ledford 7ac786c2df4bd82b4cf620527e349753b03e98b8 * Add a logrotate script to opensm Wed Apr 4 08:58:38 2007 -0400 Doug Ledford fea4cabd50af96bbfa645b09051a59e887839300 * OpenSM.conf: move log file to /var/log by default, rename log to opensm.log and cache dir name to opensm Wed Apr 4 08:54:52 2007 -0400 Doug Ledford 78fe659fbd8fac7a214e63356d80670d196219cc * Move these files over with the rest Tue Apr 3 16:47:44 2007 -0400 Doug Ledford 89ddbd7d3ea94d9d52ac2cbd5604d3d7c4c64710 * Version change in spec files Tue Apr 3 16:08:34 2007 -0400 Doug Ledford 2083dddae00a58cd5c34723ae95d2c827b725d0c * Merge of upstream master into rpm_cleanups Tue Apr 3 15:07:31 2007 -0400 Doug Ledford 606e9b196fff73f5eeae24b7e26d1b8faff919d8 * Update to correct list address Tue Apr 3 15:01:19 2007 -0400 Doug Ledford 6856fff91c5ec9b886e332d46bd6402e7b1c1692 * Move osm to opensm and diags to openib-diags so their name matches the rpm opensm-3.3.20/INSTALL0000644000205000001450000002207112104655724011051 00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== These are generic installation instructions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. (Caching is disabled by default to prevent problems with accidental use of stale cache files.) If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You only need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package. 4. Type `make install' to install the programs and any data files and documentation. 5. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you must use a version of `make' that supports the `VPATH' variable, such as GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. If you have to use a `make' that does not support the `VPATH' variable, you have to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. Installation Names ================== By default, `make install' will install the package's files in `/usr/local/bin', `/usr/local/man', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you give `configure' the option `--exec-prefix=PREFIX', the package will use PREFIX as the prefix for installing programs and libraries. Documentation and other data files will still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Optional Features ================= Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the `--target=TYPE' option to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc will cause the specified gcc to be used as the C compiler (unless it is overridden in the site shell script). `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of the options to `configure', and exit. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. opensm-3.3.20/NEWS0000644000205000001450000000006412104655724010515 00000000000000 This file will hold news about the OpenSM project. opensm-3.3.20/autogen.sh0000755000205000001450000000364512104655724012027 00000000000000#!/bin/bash # We change dir since the later utilities assume to work in the project dir cd ${0%*/*} # make sure autoconf is up-to-date ac_ver=`autoconf --version | head -n 1 | awk '{print $NF}'` ac_maj=`echo $ac_ver|sed 's/\..*//'` ac_min=`echo $ac_ver|sed 's/.*\.//'` if [[ $ac_maj -lt 2 ]]; then echo Min autoconf version is 2.57 exit 1 elif [[ $ac_maj -eq 2 && $ac_min -lt 57 ]]; then echo Min autoconf version is 2.57 exit 1 fi # make sure automake is up-to-date am_ver=`automake --version | head -n 1 | awk '{print $NF}'` am_maj=`echo $am_ver|sed 's/\..*//'` am_min=`echo $am_ver|sed 's/[^\.]*\.\([^\.]*\)\.*.*/\1/'` am_sub=`echo $am_ver|sed 's/[^\.]*\.[^\.]*\.*//'` if [[ $am_maj -lt 1 ]]; then echo Min automake version is 1.6.3 exit 1 elif [[ $am_maj -eq 1 && $am_min -lt 6 ]]; then echo "automake version is too old:$am_maj.$am_min.$am_sub < required 1.6.3" exit 1 elif [[ $am_maj -eq 1 && $am_min -eq 6 && $am_sub -lt 3 ]]; then echo "automake version is too old:$am_maj.$am_min.$am_sub < required 1.6.3" exit 1 fi # make sure libtool is up-to-date lt_ver=`libtool --version | head -n 1 | awk '{print $4}'` lt_maj=`echo $lt_ver|sed 's/\..*//'` lt_min=`echo $lt_ver|sed 's/[^\.]*\.\([^\.]*\)\.*.*/\1/'` lt_sub=`echo $lt_ver|sed 's/[^\.]*\.[^\.]*\.*//'` if [[ $lt_maj -lt 1 ]]; then echo Min libtool version is 1.4.2 exit 1 elif [[ $lt_maj -eq 1 && $lt_min -lt 4 ]]; then echo "libtool version is too old:$lt_maj.$lt_min.$lt_sub < required 1.4.2" exit 1 elif [[ $lt_maj -eq 1 && $lt_min -eq 4 && $lt_sub -lt 2 ]]; then echo "libtool version is too old:$lt_maj.$lt_min.$lt_sub < required 1.4.2" exit 1 fi # cleanup find . \( -name Makefile.in -o -name aclocal.m4 -o -name autom4te.cache -o -name configure -o -name aclocal.m4 \) -exec \rm -rf {} \; -prune aclocal -I config && \ libtoolize --force --copy && \ autoheader && \ automake --foreign --add-missing --copy && \ autoconf opensm-3.3.20/opensm.spec0000644000205000001450000001133212726323450012171 00000000000000%define RELEASE 3.3.20 %define rel %{?CUSTOM_RELEASE}%{!?CUSTOM_RELEASE:%RELEASE} %if %{?_with_console_socket:1}%{!?_with_console_socket:0} %define _enable_console_socket --enable-console-socket %endif %if %{?_without_console_socket:1}%{!?_without_console_socket:0} %define _disable_console_socket --disable-console-socket %endif %if %{?_with_perf_mgr:1}%{!?_with_perf_mgr:0} %define _enable_perf_mgr --enable-perf-mgr %endif %if %{?_without_perf_mgr:1}%{!?_without_perf_mgr:0} %define _disable_perf_mgr --disable-perf-mgr %endif %if %{?_with_event_plugin:1}%{!?_with_event_plugin:0} %define _enable_event_plugin --enable-default-event-plugin %endif %if %{?_without_event_plugin:1}%{!?_without_event_plugin:0} %define _disable_event_plugin --disable-default-event-plugin %endif %if %{?_with_node_name_map:1}%{!?_with_node_name_map:0} %define _enable_node_name_map --with-node-name-map%{?_with_node_name_map} %endif Summary: InfiniBand subnet manager and administration Name: opensm Version: 3.3.20 Release: %rel%{?dist} License: GPLv2 or BSD Group: System Environment/Daemons URL: http://openfabrics.org/ Source: http://www.openfabrics.org/downloads/management/opensm-3.3.20.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libibumad-devel, libtool Requires: %{name}-libs = %{version}-%{release}, logrotate %description OpenSM provides an implementation of an InfiniBand Subnet Manager and Administration. Such a software entity is required to run for in order to initialize the InfiniBand hardware (at least one per each InfiniBand subnet). %package libs Summary: Libraries from the opensm package Group: System Environment/Libraries Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig Obsoletes: libopensm, libosmcomp, libosmvendor %description libs Shared libraries that are part of the opensm package but are also used by other applications. If you don't need opensm itself installed, these libraries can be installed to satisfy dependencies of other applications. %package devel Summary: Development files for OpenSM Group: System Environment/Libraries Requires: %{name}-libs = %{version}-%{release} libibumad-devel Obsoletes: libopensm-devel, libosmcomp-devel, libosmvendor-devel %description devel Header files for OpenSM. %package static Summary: Static version of the opensm libraries Group: System Environment/Libraries Requires: %{name}-libs = %{version}-%{release} libibumad-devel %description static Static version of the opensm libraries %prep %setup -q %build %configure \ %{?_enable_console_socket} \ %{?_disable_console_socket} \ %{?_enable_perf_mgr} \ %{?_disable_perf_mgr} \ %{?_enable_event_plugin} \ %{?_disable_event_plugin} \ %{?_enable_node_name_map} make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -f $RPM_BUILD_ROOT%{_libdir}/*.la etc=$RPM_BUILD_ROOT%{_sysconfdir} mkdir -p ${RPM_BUILD_ROOT}/var/cache/opensm if [ -f /etc/redhat-release -o -s /etc/redhat-release ]; then REDHAT="redhat-" else REDHAT="" fi mkdir -p $etc/{init.d,logrotate.d} $etc/opensm install -m 755 scripts/${REDHAT}opensm.init $etc/init.d/opensmd install -D -m 644 scripts/opensm.logrotate $etc/logrotate.d/opensm install -m 755 scripts/sldd.sh $RPM_BUILD_ROOT%{_sbindir}/sldd.sh %clean rm -rf $RPM_BUILD_ROOT %post if [ $1 = 1 ]; then if [ -e /sbin/chkconfig ]; then /sbin/chkconfig --add opensmd elif [ -e /usr/sbin/update-rc.d ]; then /usr/sbin/update-rc.d opensmd defaults else /usr/lib/lsb/install_initd /etc/init.d/opensmd fi if type systemctl >/dev/null 2>&1; then systemctl --system daemon-reload fi else /etc/init.d/opensmd condrestart fi %preun if [ $1 = 0 ]; then /etc/init.d/opensmd stop if [ -e /sbin/chkconfig ]; then /sbin/chkconfig --del opensmd elif [ -e /usr/sbin/update-rc.d ]; then /usr/sbin/update-rc.d -f opensmd remove else /usr/lib/lsb/remove_initd /etc/init.d/opensmd fi rm -f /var/cache/opensm/* fi %post libs -p /sbin/ldconfig %postun libs -p /sbin/ldconfig %files %defattr(-,root,root,-) %{_sbindir}/opensm %{_sbindir}/osmtest %{_mandir}/man8/* %{_mandir}/man5/* %doc AUTHORS COPYING README doc/performance-manager-HOWTO.txt doc/QoS_management_in_OpenSM.txt doc/partition-config.txt doc/opensm-sriov.txt doc/current-routing.txt doc/opensm_release_notes-3.3.txt %{_sysconfdir}/init.d/opensmd %{_sbindir}/sldd.sh %config(noreplace) %{_sysconfdir}/logrotate.d/opensm %dir /var/cache/opensm %dir %{_sysconfdir}/opensm %files libs %defattr(-,root,root,-) %{_libdir}/*.so.* %files devel %defattr(-,root,root,-) %{_includedir}/infiniband/* %{_libdir}/*.so %files static %defattr(-,root,root,-) %{_libdir}/*.a opensm-3.3.20/complib/0000755000205000001450000000000012726324757011534 500000000000000opensm-3.3.20/complib/Makefile.am0000644000205000001450000000530612272264652013505 00000000000000 INCLUDES = -I$(srcdir)/../include lib_LTLIBRARIES = libosmcomp.la if DEBUG DBGFLAGS = -ggdb -D_DEBUG_ else DBGFLAGS = -g endif libosmcomp_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 if HAVE_LD_VERSION_SCRIPT libosmcomp_version_script = -Wl,--version-script=$(srcdir)/libosmcomp.map else libosmcomp_version_script = endif complib_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmcomp.ver | sed 's/LIBVERSION=//') libosmcomp_la_SOURCES = cl_complib.c cl_dispatcher.c \ cl_event.c cl_event_wheel.c \ cl_list.c cl_log.c cl_map.c \ cl_pool.c cl_ptr_vector.c \ cl_spinlock.c cl_statustext.c \ cl_thread.c cl_threadpool.c \ cl_timer.c cl_vector.c \ ib_statustext.c \ cl_nodenamemap.c libosmcomp_la_LDFLAGS = -version-info $(complib_api_version) \ -export-dynamic $(libosmcomp_version_script) libosmcomp_la_DEPENDENCIES = $(srcdir)/libosmcomp.map libosmcompincludedir = $(includedir)/infiniband/complib libosmcompinclude_HEADERS = $(srcdir)/../include/complib/cl_atomic.h \ $(srcdir)/../include/complib/cl_atomic_osd.h \ $(srcdir)/../include/complib/cl_byteswap.h \ $(srcdir)/../include/complib/cl_byteswap_osd.h \ $(srcdir)/../include/complib/cl_comppool.h \ $(srcdir)/../include/complib/cl_debug.h \ $(srcdir)/../include/complib/cl_debug_osd.h \ $(srcdir)/../include/complib/cl_dispatcher.h \ $(srcdir)/../include/complib/cl_event.h \ $(srcdir)/../include/complib/cl_event_wheel.h \ $(srcdir)/../include/complib/cl_event_osd.h \ $(srcdir)/../include/complib/cl_fleximap.h \ $(srcdir)/../include/complib/cl_list.h \ $(srcdir)/../include/complib/cl_log.h \ $(srcdir)/../include/complib/cl_map.h \ $(srcdir)/../include/complib/cl_math.h \ $(srcdir)/../include/complib/cl_nodenamemap.h \ $(srcdir)/../include/complib/cl_packoff.h \ $(srcdir)/../include/complib/cl_packon.h \ $(srcdir)/../include/complib/cl_passivelock.h \ $(srcdir)/../include/complib/cl_pool.h \ $(srcdir)/../include/complib/cl_ptr_vector.h \ $(srcdir)/../include/complib/cl_qcomppool.h \ $(srcdir)/../include/complib/cl_qlist.h \ $(srcdir)/../include/complib/cl_qmap.h \ $(srcdir)/../include/complib/cl_qpool.h \ $(srcdir)/../include/complib/cl_spinlock.h \ $(srcdir)/../include/complib/cl_spinlock_osd.h \ $(srcdir)/../include/complib/cl_thread.h \ $(srcdir)/../include/complib/cl_thread_osd.h \ $(srcdir)/../include/complib/cl_threadpool.h \ $(srcdir)/../include/complib/cl_timer.h \ $(srcdir)/../include/complib/cl_timer_osd.h \ $(srcdir)/../include/complib/cl_types.h \ $(srcdir)/../include/complib/cl_types_osd.h \ $(srcdir)/../include/complib/cl_vector.h # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmcomp.map $(srcdir)/libosmcomp.ver opensm-3.3.20/complib/Makefile.in0000644000205000001450000011752012726323425013516 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = complib DIST_COMMON = $(libosmcompinclude_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(libosmcompincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libosmcomp_la_LIBADD = am_libosmcomp_la_OBJECTS = libosmcomp_la-cl_complib.lo \ libosmcomp_la-cl_dispatcher.lo libosmcomp_la-cl_event.lo \ libosmcomp_la-cl_event_wheel.lo libosmcomp_la-cl_list.lo \ libosmcomp_la-cl_log.lo libosmcomp_la-cl_map.lo \ libosmcomp_la-cl_pool.lo libosmcomp_la-cl_ptr_vector.lo \ libosmcomp_la-cl_spinlock.lo libosmcomp_la-cl_statustext.lo \ libosmcomp_la-cl_thread.lo libosmcomp_la-cl_threadpool.lo \ libosmcomp_la-cl_timer.lo libosmcomp_la-cl_vector.lo \ libosmcomp_la-ib_statustext.lo libosmcomp_la-cl_nodenamemap.lo libosmcomp_la_OBJECTS = $(am_libosmcomp_la_OBJECTS) libosmcomp_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libosmcomp_la_CFLAGS) \ $(CFLAGS) $(libosmcomp_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libosmcomp_la_SOURCES) DIST_SOURCES = $(libosmcomp_la_SOURCES) HEADERS = $(libosmcompinclude_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(srcdir)/../include lib_LTLIBRARIES = libosmcomp.la @DEBUG_FALSE@DBGFLAGS = -g @DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_ libosmcomp_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 @HAVE_LD_VERSION_SCRIPT_FALSE@libosmcomp_version_script = @HAVE_LD_VERSION_SCRIPT_TRUE@libosmcomp_version_script = -Wl,--version-script=$(srcdir)/libosmcomp.map complib_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmcomp.ver | sed 's/LIBVERSION=//') libosmcomp_la_SOURCES = cl_complib.c cl_dispatcher.c \ cl_event.c cl_event_wheel.c \ cl_list.c cl_log.c cl_map.c \ cl_pool.c cl_ptr_vector.c \ cl_spinlock.c cl_statustext.c \ cl_thread.c cl_threadpool.c \ cl_timer.c cl_vector.c \ ib_statustext.c \ cl_nodenamemap.c libosmcomp_la_LDFLAGS = -version-info $(complib_api_version) \ -export-dynamic $(libosmcomp_version_script) libosmcomp_la_DEPENDENCIES = $(srcdir)/libosmcomp.map libosmcompincludedir = $(includedir)/infiniband/complib libosmcompinclude_HEADERS = $(srcdir)/../include/complib/cl_atomic.h \ $(srcdir)/../include/complib/cl_atomic_osd.h \ $(srcdir)/../include/complib/cl_byteswap.h \ $(srcdir)/../include/complib/cl_byteswap_osd.h \ $(srcdir)/../include/complib/cl_comppool.h \ $(srcdir)/../include/complib/cl_debug.h \ $(srcdir)/../include/complib/cl_debug_osd.h \ $(srcdir)/../include/complib/cl_dispatcher.h \ $(srcdir)/../include/complib/cl_event.h \ $(srcdir)/../include/complib/cl_event_wheel.h \ $(srcdir)/../include/complib/cl_event_osd.h \ $(srcdir)/../include/complib/cl_fleximap.h \ $(srcdir)/../include/complib/cl_list.h \ $(srcdir)/../include/complib/cl_log.h \ $(srcdir)/../include/complib/cl_map.h \ $(srcdir)/../include/complib/cl_math.h \ $(srcdir)/../include/complib/cl_nodenamemap.h \ $(srcdir)/../include/complib/cl_packoff.h \ $(srcdir)/../include/complib/cl_packon.h \ $(srcdir)/../include/complib/cl_passivelock.h \ $(srcdir)/../include/complib/cl_pool.h \ $(srcdir)/../include/complib/cl_ptr_vector.h \ $(srcdir)/../include/complib/cl_qcomppool.h \ $(srcdir)/../include/complib/cl_qlist.h \ $(srcdir)/../include/complib/cl_qmap.h \ $(srcdir)/../include/complib/cl_qpool.h \ $(srcdir)/../include/complib/cl_spinlock.h \ $(srcdir)/../include/complib/cl_spinlock_osd.h \ $(srcdir)/../include/complib/cl_thread.h \ $(srcdir)/../include/complib/cl_thread_osd.h \ $(srcdir)/../include/complib/cl_threadpool.h \ $(srcdir)/../include/complib/cl_timer.h \ $(srcdir)/../include/complib/cl_timer_osd.h \ $(srcdir)/../include/complib/cl_types.h \ $(srcdir)/../include/complib/cl_types_osd.h \ $(srcdir)/../include/complib/cl_vector.h # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmcomp.map $(srcdir)/libosmcomp.ver all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign complib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign complib/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libosmcomp.la: $(libosmcomp_la_OBJECTS) $(libosmcomp_la_DEPENDENCIES) $(libosmcomp_la_LINK) -rpath $(libdir) $(libosmcomp_la_OBJECTS) $(libosmcomp_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_complib.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_dispatcher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_event.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_event_wheel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_nodenamemap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_ptr_vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_spinlock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_statustext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_threadpool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_timer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-cl_vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmcomp_la-ib_statustext.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libosmcomp_la-cl_complib.lo: cl_complib.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_complib.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_complib.Tpo -c -o libosmcomp_la-cl_complib.lo `test -f 'cl_complib.c' || echo '$(srcdir)/'`cl_complib.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_complib.Tpo $(DEPDIR)/libosmcomp_la-cl_complib.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_complib.c' object='libosmcomp_la-cl_complib.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_complib.lo `test -f 'cl_complib.c' || echo '$(srcdir)/'`cl_complib.c libosmcomp_la-cl_dispatcher.lo: cl_dispatcher.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_dispatcher.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_dispatcher.Tpo -c -o libosmcomp_la-cl_dispatcher.lo `test -f 'cl_dispatcher.c' || echo '$(srcdir)/'`cl_dispatcher.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_dispatcher.Tpo $(DEPDIR)/libosmcomp_la-cl_dispatcher.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_dispatcher.c' object='libosmcomp_la-cl_dispatcher.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_dispatcher.lo `test -f 'cl_dispatcher.c' || echo '$(srcdir)/'`cl_dispatcher.c libosmcomp_la-cl_event.lo: cl_event.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_event.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_event.Tpo -c -o libosmcomp_la-cl_event.lo `test -f 'cl_event.c' || echo '$(srcdir)/'`cl_event.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_event.Tpo $(DEPDIR)/libosmcomp_la-cl_event.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_event.c' object='libosmcomp_la-cl_event.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_event.lo `test -f 'cl_event.c' || echo '$(srcdir)/'`cl_event.c libosmcomp_la-cl_event_wheel.lo: cl_event_wheel.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_event_wheel.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_event_wheel.Tpo -c -o libosmcomp_la-cl_event_wheel.lo `test -f 'cl_event_wheel.c' || echo '$(srcdir)/'`cl_event_wheel.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_event_wheel.Tpo $(DEPDIR)/libosmcomp_la-cl_event_wheel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_event_wheel.c' object='libosmcomp_la-cl_event_wheel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_event_wheel.lo `test -f 'cl_event_wheel.c' || echo '$(srcdir)/'`cl_event_wheel.c libosmcomp_la-cl_list.lo: cl_list.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_list.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_list.Tpo -c -o libosmcomp_la-cl_list.lo `test -f 'cl_list.c' || echo '$(srcdir)/'`cl_list.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_list.Tpo $(DEPDIR)/libosmcomp_la-cl_list.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_list.c' object='libosmcomp_la-cl_list.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_list.lo `test -f 'cl_list.c' || echo '$(srcdir)/'`cl_list.c libosmcomp_la-cl_log.lo: cl_log.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_log.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_log.Tpo -c -o libosmcomp_la-cl_log.lo `test -f 'cl_log.c' || echo '$(srcdir)/'`cl_log.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_log.Tpo $(DEPDIR)/libosmcomp_la-cl_log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_log.c' object='libosmcomp_la-cl_log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_log.lo `test -f 'cl_log.c' || echo '$(srcdir)/'`cl_log.c libosmcomp_la-cl_map.lo: cl_map.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_map.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_map.Tpo -c -o libosmcomp_la-cl_map.lo `test -f 'cl_map.c' || echo '$(srcdir)/'`cl_map.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_map.Tpo $(DEPDIR)/libosmcomp_la-cl_map.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_map.c' object='libosmcomp_la-cl_map.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_map.lo `test -f 'cl_map.c' || echo '$(srcdir)/'`cl_map.c libosmcomp_la-cl_pool.lo: cl_pool.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_pool.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_pool.Tpo -c -o libosmcomp_la-cl_pool.lo `test -f 'cl_pool.c' || echo '$(srcdir)/'`cl_pool.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_pool.Tpo $(DEPDIR)/libosmcomp_la-cl_pool.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_pool.c' object='libosmcomp_la-cl_pool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_pool.lo `test -f 'cl_pool.c' || echo '$(srcdir)/'`cl_pool.c libosmcomp_la-cl_ptr_vector.lo: cl_ptr_vector.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_ptr_vector.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Tpo -c -o libosmcomp_la-cl_ptr_vector.lo `test -f 'cl_ptr_vector.c' || echo '$(srcdir)/'`cl_ptr_vector.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Tpo $(DEPDIR)/libosmcomp_la-cl_ptr_vector.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_ptr_vector.c' object='libosmcomp_la-cl_ptr_vector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_ptr_vector.lo `test -f 'cl_ptr_vector.c' || echo '$(srcdir)/'`cl_ptr_vector.c libosmcomp_la-cl_spinlock.lo: cl_spinlock.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_spinlock.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_spinlock.Tpo -c -o libosmcomp_la-cl_spinlock.lo `test -f 'cl_spinlock.c' || echo '$(srcdir)/'`cl_spinlock.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_spinlock.Tpo $(DEPDIR)/libosmcomp_la-cl_spinlock.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_spinlock.c' object='libosmcomp_la-cl_spinlock.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_spinlock.lo `test -f 'cl_spinlock.c' || echo '$(srcdir)/'`cl_spinlock.c libosmcomp_la-cl_statustext.lo: cl_statustext.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_statustext.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_statustext.Tpo -c -o libosmcomp_la-cl_statustext.lo `test -f 'cl_statustext.c' || echo '$(srcdir)/'`cl_statustext.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_statustext.Tpo $(DEPDIR)/libosmcomp_la-cl_statustext.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_statustext.c' object='libosmcomp_la-cl_statustext.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_statustext.lo `test -f 'cl_statustext.c' || echo '$(srcdir)/'`cl_statustext.c libosmcomp_la-cl_thread.lo: cl_thread.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_thread.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_thread.Tpo -c -o libosmcomp_la-cl_thread.lo `test -f 'cl_thread.c' || echo '$(srcdir)/'`cl_thread.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_thread.Tpo $(DEPDIR)/libosmcomp_la-cl_thread.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_thread.c' object='libosmcomp_la-cl_thread.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_thread.lo `test -f 'cl_thread.c' || echo '$(srcdir)/'`cl_thread.c libosmcomp_la-cl_threadpool.lo: cl_threadpool.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_threadpool.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_threadpool.Tpo -c -o libosmcomp_la-cl_threadpool.lo `test -f 'cl_threadpool.c' || echo '$(srcdir)/'`cl_threadpool.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_threadpool.Tpo $(DEPDIR)/libosmcomp_la-cl_threadpool.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_threadpool.c' object='libosmcomp_la-cl_threadpool.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_threadpool.lo `test -f 'cl_threadpool.c' || echo '$(srcdir)/'`cl_threadpool.c libosmcomp_la-cl_timer.lo: cl_timer.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_timer.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_timer.Tpo -c -o libosmcomp_la-cl_timer.lo `test -f 'cl_timer.c' || echo '$(srcdir)/'`cl_timer.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_timer.Tpo $(DEPDIR)/libosmcomp_la-cl_timer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_timer.c' object='libosmcomp_la-cl_timer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_timer.lo `test -f 'cl_timer.c' || echo '$(srcdir)/'`cl_timer.c libosmcomp_la-cl_vector.lo: cl_vector.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_vector.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_vector.Tpo -c -o libosmcomp_la-cl_vector.lo `test -f 'cl_vector.c' || echo '$(srcdir)/'`cl_vector.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_vector.Tpo $(DEPDIR)/libosmcomp_la-cl_vector.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_vector.c' object='libosmcomp_la-cl_vector.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_vector.lo `test -f 'cl_vector.c' || echo '$(srcdir)/'`cl_vector.c libosmcomp_la-ib_statustext.lo: ib_statustext.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-ib_statustext.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-ib_statustext.Tpo -c -o libosmcomp_la-ib_statustext.lo `test -f 'ib_statustext.c' || echo '$(srcdir)/'`ib_statustext.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-ib_statustext.Tpo $(DEPDIR)/libosmcomp_la-ib_statustext.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ib_statustext.c' object='libosmcomp_la-ib_statustext.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-ib_statustext.lo `test -f 'ib_statustext.c' || echo '$(srcdir)/'`ib_statustext.c libosmcomp_la-cl_nodenamemap.lo: cl_nodenamemap.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -MT libosmcomp_la-cl_nodenamemap.lo -MD -MP -MF $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Tpo -c -o libosmcomp_la-cl_nodenamemap.lo `test -f 'cl_nodenamemap.c' || echo '$(srcdir)/'`cl_nodenamemap.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Tpo $(DEPDIR)/libosmcomp_la-cl_nodenamemap.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cl_nodenamemap.c' object='libosmcomp_la-cl_nodenamemap.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmcomp_la_CFLAGS) $(CFLAGS) -c -o libosmcomp_la-cl_nodenamemap.lo `test -f 'cl_nodenamemap.c' || echo '$(srcdir)/'`cl_nodenamemap.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libosmcompincludeHEADERS: $(libosmcompinclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(libosmcompincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmcompincludedir)" @list='$(libosmcompinclude_HEADERS)'; test -n "$(libosmcompincludedir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libosmcompincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libosmcompincludedir)" || exit $$?; \ done uninstall-libosmcompincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libosmcompinclude_HEADERS)'; test -n "$(libosmcompincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(libosmcompincludedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libosmcompincludedir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmcompincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libosmcompincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES \ uninstall-libosmcompincludeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libosmcompincludeHEADERS \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libosmcompincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/complib/ChangeLog0000644000205000001450000000530612104655724013221 000000000000002007-07=11 Hal Rosenstock * configure.in: to version 2.2.1 2007-06-25 Hal Rosenstock * cl_event_wheel.c: Fix some typos in printfs when __CL_EVENT_WHEEL_TEST__ defined 2007-06-20 Hal Rosenstock * libosmcomp.map: Add get_next map functions as global 2007-06-20 Todd Rimmer * include/complib/cl_map.h, include/complib/cl_qmap.h, include/complib/cl_fleximap.h, cl_map.c: Add get_next functions to the various maps * include/complib/cl_fleximap.h: In cl_fmap_remove_all, make sure the count field is properly maintained. 2007-06-19 Todd Rimmer * include/complib/cl_qmap.h: In cl_qmap_remove_all, make sure the count field is properly maintained. 2007-06-19 Hal Rosenstock * include/complib/cl_threadpool.h: Eliminate compile warning with cl_threadpool.c introduced by previous change 2007-06-13 Sasha Khapyorsky * include/complib/cl_threadpool.h, complib/cl_threadpool.c, complib/cl_dispatcher.c, complib/libosmcomp.map: Thread pool rework 2007-06-13 Hal Rosenstock * configure.in: Bump to version 2.2.0 * libosmcomp.ver, libosmcomp.map: Update version info for previous API removals * include/complib/cl_memory.h, include/complib/cl_memtrack.h, complib/cl_memory.c, complib/cl_memtrack.c, include/Makefile.am: Remove deprecated memory allocation related routines 2007-06-13 Yevgeny Kliteynik * include/complib/cl_perf.h, include/complib/cl_async_proc.h, complib/cl_perf.c, complib/cl_async_proc.c, Makefile.am, libosmcomp.map: Remove unused cl_perf and cl_async_proc 2007-05-09 Hal Rosenstock * configure.in: Bump to version 2.1.2 2007-03-29 Hal Rosenstock * configure.in: Bump to version 2.1.1 2007-01-08 Sasha Khapyorsky * cl_log.c: SIGUSR1 fixes 2007-01-08 Ira Weiny * cl_log.c: Add SIGUSR1 handling to reopen osm.log 2006-10-31 Hal Rosenstock * configure.in: Bumped to version version 2.1.0 2006-09-05 Sasha Khapyorsky * cl_event_wheel.c: Changes to support new osm_log initializer osm_log_init_v2() 2006-08-29 Sasha Khapyorsky * cl_event_wheel.c: Support option to limit size of OpenSM log file 2006-07-20 Sasha Khapyorsky * cl_pool.c: Fix memory corruption in cl_qcpool_init 2006-07-19 Hal Rosenstock * Makefile.am: Eliminate deprecated warnings 2006-06-11 Hal Rosenstock * configure.in: Released version 1.2.1 (OFED 1.1) opensm-3.3.20/complib/cl_complib.c0000644000205000001450000000473412104655724013722 00000000000000/* * 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include /* * Prototypes */ extern cl_status_t __cl_timer_prov_create(void); extern void __cl_timer_prov_destroy(void); cl_spinlock_t cl_atomic_spinlock; void complib_init(void) { cl_status_t status = CL_SUCCESS; status = cl_spinlock_init(&cl_atomic_spinlock); if (status != CL_SUCCESS) goto _error; status = __cl_timer_prov_create(); if (status != CL_SUCCESS) goto _error; return; _error: cl_msg_out("__init: failed to create complib (%s)\n", CL_STATUS_MSG(status)); exit(1); } void complib_exit(void) { __cl_timer_prov_destroy(); cl_spinlock_destroy(&cl_atomic_spinlock); } boolean_t cl_is_debug(void) { #if defined( _DEBUG_ ) return TRUE; #else return FALSE; #endif /* defined( _DEBUG_ ) */ } opensm-3.3.20/complib/cl_dispatcher.c0000644000205000001450000002434712422204054014412 00000000000000/* * 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 Dispatcher abstraction. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include /* give some guidance when we build our cl_pool of messages */ #define CL_DISP_INITIAL_MSG_COUNT 256 #define CL_DISP_MSG_GROW_SIZE 64 /* give some guidance when we build our cl_pool of registration elements */ #define CL_DISP_INITIAL_REG_COUNT 16 #define CL_DISP_REG_GROW_SIZE 16 /******************************************************************** __cl_disp_worker Description: This function takes messages off the FIFO and calls Processmsg() This function executes as passive level. Inputs: p_disp - Pointer to Dispatcher object Outputs: None Returns: None ********************************************************************/ void __cl_disp_worker(IN void *context) { cl_disp_msg_t *p_msg; cl_dispatcher_t *p_disp = (cl_dispatcher_t *) context; cl_spinlock_acquire(&p_disp->lock); /* Process the FIFO until we drain it dry. */ while (cl_qlist_count(&p_disp->msg_fifo)) { /* Pop the message at the head from the FIFO. */ p_msg = (cl_disp_msg_t *) cl_qlist_remove_head(&p_disp->msg_fifo); /* we track the tim ethe last message spent in the queue */ p_disp->last_msg_queue_time_us = cl_get_time_stamp() - p_msg->in_time; /* * Release the spinlock while the message is processed. * The user's callback may reenter the dispatcher * and cause the lock to be reaquired. */ cl_spinlock_release(&p_disp->lock); p_msg->p_dest_reg->pfn_rcv_callback((void *)p_msg->p_dest_reg-> context, (void *)p_msg->p_data); cl_atomic_dec(&p_msg->p_dest_reg->ref_cnt); /* The client has seen the data. Notify the sender as appropriate. */ if (p_msg->pfn_xmt_callback) { p_msg->pfn_xmt_callback((void *)p_msg->context, (void *)p_msg->p_data); cl_atomic_dec(&p_msg->p_src_reg->ref_cnt); } /* Grab the lock for the next iteration through the list. */ cl_spinlock_acquire(&p_disp->lock); /* Return this message to the pool. */ cl_qpool_put(&p_disp->msg_pool, (cl_pool_item_t *) p_msg); } cl_spinlock_release(&p_disp->lock); } void cl_disp_construct(IN cl_dispatcher_t * const p_disp) { CL_ASSERT(p_disp); cl_qlist_init(&p_disp->reg_list); cl_ptr_vector_construct(&p_disp->reg_vec); cl_qlist_init(&p_disp->msg_fifo); cl_spinlock_construct(&p_disp->lock); cl_qpool_construct(&p_disp->msg_pool); } void cl_disp_shutdown(IN cl_dispatcher_t * const p_disp) { CL_ASSERT(p_disp); /* Stop the thread pool. */ cl_thread_pool_destroy(&p_disp->worker_threads); /* Process all outstanding callbacks. */ __cl_disp_worker(p_disp); /* Free all registration info. */ while (!cl_is_qlist_empty(&p_disp->reg_list)) free(cl_qlist_remove_head(&p_disp->reg_list)); } void cl_disp_destroy(IN cl_dispatcher_t * const p_disp) { CL_ASSERT(p_disp); cl_spinlock_destroy(&p_disp->lock); /* Destroy the message pool */ cl_qpool_destroy(&p_disp->msg_pool); /* Destroy the pointer vector of registrants. */ cl_ptr_vector_destroy(&p_disp->reg_vec); } cl_status_t cl_disp_init(IN cl_dispatcher_t * const p_disp, IN const uint32_t thread_count, IN const char *const name) { cl_status_t status; CL_ASSERT(p_disp); cl_disp_construct(p_disp); status = cl_spinlock_init(&p_disp->lock); if (status != CL_SUCCESS) { cl_disp_destroy(p_disp); return (status); } /* Specify no upper limit to the number of messages in the pool */ status = cl_qpool_init(&p_disp->msg_pool, CL_DISP_INITIAL_MSG_COUNT, 0, CL_DISP_MSG_GROW_SIZE, sizeof(cl_disp_msg_t), NULL, NULL, NULL); if (status != CL_SUCCESS) { cl_disp_destroy(p_disp); return (status); } status = cl_ptr_vector_init(&p_disp->reg_vec, CL_DISP_INITIAL_REG_COUNT, CL_DISP_REG_GROW_SIZE); if (status != CL_SUCCESS) { cl_disp_destroy(p_disp); return (status); } status = cl_thread_pool_init(&p_disp->worker_threads, thread_count, __cl_disp_worker, p_disp, name); if (status != CL_SUCCESS) cl_disp_destroy(p_disp); return (status); } cl_disp_reg_handle_t cl_disp_register(IN cl_dispatcher_t * const p_disp, IN const cl_disp_msgid_t msg_id, IN cl_pfn_msgrcv_cb_t pfn_callback OPTIONAL, IN const void *const context OPTIONAL) { cl_disp_reg_info_t *p_reg; cl_status_t status; CL_ASSERT(p_disp); /* Check that the requested registrant ID is available. */ cl_spinlock_acquire(&p_disp->lock); if ((msg_id != CL_DISP_MSGID_NONE) && (msg_id < cl_ptr_vector_get_size(&p_disp->reg_vec)) && (cl_ptr_vector_get(&p_disp->reg_vec, msg_id))) { cl_spinlock_release(&p_disp->lock); return (NULL); } /* Get a registration info from the pool. */ p_reg = (cl_disp_reg_info_t *) malloc(sizeof(cl_disp_reg_info_t)); if (!p_reg) { cl_spinlock_release(&p_disp->lock); return (NULL); } else { memset(p_reg, 0, sizeof(cl_disp_reg_info_t)); } p_reg->p_disp = p_disp; p_reg->ref_cnt = 0; p_reg->pfn_rcv_callback = pfn_callback; p_reg->context = context; p_reg->msg_id = msg_id; /* Insert the registration in the list. */ cl_qlist_insert_tail(&p_disp->reg_list, (cl_list_item_t *) p_reg); /* Set the array entry to the registrant. */ /* The ptr_vector grow automatically as necessary. */ if (msg_id != CL_DISP_MSGID_NONE) { status = cl_ptr_vector_set(&p_disp->reg_vec, msg_id, p_reg); if (status != CL_SUCCESS) { free(p_reg); cl_spinlock_release(&p_disp->lock); return (NULL); } } cl_spinlock_release(&p_disp->lock); return (p_reg); } void cl_disp_unregister(IN const cl_disp_reg_handle_t handle) { cl_disp_reg_info_t *p_reg; cl_dispatcher_t *p_disp; if (handle == CL_DISP_INVALID_HANDLE) return; p_reg = (cl_disp_reg_info_t *) handle; p_disp = p_reg->p_disp; CL_ASSERT(p_disp); cl_spinlock_acquire(&p_disp->lock); /* * Clear the registrant vector entry. This will cause any further * post calls to fail. */ if (p_reg->msg_id != CL_DISP_MSGID_NONE) { CL_ASSERT(p_reg->msg_id < cl_ptr_vector_get_size(&p_disp->reg_vec)); cl_ptr_vector_set(&p_disp->reg_vec, p_reg->msg_id, NULL); } cl_spinlock_release(&p_disp->lock); while (p_reg->ref_cnt > 0) cl_thread_suspend(1); cl_spinlock_acquire(&p_disp->lock); /* Remove the registrant from the list. */ cl_qlist_remove_item(&p_disp->reg_list, (cl_list_item_t *) p_reg); /* Return the registration info to the pool */ free(p_reg); cl_spinlock_release(&p_disp->lock); } cl_status_t cl_disp_post(IN const cl_disp_reg_handle_t handle, IN const cl_disp_msgid_t msg_id, IN const void *const p_data, IN cl_pfn_msgdone_cb_t pfn_callback OPTIONAL, IN const void *const context OPTIONAL) { cl_disp_reg_info_t *p_src_reg = (cl_disp_reg_info_t *) handle; cl_disp_reg_info_t *p_dest_reg; cl_dispatcher_t *p_disp; cl_disp_msg_t *p_msg; p_disp = handle->p_disp; CL_ASSERT(p_disp); CL_ASSERT(msg_id != CL_DISP_MSGID_NONE); cl_spinlock_acquire(&p_disp->lock); /* Check that the recipient exists. */ if (cl_ptr_vector_get_size(&p_disp->reg_vec) <= msg_id) { cl_spinlock_release(&p_disp->lock); return (CL_NOT_FOUND); } p_dest_reg = cl_ptr_vector_get(&p_disp->reg_vec, msg_id); if (!p_dest_reg) { cl_spinlock_release(&p_disp->lock); return (CL_NOT_FOUND); } /* Get a free message from the pool. */ p_msg = (cl_disp_msg_t *) cl_qpool_get(&p_disp->msg_pool); if (!p_msg) { cl_spinlock_release(&p_disp->lock); return (CL_INSUFFICIENT_MEMORY); } /* Initialize the message */ p_msg->p_src_reg = p_src_reg; p_msg->p_dest_reg = p_dest_reg; p_msg->p_data = p_data; p_msg->pfn_xmt_callback = pfn_callback; p_msg->context = context; p_msg->in_time = cl_get_time_stamp(); /* * Increment the sender's reference count if they request a completion * notification. */ if (pfn_callback) cl_atomic_inc(&p_src_reg->ref_cnt); /* Increment the recipient's reference count. */ cl_atomic_inc(&p_dest_reg->ref_cnt); /* Queue the message in the FIFO. */ cl_qlist_insert_tail(&p_disp->msg_fifo, (cl_list_item_t *) p_msg); cl_spinlock_release(&p_disp->lock); /* Signal the thread pool that there is work to be done. */ cl_thread_pool_signal(&p_disp->worker_threads); return (CL_SUCCESS); } void cl_disp_get_queue_status(IN const cl_disp_reg_handle_t handle, OUT uint32_t * p_num_queued_msgs, OUT uint64_t * p_last_msg_queue_time_ms) { cl_dispatcher_t *p_disp = ((cl_disp_reg_info_t *) handle)->p_disp; cl_spinlock_acquire(&p_disp->lock); if (p_last_msg_queue_time_ms) *p_last_msg_queue_time_ms = p_disp->last_msg_queue_time_us / 1000; if (p_num_queued_msgs) *p_num_queued_msgs = cl_qlist_count(&p_disp->msg_fifo); cl_spinlock_release(&p_disp->lock); } opensm-3.3.20/complib/cl_event.c0000644000205000001450000001163012104655724013407 00000000000000/* * Copyright (c) 2004-2009 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include void cl_event_construct(IN cl_event_t * p_event) { CL_ASSERT(p_event); p_event->state = CL_UNINITIALIZED; } cl_status_t cl_event_init(IN cl_event_t * const p_event, IN const boolean_t manual_reset) { CL_ASSERT(p_event); cl_event_construct(p_event); pthread_cond_init(&p_event->condvar, NULL); pthread_mutex_init(&p_event->mutex, NULL); p_event->signaled = FALSE; p_event->manual_reset = manual_reset; p_event->state = CL_INITIALIZED; return CL_SUCCESS; } void cl_event_destroy(IN cl_event_t * const p_event) { CL_ASSERT(cl_is_state_valid(p_event->state)); /* Destroy only if the event was constructed */ if (p_event->state == CL_INITIALIZED) { pthread_cond_broadcast(&p_event->condvar); pthread_cond_destroy(&p_event->condvar); pthread_mutex_destroy(&p_event->mutex); } p_event->state = CL_UNINITIALIZED; } cl_status_t cl_event_signal(IN cl_event_t * const p_event) { /* Make sure that the event was started */ CL_ASSERT(p_event->state == CL_INITIALIZED); pthread_mutex_lock(&p_event->mutex); p_event->signaled = TRUE; /* Wake up one or all depending on whether the event is auto-resetting. */ if (p_event->manual_reset) pthread_cond_broadcast(&p_event->condvar); else pthread_cond_signal(&p_event->condvar); pthread_mutex_unlock(&p_event->mutex); return CL_SUCCESS; } cl_status_t cl_event_reset(IN cl_event_t * const p_event) { /* Make sure that the event was started */ CL_ASSERT(p_event->state == CL_INITIALIZED); pthread_mutex_lock(&p_event->mutex); p_event->signaled = FALSE; pthread_mutex_unlock(&p_event->mutex); return CL_SUCCESS; } cl_status_t cl_event_wait_on(IN cl_event_t * const p_event, IN const uint32_t wait_us, IN const boolean_t interruptible) { cl_status_t status; int wait_ret; struct timespec timeout; struct timeval curtime; /* Make sure that the event was Started */ CL_ASSERT(p_event->state == CL_INITIALIZED); pthread_mutex_lock(&p_event->mutex); /* Return immediately if the event is signalled. */ if (p_event->signaled) { if (!p_event->manual_reset) p_event->signaled = FALSE; pthread_mutex_unlock(&p_event->mutex); return CL_SUCCESS; } /* If just testing the state, return CL_TIMEOUT. */ if (wait_us == 0) { pthread_mutex_unlock(&p_event->mutex); return CL_TIMEOUT; } if (wait_us == EVENT_NO_TIMEOUT) { /* Wait for condition variable to be signaled or broadcast. */ if (pthread_cond_wait(&p_event->condvar, &p_event->mutex)) status = CL_NOT_DONE; else status = CL_SUCCESS; } else { /* Get the current time */ if (gettimeofday(&curtime, NULL) == 0) { unsigned long n_sec = (curtime.tv_usec + (wait_us % 1000000)) * 1000; timeout.tv_sec = curtime.tv_sec + (wait_us / 1000000) + (n_sec / 1000000000); timeout.tv_nsec = n_sec % 1000000000; wait_ret = pthread_cond_timedwait(&p_event->condvar, &p_event->mutex, &timeout); if (wait_ret == 0) status = (p_event-> signaled ? CL_SUCCESS : CL_NOT_DONE); else if (wait_ret == ETIMEDOUT) status = CL_TIMEOUT; else status = CL_NOT_DONE; } else status = CL_ERROR; } if (!p_event->manual_reset) p_event->signaled = FALSE; pthread_mutex_unlock(&p_event->mutex); return status; } opensm-3.3.20/complib/cl_event_wheel.c0000644000205000001450000004200012272264652014570 00000000000000/* * Copyright (c) 2004-2007 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define CL_DBG(fmt, ...) static cl_status_t __event_will_age_before(IN const cl_list_item_t * const p_list_item, IN void *context) { uint64_t aging_time = *((uint64_t *) context); cl_event_wheel_reg_info_t *p_event; p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); if (p_event->aging_time < aging_time) return CL_SUCCESS; else return CL_NOT_FOUND; } static void __cl_event_wheel_callback(IN void *context) { cl_event_wheel_t *p_event_wheel = (cl_event_wheel_t *) context; cl_list_item_t *p_list_item, *p_prev_event_list_item; cl_list_item_t *p_list_next_item; cl_event_wheel_reg_info_t *p_event; uint64_t current_time; uint64_t next_aging_time; uint32_t new_timeout; cl_status_t cl_status; /* might be during closing ... */ if (p_event_wheel->closing) return; current_time = cl_get_time_stamp(); if (NULL != p_event_wheel->p_external_lock) /* Take care of the order of acquiring locks to avoid the deadlock! * The external lock goes first. */ cl_spinlock_acquire(p_event_wheel->p_external_lock); cl_spinlock_acquire(&p_event_wheel->lock); p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) /* the list is empty - nothing to do */ goto Exit; /* we found such an item. get the p_event */ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); while (p_event->aging_time <= current_time) { /* this object has aged - invoke it's callback */ if (p_event->pfn_aged_callback) next_aging_time = p_event->pfn_aged_callback(p_event->key, p_event->num_regs, p_event->context); else next_aging_time = 0; /* point to the next object in the wheel */ p_list_next_item = cl_qlist_next(p_list_item); /* We need to retire the event if the next aging time passed */ if (next_aging_time < current_time) { /* remove it from the map */ cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item)); /* pop p_event from the wheel */ cl_qlist_remove_head(&p_event_wheel->events_wheel); /* delete the event info object - allocated by cl_event_wheel_reg */ free(p_event); } else { /* update the required aging time */ p_event->aging_time = next_aging_time; p_event->num_regs++; /* do not remove from the map - but remove from the list head and place in the correct position */ /* pop p_event from the wheel */ cl_qlist_remove_head(&p_event_wheel->events_wheel); /* find the event that ages just before */ p_prev_event_list_item = cl_qlist_find_from_tail(&p_event_wheel-> events_wheel, __event_will_age_before, &p_event->aging_time); /* insert just after */ cl_qlist_insert_next(&p_event_wheel->events_wheel, p_prev_event_list_item, &p_event->list_item); /* as we have modified the list - restart from first item: */ p_list_next_item = cl_qlist_head(&p_event_wheel->events_wheel); } /* advance to next event */ p_list_item = p_list_next_item; if (p_list_item == cl_qlist_end(&p_event_wheel->events_wheel)) /* the list is empty - nothing to do */ break; /* get the p_event */ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); } /* We need to restart the timer only if the list is not empty now */ if (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { /* get the p_event */ p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); /* start the timer to the timeout [msec] */ new_timeout = (uint32_t) ((p_event->aging_time - current_time + 500) / 1000); CL_DBG("__cl_event_wheel_callback: Restart timer in: " "%u [msec]\n", new_timeout); cl_status = cl_timer_start(&p_event_wheel->timer, new_timeout); if (cl_status != CL_SUCCESS) { CL_DBG("__cl_event_wheel_callback : ERR 6200: " "Failed to start timer\n"); } } /* release the lock */ Exit: cl_spinlock_release(&p_event_wheel->lock); if (NULL != p_event_wheel->p_external_lock) cl_spinlock_release(p_event_wheel->p_external_lock); } /* * Construct and Initialize */ void cl_event_wheel_construct(IN cl_event_wheel_t * const p_event_wheel) { cl_spinlock_construct(&(p_event_wheel->lock)); cl_timer_construct(&(p_event_wheel->timer)); } cl_status_t cl_event_wheel_init(IN cl_event_wheel_t * const p_event_wheel) { cl_status_t cl_status = CL_SUCCESS; /* initialize */ p_event_wheel->p_external_lock = NULL; p_event_wheel->closing = FALSE; cl_status = cl_spinlock_init(&(p_event_wheel->lock)); if (cl_status != CL_SUCCESS) return cl_status; cl_qlist_init(&p_event_wheel->events_wheel); cl_qmap_init(&p_event_wheel->events_map); /* init the timer with timeout */ cl_status = cl_timer_init(&p_event_wheel->timer, __cl_event_wheel_callback, p_event_wheel); /* cb context */ return cl_status; } cl_status_t cl_event_wheel_init_ex(IN cl_event_wheel_t * const p_event_wheel, IN cl_spinlock_t * p_external_lock) { cl_status_t cl_status; cl_status = cl_event_wheel_init(p_event_wheel); if (CL_SUCCESS != cl_status) return cl_status; p_event_wheel->p_external_lock = p_external_lock; return cl_status; } void cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel) { cl_list_item_t *p_list_item; cl_event_wheel_reg_info_t __attribute__((__unused__)) *p_event; p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); CL_DBG("cl_event_wheel_dump: Found event key:<0x%" PRIx64 ">, num_regs:%d, aging time:%" PRIu64 "\n", p_event->key, p_event->num_regs, p_event->aging_time); p_list_item = cl_qlist_next(p_list_item); } } void cl_event_wheel_destroy(IN cl_event_wheel_t * const p_event_wheel) { cl_list_item_t *p_list_item; cl_map_item_t *p_map_item; cl_event_wheel_reg_info_t *p_event; /* we need to get a lock */ cl_spinlock_acquire(&p_event_wheel->lock); cl_event_wheel_dump(p_event_wheel); /* go over all the items in the list and remove them */ p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel); while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); CL_DBG("cl_event_wheel_destroy: Found outstanding event" " key:<0x%" PRIx64 ">\n", p_event->key); /* remove it from the map */ p_map_item = &(p_event->map_item); cl_qmap_remove_item(&p_event_wheel->events_map, p_map_item); free(p_event); /* allocated by cl_event_wheel_reg */ p_list_item = cl_qlist_remove_head(&p_event_wheel->events_wheel); } /* destroy the timer */ cl_timer_destroy(&p_event_wheel->timer); /* destroy the lock (this should be done without releasing - we don't want any other run to grab the lock at this point. */ cl_spinlock_release(&p_event_wheel->lock); cl_spinlock_destroy(&(p_event_wheel->lock)); } cl_status_t cl_event_wheel_reg(IN cl_event_wheel_t * const p_event_wheel, IN const uint64_t key, IN const uint64_t aging_time_usec, IN cl_pfn_event_aged_cb_t pfn_callback, IN void *const context) { cl_event_wheel_reg_info_t *p_event; uint64_t timeout; uint32_t to; cl_status_t cl_status = CL_SUCCESS; cl_list_item_t *prev_event_list_item; cl_map_item_t *p_map_item; /* Get the lock on the manager */ cl_spinlock_acquire(&(p_event_wheel->lock)); cl_event_wheel_dump(p_event_wheel); /* Make sure such a key does not exists */ p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { CL_DBG("cl_event_wheel_reg: Already exists key:0x%" PRIx64 "\n", key); /* already there - remove it from the list as it is getting a new time */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(&p_event_wheel->events_wheel, &p_event->list_item); /* and the qmap */ cl_qmap_remove_item(&p_event_wheel->events_map, &p_event->map_item); } else { /* make a new one */ p_event = (cl_event_wheel_reg_info_t *) malloc(sizeof(cl_event_wheel_reg_info_t)); p_event->num_regs = 0; } p_event->key = key; p_event->aging_time = aging_time_usec; p_event->pfn_aged_callback = pfn_callback; p_event->context = context; p_event->num_regs++; CL_DBG("cl_event_wheel_reg: Registering event key:0x%" PRIx64 " aging in %u [msec]\n", p_event->key, (uint32_t) ((p_event->aging_time - cl_get_time_stamp()) / 1000)); /* If the list is empty - need to start the timer */ if (cl_is_qlist_empty(&p_event_wheel->events_wheel)) { /* Edward Bortnikov 03/29/2003 * ++TBD Consider moving the timer manipulation behind the list manipulation. */ /* calculate the new timeout */ timeout = (p_event->aging_time - cl_get_time_stamp() + 500) / 1000; /* stop the timer if it is running */ /* Edward Bortnikov 03/29/2003 * Don't call cl_timer_stop() because it spins forever. * cl_timer_start() will invoke cl_timer_stop() by itself. * * The problematic scenario is when __cl_event_wheel_callback() * is in race condition with this code. It sets timer.in_timer_cb * to TRUE and then blocks on p_event_wheel->lock. Following this, * the call to cl_timer_stop() hangs. Following this, the whole system * enters into a deadlock. * * cl_timer_stop(&p_event_wheel->timer); */ /* The timeout for the cl_timer_start should be given as uint32_t. if there is an overflow - warn about it. */ to = (uint32_t) timeout; if (timeout > (uint32_t) timeout) { to = 0xffffffff; /* max 32 bit timer */ CL_DBG("cl_event_wheel_reg: timeout requested is " "too large. Using timeout: %u\n", to); } /* start the timer to the timeout [msec] */ cl_status = cl_timer_start(&p_event_wheel->timer, to); if (cl_status != CL_SUCCESS) { CL_DBG("cl_event_wheel_reg : ERR 6203: " "Failed to start timer\n"); goto Exit; } } /* insert the object to the qlist and the qmap */ /* BUT WE MUST INSERT IT IN A SORTED MANNER */ prev_event_list_item = cl_qlist_find_from_tail(&p_event_wheel->events_wheel, __event_will_age_before, &p_event->aging_time); cl_qlist_insert_next(&p_event_wheel->events_wheel, prev_event_list_item, &p_event->list_item); cl_qmap_insert(&p_event_wheel->events_map, key, &(p_event->map_item)); Exit: cl_spinlock_release(&p_event_wheel->lock); return cl_status; } void cl_event_wheel_unreg(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key) { cl_event_wheel_reg_info_t *p_event; cl_map_item_t *p_map_item; CL_DBG("cl_event_wheel_unreg: " "Removing key:0x%" PRIx64 "\n", key); cl_spinlock_acquire(&p_event_wheel->lock); p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { /* we found such an item. */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); /* remove the item from the qlist */ cl_qlist_remove_item(&p_event_wheel->events_wheel, &(p_event->list_item)); /* remove the item from the qmap */ cl_qmap_remove_item(&p_event_wheel->events_map, &(p_event->map_item)); CL_DBG("cl_event_wheel_unreg: Removed key:0x%" PRIx64 "\n", key); /* free the item */ free(p_event); } else { CL_DBG("cl_event_wheel_unreg: did not find key:0x%" PRIx64 "\n", key); } cl_spinlock_release(&p_event_wheel->lock); } uint32_t cl_event_wheel_num_regs(IN cl_event_wheel_t * const p_event_wheel, IN uint64_t key) { cl_event_wheel_reg_info_t *p_event; cl_map_item_t *p_map_item; uint32_t num_regs = 0; /* try to find the key in the map */ CL_DBG("cl_event_wheel_num_regs: Looking for key:0x%" PRIx64 "\n", key); cl_spinlock_acquire(&p_event_wheel->lock); p_map_item = cl_qmap_get(&p_event_wheel->events_map, key); if (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { /* ok so we can simply return it's num_regs */ p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); num_regs = p_event->num_regs; } cl_spinlock_release(&p_event_wheel->lock); return (num_regs); } #ifdef __CL_EVENT_WHEEL_TEST__ /* Dump out the complete state of the event wheel */ void __cl_event_wheel_dump(IN cl_event_wheel_t * const p_event_wheel) { cl_list_item_t *p_list_item; cl_map_item_t *p_map_item; cl_event_wheel_reg_info_t *p_event; printf("************** Event Wheel Dump ***********************\n"); printf("Event Wheel List has %u items:\n", cl_qlist_count(&p_event_wheel->events_wheel)); p_list_item = cl_qlist_head(&p_event_wheel->events_wheel); while (p_list_item != cl_qlist_end(&p_event_wheel->events_wheel)) { p_event = PARENT_STRUCT(p_list_item, cl_event_wheel_reg_info_t, list_item); printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n", p_event->key, (char *)p_event->context, p_event->num_regs); /* next */ p_list_item = cl_qlist_next(p_list_item); } printf("Event Map has %u items:\n", cl_qmap_count(&p_event_wheel->events_map)); p_map_item = cl_qmap_head(&p_event_wheel->events_map); while (p_map_item != cl_qmap_end(&p_event_wheel->events_map)) { p_event = PARENT_STRUCT(p_map_item, cl_event_wheel_reg_info_t, map_item); printf("Event key:0x%" PRIx64 " Context:%s NumRegs:%u\n", p_event->key, (char *)p_event->context, p_event->num_regs); /* next */ p_map_item = cl_qmap_next(p_map_item); } } /* The callback for aging event */ /* We assume we pass a text context */ static uint64_t __test_event_aging(uint64_t key, uint32_t num_regs, void *context) { printf("*****************************************************\n"); printf("Aged key: 0x%" PRIx64 " Context:%s\n", key, (char *)context); } int main() { cl_event_wheel_t event_wheel; /* uint64_t key; */ /* init complib */ complib_init(); /* construct */ cl_event_wheel_construct(&event_wheel); /* init */ cl_event_wheel_init(&event_wheel); /* Start Playing */ cl_event_wheel_reg(&event_wheel, 1, /* key */ cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ __test_event_aging, /* cb */ "The first Aging Event"); cl_event_wheel_reg(&event_wheel, 2, /* key */ cl_get_time_stamp() + 3000000, /* 3 sec lifetime */ __test_event_aging, /* cb */ "The Second Aging Event"); cl_event_wheel_reg(&event_wheel, 3, /* key */ cl_get_time_stamp() + 3500000, /* 3 sec lifetime */ __test_event_aging, /* cb */ "The Third Aging Event"); __cl_event_wheel_dump(&event_wheel); sleep(2); cl_event_wheel_reg(&event_wheel, 2, /* key */ cl_get_time_stamp() + 8000000, /* 3 sec lifetime */ __test_event_aging, /* cb */ "The Second Aging Event Moved"); __cl_event_wheel_dump(&event_wheel); sleep(1); /* remove the third event */ cl_event_wheel_unreg(&event_wheel, 3); /* key */ /* get the number of registrations for the keys */ printf("Event 1 Registered: %u\n", cl_event_wheel_num_regs(&event_wheel, 1)); printf("Event 2 Registered: %u\n", cl_event_wheel_num_regs(&event_wheel, 2)); sleep(5); /* destroy */ cl_event_wheel_destroy(&event_wheel); complib_exit(); return (0); } #endif /* __CL_EVENT_WHEEL_TEST__ */ opensm-3.3.20/complib/cl_list.c0000644000205000001450000003625512104655724013253 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2009 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 list, and list. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #define FREE_ITEM_GROW_SIZE 10 /****************************************************************************** IMPLEMENTATION OF QUICK LIST ******************************************************************************/ void cl_qlist_insert_array_head(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_array, IN uint32_t item_count, IN const uint32_t item_size) { cl_list_item_t *p_item; CL_ASSERT(p_list); CL_ASSERT(p_list->state == CL_INITIALIZED); CL_ASSERT(p_array); CL_ASSERT(item_size >= sizeof(cl_list_item_t)); CL_ASSERT(item_count); /* * 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. */ p_item = (cl_list_item_t *) ((uint8_t *) p_array + (item_size * (item_count - 1))); /* Continue to add all items to the list. */ while (item_count--) { cl_qlist_insert_head(p_list, p_item); /* Get the next object to add to the list. */ p_item = (cl_list_item_t *) ((uint8_t *) p_item - item_size); } } void cl_qlist_insert_array_tail(IN cl_qlist_t * const p_list, IN cl_list_item_t * const p_array, IN uint32_t item_count, IN const uint32_t item_size) { cl_list_item_t *p_item; CL_ASSERT(p_list); CL_ASSERT(p_list->state == CL_INITIALIZED); CL_ASSERT(p_array); CL_ASSERT(item_size >= sizeof(cl_list_item_t)); CL_ASSERT(item_count); /* Set the first item to add to the list. */ p_item = p_array; /* Continue to add all items to the list. */ while (item_count--) { cl_qlist_insert_tail(p_list, p_item); /* Get the next object to add to the list. */ p_item = (cl_list_item_t *) ((uint8_t *) p_item + item_size); } } void cl_qlist_insert_list_head(IN cl_qlist_t * const p_dest_list, IN cl_qlist_t * const p_src_list) { #if defined( _DEBUG_ ) cl_list_item_t *p_item; #endif CL_ASSERT(p_dest_list); CL_ASSERT(p_src_list); CL_ASSERT(p_dest_list->state == CL_INITIALIZED); CL_ASSERT(p_src_list->state == CL_INITIALIZED); /* * Is the src list empty? * We must have this check here for code below to work. */ if (cl_is_qlist_empty(p_src_list)) return; #if defined( _DEBUG_ ) /* Check that all items in the source list belong there. */ p_item = cl_qlist_head(p_src_list); while (p_item != cl_qlist_end(p_src_list)) { /* All list items in the source list must point to it. */ CL_ASSERT(p_item->p_list == p_src_list); /* Point them all to the destination list. */ p_item->p_list = p_dest_list; p_item = cl_qlist_next(p_item); } #endif /* Chain the destination list to the tail of the source list. */ cl_qlist_tail(p_src_list)->p_next = cl_qlist_head(p_dest_list); cl_qlist_head(p_dest_list)->p_prev = cl_qlist_tail(p_src_list); /* * Update the head of the destination list to the head of * the source list. */ p_dest_list->end.p_next = cl_qlist_head(p_src_list); cl_qlist_head(p_src_list)->p_prev = &p_dest_list->end; /* * Update the count of the destination to reflect the source items having * been added. */ p_dest_list->count += p_src_list->count; /* Update source list to reflect being empty. */ __cl_qlist_reset(p_src_list); } void cl_qlist_insert_list_tail(IN cl_qlist_t * const p_dest_list, IN cl_qlist_t * const p_src_list) { #if defined( _DEBUG_ ) cl_list_item_t *p_item; #endif CL_ASSERT(p_dest_list); CL_ASSERT(p_src_list); CL_ASSERT(p_dest_list->state == CL_INITIALIZED); CL_ASSERT(p_src_list->state == CL_INITIALIZED); /* * Is the src list empty? * We must have this check here for code below to work. */ if (cl_is_qlist_empty(p_src_list)) return; #if defined( _DEBUG_ ) /* Check that all items in the source list belong there. */ p_item = cl_qlist_head(p_src_list); while (p_item != cl_qlist_end(p_src_list)) { /* All list items in the source list must point to it. */ CL_ASSERT(p_item->p_list == p_src_list); /* Point them all to the destination list. */ p_item->p_list = p_dest_list; p_item = cl_qlist_next(p_item); } #endif /* Chain the source list to the tail of the destination list. */ cl_qlist_tail(p_dest_list)->p_next = cl_qlist_head(p_src_list); cl_qlist_head(p_src_list)->p_prev = cl_qlist_tail(p_dest_list); /* * Update the tail of the destination list to the tail of * the source list. */ p_dest_list->end.p_prev = cl_qlist_tail(p_src_list); cl_qlist_tail(p_src_list)->p_next = &p_dest_list->end; /* * Update the count of the destination to reflect the source items having * been added. */ p_dest_list->count += p_src_list->count; /* Update source list to reflect being empty. */ __cl_qlist_reset(p_src_list); } boolean_t cl_is_item_in_qlist(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item) { const cl_list_item_t *p_temp; CL_ASSERT(p_list); CL_ASSERT(p_list_item); CL_ASSERT(p_list->state == CL_INITIALIZED); /* Traverse looking for a match */ p_temp = cl_qlist_head(p_list); while (p_temp != cl_qlist_end(p_list)) { if (p_temp == p_list_item) { CL_ASSERT(p_list_item->p_list == p_list); return (TRUE); } p_temp = cl_qlist_next(p_temp); } return (FALSE); } cl_list_item_t *cl_qlist_find_next(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context) { cl_list_item_t *p_found_item; CL_ASSERT(p_list); CL_ASSERT(p_list->state == CL_INITIALIZED); CL_ASSERT(p_list_item); CL_ASSERT(p_list_item->p_list == p_list); CL_ASSERT(pfn_func); p_found_item = cl_qlist_next(p_list_item); /* The user provided a compare function */ while (p_found_item != cl_qlist_end(p_list)) { CL_ASSERT(p_found_item->p_list == p_list); if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS) break; p_found_item = cl_qlist_next(p_found_item); } /* No match */ return (p_found_item); } cl_list_item_t *cl_qlist_find_prev(IN const cl_qlist_t * const p_list, IN const cl_list_item_t * const p_list_item, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context) { cl_list_item_t *p_found_item; CL_ASSERT(p_list); CL_ASSERT(p_list->state == CL_INITIALIZED); CL_ASSERT(p_list_item); CL_ASSERT(p_list_item->p_list == p_list); CL_ASSERT(pfn_func); p_found_item = cl_qlist_prev(p_list_item); /* The user provided a compare function */ while (p_found_item != cl_qlist_end(p_list)) { CL_ASSERT(p_found_item->p_list == p_list); if (pfn_func(p_found_item, (void *)context) == CL_SUCCESS) break; p_found_item = cl_qlist_prev(p_found_item); } /* No match */ return (p_found_item); } void cl_qlist_apply_func(IN const cl_qlist_t * const p_list, IN cl_pfn_qlist_apply_t pfn_func, IN const void *const context) { cl_list_item_t *p_list_item; /* Note that context can have any arbitrary value. */ CL_ASSERT(p_list); CL_ASSERT(p_list->state == CL_INITIALIZED); CL_ASSERT(pfn_func); p_list_item = cl_qlist_head(p_list); while (p_list_item != cl_qlist_end(p_list)) { pfn_func(p_list_item, (void *)context); p_list_item = cl_qlist_next(p_list_item); } } void cl_qlist_move_items(IN cl_qlist_t * const p_src_list, IN cl_qlist_t * const p_dest_list, IN cl_pfn_qlist_find_t pfn_func, IN const void *const context) { cl_list_item_t *p_current_item, *p_next; CL_ASSERT(p_src_list); CL_ASSERT(p_dest_list); CL_ASSERT(p_src_list->state == CL_INITIALIZED); CL_ASSERT(p_dest_list->state == CL_INITIALIZED); CL_ASSERT(pfn_func); p_current_item = cl_qlist_head(p_src_list); while (p_current_item != cl_qlist_end(p_src_list)) { /* Before we do anything, get a pointer to the next item. */ p_next = cl_qlist_next(p_current_item); if (pfn_func(p_current_item, (void *)context) == CL_SUCCESS) { /* Move the item from one list to the other. */ cl_qlist_remove_item(p_src_list, p_current_item); cl_qlist_insert_tail(p_dest_list, p_current_item); } p_current_item = p_next; } } /****************************************************************************** IMPLEMENTATION OF LIST ******************************************************************************/ void cl_list_construct(IN cl_list_t * const p_list) { CL_ASSERT(p_list); cl_qpool_construct(&p_list->list_item_pool); } cl_status_t cl_list_init(IN cl_list_t * const p_list, IN const size_t min_items) { uint32_t grow_size; CL_ASSERT(p_list); cl_qlist_init(&p_list->list); /* * We will grow by min_items/8 items at a time, with a minimum of * FREE_ITEM_GROW_SIZE. */ grow_size = (uint32_t) min_items >> 3; if (grow_size < FREE_ITEM_GROW_SIZE) grow_size = FREE_ITEM_GROW_SIZE; /* Initialize the pool of list items. */ return (cl_qpool_init(&p_list->list_item_pool, min_items, 0, grow_size, sizeof(cl_pool_obj_t), NULL, NULL, NULL)); } void cl_list_destroy(IN cl_list_t * const p_list) { CL_ASSERT(p_list); cl_qpool_destroy(&p_list->list_item_pool); } static cl_status_t cl_list_find_cb(IN const cl_list_item_t * const p_list_item, IN void *const context) { CL_ASSERT(p_list_item); if (cl_list_obj(p_list_item) == context) return (CL_SUCCESS); return (CL_NOT_FOUND); } cl_status_t cl_list_remove_object(IN cl_list_t * const p_list, IN const void *const p_object) { cl_list_item_t *p_list_item; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); /* find the item in question */ p_list_item = cl_qlist_find_from_head(&p_list->list, cl_list_find_cb, p_object); if (p_list_item != cl_qlist_end(&p_list->list)) { /* remove this item */ cl_qlist_remove_item(&p_list->list, p_list_item); cl_qpool_put(&p_list->list_item_pool, (cl_pool_item_t *) p_list_item); return (CL_SUCCESS); } return (CL_NOT_FOUND); } boolean_t cl_is_object_in_list(IN const cl_list_t * const p_list, IN const void *const p_object) { CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); return (cl_qlist_find_from_head (&p_list->list, cl_list_find_cb, p_object) != cl_qlist_end(&p_list->list)); } cl_status_t cl_list_insert_array_head(IN cl_list_t * const p_list, IN const void *const p_array, IN uint32_t item_count, IN const uint32_t item_size) { cl_status_t status; void *p_object; uint32_t items_remain = item_count; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); CL_ASSERT(p_array); CL_ASSERT(item_size); CL_ASSERT(item_count); /* * 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. */ p_object = ((uint8_t *) p_array + (item_size * (item_count - 1))); /* Continue to add all items to the list. */ while (items_remain--) { status = cl_list_insert_head(p_list, p_object); if (status != CL_SUCCESS) { /* Remove all items that have been inserted. */ while (items_remain++ < (item_count - 1)) cl_list_remove_head(p_list); return (status); } /* Get the next object to add to the list. */ p_object = ((uint8_t *) p_object - item_size); } return (CL_SUCCESS); } cl_status_t cl_list_insert_array_tail(IN cl_list_t * const p_list, IN const void *const p_array, IN uint32_t item_count, IN const uint32_t item_size) { cl_status_t status; void *p_object; uint32_t items_remain = item_count; CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); CL_ASSERT(p_array); CL_ASSERT(item_size); CL_ASSERT(item_count); /* Set the first item to add to the list. */ p_object = (void *)p_array; /* Continue to add all items to the list. */ while (items_remain--) { status = cl_list_insert_tail(p_list, p_object); if (status != CL_SUCCESS) { /* Remove all items that have been inserted. */ while (items_remain++ < (item_count - 1)) cl_list_remove_tail(p_list); return (status); } /* Get the next object to add to the list. */ p_object = ((uint8_t *) p_object + item_size); } return (CL_SUCCESS); } cl_list_iterator_t cl_list_find_from_head(IN const cl_list_t * const p_list, IN cl_pfn_list_find_t pfn_func, IN const void *const context) { cl_status_t status; cl_list_iterator_t itor; /* Note that context can have any arbitrary value. */ CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); CL_ASSERT(pfn_func); itor = cl_list_head(p_list); while (itor != cl_list_end(p_list)) { status = pfn_func(cl_list_obj(itor), (void *)context); if (status == CL_SUCCESS) break; itor = cl_list_next(itor); } /* no match */ return (itor); } cl_list_iterator_t cl_list_find_from_tail(IN const cl_list_t * const p_list, IN cl_pfn_list_find_t pfn_func, IN const void *const context) { cl_status_t status; cl_list_iterator_t itor; /* Note that context can have any arbitrary value. */ CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); CL_ASSERT(pfn_func); itor = cl_list_tail(p_list); while (itor != cl_list_end(p_list)) { status = pfn_func(cl_list_obj(itor), (void *)context); if (status == CL_SUCCESS) break; itor = cl_list_prev(itor); } /* no match */ return (itor); } void cl_list_apply_func(IN const cl_list_t * const p_list, IN cl_pfn_list_apply_t pfn_func, IN const void *const context) { cl_list_iterator_t itor; /* Note that context can have any arbitrary value. */ CL_ASSERT(p_list); CL_ASSERT(cl_is_qpool_inited(&p_list->list_item_pool)); CL_ASSERT(pfn_func); itor = cl_list_head(p_list); while (itor != cl_list_end(p_list)) { pfn_func(cl_list_obj(itor), (void *)context); itor = cl_list_next(itor); } } opensm-3.3.20/complib/cl_log.c0000644000205000001450000000651712104655724013057 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #ifdef __WIN__ #pragma warning(disable : 4996) #endif #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include /* Maximum number of bytes that can be logged. */ #define CL_MAX_LOG_DATA (256) /* * Size of the character buffer to allow logging the above * number of bytes. A space is added after every DWORD, and * a new line is added after 8 DWORDS (for a line length less than 80). */ #define CL_LOG_DATA_SIZE (CL_MAX_LOG_DATA + (CL_MAX_LOG_DATA/4)) void cl_log_event(IN const char *const name, IN const cl_log_type_t type, IN const char *const message, IN const void *const p_data OPTIONAL, IN const uint32_t data_len) { int priority, i; char data[CL_LOG_DATA_SIZE]; char *p_buf; uint8_t *p_int_data = (uint8_t *) p_data; CL_ASSERT(name); CL_ASSERT(message); openlog(name, LOG_NDELAY | LOG_PID, LOG_USER); switch (type) { case CL_LOG_ERROR: priority = LOG_ERR; break; case CL_LOG_WARN: priority = LOG_WARNING; break; case CL_LOG_INFO: default: priority = LOG_INFO; break; } if (p_data) { CL_ASSERT(data_len); if (data_len < CL_MAX_LOG_DATA) { p_buf = data; /* Format the data into ASCII. */ for (i = 0; i < data_len; i++) { sprintf(p_buf, "%02x", *p_int_data++); p_buf += 2; /* Add line break after 8 DWORDS. */ if (i % 32) { sprintf(p_buf++, "\n"); continue; } /* Add a space between DWORDS. */ if (i % 4) sprintf(p_buf++, " "); } syslog(priority, "%s data:\n%s\n", message, p_buf); } else { /* The data portion is too large to log. */ cl_msg_out ("cl_log() - WARNING: data too large to log.\n"); syslog(priority, "%s\n", message); } } else { syslog(priority, "%s\n", message); } closelog(); } opensm-3.3.20/complib/cl_map.c0000644000205000001450000012550412104655724013051 00000000000000/* * Copyright (c) 2004-2009 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. * */ /***************************************************************************** * * 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. * *****************************************************************************/ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #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) { CL_ASSERT(p_map); return (p_map->root.p_left); } /* * Returns whether a given item is on the left of its parent. */ static boolean_t __cl_map_is_left_child(IN const cl_map_item_t * const p_item) { CL_ASSERT(p_item); CL_ASSERT(p_item->p_up); CL_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) { CL_ASSERT(p_item); CL_ASSERT(p_item->p_up); CL_ASSERT(p_item->p_up != p_item); if (__cl_map_is_left_child(p_item)) return (&p_item->p_up->p_left); CL_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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_ASSERT(p_item->p_right != &p_map->nil); 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) (*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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_ASSERT(p_item->p_left != &p_map->nil); /* 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) (*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) { CL_ASSERT(p_map); memset(p_map, 0, 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; p_map->root.p_right = &p_map->nil; p_map->root.color = CL_MAP_BLACK; /* Setup the node used as terminator for all leaves. */ p_map->nil.p_up = &p_map->nil; p_map->nil.p_left = &p_map->nil; p_map->nil.p_right = &p_map->nil; p_map->nil.color = CL_MAP_BLACK; p_map->state = CL_INITIALIZED; cl_qmap_remove_all(p_map); } cl_map_item_t *cl_qmap_get(IN const cl_qmap_t * const p_map, IN const uint64_t key) { cl_map_item_t *p_item; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_item = __cl_map_root(p_map); while (p_item != &p_map->nil) { 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 */ } return (p_item); } cl_map_item_t *cl_qmap_get_next(IN const cl_qmap_t * const p_map, IN const uint64_t key) { cl_map_item_t *p_item; cl_map_item_t *p_item_found; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_item = __cl_map_root(p_map); p_item_found = (cl_map_item_t *) & p_map->nil; while (p_item != &p_map->nil) { if (key < p_item->key) { p_item_found = p_item; p_item = p_item->p_left; } else { p_item = p_item->p_right; } } return (p_item_found); } 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. */ CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_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; CL_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; CL_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_t key, IN cl_map_item_t * const p_item) { cl_map_item_t *p_insert_at, *p_comp_item; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_ASSERT(p_item); CL_ASSERT(p_map->root.p_up == &p_map->root); CL_ASSERT(p_map->root.color != CL_MAP_RED); CL_ASSERT(p_map->nil.color != CL_MAP_RED); p_item->p_left = &p_map->nil; p_item->p_right = &p_map->nil; p_item->key = key; p_item->color = CL_MAP_RED; /* Find the insertion location. */ p_insert_at = &p_map->root; p_comp_item = __cl_map_root(p_map); while (p_comp_item != &p_map->nil) { 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; else p_comp_item = p_insert_at->p_right; } CL_ASSERT(p_insert_at != &p_map->nil); CL_ASSERT(p_comp_item == &p_map->nil); /* 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.pool_item.list_item, &p_item->pool_item.list_item); } else if (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. */ #ifdef _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; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_ASSERT(p_item); if (p_item == cl_qmap_end(p_map)) return; /* must be checked after comparing to cl_qmap_end, since the end is not a valid item. */ CL_ASSERT(p_item->p_map == p_map); if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) { /* 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); CL_ASSERT(p_del_item != &p_map->nil); } /* 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) 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; } CL_ASSERT(p_map->nil.color != CL_MAP_RED); #ifdef _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_t key) { cl_map_item_t *p_item; CL_ASSERT(p_map); CL_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); } 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; CL_ASSERT(p_dest_map); CL_ASSERT(p_src_map); 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); CL_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 __attribute__((__unused__)) *p_temp; cl_map_item_t *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. */ CL_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_t key1, key2; CL_ASSERT(p_map1); CL_ASSERT(p_map2); CL_ASSERT(p_new); CL_ASSERT(p_old); CL_ASSERT(cl_is_qmap_empty(p_new)); CL_ASSERT(cl_is_qmap_empty(p_old)); 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 ******************************************************************************/ #define MAP_GROW_SIZE 32 void cl_map_construct(IN cl_map_t * const p_map) { CL_ASSERT(p_map); cl_qpool_construct(&p_map->pool); } cl_status_t cl_map_init(IN cl_map_t * const p_map, IN const uint32_t min_items) { uint32_t grow_size; CL_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) { CL_ASSERT(p_map); cl_qpool_destroy(&p_map->pool); } void *cl_map_insert(IN cl_map_t * const p_map, IN const uint64_t key, IN const void *const p_object) { cl_map_obj_t *p_map_obj, *p_obj_at_key; CL_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_t key) { cl_map_item_t *p_item; CL_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_get_next(IN const cl_map_t * const p_map, IN const uint64_t key) { cl_map_item_t *p_item; CL_ASSERT(p_map); p_item = cl_qmap_get_next(&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) { CL_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_t key) { cl_map_item_t *p_item; void *p_obj; CL_ASSERT(p_map); p_item = cl_qmap_remove(&p_map->qmap, key); if (p_item == cl_qmap_end(&p_map->qmap)) return (NULL); p_obj = cl_qmap_obj((cl_map_obj_t *) p_item); cl_qpool_put(&p_map->pool, &p_item->pool_item); return (p_obj); } void cl_map_remove_all(IN cl_map_t * const p_map) { cl_map_item_t *p_item; CL_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_t key; void *p_obj, *p_obj2; CL_ASSERT(p_dest_map); CL_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); CL_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 __attribute__((__unused__)) status; /* Restore the initial state. */ status = cl_map_merge(p_map1, p_old); CL_ASSERT(status == CL_SUCCESS); status = cl_map_merge(p_map2, p_new); CL_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_t 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); CL_ASSERT(p_obj2 == p_obj); return (CL_INSUFFICIENT_MEMORY); } /* We should never get a duplicate */ CL_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_t key1, key2; cl_status_t status; CL_ASSERT(p_map1); CL_ASSERT(p_map2); CL_ASSERT(p_new); CL_ASSERT(p_old); CL_ASSERT(cl_is_map_empty(p_new)); CL_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) { CL_ASSERT(p_map); return (p_map->root.p_left); } /* * Returns whether a given item is on the left of its parent. */ static boolean_t __cl_fmap_is_left_child(IN const cl_fmap_item_t * const p_item) { CL_ASSERT(p_item); CL_ASSERT(p_item->p_up); CL_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) { CL_ASSERT(p_item); CL_ASSERT(p_item->p_up); CL_ASSERT(p_item->p_up != p_item); if (__cl_fmap_is_left_child(p_item)) return (&p_item->p_up->p_left); CL_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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_ASSERT(p_item->p_right != &p_map->nil); 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) (*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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_ASSERT(p_item->p_left != &p_map->nil); /* 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) (*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) { CL_ASSERT(p_map); CL_ASSERT(pfn_compare); memset(p_map, 0, 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; p_map->root.p_right = &p_map->nil; p_map->root.color = CL_MAP_BLACK; /* Setup the node used as terminator for all leaves. */ p_map->nil.p_up = &p_map->nil; p_map->nil.p_left = &p_map->nil; p_map->nil.p_right = &p_map->nil; p_map->nil.color = CL_MAP_BLACK; /* 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_match(IN const cl_fmap_t * const p_map, IN const void *const p_key, IN cl_pfn_fmap_cmp_t pfn_compare) { cl_fmap_item_t *p_item; int cmp; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_item = __cl_fmap_root(p_map); while (p_item != &p_map->nil) { cmp = pfn_compare ? pfn_compare(p_key, p_item->p_key) : 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); } cl_fmap_item_t *cl_fmap_get(IN const cl_fmap_t * const p_map, IN const void *const p_key) { return cl_fmap_match(p_map, p_key, p_map->pfn_compare); } cl_fmap_item_t *cl_fmap_get_next(IN const cl_fmap_t * const p_map, IN const void *const p_key) { cl_fmap_item_t *p_item; cl_fmap_item_t *p_item_found; int cmp; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); p_item = __cl_fmap_root(p_map); p_item_found = (cl_fmap_item_t *) & p_map->nil; while (p_item != &p_map->nil) { cmp = p_map->pfn_compare(p_key, p_item->p_key); if (cmp < 0) { p_item_found = p_item; p_item = p_item->p_left; /* too small */ } else { p_item = p_item->p_right; /* too big or match */ } } return (p_item_found); } 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. */ CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_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; CL_ASSERT(p_map); CL_ASSERT(p_item); CL_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; CL_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; CL_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; int cmp = 0; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_ASSERT(p_item); CL_ASSERT(p_map->root.p_up == &p_map->root); CL_ASSERT(p_map->root.color != CL_MAP_RED); CL_ASSERT(p_map->nil.color != CL_MAP_RED); p_item->p_left = &p_map->nil; p_item->p_right = &p_map->nil; 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) { 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; } CL_ASSERT(p_insert_at != &p_map->nil); CL_ASSERT(p_comp_item == &p_map->nil); /* 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.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. */ #ifdef _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; CL_ASSERT(p_map); CL_ASSERT(p_map->state == CL_INITIALIZED); CL_ASSERT(p_item); CL_ASSERT(p_item->p_map == p_map); if (p_item == cl_fmap_end(p_map)) return; if ((p_item->p_right == &p_map->nil) || (p_item->p_left == &p_map->nil)) { /* 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); CL_ASSERT(p_del_item != &p_map->nil); } /* 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) 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; } CL_ASSERT(p_map->nil.color != CL_MAP_RED); #ifdef _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; CL_ASSERT(p_map); CL_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; CL_ASSERT(p_dest_map); CL_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); CL_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 __attribute__((__unused__)) *p_temp; cl_fmap_item_t *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. */ CL_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; int cmp; CL_ASSERT(p_map1); CL_ASSERT(p_map2); CL_ASSERT(p_new); CL_ASSERT(p_old); CL_ASSERT(cl_is_fmap_empty(p_new)); CL_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); } opensm-3.3.20/complib/cl_pool.c0000644000205000001450000004406212104655724013244 00000000000000/* * Copyright (c) 2004-2009 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 the grow pools. The grow pools manage a pool of objects. * The pools can grow to meet demand, limited only by system memory. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include /* * IMPLEMENTATION OF QUICK COMPOSITE POOL */ void cl_qcpool_construct(IN cl_qcpool_t * const p_pool) { CL_ASSERT(p_pool); memset(p_pool, 0, sizeof(cl_qcpool_t)); p_pool->state = CL_UNINITIALIZED; } cl_status_t cl_qcpool_init(IN cl_qcpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN const size_t * const component_sizes, IN const uint32_t num_components, IN cl_pfn_qcpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_qcpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context) { cl_status_t status; uint32_t i; CL_ASSERT(p_pool); /* Must have a minimum of 1 component. */ CL_ASSERT(num_components); /* A component size array is required. */ CL_ASSERT(component_sizes); /* * If no initializer is provided, the first component must be large * enough to hold a pool item. */ CL_ASSERT(pfn_initializer || (component_sizes[0] >= sizeof(cl_pool_item_t))); cl_qcpool_construct(p_pool); if (num_components > 1 && !pfn_initializer) return (CL_INVALID_SETTING); if (max_size && max_size < min_size) return (CL_INVALID_SETTING); /* * Allocate the array of component sizes and component pointers all * in one allocation. */ p_pool->component_sizes = (size_t *) malloc((sizeof(size_t) + sizeof(void *)) * num_components); if (!p_pool->component_sizes) return (CL_INSUFFICIENT_MEMORY); else memset(p_pool->component_sizes, 0, (sizeof(size_t) + sizeof(void *)) * num_components); /* Calculate the pointer to the array of pointers, used for callbacks. */ p_pool->p_components = (void **)(p_pool->component_sizes + num_components); /* Copy the user's sizes into our array for future use. */ memcpy(p_pool->component_sizes, component_sizes, sizeof(component_sizes[0]) * num_components); /* Store the number of components per object. */ p_pool->num_components = num_components; /* Round up and store the size of the components. */ for (i = 0; i < num_components; i++) { /* * We roundup each component size so that all components * are aligned on a natural boundary. */ p_pool->component_sizes[i] = ROUNDUP(p_pool->component_sizes[i], sizeof(uintptr_t)); } p_pool->max_objects = max_size ? max_size : ~(size_t) 0; p_pool->grow_size = grow_size; /* Store callback function pointers. */ p_pool->pfn_init = pfn_initializer; /* may be NULL */ p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ p_pool->context = context; cl_qlist_init(&p_pool->alloc_list); cl_qlist_init(&p_pool->free_list); /* * We are now initialized. We change the initialized flag before * growing since the grow function asserts that we are initialized. */ p_pool->state = CL_INITIALIZED; /* Allocate the minimum number of objects as requested. */ if (!min_size) return (CL_SUCCESS); status = cl_qcpool_grow(p_pool, min_size); /* Trap for error and cleanup if necessary. */ if (status != CL_SUCCESS) cl_qcpool_destroy(p_pool); return (status); } void cl_qcpool_destroy(IN cl_qcpool_t * const p_pool) { /* CL_ASSERT that a non-NULL pointer was provided. */ CL_ASSERT(p_pool); /* CL_ASSERT that we are in a valid state (not uninitialized memory). */ CL_ASSERT(cl_is_state_valid(p_pool->state)); if (p_pool->state == CL_INITIALIZED) { /* * 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! */ #ifdef _DEBUG_ /* but we do not want "free" version to assert on this one */ CL_ASSERT(cl_qcpool_count(p_pool) == p_pool->num_objects); #endif /* call the user's destructor for each object in the pool */ if (p_pool->pfn_dtor) { while (!cl_is_qlist_empty(&p_pool->free_list)) { p_pool->pfn_dtor((cl_pool_item_t *) cl_qlist_remove_head(&p_pool-> free_list), (void *)p_pool->context); } } else { cl_qlist_remove_all(&p_pool->free_list); } /* Free all allocated memory blocks. */ while (!cl_is_qlist_empty(&p_pool->alloc_list)) free(cl_qlist_remove_head(&p_pool->alloc_list)); if (p_pool->component_sizes) { free(p_pool->component_sizes); p_pool->component_sizes = NULL; } } p_pool->state = CL_UNINITIALIZED; } cl_status_t cl_qcpool_grow(IN cl_qcpool_t * const p_pool, IN size_t obj_count) { cl_status_t status = CL_SUCCESS; uint8_t *p_objects; cl_pool_item_t *p_pool_item; uint32_t i; size_t obj_size; CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); CL_ASSERT(obj_count); /* Validate that growth is possible. */ if (p_pool->num_objects == p_pool->max_objects) return (CL_INSUFFICIENT_MEMORY); /* Cap the growth to the desired maximum. */ if (obj_count > (p_pool->max_objects - p_pool->num_objects)) obj_count = p_pool->max_objects - p_pool->num_objects; /* Calculate the size of an object. */ obj_size = 0; for (i = 0; i < p_pool->num_components; i++) obj_size += p_pool->component_sizes[i]; /* Allocate the buffer for the new objects. */ p_objects = (uint8_t *) malloc(sizeof(cl_list_item_t) + (obj_size * obj_count)); /* Make sure the allocation succeeded. */ if (!p_objects) return (CL_INSUFFICIENT_MEMORY); else memset(p_objects, 0, sizeof(cl_list_item_t) + (obj_size * obj_count)); /* Insert the allocation in our list. */ cl_qlist_insert_tail(&p_pool->alloc_list, (cl_list_item_t *) p_objects); p_objects += sizeof(cl_list_item_t); /* initialize the new elements and add them to the free list */ while (obj_count--) { /* Setup the array of components for the current object. */ p_pool->p_components[0] = p_objects; for (i = 1; i < p_pool->num_components; i++) { /* Calculate the pointer to the next component. */ p_pool->p_components[i] = (uint8_t *) p_pool->p_components[i - 1] + p_pool->component_sizes[i - 1]; } /* * call the user's initializer * this can fail! */ if (p_pool->pfn_init) { p_pool_item = NULL; status = p_pool->pfn_init(p_pool->p_components, p_pool->num_components, (void *)p_pool->context, &p_pool_item); if (status != CL_SUCCESS) { /* * User initialization failed * we may have only grown the pool by some partial amount * Invoke the destructor for the object that failed * initialization. */ if (p_pool->pfn_dtor) p_pool->pfn_dtor(p_pool_item, (void *)p_pool-> context); /* Return the user's status. */ return (status); } CL_ASSERT(p_pool_item); } else { /* * If no initializer is provided, assume that the pool item * is stored at the beginning of the first component. */ p_pool_item = (cl_pool_item_t *) p_pool->p_components[0]; } #ifdef _DEBUG_ /* * Set the pool item's pool pointer to this pool so that we can * check that items get returned to the correct pool. */ p_pool_item->p_pool = p_pool; #endif /* Insert the new item in the free list, traping for failure. */ cl_qlist_insert_head(&p_pool->free_list, &p_pool_item->list_item); p_pool->num_objects++; /* move the pointer to the next item */ p_objects += obj_size; } return (status); } cl_pool_item_t *cl_qcpool_get(IN cl_qcpool_t * const p_pool) { cl_list_item_t *p_list_item; CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); if (cl_is_qlist_empty(&p_pool->free_list)) { /* * No object is available. * Return NULL if the user does not want automatic growth. */ if (!p_pool->grow_size) return (NULL); /* We ran out of elements. Get more */ cl_qcpool_grow(p_pool, p_pool->grow_size); /* * We may not have gotten everything we wanted but we might have * gotten something. */ if (cl_is_qlist_empty(&p_pool->free_list)) return (NULL); } p_list_item = cl_qlist_remove_head(&p_pool->free_list); /* OK, at this point we have an object */ CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list)); return ((cl_pool_item_t *) p_list_item); } cl_pool_item_t *cl_qcpool_get_tail(IN cl_qcpool_t * const p_pool) { cl_list_item_t *p_list_item; CL_ASSERT(p_pool); CL_ASSERT(p_pool->state == CL_INITIALIZED); if (cl_is_qlist_empty(&p_pool->free_list)) { /* * No object is available. * Return NULL if the user does not want automatic growth. */ if (!p_pool->grow_size) return (NULL); /* We ran out of elements. Get more */ cl_qcpool_grow(p_pool, p_pool->grow_size); /* * We may not have gotten everything we wanted but we might have * gotten something. */ if (cl_is_qlist_empty(&p_pool->free_list)) return (NULL); } p_list_item = cl_qlist_remove_tail(&p_pool->free_list); /* OK, at this point we have an object */ CL_ASSERT(p_list_item != cl_qlist_end(&p_pool->free_list)); return ((cl_pool_item_t *) p_list_item); } /* * IMPLEMENTATION OF QUICK GROW POOL */ /* * Callback to translate quick composite to quick grow pool * initializer callback. */ static cl_status_t __cl_qpool_init_cb(IN void **const p_comp_array, IN const uint32_t num_components, IN void *const context, OUT cl_pool_item_t ** const pp_pool_item) { cl_qpool_t *p_pool = (cl_qpool_t *) context; CL_ASSERT(p_pool); CL_ASSERT(p_pool->pfn_init); CL_ASSERT(num_components == 1); UNUSED_PARAM(num_components); return (p_pool->pfn_init(p_comp_array[0], (void *)p_pool->context, pp_pool_item)); } /* * Callback to translate quick composite to quick grow pool * destructor callback. */ static void __cl_qpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, IN void *const context) { cl_qpool_t *p_pool = (cl_qpool_t *) context; CL_ASSERT(p_pool); CL_ASSERT(p_pool->pfn_dtor); p_pool->pfn_dtor(p_pool_item, (void *)p_pool->context); } void cl_qpool_construct(IN cl_qpool_t * const p_pool) { memset(p_pool, 0, sizeof(cl_qpool_t)); cl_qcpool_construct(&p_pool->qcpool); } cl_status_t cl_qpool_init(IN cl_qpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN const size_t object_size, IN cl_pfn_qpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_qpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context) { cl_status_t status; CL_ASSERT(p_pool); p_pool->pfn_init = pfn_initializer; /* may be NULL */ p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ p_pool->context = context; status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, &object_size, 1, pfn_initializer ? __cl_qpool_init_cb : NULL, pfn_destructor ? __cl_qpool_dtor_cb : NULL, p_pool); return (status); } /* * IMPLEMENTATION OF COMPOSITE POOL */ /* * Callback to translate quick composite to compsite pool * initializer callback. */ static cl_status_t __cl_cpool_init_cb(IN void **const p_comp_array, IN const uint32_t num_components, IN void *const context, OUT cl_pool_item_t ** const pp_pool_item) { cl_cpool_t *p_pool = (cl_cpool_t *) context; cl_pool_obj_t *p_pool_obj; cl_status_t status = CL_SUCCESS; CL_ASSERT(p_pool); /* * Set our pointer to the list item, which is stored at the beginning of * the first component. */ p_pool_obj = (cl_pool_obj_t *) p_comp_array[0]; /* Set the pool item pointer for the caller. */ *pp_pool_item = &p_pool_obj->pool_item; /* Calculate the pointer to the user's first component. */ p_comp_array[0] = ((uint8_t *) p_comp_array[0]) + sizeof(cl_pool_obj_t); /* * Set the object pointer in the pool object to point to the first of the * user's components. */ p_pool_obj->p_object = p_comp_array[0]; /* Invoke the user's constructor callback. */ if (p_pool->pfn_init) { status = p_pool->pfn_init(p_comp_array, num_components, (void *)p_pool->context); } return (status); } /* * Callback to translate quick composite to composite pool * destructor callback. */ static void __cl_cpool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, IN void *const context) { cl_cpool_t *p_pool = (cl_cpool_t *) context; CL_ASSERT(p_pool); CL_ASSERT(p_pool->pfn_dtor); CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object); /* Invoke the user's destructor callback. */ p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object, (void *)p_pool->context); } void cl_cpool_construct(IN cl_cpool_t * const p_pool) { CL_ASSERT(p_pool); memset(p_pool, 0, sizeof(cl_cpool_t)); cl_qcpool_construct(&p_pool->qcpool); } cl_status_t cl_cpool_init(IN cl_cpool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN size_t * const component_sizes, IN const uint32_t num_components, IN cl_pfn_cpool_init_t pfn_initializer OPTIONAL, IN cl_pfn_cpool_dtor_t pfn_destructor OPTIONAL, IN const void *const context) { cl_status_t status; CL_ASSERT(p_pool); CL_ASSERT(num_components); CL_ASSERT(component_sizes); /* Add the size of the pool object to the first component. */ component_sizes[0] += sizeof(cl_pool_obj_t); /* Store callback function pointers. */ p_pool->pfn_init = pfn_initializer; /* may be NULL */ p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ p_pool->context = context; status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, component_sizes, num_components, __cl_cpool_init_cb, pfn_destructor ? __cl_cpool_dtor_cb : NULL, p_pool); /* Restore the original value of the first component. */ component_sizes[0] -= sizeof(cl_pool_obj_t); return (status); } /* * IMPLEMENTATION OF GROW POOL */ /* * Callback to translate quick composite to grow pool constructor callback. */ static cl_status_t __cl_pool_init_cb(IN void **const pp_obj, IN const uint32_t count, IN void *const context, OUT cl_pool_item_t ** const pp_pool_item) { cl_pool_t *p_pool = (cl_pool_t *) context; cl_pool_obj_t *p_pool_obj; cl_status_t status = CL_SUCCESS; CL_ASSERT(p_pool); CL_ASSERT(pp_obj); CL_ASSERT(count == 1); UNUSED_PARAM(count); /* * Set our pointer to the list item, which is stored at the beginning of * the first component. */ p_pool_obj = (cl_pool_obj_t *) * pp_obj; *pp_pool_item = &p_pool_obj->pool_item; /* Calculate the pointer to the user's first component. */ *pp_obj = ((uint8_t *) * pp_obj) + sizeof(cl_pool_obj_t); /* * Set the object pointer in the pool item to point to the first of the * user's components. */ p_pool_obj->p_object = *pp_obj; /* Invoke the user's constructor callback. */ if (p_pool->pfn_init) status = p_pool->pfn_init(*pp_obj, (void *)p_pool->context); return (status); } /* * Callback to translate quick composite to grow pool destructor callback. */ static void __cl_pool_dtor_cb(IN const cl_pool_item_t * const p_pool_item, IN void *const context) { cl_pool_t *p_pool = (cl_pool_t *) context; CL_ASSERT(p_pool); CL_ASSERT(p_pool->pfn_dtor); CL_ASSERT(((cl_pool_obj_t *) p_pool_item)->p_object); /* Invoke the user's destructor callback. */ p_pool->pfn_dtor((void *)((cl_pool_obj_t *) p_pool_item)->p_object, (void *)p_pool->context); } void cl_pool_construct(IN cl_pool_t * const p_pool) { CL_ASSERT(p_pool); memset(p_pool, 0, sizeof(cl_pool_t)); cl_qcpool_construct(&p_pool->qcpool); } cl_status_t cl_pool_init(IN cl_pool_t * const p_pool, IN const size_t min_size, IN const size_t max_size, IN const size_t grow_size, IN const size_t object_size, IN cl_pfn_pool_init_t pfn_initializer OPTIONAL, IN cl_pfn_pool_dtor_t pfn_destructor OPTIONAL, IN const void *const context) { cl_status_t status; size_t total_size; CL_ASSERT(p_pool); /* Add the size of the list item to the first component. */ total_size = object_size + sizeof(cl_pool_obj_t); /* Store callback function pointers. */ p_pool->pfn_init = pfn_initializer; /* may be NULL */ p_pool->pfn_dtor = pfn_destructor; /* may be NULL */ p_pool->context = context; /* * We need an initializer in all cases for quick composite pool, since * the user pointer must be manipulated to hide the prefixed cl_pool_obj_t. */ status = cl_qcpool_init(&p_pool->qcpool, min_size, max_size, grow_size, &total_size, 1, __cl_pool_init_cb, pfn_destructor ? __cl_pool_dtor_cb : NULL, p_pool); return (status); } opensm-3.3.20/complib/cl_ptr_vector.c0000644000205000001450000002035512104655724014461 00000000000000/* * 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: * This file contains ivector and isvector implementations. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include void cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector) { CL_ASSERT(p_vector); memset(p_vector, 0, sizeof(cl_ptr_vector_t)); p_vector->state = CL_UNINITIALIZED; } cl_status_t cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector, IN const size_t min_size, IN const size_t grow_size) { cl_status_t status = CL_SUCCESS; CL_ASSERT(p_vector); cl_ptr_vector_construct(p_vector); p_vector->grow_size = grow_size; /* * Set the state to initialized so that the call to set_size * doesn't assert. */ p_vector->state = CL_INITIALIZED; /* get the storage needed by the user */ if (min_size) { status = cl_ptr_vector_set_size(p_vector, min_size); if (status != CL_SUCCESS) cl_ptr_vector_destroy(p_vector); } return (status); } void cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector) { CL_ASSERT(p_vector); CL_ASSERT(cl_is_state_valid(p_vector->state)); /* Call the user's destructor for each element in the array. */ if (p_vector->state == CL_INITIALIZED) { /* Destroy the page vector. */ if (p_vector->p_ptr_array) { free((void *)p_vector->p_ptr_array); p_vector->p_ptr_array = NULL; } } p_vector->state = CL_UNINITIALIZED; } cl_status_t cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector, IN const size_t index, OUT void **const p_element) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Range check */ if (index >= p_vector->size) return (CL_INVALID_PARAMETER); *p_element = cl_ptr_vector_get(p_vector, index); return (CL_SUCCESS); } cl_status_t cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector, IN const size_t index, IN const void *const element) { cl_status_t status; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Determine if the vector has room for this element. */ if (index >= p_vector->size) { /* Resize to accomodate the given index. */ status = cl_ptr_vector_set_size(p_vector, index + 1); /* Check for failure on or before the given index. */ if ((status != CL_SUCCESS) && (p_vector->size < index)) return (status); } /* At this point, the array is guaranteed to be big enough */ p_vector->p_ptr_array[index] = element; return (CL_SUCCESS); } void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector, IN const size_t index) { size_t src; const void *element; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(p_vector->size > index); /* Store a copy of the element to return. */ element = p_vector->p_ptr_array[index]; /* Shift all items above the removed item down. */ if (index < --p_vector->size) { for (src = index; src < p_vector->size; src++) p_vector->p_ptr_array[src] = p_vector->p_ptr_array[src + 1]; } /* Clear the entry for the element just outside of the new upper bound. */ p_vector->p_ptr_array[p_vector->size] = NULL; return ((void *)element); } cl_status_t cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector, IN const size_t new_capacity) { void *p_new_ptr_array; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Do we have to do anything here? */ if (new_capacity <= p_vector->capacity) { /* Nope */ return (CL_SUCCESS); } /* Allocate our pointer array. */ p_new_ptr_array = malloc(new_capacity * sizeof(void *)); if (!p_new_ptr_array) return (CL_INSUFFICIENT_MEMORY); else memset(p_new_ptr_array, 0, new_capacity * sizeof(void *)); if (p_vector->p_ptr_array) { /* Copy the old pointer array into the new. */ memcpy(p_new_ptr_array, p_vector->p_ptr_array, p_vector->capacity * sizeof(void *)); /* Free the old pointer array. */ free((void *)p_vector->p_ptr_array); } /* Set the new array. */ p_vector->p_ptr_array = p_new_ptr_array; /* Update the vector with the new capactity. */ p_vector->capacity = new_capacity; return (CL_SUCCESS); } cl_status_t cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector, IN const size_t size) { cl_status_t status; size_t new_capacity; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Check to see if the requested size is the same as the existing size. */ if (size == p_vector->size) return (CL_SUCCESS); /* Determine if the vector has room for this element. */ if (size >= p_vector->capacity) { if (!p_vector->grow_size) return (CL_INSUFFICIENT_MEMORY); /* Calculate the new capacity, taking into account the grow size. */ new_capacity = size; if (size % p_vector->grow_size) { /* Round up to nearest grow_size boundary. */ new_capacity += p_vector->grow_size - (size % p_vector->grow_size); } status = cl_ptr_vector_set_capacity(p_vector, new_capacity); if (status != CL_SUCCESS) return (status); } p_vector->size = size; return (CL_SUCCESS); } cl_status_t cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector, IN const size_t min_size) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); if (min_size > p_vector->size) { /* We have to resize the array */ return (cl_ptr_vector_set_size(p_vector, min_size)); } /* We didn't have to do anything */ return (CL_SUCCESS); } void cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_apply_t pfn_callback, IN const void *const context) { size_t i; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); for (i = 0; i < p_vector->size; i++) pfn_callback(i, (void *)p_vector->p_ptr_array[i], (void *)context); } size_t cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_find_t pfn_callback, IN const void *const context) { size_t i; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); for (i = 0; i < p_vector->size; i++) { /* Invoke the callback */ if (pfn_callback(i, (void *)p_vector->p_ptr_array[i], (void *)context) == CL_SUCCESS) { break; } } return (i); } size_t cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector, IN cl_pfn_ptr_vec_find_t pfn_callback, IN const void *const context) { size_t i; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); i = p_vector->size; while (i) { /* Invoke the callback for the current element. */ i--; if (pfn_callback(i, (void *)p_vector->p_ptr_array[i], (void *)context) == CL_SUCCESS) { return (i); } } return (p_vector->size); } opensm-3.3.20/complib/cl_spinlock.c0000644000205000001450000000551612104655724014116 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include void cl_spinlock_construct(IN cl_spinlock_t * const p_spinlock) { CL_ASSERT(p_spinlock); p_spinlock->state = CL_UNINITIALIZED; } cl_status_t cl_spinlock_init(IN cl_spinlock_t * const p_spinlock) { CL_ASSERT(p_spinlock); cl_spinlock_construct(p_spinlock); /* Initialize with pthread_mutexattr_t = NULL */ if (pthread_mutex_init(&p_spinlock->mutex, NULL)) return (CL_ERROR); p_spinlock->state = CL_INITIALIZED; return (CL_SUCCESS); } void cl_spinlock_destroy(IN cl_spinlock_t * const p_spinlock) { CL_ASSERT(p_spinlock); CL_ASSERT(cl_is_state_valid(p_spinlock->state)); if (p_spinlock->state == CL_INITIALIZED) { p_spinlock->state = CL_UNINITIALIZED; pthread_mutex_lock(&p_spinlock->mutex); pthread_mutex_unlock(&p_spinlock->mutex); pthread_mutex_destroy(&p_spinlock->mutex); } p_spinlock->state = CL_UNINITIALIZED; } void cl_spinlock_acquire(IN cl_spinlock_t * const p_spinlock) { CL_ASSERT(p_spinlock); CL_ASSERT(p_spinlock->state == CL_INITIALIZED); pthread_mutex_lock(&p_spinlock->mutex); } void cl_spinlock_release(IN cl_spinlock_t * const p_spinlock) { CL_ASSERT(p_spinlock); CL_ASSERT(p_spinlock->state == CL_INITIALIZED); pthread_mutex_unlock(&p_spinlock->mutex); } opensm-3.3.20/complib/cl_statustext.c0000644000205000001450000000431612104655724014521 00000000000000/* * Copyright (c) 2004, 2005 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: * Defines string to decode cl_status_t return values. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include /* Status values above converted to text for easier printing. */ const char *cl_status_text[] = { "CL_SUCCESS", "CL_ERROR", "CL_INVALID_STATE", "CL_INVALID_OPERATION", "CL_INVALID_SETTING", "CL_INVALID_PARAMETER", "CL_INSUFFICIENT_RESOURCES", "CL_INSUFFICIENT_MEMORY", "CL_INVALID_PERMISSION", "CL_COMPLETED", "CL_NOT_DONE", "CL_PENDING", "CL_TIMEOUT", "CL_CANCELED", "CL_REJECT", "CL_OVERRUN", "CL_NOT_FOUND", "CL_UNAVAILABLE", "CL_BUSY", "CL_DISCONNECT", "CL_DUPLICATE" }; opensm-3.3.20/complib/cl_thread.c0000644000205000001450000000746512104655724013550 00000000000000/* * Copyright (c) 2004, 2005 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include /* * 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 void *__cl_thread_wrapper(void *arg) { cl_thread_t *p_thread = (cl_thread_t *) arg; CL_ASSERT(p_thread); CL_ASSERT(p_thread->pfn_callback); p_thread->pfn_callback((void *)p_thread->context); return (NULL); } void cl_thread_construct(IN cl_thread_t * const p_thread) { CL_ASSERT(p_thread); p_thread->osd.state = CL_UNINITIALIZED; } cl_status_t cl_thread_init(IN cl_thread_t * const p_thread, IN cl_pfn_thread_callback_t pfn_callback, IN const void *const context, IN const char *const name) { int ret; CL_ASSERT(p_thread); cl_thread_construct(p_thread); /* Initialize the thread structure */ p_thread->pfn_callback = pfn_callback; p_thread->context = context; ret = pthread_create(&p_thread->osd.id, NULL, __cl_thread_wrapper, (void *)p_thread); if (ret != 0) /* pthread_create returns a "0" for success */ return (CL_ERROR); p_thread->osd.state = CL_INITIALIZED; return (CL_SUCCESS); } void cl_thread_destroy(IN cl_thread_t * const p_thread) { CL_ASSERT(p_thread); CL_ASSERT(cl_is_state_valid(p_thread->osd.state)); if (p_thread->osd.state == CL_INITIALIZED) pthread_join(p_thread->osd.id, NULL); p_thread->osd.state = CL_UNINITIALIZED; } void cl_thread_suspend(IN const uint32_t pause_ms) { /* Convert to micro seconds */ usleep(pause_ms * 1000); } void cl_thread_stall(IN const uint32_t pause_us) { /* * Not quite a busy wait, but Linux is lacking in terms of high * resolution time stamp information in user mode. */ usleep(pause_us); } int cl_proc_count(void) { uint32_t ret; ret = get_nprocs(); if (!ret) return 1; /* Workaround for PPC where get_nprocs() returns 0 */ return ret; } boolean_t cl_is_current_thread(IN const cl_thread_t * const p_thread) { pthread_t current; CL_ASSERT(p_thread); CL_ASSERT(p_thread->osd.state == CL_INITIALIZED); current = pthread_self(); return (pthread_equal(current, p_thread->osd.id)); } opensm-3.3.20/complib/cl_threadpool.c0000644000205000001450000001030312272264652014425 00000000000000/* * Copyright (c) 2004-2007 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 thread pool. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include static void cleanup_mutex(void *arg) { pthread_mutex_unlock(&((cl_thread_pool_t *) arg)->mutex); } static void *thread_pool_routine(void *context) { cl_thread_pool_t *p_thread_pool = (cl_thread_pool_t *) context; do { pthread_mutex_lock(&p_thread_pool->mutex); pthread_cleanup_push(cleanup_mutex, p_thread_pool); while (!p_thread_pool->events) pthread_cond_wait(&p_thread_pool->cond, &p_thread_pool->mutex); p_thread_pool->events--; pthread_cleanup_pop(1); /* The event has been signalled. Invoke the callback. */ (*p_thread_pool->pfn_callback) (p_thread_pool->context); } while (1); return NULL; } cl_status_t cl_thread_pool_init(IN cl_thread_pool_t * const p_thread_pool, IN unsigned count, IN void (*pfn_callback) (void *), IN void *context, IN const char *const name) { int i; CL_ASSERT(p_thread_pool); CL_ASSERT(pfn_callback); memset(p_thread_pool, 0, sizeof(*p_thread_pool)); if (!count) count = cl_proc_count(); pthread_mutex_init(&p_thread_pool->mutex, NULL); pthread_cond_init(&p_thread_pool->cond, NULL); p_thread_pool->events = 0; p_thread_pool->pfn_callback = pfn_callback; p_thread_pool->context = context; p_thread_pool->tid = calloc(count, sizeof(*p_thread_pool->tid)); if (!p_thread_pool->tid) { cl_thread_pool_destroy(p_thread_pool); return CL_INSUFFICIENT_MEMORY; } p_thread_pool->running_count = count; for (i = 0; i < count; i++) { if (pthread_create(&p_thread_pool->tid[i], NULL, thread_pool_routine, p_thread_pool) != 0) { cl_thread_pool_destroy(p_thread_pool); return CL_INSUFFICIENT_RESOURCES; } } return (CL_SUCCESS); } void cl_thread_pool_destroy(IN cl_thread_pool_t * const p_thread_pool) { int i; CL_ASSERT(p_thread_pool); for (i = 0; i < p_thread_pool->running_count; i++) if (p_thread_pool->tid[i]) pthread_cancel(p_thread_pool->tid[i]); for (i = 0; i < p_thread_pool->running_count; i++) if (p_thread_pool->tid[i]) pthread_join(p_thread_pool->tid[i], NULL); p_thread_pool->running_count = 0; free(p_thread_pool->tid); pthread_cond_destroy(&p_thread_pool->cond); pthread_mutex_destroy(&p_thread_pool->mutex); p_thread_pool->events = 0; } cl_status_t cl_thread_pool_signal(IN cl_thread_pool_t * const p_thread_pool) { int ret; CL_ASSERT(p_thread_pool); pthread_mutex_lock(&p_thread_pool->mutex); p_thread_pool->events++; ret = pthread_cond_signal(&p_thread_pool->cond); pthread_mutex_unlock(&p_thread_pool->mutex); return ret; } opensm-3.3.20/complib/cl_timer.c0000644000205000001450000002742412104655724013416 00000000000000/* * 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: * Abstraction of Timer create, destroy functions. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include /* Timer provider (emulates timers in user mode). */ typedef struct _cl_timer_prov { pthread_t thread; pthread_mutex_t mutex; pthread_cond_t cond; cl_qlist_t queue; boolean_t exit; } cl_timer_prov_t; /* Global timer provider. */ static cl_timer_prov_t *gp_timer_prov = NULL; static void *__cl_timer_prov_cb(IN void *const context); /* * Creates the process global timer provider. Must be called by the shared * object framework to solve all serialization issues. */ cl_status_t __cl_timer_prov_create(void) { CL_ASSERT(gp_timer_prov == NULL); gp_timer_prov = malloc(sizeof(cl_timer_prov_t)); if (!gp_timer_prov) return (CL_INSUFFICIENT_MEMORY); else memset(gp_timer_prov, 0, sizeof(cl_timer_prov_t)); cl_qlist_init(&gp_timer_prov->queue); pthread_mutex_init(&gp_timer_prov->mutex, NULL); pthread_cond_init(&gp_timer_prov->cond, NULL); if (pthread_create(&gp_timer_prov->thread, NULL, __cl_timer_prov_cb, NULL)) { __cl_timer_prov_destroy(); return (CL_ERROR); } return (CL_SUCCESS); } void __cl_timer_prov_destroy(void) { pthread_t tid; if (!gp_timer_prov) return; tid = gp_timer_prov->thread; pthread_mutex_lock(&gp_timer_prov->mutex); gp_timer_prov->exit = TRUE; pthread_cond_broadcast(&gp_timer_prov->cond); pthread_mutex_unlock(&gp_timer_prov->mutex); pthread_join(tid, NULL); /* Destroy the mutex and condition variable. */ pthread_mutex_destroy(&gp_timer_prov->mutex); pthread_cond_destroy(&gp_timer_prov->cond); /* Free the memory and reset the global pointer. */ free(gp_timer_prov); gp_timer_prov = NULL; } /* * This is the internal work function executed by the timer's thread. */ static void *__cl_timer_prov_cb(IN void *const context) { int ret; cl_timer_t *p_timer; pthread_mutex_lock(&gp_timer_prov->mutex); while (!gp_timer_prov->exit) { if (cl_is_qlist_empty(&gp_timer_prov->queue)) { /* Wait until we exit or a timer is queued. */ /* cond wait does: * pthread_cond_wait atomically unlocks the mutex (as per * pthread_unlock_mutex) and waits for the condition variable * cond to be signaled. The thread execution is suspended and * does not consume any CPU time until the condition variable is * signaled. The mutex must be locked by the calling thread on * entrance to pthread_cond_wait. Before RETURNING TO THE * CALLING THREAD, PTHREAD_COND_WAIT RE-ACQUIRES MUTEX (as per * pthread_lock_mutex). */ ret = pthread_cond_wait(&gp_timer_prov->cond, &gp_timer_prov->mutex); } else { /* * The timer elements are on the queue in expiration order. * Get the first in the list to determine how long to wait. */ p_timer = (cl_timer_t *) cl_qlist_head(&gp_timer_prov->queue); ret = pthread_cond_timedwait(&gp_timer_prov->cond, &gp_timer_prov->mutex, &p_timer->timeout); /* Sleep again on every event other than timeout and invalid Note: EINVAL means that we got behind. This can occur when we are very busy... */ if (ret != ETIMEDOUT && ret != EINVAL) continue; /* * The timer expired. Check the state in case it was cancelled * after it expired but before we got a chance to invoke the * callback. */ if (p_timer->timer_state != CL_TIMER_QUEUED) continue; /* * Mark the timer as running to synchronize with its * cancelation since we can't hold the mutex during the * callback. */ p_timer->timer_state = CL_TIMER_RUNNING; /* Remove the item from the timer queue. */ cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); pthread_mutex_unlock(&gp_timer_prov->mutex); /* Invoke the callback. */ p_timer->pfn_callback((void *)p_timer->context); /* Acquire the mutex again. */ pthread_mutex_lock(&gp_timer_prov->mutex); /* * Only set the state to idle if the timer has not been accessed * from the callback */ if (p_timer->timer_state == CL_TIMER_RUNNING) p_timer->timer_state = CL_TIMER_IDLE; /* * Signal any thread trying to manipulate the timer * that expired. */ pthread_cond_signal(&p_timer->cond); } } gp_timer_prov->thread = 0; pthread_mutex_unlock(&gp_timer_prov->mutex); pthread_exit(NULL); } /* Timer implementation. */ void cl_timer_construct(IN cl_timer_t * const p_timer) { memset(p_timer, 0, sizeof(cl_timer_t)); p_timer->state = CL_UNINITIALIZED; } cl_status_t cl_timer_init(IN cl_timer_t * const p_timer, IN cl_pfn_timer_callback_t pfn_callback, IN const void *const context) { CL_ASSERT(p_timer); CL_ASSERT(pfn_callback); cl_timer_construct(p_timer); if (!gp_timer_prov) return (CL_ERROR); /* Store timer parameters. */ p_timer->pfn_callback = pfn_callback; p_timer->context = context; /* Mark the timer as idle. */ p_timer->timer_state = CL_TIMER_IDLE; /* Create the condition variable that is used when cancelling a timer. */ pthread_cond_init(&p_timer->cond, NULL); p_timer->state = CL_INITIALIZED; return (CL_SUCCESS); } void cl_timer_destroy(IN cl_timer_t * const p_timer) { CL_ASSERT(p_timer); CL_ASSERT(cl_is_state_valid(p_timer->state)); if (p_timer->state == CL_INITIALIZED) cl_timer_stop(p_timer); p_timer->state = CL_UNINITIALIZED; /* is it possible we have some threads waiting on the cond now? */ pthread_cond_broadcast(&p_timer->cond); pthread_cond_destroy(&p_timer->cond); } /* * Return TRUE if timeout value 1 is earlier than timeout value 2. */ static __inline boolean_t __cl_timer_is_earlier(IN struct timespec *p_timeout1, IN struct timespec *p_timeout2) { return ((p_timeout1->tv_sec < p_timeout2->tv_sec) || ((p_timeout1->tv_sec == p_timeout2->tv_sec) && (p_timeout1->tv_nsec < p_timeout2->tv_nsec))); } /* * Search for a timer with an earlier timeout than the one provided by * the context. Both the list item and the context are pointers to * a cl_timer_t structure with valid timeouts. */ static cl_status_t __cl_timer_find(IN const cl_list_item_t * const p_list_item, IN void *const context) { cl_timer_t *p_in_list; cl_timer_t *p_new; CL_ASSERT(p_list_item); CL_ASSERT(context); p_in_list = (cl_timer_t *) p_list_item; p_new = (cl_timer_t *) context; CL_ASSERT(p_in_list->state == CL_INITIALIZED); CL_ASSERT(p_new->state == CL_INITIALIZED); CL_ASSERT(p_in_list->timer_state == CL_TIMER_QUEUED); if (__cl_timer_is_earlier(&p_in_list->timeout, &p_new->timeout)) return (CL_SUCCESS); return (CL_NOT_FOUND); } /* * Calculate 'struct timespec' value that is the * current time plus the 'time_ms' milliseconds. */ static __inline void __cl_timer_calculate(IN const uint32_t time_ms, OUT struct timespec * const p_timer) { struct timeval curtime, deltatime, endtime; gettimeofday(&curtime, NULL); deltatime.tv_sec = time_ms / 1000; deltatime.tv_usec = (time_ms % 1000) * 1000; timeradd(&curtime, &deltatime, &endtime); p_timer->tv_sec = endtime.tv_sec; p_timer->tv_nsec = endtime.tv_usec * 1000; } cl_status_t cl_timer_start(IN cl_timer_t * const p_timer, IN const uint32_t time_ms) { cl_list_item_t *p_list_item; CL_ASSERT(p_timer); CL_ASSERT(p_timer->state == CL_INITIALIZED); pthread_mutex_lock(&gp_timer_prov->mutex); /* Signal the timer provider thread to wake up. */ pthread_cond_signal(&gp_timer_prov->cond); /* Remove the timer from the queue if currently queued. */ if (p_timer->timer_state == CL_TIMER_QUEUED) cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); __cl_timer_calculate(time_ms, &p_timer->timeout); /* Add the timer to the queue. */ if (cl_is_qlist_empty(&gp_timer_prov->queue)) { /* The timer list is empty. Add to the head. */ cl_qlist_insert_head(&gp_timer_prov->queue, &p_timer->list_item); } else { /* Find the correct insertion place in the list for the timer. */ p_list_item = cl_qlist_find_from_tail(&gp_timer_prov->queue, __cl_timer_find, p_timer); /* Insert the timer. */ cl_qlist_insert_next(&gp_timer_prov->queue, p_list_item, &p_timer->list_item); } /* Set the state. */ p_timer->timer_state = CL_TIMER_QUEUED; pthread_mutex_unlock(&gp_timer_prov->mutex); return (CL_SUCCESS); } void cl_timer_stop(IN cl_timer_t * const p_timer) { CL_ASSERT(p_timer); CL_ASSERT(p_timer->state == CL_INITIALIZED); pthread_mutex_lock(&gp_timer_prov->mutex); switch (p_timer->timer_state) { case CL_TIMER_RUNNING: /* Wait for the callback to complete. */ pthread_cond_wait(&p_timer->cond, &gp_timer_prov->mutex); /* Timer could have been queued while we were waiting. */ if (p_timer->timer_state != CL_TIMER_QUEUED) break; case CL_TIMER_QUEUED: /* Change the state of the timer. */ p_timer->timer_state = CL_TIMER_IDLE; /* Remove the timer from the queue. */ cl_qlist_remove_item(&gp_timer_prov->queue, &p_timer->list_item); /* * Signal the timer provider thread to move onto the * next timer in the queue. */ pthread_cond_signal(&gp_timer_prov->cond); break; case CL_TIMER_IDLE: break; } pthread_mutex_unlock(&gp_timer_prov->mutex); } cl_status_t cl_timer_trim(IN cl_timer_t * const p_timer, IN const uint32_t time_ms) { struct timespec newtime; cl_status_t status; CL_ASSERT(p_timer); CL_ASSERT(p_timer->state == CL_INITIALIZED); pthread_mutex_lock(&gp_timer_prov->mutex); __cl_timer_calculate(time_ms, &newtime); if (p_timer->timer_state == CL_TIMER_QUEUED) { /* If the old time is earlier, do not trim it. Just return. */ if (__cl_timer_is_earlier(&p_timer->timeout, &newtime)) { pthread_mutex_unlock(&gp_timer_prov->mutex); return (CL_SUCCESS); } } /* Reset the timer to the new timeout value. */ pthread_mutex_unlock(&gp_timer_prov->mutex); status = cl_timer_start(p_timer, time_ms); return (status); } uint64_t cl_get_time_stamp(void) { uint64_t tstamp; struct timeval tv; gettimeofday(&tv, NULL); /* Convert the time of day into a microsecond timestamp. */ tstamp = ((uint64_t) tv.tv_sec * 1000000) + (uint64_t) tv.tv_usec; return (tstamp); } uint32_t cl_get_time_stamp_sec(void) { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec); } opensm-3.3.20/complib/cl_vector.c0000644000205000001450000003237612104655724013602 00000000000000/* * 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: * This file contains ivector and isvector implementations. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include /* * Define the maximum size for array pages in an cl_vector_t. * This size is in objects, not bytes. */ #define SVEC_MAX_PAGE_SIZE 0x1000 /* * cl_vector_copy_general * * Description: * copy operator used when size of the user object doesn't fit one of the * other optimized copy functions. * * Inputs: * p_src - source for copy * * Outputs: * p_dest - destination for copy * * Returns: * None * */ static void cl_vector_copy_general(OUT void *const p_dest, IN const void *const p_src, IN const size_t size) { memcpy(p_dest, p_src, size); } /* * cl_vector_copy8 * * Description: * copy operator used when the user structure is only 8 bits long. * * Inputs: * p_src - source for copy * * Outputs: * p_dest - destination for copy * * Returns: * None * */ static void cl_vector_copy8(OUT void *const p_dest, IN const void *const p_src, IN const size_t size) { CL_ASSERT(size == sizeof(uint8_t)); UNUSED_PARAM(size); *(uint8_t *) p_dest = *(uint8_t *) p_src; } /* * cl_vector_copy16 * * Description: * copy operator used when the user structure is only 16 bits long. * * Inputs: * p_src - source for copy * * Outputs: * p_dest - destination for copy * * Returns: * None * */ void cl_vector_copy16(OUT void *const p_dest, IN const void *const p_src, IN const size_t size) { CL_ASSERT(size == sizeof(uint16_t)); UNUSED_PARAM(size); *(uint16_t *) p_dest = *(uint16_t *) p_src; } /* * cl_vector_copy32 * * Description: * copy operator used when the user structure is only 32 bits long. * * Inputs: * p_src - source for copy * * Outputs: * p_dest - destination for copy * * Returns: * None * */ void cl_vector_copy32(OUT void *const p_dest, IN const void *const p_src, IN const size_t size) { CL_ASSERT(size == sizeof(uint32_t)); UNUSED_PARAM(size); *(uint32_t *) p_dest = *(uint32_t *) p_src; } /* * cl_vector_copy64 * * Description: * copy operator used when the user structure is only 64 bits long. * * Inputs: * p_src - source for copy * * Outputs: * p_dest - destination for copy * * Returns: * None * */ void cl_vector_copy64(OUT void *const p_dest, IN const void *const p_src, IN const size_t size) { CL_ASSERT(size == sizeof(uint64_t)); UNUSED_PARAM(size); *(uint64_t *) p_dest = *(uint64_t *) p_src; } void cl_vector_construct(IN cl_vector_t * const p_vector) { CL_ASSERT(p_vector); memset(p_vector, 0, sizeof(cl_vector_t)); p_vector->state = CL_UNINITIALIZED; } cl_status_t cl_vector_init(IN cl_vector_t * const p_vector, IN const size_t min_size, IN const size_t grow_size, IN const size_t element_size, IN cl_pfn_vec_init_t pfn_init OPTIONAL, IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL, IN const void *const context) { cl_status_t status = CL_SUCCESS; CL_ASSERT(p_vector); CL_ASSERT(element_size); cl_vector_construct(p_vector); p_vector->grow_size = grow_size; p_vector->element_size = element_size; p_vector->pfn_init = pfn_init; p_vector->pfn_dtor = pfn_dtor; p_vector->context = context; /* * Try to choose a smart copy operator * someday, we could simply let the users pass one in */ switch (element_size) { case sizeof(uint8_t): p_vector->pfn_copy = cl_vector_copy8; break; case sizeof(uint16_t): p_vector->pfn_copy = cl_vector_copy16; break; case sizeof(uint32_t): p_vector->pfn_copy = cl_vector_copy32; break; case sizeof(uint64_t): p_vector->pfn_copy = cl_vector_copy64; break; default: p_vector->pfn_copy = cl_vector_copy_general; break; } /* * Set the state to initialized so that the call to set_size * doesn't assert. */ p_vector->state = CL_INITIALIZED; /* Initialize the allocation list */ cl_qlist_init(&p_vector->alloc_list); /* get the storage needed by the user */ if (min_size) { status = cl_vector_set_size(p_vector, min_size); if (status != CL_SUCCESS) cl_vector_destroy(p_vector); } return (status); } void cl_vector_destroy(IN cl_vector_t * const p_vector) { size_t i; void *p_element; CL_ASSERT(p_vector); CL_ASSERT(cl_is_state_valid(p_vector->state)); /* Call the user's destructor for each element in the array. */ if (p_vector->state == CL_INITIALIZED) { if (p_vector->pfn_dtor) { for (i = 0; i < p_vector->size; i++) { p_element = p_vector->p_ptr_array[i]; /* Sanity check! */ CL_ASSERT(p_element); p_vector->pfn_dtor(p_element, (void *)p_vector->context); } } /* Deallocate the pages */ while (!cl_is_qlist_empty(&p_vector->alloc_list)) free(cl_qlist_remove_head(&p_vector->alloc_list)); /* Destroy the page vector. */ if (p_vector->p_ptr_array) { free(p_vector->p_ptr_array); p_vector->p_ptr_array = NULL; } } p_vector->state = CL_UNINITIALIZED; } cl_status_t cl_vector_at(IN const cl_vector_t * const p_vector, IN const size_t index, OUT void *const p_element) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Range check */ if (index >= p_vector->size) return (CL_INVALID_PARAMETER); cl_vector_get(p_vector, index, p_element); return (CL_SUCCESS); } cl_status_t cl_vector_set(IN cl_vector_t * const p_vector, IN const size_t index, IN void *const p_element) { cl_status_t status; void *p_dest; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(p_element); /* Determine if the vector has room for this element. */ if (index >= p_vector->size) { /* Resize to accomodate the given index. */ status = cl_vector_set_size(p_vector, index + 1); /* Check for failure on or before the given index. */ if ((status != CL_SUCCESS) && (p_vector->size < index)) return (status); } /* At this point, the array is guaranteed to be big enough */ p_dest = cl_vector_get_ptr(p_vector, index); /* Sanity check! */ CL_ASSERT(p_dest); /* Copy the data into the array */ p_vector->pfn_copy(p_dest, p_element, p_vector->element_size); return (CL_SUCCESS); } cl_status_t cl_vector_set_capacity(IN cl_vector_t * const p_vector, IN const size_t new_capacity) { size_t new_elements; size_t alloc_size; size_t i; cl_list_item_t *p_buf; void *p_new_ptr_array; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Do we have to do anything here? */ if (new_capacity <= p_vector->capacity) { /* Nope */ return (CL_SUCCESS); } /* Allocate our pointer array. */ p_new_ptr_array = malloc(new_capacity * sizeof(void *)); if (!p_new_ptr_array) return (CL_INSUFFICIENT_MEMORY); else memset(p_new_ptr_array, 0, new_capacity * sizeof(void *)); if (p_vector->p_ptr_array) { /* Copy the old pointer array into the new. */ memcpy(p_new_ptr_array, p_vector->p_ptr_array, p_vector->capacity * sizeof(void *)); /* Free the old pointer array. */ free(p_vector->p_ptr_array); } /* Set the new array. */ p_vector->p_ptr_array = p_new_ptr_array; /* * We have to add capacity to the array. Determine how many * elements to add. */ new_elements = new_capacity - p_vector->capacity; /* Determine the allocation size for the new array elements. */ alloc_size = new_elements * p_vector->element_size; p_buf = (cl_list_item_t *) malloc(alloc_size + sizeof(cl_list_item_t)); if (!p_buf) return (CL_INSUFFICIENT_MEMORY); else memset(p_buf, 0, alloc_size + sizeof(cl_list_item_t)); cl_qlist_insert_tail(&p_vector->alloc_list, p_buf); /* Advance the buffer pointer past the list item. */ p_buf++; for (i = p_vector->capacity; i < new_capacity; i++) { p_vector->p_ptr_array[i] = p_buf; /* Move the buffer pointer to the next element. */ p_buf = (void *)(((uint8_t *) p_buf) + p_vector->element_size); } /* Update the vector with the new capactity. */ p_vector->capacity = new_capacity; return (CL_SUCCESS); } cl_status_t cl_vector_set_size(IN cl_vector_t * const p_vector, IN const size_t size) { cl_status_t status; size_t new_capacity; size_t index; void *p_element; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); /* Check to see if the requested size is the same as the existing size. */ if (size == p_vector->size) return (CL_SUCCESS); /* Determine if the vector has room for this element. */ if (size >= p_vector->capacity) { if (!p_vector->grow_size) return (CL_INSUFFICIENT_MEMORY); /* Calculate the new capacity, taking into account the grow size. */ new_capacity = size; if (size % p_vector->grow_size) { /* Round up to nearest grow_size boundary. */ new_capacity += p_vector->grow_size - (size % p_vector->grow_size); } status = cl_vector_set_capacity(p_vector, new_capacity); if (status != CL_SUCCESS) return (status); } /* Are we growing the array and need to invoke an initializer callback? */ if (size > p_vector->size && p_vector->pfn_init) { for (index = p_vector->size; index < size; index++) { /* Get a pointer to this element */ p_element = cl_vector_get_ptr(p_vector, index); /* Call the user's initializer and trap failures. */ status = p_vector->pfn_init(p_element, (void *)p_vector->context); if (status != CL_SUCCESS) { /* Call the destructor for this object */ if (p_vector->pfn_dtor) p_vector->pfn_dtor(p_element, (void *)p_vector-> context); /* Return the failure status to the caller. */ return (status); } /* The array just grew by one element */ p_vector->size++; } } else if (p_vector->pfn_dtor) { /* The array is shrinking and there is a destructor to invoke. */ for (index = size; index < p_vector->size; index++) { /* compute the address of the new elements */ p_element = cl_vector_get_ptr(p_vector, index); /* call the user's destructor */ p_vector->pfn_dtor(p_element, (void *)p_vector->context); } } p_vector->size = size; return (CL_SUCCESS); } cl_status_t cl_vector_set_min_size(IN cl_vector_t * const p_vector, IN const size_t min_size) { CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); if (min_size > p_vector->size) { /* We have to resize the array */ return (cl_vector_set_size(p_vector, min_size)); } /* We didn't have to do anything */ return (CL_SUCCESS); } void cl_vector_apply_func(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_apply_t pfn_callback, IN const void *const context) { size_t i; void *p_element; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); for (i = 0; i < p_vector->size; i++) { p_element = cl_vector_get_ptr(p_vector, i); pfn_callback(i, p_element, (void *)context); } } size_t cl_vector_find_from_start(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_find_t pfn_callback, IN const void *const context) { size_t i; void *p_element; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); for (i = 0; i < p_vector->size; i++) { p_element = cl_vector_get_ptr(p_vector, i); /* Invoke the callback */ if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS) break; } return (i); } size_t cl_vector_find_from_end(IN const cl_vector_t * const p_vector, IN cl_pfn_vec_find_t pfn_callback, IN const void *const context) { size_t i; void *p_element; CL_ASSERT(p_vector); CL_ASSERT(p_vector->state == CL_INITIALIZED); CL_ASSERT(pfn_callback); i = p_vector->size; while (i) { /* Get a pointer to the element in the array. */ p_element = cl_vector_get_ptr(p_vector, --i); CL_ASSERT(p_element); /* Invoke the callback for the current element. */ if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS) return (i); } return (p_vector->size); } opensm-3.3.20/complib/ib_statustext.c0000644000205000001450000001037012104655724014512 00000000000000/* * Copyright (c) 2004, 2005 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: * Defines string to decode ib_api_status_t return values. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include /* ib_api_status_t values above converted to text for easier printing. */ const char *ib_error_str[] = { "IB_SUCCESS", "IB_INSUFFICIENT_RESOURCES", "IB_INSUFFICIENT_MEMORY", "IB_INVALID_PARAMETER", "IB_INVALID_SETTING", "IB_NOT_FOUND", "IB_TIMEOUT", "IB_CANCELED", "IB_INTERRUPTED", "IB_INVALID_PERMISSION", "IB_UNSUPPORTED", "IB_OVERFLOW", "IB_MAX_MCAST_QPS_REACHED", "IB_INVALID_QP_STATE", "IB_INVALID_EEC_STATE", "IB_INVALID_APM_STATE", "IB_INVALID_PORT_STATE", "IB_INVALID_STATE", "IB_RESOURCE_BUSY", "IB_INVALID_PKEY", "IB_INVALID_LKEY", "IB_INVALID_RKEY", "IB_INVALID_MAX_WRS", "IB_INVALID_MAX_SGE", "IB_INVALID_CQ_SIZE", "IB_INVALID_SERVICE_TYPE", "IB_INVALID_GID", "IB_INVALID_LID", "IB_INVALID_GUID", "IB_INVALID_CA_HANDLE", "IB_INVALID_AV_HANDLE", "IB_INVALID_CQ_HANDLE", "IB_INVALID_EEC_HANDLE", "IB_INVALID_QP_HANDLE", "IB_INVALID_PD_HANDLE", "IB_INVALID_MR_HANDLE", "IB_INVALID_MW_HANDLE", "IB_INVALID_RDD_HANDLE", "IB_INVALID_MCAST_HANDLE", "IB_INVALID_CALLBACK", "IB_INVALID_AL_HANDLE", "IB_INVALID_HANDLE", "IB_ERROR", "IB_REMOTE_ERROR", /* Infiniband Access Layer */ "IB_VERBS_PROCESSING_DONE", "IB_INVALID_WR_TYPE", "IB_QP_IN_TIMEWAIT", "IB_EE_IN_TIMEWAIT", "IB_INVALID_PORT", "IB_NOT_DONE", "IB_UNKNOWN_ERROR" }; /* ib_async_event_t values above converted to text for easier printing. */ const char *ib_async_event_str[] = { "IB_AE_SQ_ERROR", "IB_AE_SQ_DRAINED", "IB_AE_RQ_ERROR", "IB_AE_CQ_ERROR", "IB_AE_QP_FATAL", "IB_AE_QP_COMM", "IB_AE_QP_APM", "IB_AE_EEC_FATAL", "IB_AE_EEC_COMM", "IB_AE_EEC_APM", "IB_AE_LOCAL_FATAL", "IB_AE_PKEY_TRAP", "IB_AE_QKEY_TRAP", "IB_AE_MKEY_TRAP", "IB_AE_PORT_TRAP", "IB_AE_SYSIMG_GUID_TRAP", "IB_AE_BUF_OVERRUN", "IB_AE_LINK_INTEGRITY", "IB_AE_FLOW_CTRL_ERROR", "IB_AE_BKEY_TRAP", "IB_AE_QP_APM_ERROR", "IB_AE_EEC_APM_ERROR", "IB_AE_WQ_REQ_ERROR", "IB_AE_WQ_ACCESS_ERROR", "IB_AE_PORT_ACTIVE", /* ACTIVE STATE */ "IB_AE_PORT_DOWN", /* INIT", ARMED", DOWN */ "IB_AE_UNKNOWN" }; const char *ib_wc_status_str[] = { "IB_WCS_SUCCESS", "IB_WCS_LOCAL_LEN_ERR", "IB_WCS_LOCAL_OP_ERR", "IB_WCS_LOCAL_EEC_OP_ERR", "IB_WCS_LOCAL_PROTECTION_ERR", "IB_WCS_WR_FLUSHED_ERR", "IB_WCS_MEM_WINDOW_BIND_ERR", "IB_WCS_REM_ACCESS_ERR", "IB_WCS_REM_OP_ERR", "IB_WCS_RNR_RETRY_ERR", "IB_WCS_TIMEOUT_RETRY_ERR", "IB_WCS_REM_INVALID_REQ_ERR", "IB_WCS_REM_INVALID_RD_REQ_ERR", "IB_WCS_INVALID_EECN", "IB_WCS_INVALID_EEC_STATE", "IB_WCS_UNMATCHED_RESPONSE", /* InfiniBand Access Layer */ "IB_WCS_CANCELED", /* InfiniBand Access Layer */ "IB_WCS_UNKNOWN" }; opensm-3.3.20/complib/cl_nodenamemap.c0000644000205000001450000001230612272264652014555 00000000000000/* * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 Lawrence Livermore National Lab * * 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. * */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #define PARSE_NODE_MAP_BUFLEN 256 static int parse_node_map_wrap(const char *file_name, int (*create)(void *, uint64_t, char *), void *cxt, char *linebuf, unsigned int linebuflen); static int map_name(void *cxt, uint64_t guid, char *p) { cl_qmap_t *map = cxt; name_map_item_t *item; p = strtok(p, "\"#"); if (!p) return 0; item = malloc(sizeof(*item)); if (!item) return -1; item->guid = guid; item->name = strdup(p); cl_qmap_insert(map, item->guid, (cl_map_item_t *) item); return 0; } nn_map_t *open_node_name_map(const char *node_name_map) { nn_map_t *map; char linebuf[PARSE_NODE_MAP_BUFLEN + 1]; if (!node_name_map) { #ifdef HAVE_DEFAULT_NODENAME_MAP struct stat buf; node_name_map = HAVE_DEFAULT_NODENAME_MAP; if (stat(node_name_map, &buf)) return NULL; #else return NULL; #endif /* HAVE_DEFAULT_NODENAME_MAP */ } map = malloc(sizeof(*map)); if (!map) return NULL; cl_qmap_init(map); memset(linebuf, '\0', PARSE_NODE_MAP_BUFLEN + 1); if (parse_node_map_wrap(node_name_map, map_name, map, linebuf, PARSE_NODE_MAP_BUFLEN)) { if (errno == EIO) { fprintf(stderr, "WARNING failed to parse node name map " "\"%s\"\n", node_name_map); fprintf(stderr, "WARNING failed line: \"%s\"\n", linebuf); } else fprintf(stderr, "WARNING failed to open node name map " "\"%s\" (%s)\n", node_name_map, strerror(errno)); close_node_name_map(map); return NULL; } return map; } void close_node_name_map(nn_map_t * map) { name_map_item_t *item = NULL; if (!map) return; item = (name_map_item_t *) cl_qmap_head(map); while (item != (name_map_item_t *) cl_qmap_end(map)) { item = (name_map_item_t *) cl_qmap_remove(map, item->guid); free(item->name); free(item); item = (name_map_item_t *) cl_qmap_head(map); } free(map); } char *remap_node_name(nn_map_t * map, uint64_t target_guid, char *nodedesc) { char *rc = NULL; name_map_item_t *item = NULL; if (!map) goto done; item = (name_map_item_t *) cl_qmap_get(map, target_guid); if (item != (name_map_item_t *) cl_qmap_end(map)) rc = strdup(item->name); done: if (rc == NULL) rc = strdup(clean_nodedesc(nodedesc)); return (rc); } char *clean_nodedesc(char *nodedesc) { int i = 0; nodedesc[63] = '\0'; while (nodedesc[i]) { if (!isprint(nodedesc[i])) nodedesc[i] = ' '; i++; } return (nodedesc); } static int parse_node_map_wrap(const char *file_name, int (*create) (void *, uint64_t, char *), void *cxt, char *linebuf, unsigned int linebuflen) { char line[PARSE_NODE_MAP_BUFLEN]; FILE *f; if (!(f = fopen(file_name, "r"))) return -1; while (fgets(line, sizeof(line), f)) { uint64_t guid; char *p, *e; p = line; while (isspace(*p)) p++; if (*p == '\0' || *p == '\n' || *p == '#') continue; guid = strtoull(p, &e, 0); if (e == p || (!isspace(*e) && *e != '#' && *e != '\0')) { fclose(f); errno = EIO; if (linebuf) { memcpy(linebuf, line, MIN(PARSE_NODE_MAP_BUFLEN, linebuflen)); e = strpbrk(linebuf, "\n"); if (e) *e = '\0'; } return -1; } p = e; while (isspace(*p)) p++; e = strpbrk(p, "\n"); if (e) *e = '\0'; if (create(cxt, guid, p)) { fclose(f); return -1; } } fclose(f); return 0; } int parse_node_map(const char *file_name, int (*create) (void *, uint64_t, char *), void *cxt) { return parse_node_map_wrap(file_name, create, cxt, NULL, 0); } opensm-3.3.20/complib/libosmcomp.map0000644000205000001450000000627312104655724014316 00000000000000OSMCOMP_2.3 { global: complib_init; complib_exit; cl_is_debug; cl_disp_construct; cl_disp_init; cl_disp_destroy; cl_disp_register; cl_disp_unregister; cl_disp_post; cl_disp_shutdown; cl_disp_get_queue_status; cl_event_construct; cl_event_init; cl_event_destroy; cl_event_signal; cl_event_reset; cl_event_wait_on; cl_event_wheel_construct; cl_event_wheel_init; cl_event_wheel_init_ex; cl_event_wheel_destroy; cl_event_wheel_dump; cl_event_wheel_reg; cl_event_wheel_unreg; cl_event_wheel_num_regs; cl_qlist_insert_array_head; cl_qlist_insert_array_tail; cl_qlist_insert_list_head; cl_qlist_insert_list_tail; cl_is_item_in_qlist; cl_qlist_find_next; cl_qlist_find_prev; cl_qlist_apply_func; cl_qlist_move_items; cl_list_construct; cl_list_init; cl_list_destroy; cl_list_remove_object; cl_is_object_in_list; cl_list_insert_array_head; cl_list_insert_array_tail; cl_list_find_from_head; cl_list_find_from_tail; cl_list_apply_func; cl_log_event; cl_qmap_init; cl_qmap_get; cl_qmap_get_next; cl_qmap_apply_func; cl_qmap_insert; cl_qmap_remove_item; cl_qmap_remove; cl_qmap_merge; cl_qmap_delta; cl_map_construct; cl_map_init; cl_map_destroy; cl_map_insert; cl_map_get; cl_map_get_next; cl_map_remove_item; cl_map_remove; cl_map_remove_all; cl_map_merge; cl_map_delta; cl_fmap_init; cl_fmap_match; cl_fmap_get; cl_fmap_get_next; cl_fmap_apply_func; cl_fmap_insert; cl_fmap_remove_item; cl_fmap_remove; cl_fmap_merge; cl_fmap_delta; cl_qcpool_construct; cl_qcpool_init; cl_qcpool_destroy; cl_qcpool_grow; cl_qcpool_get; cl_qcpool_get_tail; cl_qpool_construct; cl_qpool_init; cl_cpool_construct; cl_cpool_init; cl_pool_construct; cl_pool_init; cl_ptr_vector_construct; cl_ptr_vector_init; cl_ptr_vector_destroy; cl_ptr_vector_at; cl_ptr_vector_set; cl_ptr_vector_remove; cl_ptr_vector_set_capacity; cl_ptr_vector_set_size; cl_ptr_vector_set_min_size; cl_ptr_vector_apply_func; cl_ptr_vector_find_from_start; cl_ptr_vector_find_from_end; cl_spinlock_construct; cl_spinlock_init; cl_spinlock_destroy; cl_spinlock_acquire; cl_spinlock_release; cl_status_text; cl_thread_construct; cl_thread_init; cl_thread_destroy; cl_thread_suspend; cl_thread_stall; cl_proc_count; cl_is_current_thread; cl_thread_pool_construct; cl_thread_pool_init; cl_thread_pool_destroy; cl_thread_pool_signal; __cl_timer_prov_create; __cl_timer_prov_destroy; cl_timer_construct; cl_timer_init; cl_timer_destroy; cl_timer_start; cl_timer_stop; cl_timer_trim; cl_get_time_stamp; cl_get_time_stamp_sec; cl_vector_copy_general; cl_vector_copy16; cl_vector_copy32; cl_vector_copy64; cl_vector_construct; cl_vector_init; cl_vector_destroy; cl_vector_at; cl_vector_set; cl_vector_set_capacity; cl_vector_set_size; cl_vector_set_min_size; cl_vector_apply_func; cl_vector_find_from_start; cl_vector_find_from_end; cl_atomic_spinlock; cl_atomic_dec; ib_error_str; ib_async_event_str; ib_wc_status_str; open_node_name_map; close_node_name_map; parse_node_map; remap_node_name; clean_nodedesc; local: *; }; opensm-3.3.20/complib/libosmcomp.ver0000644000205000001450000000051612726304101014315 00000000000000# In this file we track the current API version # of the complib library interface # The version is built of the following # tree numbers: # API_REV:RUNNING_REV:AGE # API_REV - advance on any added API # RUNNING_REV - advance any change to the vendor files # AGE - number of backward versions the API still supports LIBVERSION=3:10:0 opensm-3.3.20/libvendor/0000755000205000001450000000000012726324761012066 500000000000000opensm-3.3.20/libvendor/Makefile.am0000644000205000001450000000464512272264652014051 00000000000000 SUBDIRS = . if DEBUG DBGFLAGS = -ggdb -D_DEBUG_ else DBGFLAGS = -g endif INCLUDES = $(OSMV_INCLUDES) lib_LTLIBRARIES = libosmvendor.la libosmvendor_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) if HAVE_LD_VERSION_SCRIPT libosmvendor_version_script = -Wl,--version-script=$(srcdir)/libosmvendor.map else libosmvendor_version_script = endif osmvendor_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmvendor.ver | sed 's/LIBVERSION=//') COMM_HDRS= $(srcdir)/../include/vendor/osm_vendor_api.h \ $(srcdir)/../include/vendor/osm_vendor.h \ $(srcdir)/../include/vendor/osm_vendor_sa_api.h if OSMV_OPENIB libosmvendor_la_SOURCES = osm_vendor_ibumad.c \ osm_vendor_ibumad_sa.c HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_ibumad.h endif if OSMV_SIM libosmvendor_la_SOURCES = osm_vendor_mlx.c \ osm_vendor_mlx_sim.c \ osm_vendor_mlx_hca_sim.c \ osm_vendor_mlx_dispatcher.c \ osm_vendor_mlx_rmpp_ctx.c \ osm_vendor_mlx_sar.c \ osm_vendor_mlx_sender.c \ osm_vendor_mlx_txn.c \ osm_vendor_mlx_sa.c \ osm_pkt_randomizer.c HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ $(srcdir)/../include/vendor/osm_pkt_randomizer.h endif if OSMV_GEN1 libosmvendor_la_SOURCES = osm_vendor_mlx.c \ osm_pkt_randomizer.c \ osm_vendor_mlx_hca.c \ osm_vendor_mlx_dispatcher.c \ osm_vendor_mlx_rmpp_ctx.c \ osm_vendor_mlx_sar.c \ osm_vendor_mlx_sender.c \ osm_vendor_mlx_ts.c \ osm_vendor_mlx_txn.c \ osm_vendor_mlx_sa.c HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ $(srcdir)/../include/vendor/osm_pkt_randomizer.h endif if OSMV_VAPI libosmvendor_la_SOURCES = osm_vendor_mlx.c \ osm_pkt_randomizer.c \ osm_vendor_mlx_hca.c \ osm_vendor_mlx_dispatcher.c \ osm_vendor_mlx_rmpp_ctx.c \ osm_vendor_mlx_sar.c \ osm_vendor_mlx_sender.c \ osm_vendor_mlx_ibmgt.c \ osm_vendor_mlx_txn.c \ osm_vendor_mlx_sa.c HDRS =$(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ $(srcdir)/../include/vendor/osm_pkt_randomizer.h endif libosmvendor_la_LIBADD = -L../complib -losmcomp libosmvendor_la_LDFLAGS = -version-info $(osmvendor_api_version) \ -export-dynamic $(libosmvendor_version_script) libosmvendor_la_DEPENDENCIES = $(srcdir)/libosmvendor.map libosmvendorincludedir = $(includedir)/infiniband/vendor libosmvendorinclude_HEADERS = $(HDRS) # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmvendor.map $(srcdir)/libosmvendor.ver opensm-3.3.20/libvendor/Makefile.in0000644000205000001450000014107312726323425014055 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = libvendor DIST_COMMON = $(am__libosmvendorinclude_HEADERS_DIST) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(libosmvendorincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__libosmvendor_la_SOURCES_DIST = osm_vendor_mlx.c \ osm_pkt_randomizer.c osm_vendor_mlx_hca.c \ osm_vendor_mlx_dispatcher.c osm_vendor_mlx_rmpp_ctx.c \ osm_vendor_mlx_sar.c osm_vendor_mlx_sender.c \ osm_vendor_mlx_ts.c osm_vendor_mlx_txn.c osm_vendor_mlx_sa.c \ osm_vendor_ibumad.c osm_vendor_ibumad_sa.c \ osm_vendor_mlx_sim.c osm_vendor_mlx_hca_sim.c \ osm_vendor_mlx_ibmgt.c @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_mlx.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_pkt_randomizer.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_hca.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_dispatcher.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_sar.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_sender.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_ibmgt.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_txn.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_FALSE@@OSMV_VAPI_TRUE@ libosmvendor_la-osm_vendor_mlx_sa.lo @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_mlx.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_sim.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_hca_sim.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_dispatcher.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_sar.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_sender.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_txn.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_vendor_mlx_sa.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_FALSE@@OSMV_SIM_TRUE@ libosmvendor_la-osm_pkt_randomizer.lo @OSMV_GEN1_FALSE@@OSMV_OPENIB_TRUE@am_libosmvendor_la_OBJECTS = libosmvendor_la-osm_vendor_ibumad.lo \ @OSMV_GEN1_FALSE@@OSMV_OPENIB_TRUE@ libosmvendor_la-osm_vendor_ibumad_sa.lo @OSMV_GEN1_TRUE@am_libosmvendor_la_OBJECTS = \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_pkt_randomizer.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_hca.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_dispatcher.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_sar.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_sender.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_ts.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_txn.lo \ @OSMV_GEN1_TRUE@ libosmvendor_la-osm_vendor_mlx_sa.lo libosmvendor_la_OBJECTS = $(am_libosmvendor_la_OBJECTS) libosmvendor_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libosmvendor_la_CFLAGS) \ $(CFLAGS) $(libosmvendor_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libosmvendor_la_SOURCES) DIST_SOURCES = $(am__libosmvendor_la_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__libosmvendorinclude_HEADERS_DIST = \ $(srcdir)/../include/vendor/osm_vendor_api.h \ $(srcdir)/../include/vendor/osm_vendor.h \ $(srcdir)/../include/vendor/osm_vendor_sa_api.h \ $(srcdir)/../include/vendor/osm_vendor_mlx.h \ $(srcdir)/../include/vendor/osm_pkt_randomizer.h \ $(srcdir)/../include/vendor/osm_vendor_ibumad.h HEADERS = $(libosmvendorinclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . @DEBUG_FALSE@DBGFLAGS = -g @DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_ INCLUDES = $(OSMV_INCLUDES) lib_LTLIBRARIES = libosmvendor.la libosmvendor_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) @HAVE_LD_VERSION_SCRIPT_FALSE@libosmvendor_version_script = @HAVE_LD_VERSION_SCRIPT_TRUE@libosmvendor_version_script = -Wl,--version-script=$(srcdir)/libosmvendor.map osmvendor_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmvendor.ver | sed 's/LIBVERSION=//') COMM_HDRS = $(srcdir)/../include/vendor/osm_vendor_api.h \ $(srcdir)/../include/vendor/osm_vendor.h \ $(srcdir)/../include/vendor/osm_vendor_sa_api.h @OSMV_GEN1_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \ @OSMV_GEN1_TRUE@ osm_pkt_randomizer.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_hca.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_dispatcher.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_rmpp_ctx.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_sar.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_sender.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_ts.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_txn.c \ @OSMV_GEN1_TRUE@ osm_vendor_mlx_sa.c @OSMV_OPENIB_TRUE@libosmvendor_la_SOURCES = osm_vendor_ibumad.c \ @OSMV_OPENIB_TRUE@ osm_vendor_ibumad_sa.c @OSMV_SIM_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_sim.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_hca_sim.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_dispatcher.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_rmpp_ctx.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_sar.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_sender.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_txn.c \ @OSMV_SIM_TRUE@ osm_vendor_mlx_sa.c \ @OSMV_SIM_TRUE@ osm_pkt_randomizer.c @OSMV_VAPI_TRUE@libosmvendor_la_SOURCES = osm_vendor_mlx.c \ @OSMV_VAPI_TRUE@ osm_pkt_randomizer.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_hca.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_dispatcher.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_rmpp_ctx.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_sar.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_sender.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_ibmgt.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_txn.c \ @OSMV_VAPI_TRUE@ osm_vendor_mlx_sa.c @OSMV_GEN1_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ @OSMV_GEN1_TRUE@ $(srcdir)/../include/vendor/osm_pkt_randomizer.h @OSMV_OPENIB_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_ibumad.h @OSMV_SIM_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ @OSMV_SIM_TRUE@ $(srcdir)/../include/vendor/osm_pkt_randomizer.h @OSMV_VAPI_TRUE@HDRS = $(COMM_HDRS) $(srcdir)/../include/vendor/osm_vendor_mlx.h \ @OSMV_VAPI_TRUE@ $(srcdir)/../include/vendor/osm_pkt_randomizer.h libosmvendor_la_LIBADD = -L../complib -losmcomp libosmvendor_la_LDFLAGS = -version-info $(osmvendor_api_version) \ -export-dynamic $(libosmvendor_version_script) libosmvendor_la_DEPENDENCIES = $(srcdir)/libosmvendor.map libosmvendorincludedir = $(includedir)/infiniband/vendor libosmvendorinclude_HEADERS = $(HDRS) # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmvendor.map $(srcdir)/libosmvendor.ver all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libvendor/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libvendor/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libosmvendor.la: $(libosmvendor_la_OBJECTS) $(libosmvendor_la_DEPENDENCIES) $(libosmvendor_la_LINK) -rpath $(libdir) $(libosmvendor_la_OBJECTS) $(libosmvendor_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libosmvendor_la-osm_vendor_mlx.lo: osm_vendor_mlx.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Tpo -c -o libosmvendor_la-osm_vendor_mlx.lo `test -f 'osm_vendor_mlx.c' || echo '$(srcdir)/'`osm_vendor_mlx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx.c' object='libosmvendor_la-osm_vendor_mlx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx.lo `test -f 'osm_vendor_mlx.c' || echo '$(srcdir)/'`osm_vendor_mlx.c libosmvendor_la-osm_pkt_randomizer.lo: osm_pkt_randomizer.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_pkt_randomizer.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Tpo -c -o libosmvendor_la-osm_pkt_randomizer.lo `test -f 'osm_pkt_randomizer.c' || echo '$(srcdir)/'`osm_pkt_randomizer.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Tpo $(DEPDIR)/libosmvendor_la-osm_pkt_randomizer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_pkt_randomizer.c' object='libosmvendor_la-osm_pkt_randomizer.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_pkt_randomizer.lo `test -f 'osm_pkt_randomizer.c' || echo '$(srcdir)/'`osm_pkt_randomizer.c libosmvendor_la-osm_vendor_mlx_hca.lo: osm_vendor_mlx_hca.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_hca.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Tpo -c -o libosmvendor_la-osm_vendor_mlx_hca.lo `test -f 'osm_vendor_mlx_hca.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_hca.c' object='libosmvendor_la-osm_vendor_mlx_hca.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_hca.lo `test -f 'osm_vendor_mlx_hca.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca.c libosmvendor_la-osm_vendor_mlx_dispatcher.lo: osm_vendor_mlx_dispatcher.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_dispatcher.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Tpo -c -o libosmvendor_la-osm_vendor_mlx_dispatcher.lo `test -f 'osm_vendor_mlx_dispatcher.c' || echo '$(srcdir)/'`osm_vendor_mlx_dispatcher.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_dispatcher.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_dispatcher.c' object='libosmvendor_la-osm_vendor_mlx_dispatcher.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_dispatcher.lo `test -f 'osm_vendor_mlx_dispatcher.c' || echo '$(srcdir)/'`osm_vendor_mlx_dispatcher.c libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo: osm_vendor_mlx_rmpp_ctx.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Tpo -c -o libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo `test -f 'osm_vendor_mlx_rmpp_ctx.c' || echo '$(srcdir)/'`osm_vendor_mlx_rmpp_ctx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_rmpp_ctx.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_rmpp_ctx.c' object='libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_rmpp_ctx.lo `test -f 'osm_vendor_mlx_rmpp_ctx.c' || echo '$(srcdir)/'`osm_vendor_mlx_rmpp_ctx.c libosmvendor_la-osm_vendor_mlx_sar.lo: osm_vendor_mlx_sar.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sar.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sar.lo `test -f 'osm_vendor_mlx_sar.c' || echo '$(srcdir)/'`osm_vendor_mlx_sar.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sar.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_sar.c' object='libosmvendor_la-osm_vendor_mlx_sar.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sar.lo `test -f 'osm_vendor_mlx_sar.c' || echo '$(srcdir)/'`osm_vendor_mlx_sar.c libosmvendor_la-osm_vendor_mlx_sender.lo: osm_vendor_mlx_sender.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sender.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sender.lo `test -f 'osm_vendor_mlx_sender.c' || echo '$(srcdir)/'`osm_vendor_mlx_sender.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sender.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_sender.c' object='libosmvendor_la-osm_vendor_mlx_sender.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sender.lo `test -f 'osm_vendor_mlx_sender.c' || echo '$(srcdir)/'`osm_vendor_mlx_sender.c libosmvendor_la-osm_vendor_mlx_ts.lo: osm_vendor_mlx_ts.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_ts.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Tpo -c -o libosmvendor_la-osm_vendor_mlx_ts.lo `test -f 'osm_vendor_mlx_ts.c' || echo '$(srcdir)/'`osm_vendor_mlx_ts.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ts.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_ts.c' object='libosmvendor_la-osm_vendor_mlx_ts.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_ts.lo `test -f 'osm_vendor_mlx_ts.c' || echo '$(srcdir)/'`osm_vendor_mlx_ts.c libosmvendor_la-osm_vendor_mlx_txn.lo: osm_vendor_mlx_txn.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_txn.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Tpo -c -o libosmvendor_la-osm_vendor_mlx_txn.lo `test -f 'osm_vendor_mlx_txn.c' || echo '$(srcdir)/'`osm_vendor_mlx_txn.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_txn.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_txn.c' object='libosmvendor_la-osm_vendor_mlx_txn.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_txn.lo `test -f 'osm_vendor_mlx_txn.c' || echo '$(srcdir)/'`osm_vendor_mlx_txn.c libosmvendor_la-osm_vendor_mlx_sa.lo: osm_vendor_mlx_sa.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sa.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sa.lo `test -f 'osm_vendor_mlx_sa.c' || echo '$(srcdir)/'`osm_vendor_mlx_sa.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sa.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_sa.c' object='libosmvendor_la-osm_vendor_mlx_sa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sa.lo `test -f 'osm_vendor_mlx_sa.c' || echo '$(srcdir)/'`osm_vendor_mlx_sa.c libosmvendor_la-osm_vendor_ibumad.lo: osm_vendor_ibumad.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_ibumad.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Tpo -c -o libosmvendor_la-osm_vendor_ibumad.lo `test -f 'osm_vendor_ibumad.c' || echo '$(srcdir)/'`osm_vendor_ibumad.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_ibumad.c' object='libosmvendor_la-osm_vendor_ibumad.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_ibumad.lo `test -f 'osm_vendor_ibumad.c' || echo '$(srcdir)/'`osm_vendor_ibumad.c libosmvendor_la-osm_vendor_ibumad_sa.lo: osm_vendor_ibumad_sa.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_ibumad_sa.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Tpo -c -o libosmvendor_la-osm_vendor_ibumad_sa.lo `test -f 'osm_vendor_ibumad_sa.c' || echo '$(srcdir)/'`osm_vendor_ibumad_sa.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_ibumad_sa.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_ibumad_sa.c' object='libosmvendor_la-osm_vendor_ibumad_sa.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_ibumad_sa.lo `test -f 'osm_vendor_ibumad_sa.c' || echo '$(srcdir)/'`osm_vendor_ibumad_sa.c libosmvendor_la-osm_vendor_mlx_sim.lo: osm_vendor_mlx_sim.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_sim.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Tpo -c -o libosmvendor_la-osm_vendor_mlx_sim.lo `test -f 'osm_vendor_mlx_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_sim.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_sim.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_sim.c' object='libosmvendor_la-osm_vendor_mlx_sim.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_sim.lo `test -f 'osm_vendor_mlx_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_sim.c libosmvendor_la-osm_vendor_mlx_hca_sim.lo: osm_vendor_mlx_hca_sim.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_hca_sim.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Tpo -c -o libosmvendor_la-osm_vendor_mlx_hca_sim.lo `test -f 'osm_vendor_mlx_hca_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca_sim.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_hca_sim.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_hca_sim.c' object='libosmvendor_la-osm_vendor_mlx_hca_sim.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_hca_sim.lo `test -f 'osm_vendor_mlx_hca_sim.c' || echo '$(srcdir)/'`osm_vendor_mlx_hca_sim.c libosmvendor_la-osm_vendor_mlx_ibmgt.lo: osm_vendor_mlx_ibmgt.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -MT libosmvendor_la-osm_vendor_mlx_ibmgt.lo -MD -MP -MF $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Tpo -c -o libosmvendor_la-osm_vendor_mlx_ibmgt.lo `test -f 'osm_vendor_mlx_ibmgt.c' || echo '$(srcdir)/'`osm_vendor_mlx_ibmgt.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Tpo $(DEPDIR)/libosmvendor_la-osm_vendor_mlx_ibmgt.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osm_vendor_mlx_ibmgt.c' object='libosmvendor_la-osm_vendor_mlx_ibmgt.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmvendor_la_CFLAGS) $(CFLAGS) -c -o libosmvendor_la-osm_vendor_mlx_ibmgt.lo `test -f 'osm_vendor_mlx_ibmgt.c' || echo '$(srcdir)/'`osm_vendor_mlx_ibmgt.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libosmvendorincludeHEADERS: $(libosmvendorinclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(libosmvendorincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmvendorincludedir)" @list='$(libosmvendorinclude_HEADERS)'; test -n "$(libosmvendorincludedir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libosmvendorincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libosmvendorincludedir)" || exit $$?; \ done uninstall-libosmvendorincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libosmvendorinclude_HEADERS)'; test -n "$(libosmvendorincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(libosmvendorincludedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libosmvendorincludedir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmvendorincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-libosmvendorincludeHEADERS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-libLTLIBRARIES \ uninstall-libosmvendorincludeHEADERS .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool ctags ctags-recursive \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES \ install-libosmvendorincludeHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-libosmvendorincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/libvendor/ChangeLog0000644000205000001450000000346612104655724013565 000000000000002007-07-11 Hal Rosenstock * configure.in: Bump version to 2.2.1 2007-07-10 Sean Hefty * osm_vendor_ibumad.c: Use pkey index, rather than pkey on umad_set_pkey call. Using index 0 for now. 2007-05-07 Hal Rosenstock * osm_vendor_ibumad.(h c): Remove support for issmdisabled 2007-03-29 Hal Rosenstock * configure.in: Bump version to 2.2.0 2007-03-27 Hal Rosenstock * osm_vendor_ibumad.(h c): Add support for issmdisabled 2007-03-13 Hal Rosenstock * osm_vendor_ibumad.c: In osm_vendor_set_sm, set issmfd to -1 on open error 2007-03-12 Hal Rosenstock * osm_vendor_ibumad.c: In umad_receiver, display DR path of sent MAD when it times out. In osm_vendor_send, simplify redundant code. Cosmetic change to osm_log message in osm_vendor_bind. 2007-02-20 Hal Rosenstock * configure.in: Bump version to 2.1.1 2007-02-20 Sasha Khapyorsky * osm_vendor_ibumad.(h c): Fix termination crash associated with umad_receiver thread termination. * osm_vendor_mlx_sa.c, osm_vendor_mlx_sim.c: Changes for compilation failures detected during ibutils/ibmgtsim building 2007=01-10 Sasha Khapyorsky * osm_vendor_ibumad.c: Close umad port in osm_vendor_delete so same process can reinitialize and resuse vendor layer. 2006-10-12 Hal Rosenstock * osm_vendor_ibumad.c (umad_receiver): Fix endian of LID displayed in send timeout error message. 2006-10-10 Hal Rosenstock * osm_vendor_ibumad.c: Print errors to stderr rather than stdout. 2006-09-28 Eitan Zahavi * osm_vendor_mlx_sa.c: Missing status on timeout SA query. opensm-3.3.20/libvendor/osm_vendor_mlx.c0000644000205000001450000005160412104655724015207 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include /** * FORWARD REFERENCES */ static ib_api_status_t __osmv_get_send_txn(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t is_rmpp, IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn); static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind); /* * NAME osm_vendor_new * * DESCRIPTION Create and Initialize the osm_vendor_t Object */ osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log, IN const uint32_t timeout) { ib_api_status_t status; osm_vendor_t *p_vend; OSM_LOG_ENTER(p_log); CL_ASSERT(p_log); p_vend = malloc(sizeof(*p_vend)); if (p_vend != NULL) { memset(p_vend, 0, sizeof(*p_vend)); status = osm_vendor_init(p_vend, p_log, timeout); if (status != IB_SUCCESS) { osm_vendor_delete(&p_vend); } } else { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_new: ERR 7301: " "Fail to allocate vendor object.\n"); } OSM_LOG_EXIT(p_log); return (p_vend); } /* * NAME osm_vendor_delete * * DESCRIPTION Delete all the binds behind the vendor + free the vendor object */ void osm_vendor_delete(IN osm_vendor_t ** const pp_vend) { cl_list_item_t *p_item; cl_list_obj_t *p_obj; osm_bind_handle_t bind_h; osm_log_t *p_log; OSM_LOG_ENTER((*pp_vend)->p_log); p_log = (*pp_vend)->p_log; /* go over the bind handles , unbind them and remove from list */ p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles)); while (p_item != cl_qlist_end(&((*pp_vend)->bind_handles))) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); bind_h = (osm_bind_handle_t *) cl_qlist_obj(p_obj); osm_log(p_log, OSM_LOG_DEBUG, "osm_vendor_delete: unbinding bind_h:%p \n", bind_h); __osm_vendor_internal_unbind(bind_h); free(p_obj); /*removing from list */ p_item = cl_qlist_remove_head(&((*pp_vend)->bind_handles)); } if (NULL != ((*pp_vend)->p_transport_info)) { free((*pp_vend)->p_transport_info); (*pp_vend)->p_transport_info = NULL; } /* remove the packet randomizer object */ if ((*pp_vend)->run_randomizer == TRUE) osm_pkt_randomizer_destroy(&((*pp_vend)->p_pkt_randomizer), p_log); free(*pp_vend); *pp_vend = NULL; OSM_LOG_EXIT(p_log); } /* * NAME osm_vendor_init * * DESCRIPTION Initialize the vendor object */ ib_api_status_t osm_vendor_init(IN osm_vendor_t * const p_vend, IN osm_log_t * const p_log, IN const uint32_t timeout) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); p_vend->p_transport_info = NULL; p_vend->p_log = p_log; p_vend->resp_timeout = timeout; p_vend->ttime_timeout = timeout * OSMV_TXN_TIMEOUT_FACTOR; cl_qlist_init(&p_vend->bind_handles); /* update the run_randomizer flag */ if (getenv("OSM_PKT_DROP_RATE") != NULL && atol(getenv("OSM_PKT_DROP_RATE")) != 0) { /* if the OSM_PKT_DROP_RATE global variable is defined to a non-zero value - then the randomizer should be called. Need to create the packet randomizer object */ p_vend->run_randomizer = TRUE; status = osm_pkt_randomizer_init(&(p_vend->p_pkt_randomizer), p_log); if (status != IB_SUCCESS) return status; } else { p_vend->run_randomizer = FALSE; p_vend->p_pkt_randomizer = NULL; } OSM_LOG_EXIT(p_log); return (IB_SUCCESS); } /* * NAME osm_vendor_bind * * DESCRIPTION Create a new bind object under the vendor object */ osm_bind_handle_t osm_vendor_bind(IN osm_vendor_t * const p_vend, IN osm_bind_info_t * const p_bind_info, IN osm_mad_pool_t * const p_mad_pool, IN osm_vend_mad_recv_callback_t mad_recv_callback, IN osm_vend_mad_send_err_callback_t send_err_callback, IN void *context) { osmv_bind_obj_t *p_bo; ib_api_status_t status; char hca_id[32]; cl_status_t cl_st; cl_list_obj_t *p_obj; uint8_t hca_index; if (NULL == p_vend || NULL == p_bind_info || NULL == p_mad_pool || NULL == mad_recv_callback || NULL == send_err_callback) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7302: " "NULL parameter passed in: p_vend=%p p_bind_info=%p p_mad_pool=%p recv_cb=%p send_err_cb=%p\n", p_vend, p_bind_info, p_mad_pool, mad_recv_callback, send_err_callback); return OSM_BIND_INVALID_HANDLE; } p_bo = malloc(sizeof(osmv_bind_obj_t)); if (NULL == p_bo) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7303: could not allocate the bind object\n"); return OSM_BIND_INVALID_HANDLE; } memset(p_bo, 0, sizeof(osmv_bind_obj_t)); p_bo->p_vendor = p_vend; p_bo->recv_cb = mad_recv_callback; p_bo->send_err_cb = send_err_callback; p_bo->cb_context = context; p_bo->p_osm_pool = p_mad_pool; /* obtain the hca name and port num from the guid */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osm_vendor_bind: " "Finding CA and Port that owns port guid 0x%" PRIx64 ".\n", cl_ntoh64(p_bind_info->port_guid)); status = osm_vendor_get_guid_ca_and_port(p_bo->p_vendor, p_bind_info->port_guid, &(p_bo->hca_hndl), hca_id, &hca_index, &(p_bo->port_num)); if (status != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7304: " "Fail to find port number of port guid:0x%016" PRIx64 "\n", p_bind_info->port_guid); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* Initialize the magic_ptr to the pointer of the p_bo info. This will be used to signal when the object is being destroyed, so no real action will be done then. */ p_bo->magic_ptr = p_bo; p_bo->is_closing = FALSE; cl_spinlock_construct(&(p_bo->lock)); cl_st = cl_spinlock_init(&(p_bo->lock)); if (cl_st != CL_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7305: " "could not initialize the spinlock ...\n"); free(p_bo); return OSM_BIND_INVALID_HANDLE; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osm_vendor_bind: osmv_txnmgr_init ... \n"); if (osmv_txnmgr_init(&p_bo->txn_mgr, p_vend->p_log, &(p_bo->lock)) != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7306: " "osmv_txnmgr_init failed \n"); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* Do the real job! (Transport-dependent) */ if (IB_SUCCESS != osmv_transport_init(p_bind_info, hca_id, hca_index, p_bo)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7307: " "osmv_transport_init failed \n"); osmv_txnmgr_done((osm_bind_handle_t) p_bo); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } /* insert bind handle into db */ p_obj = malloc(sizeof(cl_list_obj_t)); if (NULL == p_obj) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osm_vendor_bind: ERR 7308: " "osm_vendor_bind: could not allocate the list object\n"); osmv_transport_done(p_bo->p_transp_mgr); osmv_txnmgr_done((osm_bind_handle_t) p_bo); cl_spinlock_destroy(&p_bo->lock); free(p_bo); return OSM_BIND_INVALID_HANDLE; } memset(p_obj, 0, sizeof(cl_list_obj_t)); cl_qlist_set_obj(p_obj, p_bo); cl_qlist_insert_head(&p_vend->bind_handles, &p_obj->list_item); return (osm_bind_handle_t) p_bo; } /* * NAME osm_vendor_unbind * * DESCRIPTION Destroy the bind object and remove it from the vendor's list */ void osm_vendor_unbind(IN osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_log_t *p_log = p_bo->p_vendor->p_log; cl_list_obj_t *p_obj = NULL; cl_list_item_t *p_item, *p_item_tmp; cl_qlist_t *const p_bh_list = (cl_qlist_t * const)&p_bo->p_vendor->bind_handles; OSM_LOG_ENTER(p_log); /* go over all the items in the list and remove the specific item */ p_item = cl_qlist_head(p_bh_list); while (p_item != cl_qlist_end(p_bh_list)) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); if (cl_qlist_obj(p_obj) == h_bind) { break; } p_item_tmp = cl_qlist_next(p_item); p_item = p_item_tmp; } CL_ASSERT(p_item != cl_qlist_end(p_bh_list)); cl_qlist_remove_item(p_bh_list, p_item); if (p_obj) free(p_obj); if (h_bind != 0) { __osm_vendor_internal_unbind(h_bind); } OSM_LOG_EXIT(p_log); } /* * NAME osm_vendor_get * * DESCRIPTION Allocate the space for a new MAD */ ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind, IN const uint32_t mad_size, IN osm_vend_wrap_t * const p_vw) { ib_mad_t *p_mad; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; uint32_t act_mad_size; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vw); if (mad_size < MAD_BLOCK_SIZE) { /* Stupid, but the applications want that! */ act_mad_size = MAD_BLOCK_SIZE; } else { act_mad_size = mad_size; } /* allocate it */ p_mad = (ib_mad_t *) malloc(act_mad_size); if (p_mad == NULL) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get: ERR 7309: " "Error Obtaining MAD buffer.\n"); goto Exit; } memset(p_mad, 0, act_mad_size); if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get: " "Allocated MAD %p, size = %u.\n", p_mad, act_mad_size); } p_vw->p_mad = p_mad; Exit: OSM_LOG_EXIT(p_vend->p_log); return (p_mad); } /* * NAME osm_vendor_send * * DESCRIPTION Send a MAD buffer (RMPP or simple send). * * Semantics: * (1) The RMPP send completes when every segment * is acknowledged (synchronous) * (2) The simple send completes when the send completion * is received (asynchronous) */ ib_api_status_t osm_vendor_send(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t const resp_expected) { ib_api_status_t ret = IB_SUCCESS; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; boolean_t is_rmpp = FALSE, is_rmpp_ds = FALSE; osmv_txn_ctx_t *p_txn = NULL; ib_mad_t *p_mad; osm_log_t *p_log = p_bo->p_vendor->p_log; osm_mad_pool_t *p_mad_pool = p_bo->p_osm_pool; OSM_LOG_ENTER(p_log); if (NULL == h_bind || NULL == p_madw || NULL == (p_mad = osm_madw_get_mad_ptr(p_madw)) || NULL == osm_madw_get_mad_addr_ptr(p_madw)) { return IB_INVALID_PARAMETER; } is_rmpp = (p_madw->mad_size > MAD_BLOCK_SIZE || osmv_mad_is_rmpp(p_mad)); /* is this rmpp double sided? This means we expect a response that can be an rmpp or not */ is_rmpp_ds = (TRUE == is_rmpp && TRUE == resp_expected); /* Make our operations with the send context atomic */ osmv_txn_lock(p_bo); if (TRUE == p_bo->is_closing) { osm_log(p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 7310: " "The handle %p is being unbound, cannot send.\n", h_bind); ret = IB_INTERRUPTED; /* When closing p_bo could be detroyed or is going to , thus could not refer to it */ goto send_done; } if (TRUE == resp_expected || TRUE == is_rmpp) { /* We must run under a transaction framework. * Get the transaction object (old or new) */ ret = __osmv_get_send_txn(h_bind, p_madw, is_rmpp, resp_expected, &p_txn); if (IB_SUCCESS != ret) { goto send_done; } } if (TRUE == is_rmpp) { /* Do the job - RMPP! * The call returns as all the packets are ACK'ed/upon error * The txn lock will be released each time the function sleeps * and re-acquired when it wakes up */ ret = osmv_rmpp_send_madw(h_bind, p_madw, p_txn, is_rmpp_ds); } else { /* Do the job - single MAD! * The call returns as soon as the MAD is put on the wire */ ret = osmv_simple_send_madw(h_bind, p_madw, p_txn, FALSE); } if (IB_SUCCESS == ret) { if ((TRUE == is_rmpp) && (FALSE == is_rmpp_ds)) { /* For double-sided sends, the txn continues to live */ osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE /*not in callback */ ); } if (FALSE == resp_expected) { osm_mad_pool_put(p_mad_pool, p_madw); } } else if (IB_INTERRUPTED != ret) { if (NULL != p_txn) { osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE /*not in callback */ ); } osm_log(p_log, OSM_LOG_ERROR, "osm_vendor_send: ERR 7311: failed to send MADW %p\n", p_madw); if (TRUE == resp_expected) { /* Change the status on the p_madw */ p_madw->status = ret; /* Only the requester expects the error callback */ p_bo->send_err_cb(p_bo->cb_context, p_madw); } else { /* put back the mad - it is useless ... */ osm_mad_pool_put(p_mad_pool, p_madw); } } else { /* the transaction was aborted due to p_bo exit */ osm_mad_pool_put(p_mad_pool, p_madw); goto aborted; } send_done: osmv_txn_unlock(p_bo); aborted: OSM_LOG_EXIT(p_log); return ret; } /* * NAME osm_vendor_put * * DESCRIPTION Free the MAD's memory */ void osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; if (p_bo->is_closing != TRUE) { OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vw); CL_ASSERT(p_vw->p_mad); if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_put: " "Retiring MAD %p.\n", p_vw->p_mad); } free(p_vw->p_mad); p_vw->p_mad = NULL; OSM_LOG_EXIT(p_vend->p_log); } } /* * NAME osm_vendor_local_lid_change * * DESCRIPTION Notifies the vendor transport layer that the local address * has changed. This allows the vendor layer to perform * housekeeping functions such as address vector updates. */ ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind) { osm_vendor_t const *p_vend = ((osmv_bind_obj_t *) h_bind)->p_vendor; OSM_LOG_ENTER(p_vend->p_log); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_local_lid_change: " "Change of LID.\n"); OSM_LOG_EXIT(p_vend->p_log); return (IB_SUCCESS); } /* * NAME osm_vendor_set_sm * * DESCRIPTION Modifies the port info for the bound port to set the "IS_SM" bit * according to the value given (TRUE or FALSE). */ #if !(defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_SIM) || defined(OSM_VENDOR_INTF_TS)) void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; VAPI_ret_t status; VAPI_hca_attr_t attr_mod; VAPI_hca_attr_mask_t attr_mask; OSM_LOG_ENTER(p_vend->p_log); memset(&attr_mod, 0, sizeof(attr_mod)); memset(&attr_mask, 0, sizeof(attr_mask)); attr_mod.is_sm = is_sm_val; attr_mask = HCA_ATTR_IS_SM; status = VAPI_modify_hca_attr(p_bo->hca_hndl, p_bo->port_num, &attr_mod, &attr_mask); if (status != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_set_sm: ERR 7312: " "Unable set 'IS_SM' bit to:%u in port attributes (%d).\n", is_sm_val, status); } OSM_LOG_EXIT(p_vend->p_log); } #endif /* * NAME __osm_vendor_internal_unbind * * DESCRIPTION Destroying a bind: * (1) Wait for the completion of the sends in flight * (2) Destroy the associated data structures */ static void __osm_vendor_internal_unbind(osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_log_t *p_log = p_bo->p_vendor->p_log; OSM_LOG_ENTER(p_log); /* "notifying" all that from now on no new sends can be done */ p_bo->txn_mgr.p_event_wheel->closing = TRUE; osmv_txn_lock(p_bo); /* the is_closing is set under lock we we know we only need to check for it after obtaining the lock */ p_bo->is_closing = TRUE; /* notifying all sleeping rmpp sends to exit */ osmv_txn_abort_rmpp_txns(h_bind); /* unlock the bo to allow for any residual mads to be dispatched */ osmv_txn_unlock(p_bo); osm_log(p_log, OSM_LOG_DEBUG, "__osm_vendor_internal_unbind: destroying transport mgr.. \n"); /* wait for the receiver thread to exit */ osmv_transport_done(h_bind); /* lock to avoid any collissions while we cleanup the structs */ osmv_txn_lock(p_bo); osm_log(p_log, OSM_LOG_DEBUG, "__osm_vendor_internal_unbind: destroying txn mgr.. \n"); osmv_txnmgr_done(h_bind); osm_log(p_log, OSM_LOG_DEBUG, "__osm_vendor_internal_unbind: destroying bind lock.. \n"); osmv_txn_unlock(p_bo); /* we intentionally let the p_bo and its lock leak - as we did not implement a way to track active bind handles provided to the client - and the client might use them cl_spinlock_destroy(&p_bo->lock); free(p_bo); */ OSM_LOG_EXIT(p_log); } /* * NAME __osmv_get_send_txn * * DESCRIPTION Return a transaction object that corresponds to this MAD. * Optionally, create it, if the new request (query) is sent or received. */ static ib_api_status_t __osmv_get_send_txn(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t is_rmpp, IN boolean_t resp_expected, OUT osmv_txn_ctx_t ** pp_txn) { ib_api_status_t ret; uint64_t tid, key; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw); OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(NULL != pp_txn); key = tid = cl_ntoh64(p_mad->trans_id); if (TRUE == resp_expected) { /* Create a unique identifier at the requester side */ key = osmv_txn_uniq_key(tid); } /* We must run under a transaction framework */ ret = osmv_txn_lookup(h_bind, key, pp_txn); if (IB_NOT_FOUND == ret) { /* Generally, we start a new transaction */ ret = osmv_txn_init(h_bind, tid, key, pp_txn); if (IB_SUCCESS != ret) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_get_send_txn: ERR 7313: " "The transaction id=0x%" PRIx64 " failed to init.\n", tid); goto get_send_txn_done; } } else { CL_ASSERT(NULL != *pp_txn); /* The transaction context exists. * This is legal only if I am going to return an * (RMPP?) reply to an RMPP request sent by the other part * (double-sided RMPP transfer) */ if (FALSE == is_rmpp || FALSE == osmv_txn_is_rmpp_init_by_peer(*pp_txn)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_get_send_txn: ERR 7314: " "The transaction id=0x%" PRIx64 " is not unique. Send failed.\n", tid); ret = IB_INVALID_SETTING; goto get_send_txn_done; } if (TRUE == resp_expected) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_get_send_txn: ERR 7315: " "The transaction id=0x%" PRIx64 " can't expect a response. Send failed.\n", tid); ret = IB_INVALID_PARAMETER; goto get_send_txn_done; } } if (TRUE == is_rmpp) { ret = osmv_txn_init_rmpp_sender(h_bind, *pp_txn, p_madw); if (IB_SUCCESS != ret) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_get_send_txn: ERR 7316: " "The transaction id=0x%" PRIx64 " failed to init the rmpp mad. Send failed.\n", tid); osmv_txn_done(h_bind, tid, FALSE); goto get_send_txn_done; } } /* Save a reference to the MAD in the txn context * We'll need to match it in two cases: * (1) When the response is returned, if I am the requester * (2) In RMPP retransmissions */ osmv_txn_set_madw(*pp_txn, p_madw); get_send_txn_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; } void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level) { } opensm-3.3.20/libvendor/osm_pkt_randomizer.c0000644000205000001450000002301512272264652016057 00000000000000/* * Copyright (c) 2004-2008 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 osm_pkt_randomizer_t. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #ifndef __WIN__ #include #include #endif /********************************************************************** * Return TRUE if the path is in a fault path, and FALSE otherwise. * By in a fault path the meaning is that there is a path in the fault * paths that the given path includes it. * E.g: if there is a fault path: 0,1,4 * For the given path: 0,1,4,7 the return value will be TRUE, also for * the given path: 0,1,4 the return value will be TRUE, but for * the given paths: 0,1 or 0,3,1,4 - the return value will be FALSE. **********************************************************************/ boolean_t __osm_pkt_randomizer_is_path_in_fault_paths(IN osm_log_t * p_log, IN osm_dr_path_t * p_dr_path, IN osm_pkt_randomizer_t * p_pkt_rand) { boolean_t res = FALSE, found_path; osm_dr_path_t *p_found_dr_path; uint8_t ind1, ind2; OSM_LOG_ENTER(p_log); for (ind1 = 0; ind1 < p_pkt_rand->num_paths_initialized; ind1++) { found_path = TRUE; p_found_dr_path = &(p_pkt_rand->fault_dr_paths[ind1]); /* if the hop count of the found path is greater than the hop count of the input path - then it is not part of it. Check the next path. */ if (p_found_dr_path->hop_count > p_dr_path->hop_count) continue; /* go over all the ports in the found path and see if they match the ports in the input path */ for (ind2 = 0; ind2 <= p_found_dr_path->hop_count; ind2++) if (p_found_dr_path->path[ind2] != p_dr_path->path[ind2]) found_path = FALSE; /* If found_path is TRUE then there is a full match of the path */ if (found_path == TRUE) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Given path is in a fault path\n"); res = TRUE; break; } } OSM_LOG_EXIT(p_log); return res; } /********************************************************************** * For a given dr_path - return TRUE if the path should be dropped, * return FALSE otherwise. * The check uses random criteria in order to determine whether or not * the path should be dropped. * First - if not all paths are initialized, it randomally chooses if * to use this path as a fault path or not. * Second - if the path is in the fault paths (meaning - it is equal * to or includes one of the fault paths) - then it randomally chooses * if to drop it or not. **********************************************************************/ boolean_t __osm_pkt_randomizer_process_path(IN osm_log_t * p_log, IN osm_pkt_randomizer_t * p_pkt_rand, IN osm_dr_path_t * p_dr_path) { boolean_t res = FALSE; static boolean_t rand_value_init = FALSE; static int rand_value; boolean_t in_fault_paths; uint8_t i; char buf[BUF_SIZE]; char line[BUF_SIZE]; OSM_LOG_ENTER(p_log); if (rand_value_init == FALSE) { int seed; #ifdef __WIN__ SYSTEMTIME st; #else struct timeval tv; struct timezone tz; #endif /* __WIN__ */ /* initiate the rand_value according to timeofday */ rand_value_init = TRUE; #ifdef __WIN__ GetLocalTime(&st); seed = st.wMilliseconds; #else gettimeofday(&tv, &tz); seed = tv.tv_usec; #endif /* __WIN__ */ srand(seed); } /* If the hop_count is 1 - then this is a mad down to our local port - don't drop it */ if (p_dr_path->hop_count <= 1) goto Exit; rand_value = rand(); sprintf(buf, "Path: "); /* update the dr_path into the buf */ for (i = 0; i <= p_dr_path->hop_count; i++) { sprintf(line, "[%X]", p_dr_path->path[i]); strcat(buf, line); } /* Check if the path given is in one of the fault paths */ in_fault_paths = __osm_pkt_randomizer_is_path_in_fault_paths(p_log, p_dr_path, p_pkt_rand); /* Check if all paths are initialized */ if (p_pkt_rand->num_paths_initialized < p_pkt_rand->osm_pkt_num_unstable_links) { /* Not all packets are initialized. */ if (in_fault_paths == FALSE) { /* the path is not in the false paths. Check using the rand value if to update it there or not. */ if (rand_value % (p_pkt_rand->osm_pkt_unstable_link_rate) == 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "%s added to the fault_dr_paths list\n" "\t\t\t rand_value:%u, unstable_link_rate:%u \n", buf, rand_value, p_pkt_rand->osm_pkt_unstable_link_rate); /* update the path in the fault paths */ memcpy(& (p_pkt_rand-> fault_dr_paths[p_pkt_rand-> num_paths_initialized]), p_dr_path, sizeof(osm_dr_path_t)); p_pkt_rand->num_paths_initialized++; in_fault_paths = TRUE; } } } if (in_fault_paths == FALSE) { /* If in_fault_paths is FALSE - just ignore the path */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "%s not in fault paths\n", buf); goto Exit; } /* The path is in the fault paths. Need to choose (randomally if to drop it or not. */ rand_value = rand(); if (rand_value % (p_pkt_rand->osm_pkt_drop_rate) == 0) { /* drop the current packet */ res = TRUE; OSM_LOG(p_log, OSM_LOG_VERBOSE, "Dropping path:%s\n", buf); } Exit: OSM_LOG_EXIT(p_log); return res; } boolean_t osm_pkt_randomizer_mad_drop(IN osm_log_t * p_log, IN osm_pkt_randomizer_t * p_pkt_randomizer, IN const ib_mad_t * p_mad) { const ib_smp_t *p_smp; boolean_t res = FALSE; osm_dr_path_t dr_path; OSM_LOG_ENTER(p_log); p_smp = (ib_smp_t *) p_mad; if (p_smp->mgmt_class != IB_MCLASS_SUBN_DIR) /* This is a lid route mad. Don't drop it */ goto Exit; osm_dr_path_init(&dr_path, p_smp->hop_count, p_smp->initial_path); if (__osm_pkt_randomizer_process_path (p_log, p_pkt_randomizer, &dr_path)) { /* the mad should be dropped o */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "mad TID: 0x%" PRIx64 " is being dropped\n", cl_ntoh64(p_smp->trans_id)); res = TRUE; } Exit: OSM_LOG_EXIT(p_log); return res; } ib_api_status_t osm_pkt_randomizer_init(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer, IN osm_log_t * p_log) { uint8_t tmp; ib_api_status_t res = IB_SUCCESS; OSM_LOG_ENTER(p_log); *pp_pkt_randomizer = malloc(sizeof(osm_pkt_randomizer_t)); if (*pp_pkt_randomizer == NULL) { res = IB_INSUFFICIENT_MEMORY; goto Exit; } memset(*pp_pkt_randomizer, 0, sizeof(osm_pkt_randomizer_t)); (*pp_pkt_randomizer)->num_paths_initialized = 0; tmp = atol(getenv("OSM_PKT_DROP_RATE")); (*pp_pkt_randomizer)->osm_pkt_drop_rate = tmp; if (getenv("OSM_PKT_NUM_UNSTABLE_LINKS") != NULL && (tmp = atol(getenv("OSM_PKT_NUM_UNSTABLE_LINKS"))) > 0) (*pp_pkt_randomizer)->osm_pkt_num_unstable_links = tmp; else (*pp_pkt_randomizer)->osm_pkt_num_unstable_links = 1; if (getenv("OSM_PKT_UNSTABLE_LINK_RATE") != NULL && (tmp = atol(getenv("OSM_PKT_UNSTABLE_LINK_RATE"))) > 0) (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = tmp; else (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate = 20; OSM_LOG(p_log, OSM_LOG_VERBOSE, "Using OSM_PKT_DROP_RATE=%u \n" "\t\t\t\t OSM_PKT_NUM_UNSTABLE_LINKS=%u \n" "\t\t\t\t OSM_PKT_UNSTABLE_LINK_RATE=%u \n", (*pp_pkt_randomizer)->osm_pkt_drop_rate, (*pp_pkt_randomizer)->osm_pkt_num_unstable_links, (*pp_pkt_randomizer)->osm_pkt_unstable_link_rate); /* allocate the fault_dr_paths variable */ /* It is the number of the paths that will be saved as fault = osm_pkt_num_unstable_links */ (*pp_pkt_randomizer)->fault_dr_paths = malloc(sizeof(osm_dr_path_t) * (*pp_pkt_randomizer)-> osm_pkt_num_unstable_links); if ((*pp_pkt_randomizer)->fault_dr_paths == NULL) { res = IB_INSUFFICIENT_MEMORY; goto Exit; } memset((*pp_pkt_randomizer)->fault_dr_paths, 0, sizeof(osm_dr_path_t) * (*pp_pkt_randomizer)->osm_pkt_num_unstable_links); Exit: OSM_LOG_EXIT(p_log); return (res); } void osm_pkt_randomizer_destroy(IN OUT osm_pkt_randomizer_t ** pp_pkt_randomizer, IN osm_log_t * p_log) { OSM_LOG_ENTER(p_log); if (*pp_pkt_randomizer != NULL) { free((*pp_pkt_randomizer)->fault_dr_paths); free(*pp_pkt_randomizer); } OSM_LOG_EXIT(p_log); } opensm-3.3.20/libvendor/osm_vendor_mlx_hca.c0000644000205000001450000003521112104655724016016 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #if defined(OSM_VENDOR_INTF_MTL) | defined(OSM_VENDOR_INTF_TS) #undef IN #undef OUT #include #include #include #include #include #include /******************************************************************************** * * Provide the functionality for selecting an HCA Port and Obtaining it's guid. * ********************************************************************************/ typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /********************************************************************** * Convert the given GID to GUID by copy of it's upper 8 bytes **********************************************************************/ ib_api_status_t __osm_vendor_gid_to_guid(IN u_int8_t * gid, OUT VAPI_gid_t * guid) { memcpy(guid, gid + 8, 8); return (IB_SUCCESS); } /********************************************************************** * Returns a pointer to the port attribute of the specified port * owned by this CA. ************************************************************************/ static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (&p_ca_info->p_attr->p_port_attr[index]); } /******************************************************************************** * get the CA names available on the system * NOTE: user of this function needs to deallocate p_hca_ids after usage. ********************************************************************************/ static ib_api_status_t __osm_vendor_get_ca_ids(IN osm_vendor_t * const p_vend, IN VAPI_hca_id_t ** const p_hca_ids, IN uint32_t * const p_num_guids) { ib_api_status_t status; VAPI_ret_t vapi_res; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_hca_ids); CL_ASSERT(p_num_guids); /* first call is just to get the number */ vapi_res = EVAPI_list_hcas(0, p_num_guids, NULL); /* fail ? */ if (vapi_res == VAPI_EINVAL_PARAM) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_vendor_get_ca_ids: ERR 3D08: : " "Bad parameter in calling: EVAPI_list_hcas. (%d)\n", vapi_res); status = IB_ERROR; goto Exit; } /* NO HCA ? */ if (*p_num_guids == 0) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_vendor_get_ca_ids: ERR 3D09: " "No available channel adapters.\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } /* allocate and really call - user of this function needs to deallocate it */ *p_hca_ids = (VAPI_hca_id_t *) malloc(*p_num_guids * sizeof(VAPI_hca_id_t)); /* now call it really */ vapi_res = EVAPI_list_hcas(*p_num_guids, p_num_guids, *p_hca_ids); /* too many ? */ if (vapi_res == VAPI_EAGAIN) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_vendor_get_ca_ids: ERR 3D10: " "More CA GUIDs than allocated array (%d).\n", *p_num_guids); status = IB_ERROR; goto Exit; } /* fail ? */ if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_vendor_get_ca_ids: ERR 3D11: : " "Bad parameter in calling: EVAPI_list_hcas.\n"); status = IB_ERROR; goto Exit; } if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_vendor_get_ca_ids: " "Detected %u local channel adapters.\n", *p_num_guids); } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } /********************************************************************** * Initialize an Info Struct for the Given HCA by its Id **********************************************************************/ static ib_api_status_t __osm_ca_info_init(IN osm_vendor_t * const p_vend, IN VAPI_hca_id_t ca_id, OUT osm_ca_info_t * const p_ca_info) { ib_api_status_t status = IB_ERROR; VAPI_ret_t vapi_res; VAPI_hca_hndl_t hca_hndl; VAPI_hca_vendor_t hca_vendor; VAPI_hca_cap_t hca_cap; VAPI_hca_port_t hca_port; uint8_t port_num; IB_gid_t *p_port_gid; uint16_t maxNumGids; OSM_LOG_ENTER(p_vend->p_log); /* get the HCA handle */ vapi_res = EVAPI_get_hca_hndl(ca_id, &hca_hndl); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 3D05: " "Fail to get HCA handle (%u).\n", vapi_res); goto Exit; } if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__osm_ca_info_init: " "Querying CA %s.\n", ca_id); } /* query and get the HCA capability */ vapi_res = VAPI_query_hca_cap(hca_hndl, &hca_vendor, &hca_cap); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 3D06: " "Fail to get HCA Capabilities (%u).\n", vapi_res); goto Exit; } /* get the guid of the HCA */ memcpy(&(p_ca_info->guid), hca_cap.node_guid, 8 * sizeof(u_int8_t)); p_ca_info->attr_size = 1; p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t)); memcpy(&(p_ca_info->p_attr->ca_guid), hca_cap.node_guid, 8 * sizeof(u_int8_t)); /* now obtain the attributes of the ports */ p_ca_info->p_attr->num_ports = hca_cap.phys_port_num; p_ca_info->p_attr->p_port_attr = (ib_port_attr_t *) malloc(hca_cap.phys_port_num * sizeof(ib_port_attr_t)); for (port_num = 0; port_num < p_ca_info->p_attr->num_ports; port_num++) { /* query the port attributes */ vapi_res = VAPI_query_hca_port_prop(hca_hndl, port_num + 1, &hca_port); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 3D07: " "Fail to get HCA Port Attributes (%d).\n", vapi_res); goto Exit; } /* first call to know the size of the gid table */ vapi_res = VAPI_query_hca_gid_tbl(hca_hndl, port_num + 1, 0, &maxNumGids, NULL); p_port_gid = (IB_gid_t *) malloc(maxNumGids * sizeof(IB_gid_t)); vapi_res = VAPI_query_hca_gid_tbl(hca_hndl, port_num + 1, maxNumGids, &maxNumGids, p_port_gid); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 3D12: " "Fail to get HCA Port GID (%d).\n", vapi_res); goto Exit; } __osm_vendor_gid_to_guid(p_port_gid[0], (IB_gid_t *) & p_ca_info->p_attr-> p_port_attr[port_num].port_guid); p_ca_info->p_attr->p_port_attr[port_num].lid = hca_port.lid; p_ca_info->p_attr->p_port_attr[port_num].link_state = hca_port.state; p_ca_info->p_attr->p_port_attr[port_num].sm_lid = hca_port.sm_lid; free(p_port_gid); } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } void osm_ca_info_destroy(IN osm_vendor_t * const p_vend, IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca) { osm_ca_info_t *p_ca; uint8_t i; OSM_LOG_ENTER(p_vend->p_log); for (i = 0; i < num_ca; i++) { p_ca = &p_ca_info[i]; if (NULL != p_ca->p_attr) { if (0 != p_ca->p_attr->num_ports) { free(p_ca->p_attr->p_port_attr); } free(p_ca->p_attr); } } free(p_ca_info); OSM_LOG_EXIT(p_vend->p_log); } /********************************************************************** * Fill in the array of port_attr with all available ports on ALL the * avilable CAs on this machine. * ALSO - * Update the vendor object list of ca_info structs **********************************************************************/ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports) { ib_api_status_t status; uint32_t ca; uint32_t ca_count = 0; uint32_t port_count = 0; uint8_t port_num; uint32_t total_ports = 0; VAPI_hca_id_t *p_ca_ids = NULL; osm_ca_info_t *p_ca_infos = NULL; uint32_t attr_array_sz = *p_num_ports; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend); /* determine the number of CA's */ status = __osm_vendor_get_ca_ids(p_vend, &p_ca_ids, &ca_count); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 3D13: " "Fail to get CA Ids.\n"); goto Exit; } /* Allocate an array big enough to hold the ca info objects */ p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t)); if (p_ca_infos == NULL) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 3D14: " "Unable to allocate CA information array.\n"); goto Exit; } memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t)); /* * For each CA, retrieve the CA info attributes */ for (ca = 0; ca < ca_count; ca++) { status = __osm_ca_info_init(p_vend, p_ca_ids[ca], &p_ca_infos[ca]); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 3D15: " "Unable to initialize CA Info object (%s).\n", ib_get_err_str(status)); goto Exit; } total_ports += p_ca_infos[ca].p_attr->num_ports; } *p_num_ports = total_ports; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get_all_port_attr: total ports:%u \n", total_ports); /* * If the user supplied enough storage, return the port guids, * otherwise, return the appropriate error. */ if (attr_array_sz >= total_ports) { for (ca = 0; ca < ca_count; ca++) { uint32_t num_ports; num_ports = p_ca_infos[ca].p_attr->num_ports; for (port_num = 0; port_num < num_ports; port_num++) { p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(&p_ca_infos [ca], port_num); port_count++; } } } else { status = IB_INSUFFICIENT_MEMORY; goto Exit; } status = IB_SUCCESS; Exit: if (p_ca_ids) free(p_ca_ids); if (p_ca_infos) { osm_ca_info_destroy(p_vend, p_ca_infos, ca_count); } OSM_LOG_EXIT(p_vend->p_log); return (status); } /********************************************************************** * Given the vendor obj and a guid * return the ca id and port number that have that guid **********************************************************************/ ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend, IN ib_net64_t const guid, OUT VAPI_hca_hndl_t * p_hca_hndl, OUT VAPI_hca_id_t * p_hca_id, OUT uint8_t * p_hca_idx, OUT uint32_t * p_port_num) { ib_api_status_t status; VAPI_hca_id_t *p_ca_ids = NULL; VAPI_ret_t vapi_res; VAPI_hca_hndl_t hca_hndl; VAPI_hca_vendor_t hca_vendor; VAPI_hca_cap_t hca_cap; IB_gid_t *p_port_gid = NULL; uint16_t maxNumGids; ib_net64_t port_guid; uint32_t ca, portIdx, ca_count; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend); /* * 1) Determine the number of CA's * 2) Allocate an array big enough to hold the ca info objects. * 3) Call again to retrieve the guids. */ status = __osm_vendor_get_ca_ids(p_vend, &p_ca_ids, &ca_count); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 3D16: " "Fail to get CA Ids.\n"); goto Exit; } /* * For each CA, retrieve the CA info attributes */ for (ca = 0; ca < ca_count; ca++) { /* get the HCA handle */ vapi_res = EVAPI_get_hca_hndl(p_ca_ids[ca], &hca_hndl); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 3D17: " "Fail to get HCA handle (%u).\n", vapi_res); goto Exit; } /* get the CA attributes - to know how many ports it has: */ if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get_guid_ca_and_port: " "Querying CA %s.\n", p_ca_ids[ca]); } /* query and get the HCA capability */ vapi_res = VAPI_query_hca_cap(hca_hndl, &hca_vendor, &hca_cap); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 3D18: " "Fail to get HCA Capabilities (%u).\n", vapi_res); goto Exit; } /* go over all ports - to obtail their guids */ for (portIdx = 0; portIdx < hca_cap.phys_port_num; portIdx++) { vapi_res = VAPI_query_hca_gid_tbl(hca_hndl, portIdx + 1, 0, &maxNumGids, NULL); p_port_gid = (IB_gid_t *) malloc(maxNumGids * sizeof(IB_gid_t)); /* get the port guid */ vapi_res = VAPI_query_hca_gid_tbl(hca_hndl, portIdx + 1, maxNumGids, &maxNumGids, p_port_gid); if (vapi_res != VAPI_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 3D19: " "Fail to get HCA Port GID (%d).\n", vapi_res); goto Exit; } /* convert to SF style */ __osm_vendor_gid_to_guid(p_port_gid[0], (VAPI_gid_t *) & port_guid); /* finally did we find it ? */ if (port_guid == guid) { *p_hca_hndl = hca_hndl; memcpy(p_hca_id, p_ca_ids[ca], sizeof(VAPI_hca_id_t)); *p_hca_idx = ca; *p_port_num = portIdx + 1; status = IB_SUCCESS; goto Exit; } free(p_port_gid); p_port_gid = NULL; } /* ALL PORTS */ } /* all HCAs */ osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 3D20: " "Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n", cl_ntoh64(guid)); status = IB_INVALID_GUID; Exit: if (p_ca_ids != NULL) free(p_ca_ids); if (p_port_gid != NULL) free(p_port_gid); OSM_LOG_EXIT(p_vend->p_log); return (status); } #endif opensm-3.3.20/libvendor/osm_vendor_mlx_dispatcher.c0000644000205000001450000005067712104655724017426 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include typedef enum _osmv_disp_route { OSMV_ROUTE_DROP, OSMV_ROUTE_SIMPLE, OSMV_ROUTE_RMPP, } osmv_disp_route_t; /** * FORWARD REFERENCES TO PRIVATE FUNCTIONS */ static osmv_disp_route_t __osmv_dispatch_route(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn); static void __osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr); static void __osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr); static void __osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr); static ib_api_status_t __osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr); static ib_api_status_t __osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN const ib_mad_t * p_mad); static void __osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr); /* * NAME * osmv_dispatch_mad * * DESCRIPTION * Lower-level MAD dispatcher. * Implements a switch between the following MAD consumers: * (1) Non-RMPP consumer (DATA) * (2) RMPP receiver (DATA/ABORT/STOP) * (3) RMPP sender (ACK/ABORT/STOP) * * PARAMETERS * h_bind The bind handle * p_mad_buf The 256 byte buffer of individual MAD * p_mad_addr The MAD originator's address */ ib_api_status_t osmv_dispatch_mad(IN osm_bind_handle_t h_bind, IN const void *p_mad_buf, IN const osm_mad_addr_t * p_mad_addr) { ib_api_status_t ret = IB_SUCCESS; const ib_mad_t *p_mad = (ib_mad_t *) p_mad_buf; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osmv_txn_ctx_t *p_txn = NULL; osm_log_t *p_log = p_bo->p_vendor->p_log; OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(NULL != h_bind && NULL != p_mad && NULL != p_mad_addr); osmv_txn_lock(p_bo); if (TRUE == p_bo->is_closing) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The bind handle %p is being closed. " "The MAD will not be dispatched.\n", p_bo); ret = IB_INTERRUPTED; goto dispatch_mad_done; } /* Add call for packet drop randomizer. This is a testing feature. If run_randomizer flag is set to TRUE, the randomizer will be called, and randomally will drop a packet. This is used for simulating unstable fabric. */ if (p_bo->p_vendor->run_randomizer == TRUE) { /* Try the randomizer */ if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log, p_bo->p_vendor-> p_pkt_randomizer, p_mad) == TRUE) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The MAD will not be dispatched.\n"); goto dispatch_mad_done; } } switch (__osmv_dispatch_route(h_bind, p_mad, &p_txn)) { case OSMV_ROUTE_DROP: break; /* Do nothing */ case OSMV_ROUTE_SIMPLE: __osmv_dispatch_simple_mad(h_bind, p_mad, p_txn, p_mad_addr); break; case OSMV_ROUTE_RMPP: __osmv_dispatch_rmpp_mad(h_bind, p_mad, p_txn, p_mad_addr); break; default: CL_ASSERT(FALSE); } dispatch_mad_done: osmv_txn_unlock(p_bo); OSM_LOG_EXIT(p_log); return ret; } /* * NAME __osmv_dispatch_route() * * DESCRIPTION Decide which way to handle the received MAD: simple txn/RMPP/drop */ static osmv_disp_route_t __osmv_dispatch_route(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, OUT osmv_txn_ctx_t ** pp_txn) { ib_api_status_t ret; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; boolean_t is_resp = ib_mad_is_response(p_mad); boolean_t is_txn; uint64_t key = cl_ntoh64(p_mad->trans_id); CL_ASSERT(NULL != pp_txn); ret = osmv_txn_lookup(h_bind, key, pp_txn); is_txn = (IB_SUCCESS == ret); if (FALSE == is_txn && TRUE == is_resp) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Received a response to a non-started/aged-out transaction (tid=0x%" PRIx64 "). " "Dropping the MAD.\n", key); return OSMV_ROUTE_DROP; } if (TRUE == osmv_mad_is_rmpp(p_mad)) { /* An RMPP transaction. The filtering is more delicate there */ return OSMV_ROUTE_RMPP; } if (TRUE == is_txn && FALSE == is_resp) { /* Does this MAD try to start a transaction with duplicate tid? */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Duplicate TID 0x%" PRIx64 " received (not a response). " "Dropping the MAD.\n", key); return OSMV_ROUTE_DROP; } return OSMV_ROUTE_SIMPLE; } /* * NAME __osmv_dispatch_simple_mad() * * DESCRIPTION Handle a MAD that is part of non-RMPP transfer */ static void __osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr) { osm_madw_t *p_madw; ib_mad_t *p_mad_buf; osm_madw_t *p_req_madw = NULL; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); /* Build the MAD wrapper to be returned to the user. * The actual storage for the MAD is allocated there. */ p_madw = osm_mad_pool_get(p_bo->p_osm_pool, h_bind, MAD_BLOCK_SIZE, p_mad_addr); if (NULL == p_madw) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_simple_mad: ERR 6501: " "Out Of Memory - could not allocate a buffer of size %d\n", MAD_BLOCK_SIZE); goto dispatch_simple_mad_done; } p_mad_buf = osm_madw_get_mad_ptr(p_madw); /* Copy the payload to the MAD buffer */ memcpy((void *)p_mad_buf, (void *)p_mad, MAD_BLOCK_SIZE); if (NULL != p_txn) { /* This is a RESPONSE MAD. Pair it with the REQUEST MAD, pass upstream */ p_req_madw = p_txn->p_madw; CL_ASSERT(NULL != p_req_madw); p_mad_buf->trans_id = cl_hton64(osmv_txn_get_tid(p_txn)); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Restoring the original TID to 0x%" PRIx64 "\n", cl_ntoh64(p_mad_buf->trans_id)); /* Reply matched, transaction complete */ osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE); } else { /* This is a REQUEST MAD. Don't create a context, pass upstream */ } /* Do the job ! */ p_bo->recv_cb(p_madw, p_bo->cb_context, p_req_madw); dispatch_simple_mad_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); } /* * NAME __osmv_dispatch_rmpp_mad() * * DESCRIPTION Handle a MAD that is part of RMPP transfer */ static void __osmv_dispatch_rmpp_mad(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr) { ib_api_status_t status = IB_SUCCESS; uint64_t key = cl_ntoh64(p_mad->trans_id); boolean_t is_init_by_peer = FALSE; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_madw_t *p_madw; OSM_LOG_ENTER(p_bo->p_vendor->p_log); if (NULL == p_txn) { if (FALSE == osmv_rmpp_is_data(p_mad) || FALSE == osmv_rmpp_is_first(p_mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The MAD does not match any transaction " "and does not start a sender-initiated RMPP transfer.\n"); goto dispatch_rmpp_mad_done; } /* IB Spec 13.6.2.2. This is a Sender Initiated Transfer. My peer is the requester and RMPP Sender. I am the RMPP Receiver. */ status = osmv_txn_init(h_bind, /*tid==key */ key, key, &p_txn); if (IB_SUCCESS != status) { goto dispatch_rmpp_mad_done; } is_init_by_peer = TRUE; osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "A new sender-initiated transfer (TID=0x%" PRIx64 ") started\n", key); } if (OSMV_TXN_RMPP_NONE == osmv_txn_get_rmpp_state(p_txn)) { /* Case 1: Fall through from above. * Case 2: When the transaction was initiated by me * (a single request MAD), there was an uncertainty * whether the reply will be RMPP. Now it's resolved, * since the reply is RMPP! */ status = osmv_txn_init_rmpp_receiver(h_bind, p_txn, is_init_by_peer); if (IB_SUCCESS != status) { goto dispatch_rmpp_mad_done; } } switch (osmv_txn_get_rmpp_state(p_txn)) { case OSMV_TXN_RMPP_RECEIVER: status = __osmv_dispatch_rmpp_rcv(h_bind, p_mad, p_txn, p_mad_addr); if (IB_SUCCESS != status) { if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) { /* This is a requester, still waiting for the reply. Apply the callback */ /* update the status of the p_madw */ p_madw = osmv_txn_get_madw(p_txn); p_madw->status = status; p_bo->send_err_cb(p_bo->cb_context, p_madw); } /* ABORT/STOP/LOCAL ERROR */ osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE); } break; case OSMV_TXN_RMPP_SENDER: __osmv_dispatch_rmpp_snd(h_bind, p_mad, p_txn, p_mad_addr); /* If an error happens here, it's the sender thread to cleanup the txn */ break; default: CL_ASSERT(FALSE); } dispatch_rmpp_mad_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); } /* * NAME __osmv_dispatch_rmpp_snd() * * DESCRIPTION MAD handling by an RMPP sender (ACK/ABORT/STOP) */ static void __osmv_dispatch_rmpp_snd(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr) { osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); uint32_t old_wl = p_send_ctx->window_last; uint32_t total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num); uint32_t new_wl = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->paylen_newwin); osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_rmpp_snd: ERR 6502: " "The remote side sent an ABORT/STOP indication.\n"); osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR); goto dispatch_rmpp_snd_done; } if (FALSE == osmv_rmpp_is_ack(p_mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Not supposed to receive DATA packets --> dropping the MAD\n"); goto dispatch_rmpp_snd_done; } /* Continue processing the ACK */ if (seg_num > old_wl) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_rmpp_snd: ERR 6503: " "ACK received for a non-sent segment %d\n", seg_num); osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr, IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_S2B); osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR); goto dispatch_rmpp_snd_done; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_dispatch_rmpp_snd: " "New WL = %u Old WL = %u Total Segs = %u\n", new_wl, old_wl, total_segs); if (new_wl < old_wl) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_rmpp_snd: ERR 6508: " "The receiver requests a smaller WL (%d) than before (%d)\n", new_wl, old_wl); osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr, IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_W2S); osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR); goto dispatch_rmpp_snd_done; } /* Update the sender's window, and optionally wake up the sender thread * Note! A single ACK can acknowledge a whole range of segments: [WF..SEG_NUM] */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "ACK for seg_num #%d accepted.\n", seg_num); if (seg_num == old_wl) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The send window [%d:%d] is totally acknowledged.\n", p_send_ctx->window_first, old_wl); p_send_ctx->window_first = seg_num + 1; p_send_ctx->window_last = (new_wl < total_segs) ? new_wl : total_segs; /* Remove the response timeout event for the window */ osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn)); /* Wake up the sending thread */ cl_event_signal(&p_send_ctx->event); } dispatch_rmpp_snd_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); } /* * NAME __osmv_dispatch_rmpp_rcv() * * DESCRIPTION MAD handling by an RMPP receiver (DATA/ABORT/STOP) */ static ib_api_status_t __osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr) { ib_api_status_t status = IB_SUCCESS; osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn); osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; boolean_t is_last1 = FALSE, is_last2 = FALSE; osm_madw_t *p_new_madw = NULL, *p_req_madw = NULL; ib_mad_t *p_mad_buf; uint32_t size = 0; uint64_t key = osmv_txn_get_key(p_txn); uint64_t tid = osmv_txn_get_tid(p_txn); OSM_LOG_ENTER(p_bo->p_vendor->p_log); if (TRUE == osmv_rmpp_is_ack(p_mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Not supposed to receive ACK's --> dropping the MAD\n"); goto dispatch_rmpp_rcv_done; } if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_dispatch_rmpp_rcv: ERR 6504: " "The Remote Side stopped sending\n"); status = IB_REMOTE_ERROR; goto dispatch_rmpp_rcv_done; } status = __osmv_dispatch_accept_seg(h_bind, p_txn, p_mad); switch (status) { case IB_SUCCESS: /* Check wheter this is the legal last MAD */ /* Criteria #1: the received MAD is marked last */ is_last1 = osmv_rmpp_is_last(p_mad); /* Criteria #2: the total accumulated length hits the advertised one */ is_last2 = is_last1; size = osmv_rmpp_recv_ctx_get_byte_num_from_first(p_recv_ctx); if (size > 0) { is_last2 = (osmv_rmpp_recv_ctx_get_cur_byte_num(p_recv_ctx) >= size); } if (is_last1 != is_last2) { osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr, IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_BAD_LEN); status = IB_ERROR; goto dispatch_rmpp_rcv_done; } /* TBD Consider an optimization - sending an ACK * only for the last segment in the window */ __osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr); break; case IB_INSUFFICIENT_RESOURCES: /* An out-of-order segment received. Send the ACK anyway */ __osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr); status = IB_SUCCESS; goto dispatch_rmpp_rcv_done; case IB_INSUFFICIENT_MEMORY: osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr, IB_RMPP_TYPE_STOP, IB_RMPP_STATUS_RESX); goto dispatch_rmpp_rcv_done; default: /* Illegal return code */ CL_ASSERT(FALSE); } if (TRUE != is_last1) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP MADW assembly continues, TID=0x%" PRIx64 "\n", tid); goto dispatch_rmpp_rcv_done; } /* This is the last packet. */ if (0 == size) { /* The total size was not advertised in the first packet */ size = osmv_rmpp_recv_ctx_get_byte_num_from_last(p_recv_ctx); } /* NOTE: the received mad might not be >= 256 bytes. some MADs might contain several SA records but still be less then a full MAD. We have to use RMPP to send them over since on a regular "simple" MAD there is no way to know how many records were sent */ /* Build the MAD wrapper to be returned to the user. * The actual storage for the MAD is allocated there. */ p_new_madw = osm_mad_pool_get(p_bo->p_osm_pool, h_bind, size, p_mad_addr); if (NULL == p_new_madw) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_rmpp_rcv: ERR 6506: " "Out Of Memory - could not allocate %d bytes for the MADW\n", size); status = IB_INSUFFICIENT_MEMORY; goto dispatch_rmpp_rcv_done; } p_req_madw = osmv_txn_get_madw(p_txn); p_mad_buf = osm_madw_get_mad_ptr(p_new_madw); status = osmv_rmpp_recv_ctx_reassemble_arbt_mad(p_recv_ctx, size, (uint8_t *) p_mad_buf); if (IB_SUCCESS != status) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_dispatch_rmpp_rcv: ERR 6507: " "Internal error - could not reassemble the result MAD\n"); goto dispatch_rmpp_rcv_done; /* What can happen here? */ } /* The MAD is assembled, we are about to apply the callback. * Delete the transaction context, unless the transaction is double sided */ if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn) || FALSE == osmv_mad_is_multi_resp(p_mad)) { osmv_txn_done(h_bind, key, FALSE); } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP MADW %p assembly complete, TID=0x%" PRIx64 "\n", p_new_madw, tid); p_mad_buf->trans_id = cl_hton64(tid); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Restoring the original TID to 0x%" PRIx64 "\n", cl_ntoh64(p_mad_buf->trans_id)); /* Finally, do the job! */ p_bo->recv_cb(p_new_madw, p_bo->cb_context, p_req_madw); dispatch_rmpp_rcv_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); return status; } /* * NAME __osmv_dispatch_accept_seg() * * DESCRIPTION Store a DATA segment at the RMPP receiver side, * if one is received in order. */ static ib_api_status_t __osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN const ib_mad_t * p_mad) { ib_api_status_t ret = IB_SUCCESS; uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num); osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn); osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; uint64_t tid = osmv_txn_get_tid(p_txn); OSM_LOG_ENTER(p_bo->p_vendor->p_log); if (seg_num != p_recv_ctx->expected_seg) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "TID 0x%" PRIx64 ": can't accept this segment (%d) - " "this is a Go-Back-N implementation\n", tid, seg_num); return IB_INSUFFICIENT_RESOURCES; } /* Store the packet's copy in the reassembly list. * Promote the expected segment counter. */ ret = osmv_rmpp_recv_ctx_store_mad_seg(p_recv_ctx, (uint8_t *) p_mad); if (IB_SUCCESS != ret) { return ret; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "TID 0x%" PRIx64 ": segment %d accepted\n", tid, seg_num); p_recv_ctx->expected_seg = seg_num + 1; OSM_LOG_EXIT(p_bo->p_vendor->p_log); return IB_SUCCESS; } /* * NAME __osmv_dispatch_send_ack() * * DESCRIPTION * * ISSUES * Consider sending the ACK from an async thread * if problems with the receiving side processing arise. */ static void __osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN osmv_txn_ctx_t * p_txn, IN const osm_mad_addr_t * p_mad_addr) { osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn); /* ACK the segment # that was accepted */ uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_req_mad)->seg_num); /* NOTE! The receiver can publish the New Window Last (NWL) value * that is greater than the total number of segments to be sent. * It's the sender's responsibility to compute the correct number * of segments to send in the next burst. */ uint32_t nwl = p_recv_ctx->expected_seg + OSMV_RMPP_RECV_WIN - 1; osmv_rmpp_send_ack(h_bind, p_req_mad, seg_num, nwl, p_mad_addr); } opensm-3.3.20/libvendor/osm_vendor_mlx_rmpp_ctx.c0000644000205000001450000002207312104655724017121 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include ib_api_status_t osmv_rmpp_send_ctx_init(osmv_rmpp_send_ctx_t * p_ctx, void *p_arbt_mad, uint32_t mad_sz, osm_log_t * p_log) { ib_api_status_t st = IB_SUCCESS; cl_status_t cl_st; CL_ASSERT(p_ctx); if (NULL == p_arbt_mad) { return IB_INVALID_PARAMETER; } if (osmv_mad_is_sa((ib_mad_t *) p_arbt_mad)) { p_ctx->is_sa_mad = TRUE; } else p_ctx->is_sa_mad = FALSE; p_ctx->mad_sz = mad_sz; cl_event_construct(&p_ctx->event); cl_st = cl_event_init(&p_ctx->event, FALSE); if (cl_st != CL_SUCCESS) { return IB_ERROR; } st = osmv_rmpp_sar_init(&p_ctx->sar, p_arbt_mad, p_ctx->mad_sz, p_ctx->is_sa_mad); if (st == IB_SUCCESS) { p_ctx->window_first = 1; p_ctx->window_last = 1; } p_ctx->p_log = p_log; return st; } void osmv_rmpp_send_ctx_done(IN osmv_rmpp_send_ctx_t * p_ctx) { CL_ASSERT(p_ctx); cl_event_destroy(&p_ctx->event); osmv_rmpp_sar_done(&p_ctx->sar); free(p_ctx); } uint32_t osmv_rmpp_send_ctx_get_num_segs(IN osmv_rmpp_send_ctx_t * p_send_ctx) { uint32_t data_len, data_sz, num; CL_ASSERT(p_send_ctx); if (p_send_ctx->is_sa_mad) { data_len = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; data_sz = IB_SA_DATA_SIZE; } else { data_len = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; data_sz = MAD_RMPP_DATA_SIZE; } num = data_len / data_sz; if (0 == data_len || (data_len % data_sz) > 0) { num++; } return num; } ib_api_status_t osmv_rmpp_send_ctx_get_seg(IN osmv_rmpp_send_ctx_t * p_send_ctx, IN uint32_t seg_idx, IN uint32_t resp_timeout, OUT void *p_buf) { ib_api_status_t st = IB_SUCCESS; uint32_t num_segs, paylen = 0; ib_rmpp_mad_t *p_rmpp_mad; OSM_LOG_ENTER(p_send_ctx->p_log); CL_ASSERT(p_send_ctx); st = osmv_rmpp_sar_get_mad_seg(&p_send_ctx->sar, seg_idx, p_buf); if (st != IB_SUCCESS) { goto Exit; } p_rmpp_mad = (ib_rmpp_mad_t *) p_buf; /* Set the relevant bits in the RMPP hdr */ p_rmpp_mad->rmpp_status = IB_RMPP_STATUS_SUCCESS; p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_ACTIVE; p_rmpp_mad->rmpp_flags |= resp_timeout << 3; num_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); if (1 == seg_idx) { p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_FIRST; /* This is the first segment - the reported paylen is the total amount of data. */ if (p_send_ctx->is_sa_mad) { /* sa mad hdr sz */ paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; paylen += num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); } else { /* mad hdr sz */ paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; } } if (seg_idx == num_segs) { p_rmpp_mad->rmpp_flags |= IB_RMPP_FLAG_LAST; /* This is the last segment - the reported paylen is only the amount of data left on this segment. */ if (p_send_ctx->is_sa_mad) { paylen = p_send_ctx->mad_sz - IB_SA_MAD_HDR_SIZE; paylen -= (num_segs - 1) * IB_SA_DATA_SIZE; paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); } else { paylen = p_send_ctx->mad_sz - MAD_RMPP_HDR_SIZE; paylen -= (num_segs - 1) * (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE); } } p_rmpp_mad->rmpp_type = IB_RMPP_TYPE_DATA; p_rmpp_mad->rmpp_version = 1; p_rmpp_mad->paylen_newwin = cl_ntoh32(paylen); p_rmpp_mad->seg_num = cl_ntoh32(seg_idx); Exit: OSM_LOG_EXIT(p_send_ctx->p_log); return st; } ib_api_status_t osmv_rmpp_recv_ctx_init(osmv_rmpp_recv_ctx_t * p_ctx, osm_log_t * p_log) { ib_api_status_t st = IB_SUCCESS; CL_ASSERT(p_ctx); p_ctx->is_sa_mad = FALSE; p_ctx->p_rbuf = malloc(sizeof(cl_qlist_t)); if (p_ctx->p_rbuf) { memset(p_ctx->p_rbuf, 0, sizeof(cl_qlist_t)); cl_qlist_init(p_ctx->p_rbuf); p_ctx->expected_seg = 1; } else st = IB_INSUFFICIENT_MEMORY; p_ctx->p_log = p_log; return st; } void osmv_rmpp_recv_ctx_done(IN osmv_rmpp_recv_ctx_t * p_ctx) { cl_list_item_t *p_list_item; cl_list_obj_t *p_obj; CL_ASSERT(p_ctx); /* go over all the items in the list and remove them */ p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); while (p_list_item != cl_qlist_end(p_ctx->p_rbuf)) { p_obj = PARENT_STRUCT(p_list_item, cl_list_obj_t, list_item); free(cl_qlist_obj(p_obj)); free(p_obj); p_list_item = cl_qlist_remove_head(p_ctx->p_rbuf); } osmv_rmpp_sar_done(&p_ctx->sar); free(p_ctx->p_rbuf); free(p_ctx); } ib_api_status_t osmv_rmpp_recv_ctx_store_mad_seg(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN void *p_mad) { cl_list_obj_t *p_obj = NULL; void *p_list_mad; OSM_LOG_ENTER(p_recv_ctx->p_log); CL_ASSERT(p_recv_ctx); p_list_mad = malloc(MAD_BLOCK_SIZE); if (NULL == p_list_mad) { return IB_INSUFFICIENT_MEMORY; } memset(p_list_mad, 0, MAD_BLOCK_SIZE); memcpy(p_list_mad, p_mad, MAD_BLOCK_SIZE); p_obj = malloc(sizeof(cl_list_obj_t)); if (NULL == p_obj) { free(p_list_mad); return IB_INSUFFICIENT_MEMORY; } memset(p_obj, 0, sizeof(cl_list_obj_t)); cl_qlist_set_obj(p_obj, p_list_mad); cl_qlist_insert_tail(p_recv_ctx->p_rbuf, &p_obj->list_item); if (osmv_mad_is_sa((ib_mad_t *) p_mad)) { p_recv_ctx->is_sa_mad = TRUE; } return IB_SUCCESS; } uint32_t osmv_rmpp_recv_ctx_get_cur_byte_num(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) { uint32_t num_segs; num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); if (p_recv_ctx->is_sa_mad) return ((num_segs * IB_SA_DATA_SIZE) + IB_SA_MAD_HDR_SIZE); else return ((num_segs * MAD_RMPP_DATA_SIZE) + MAD_RMPP_HDR_SIZE); } uint32_t osmv_rmpp_recv_ctx_get_byte_num_from_first(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) { cl_list_item_t *p_item; cl_list_obj_t *p_obj; void *p_list_mad; uint32_t num_bytes, num_segs; p_item = cl_qlist_head(p_recv_ctx->p_rbuf); p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); p_list_mad = cl_qlist_obj(p_obj); /* mad data sz */ num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); if (0 != num_bytes) { if (p_recv_ctx->is_sa_mad) { /* sa mad hdr sz */ num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); num_bytes -= num_segs * (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); num_bytes += IB_SA_MAD_HDR_SIZE; } else { /* mad hdr sz */ num_bytes += MAD_RMPP_HDR_SIZE; } } return num_bytes; } uint32_t osmv_rmpp_recv_ctx_get_byte_num_from_last(IN osmv_rmpp_recv_ctx_t * p_recv_ctx) { cl_list_item_t *p_item; cl_list_obj_t *p_obj; void *p_list_mad; uint32_t num_bytes, num_segs; p_item = cl_qlist_tail(p_recv_ctx->p_rbuf); p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); p_list_mad = cl_qlist_obj(p_obj); /* mad data sz */ num_segs = cl_qlist_count(p_recv_ctx->p_rbuf); num_bytes = cl_ntoh32(((ib_rmpp_mad_t *) p_list_mad)->paylen_newwin); if (0 != num_bytes) { if (p_recv_ctx->is_sa_mad) { /* sa mad hdr sz */ num_bytes += MAD_RMPP_HDR_SIZE; num_bytes += (num_segs - 1) * IB_SA_DATA_SIZE; } else { /* mad hdr sz */ num_bytes += MAD_RMPP_HDR_SIZE; num_bytes += (num_segs - 1) * MAD_RMPP_DATA_SIZE; } } return num_bytes; } /* assuming that the last rmpp pkt arrived so that data member: total_bytes has the right value */ ib_api_status_t osmv_rmpp_recv_ctx_reassemble_arbt_mad(IN osmv_rmpp_recv_ctx_t * p_recv_ctx, IN uint32_t size, IN void *p_arbt_mad) { ib_api_status_t st = IB_SUCCESS; CL_ASSERT(p_recv_ctx); st = osmv_rmpp_sar_init(&p_recv_ctx->sar, p_arbt_mad, size, p_recv_ctx->is_sa_mad); if (st != IB_SUCCESS) { return st; } st = osmv_rmpp_sar_reassemble_arbt_mad(&p_recv_ctx->sar, p_recv_ctx->p_rbuf); osmv_rmpp_sar_done(&p_recv_ctx->sar); return st; } opensm-3.3.20/libvendor/osm_vendor_mlx_sar.c0000644000205000001450000001077312104655724016056 00000000000000/* * 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include ib_api_status_t osmv_rmpp_sar_init(osmv_rmpp_sar_t * p_sar, void *p_arbt_mad, uint32_t mad_size, boolean_t is_sa_mad) { CL_ASSERT(p_sar); p_sar->p_arbt_mad = p_arbt_mad; if (is_sa_mad) { p_sar->data_len = mad_size - IB_SA_MAD_HDR_SIZE; p_sar->hdr_sz = IB_SA_MAD_HDR_SIZE; p_sar->data_sz = IB_SA_DATA_SIZE; } else { p_sar->data_len = mad_size - MAD_RMPP_HDR_SIZE; p_sar->hdr_sz = MAD_RMPP_HDR_SIZE; p_sar->data_sz = MAD_RMPP_DATA_SIZE; } return IB_SUCCESS; } void osmv_rmpp_sar_done(osmv_rmpp_sar_t * p_sar) { p_sar->p_arbt_mad = NULL; } /* the big mad should be with mad header, rmpp header ( &sa hdr) space */ ib_api_status_t osmv_rmpp_sar_get_mad_seg(IN osmv_rmpp_sar_t * p_sar, IN uint32_t seg_idx, OUT void *p_buf) { void *p_seg; uint32_t sz_left; uint32_t num_segs; CL_ASSERT(p_sar); num_segs = p_sar->data_len / p_sar->data_sz; if ((p_sar->data_len % p_sar->data_sz) > 0) { num_segs++; } if ((seg_idx > num_segs) && (seg_idx != 1)) { return IB_NOT_FOUND; } /* cleanup */ memset(p_buf, 0, MAD_BLOCK_SIZE); /* attach header */ memcpy(p_buf, p_sar->p_arbt_mad, p_sar->hdr_sz); /* fill data */ p_seg = (char *)p_sar->p_arbt_mad + p_sar->hdr_sz + ((seg_idx - 1) * p_sar->data_sz); sz_left = p_sar->data_len - ((seg_idx - 1) * p_sar->data_sz); if (sz_left > p_sar->data_sz) memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg, p_sar->data_sz); else memcpy((char *)p_buf + p_sar->hdr_sz, (char *)p_seg, sz_left); return IB_SUCCESS; } /* turns a list of mads to one big mad - including header */ /* ALSO - deallocates the list */ ib_api_status_t osmv_rmpp_sar_reassemble_arbt_mad(osmv_rmpp_sar_t * p_sar, cl_qlist_t * p_bufs) { void *buf_tmp, *p_mad; cl_list_item_t *p_item; cl_list_obj_t *p_obj; uint32_t space_left = p_sar->data_len + p_sar->hdr_sz; CL_ASSERT(p_sar); CL_ASSERT(FALSE == cl_is_qlist_empty(p_bufs)); /* attach header */ p_mad = p_sar->p_arbt_mad; p_item = cl_qlist_head(p_bufs); p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); buf_tmp = cl_qlist_obj(p_obj); memcpy(p_mad, buf_tmp, p_sar->hdr_sz); p_mad = (char *)p_mad + p_sar->hdr_sz; space_left -= p_sar->hdr_sz; /* reassemble data */ while (FALSE == cl_is_qlist_empty(p_bufs)) { p_item = cl_qlist_remove_head(p_bufs); p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); buf_tmp = cl_qlist_obj(p_obj); if (FALSE == cl_is_qlist_empty(p_bufs)) { memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz, p_sar->data_sz); p_mad = (char *)p_mad + p_sar->data_sz; space_left -= p_sar->data_sz; } else { /* the last mad on the list */ memcpy((char *)p_mad, (char *)buf_tmp + p_sar->hdr_sz, space_left); p_mad = (char *)p_mad + space_left; } free(buf_tmp); free(p_obj); } return IB_SUCCESS; } opensm-3.3.20/libvendor/osm_vendor_mlx_sender.c0000644000205000001450000002611512104655724016546 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include static ib_api_status_t __osmv_rmpp_send_segment(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN uint32_t seg_num); /****d* OSM Vendor/osmv_simple_send_madw * NAME * osmv_simple_send_madw * * DESCRIPTION * Send a single MAD (256 bytes). * * If this MAD requires a response, set the timeout event. * The function call returns when the MAD's send completion is received. * */ ib_api_status_t osmv_simple_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_retry) { ib_api_status_t ret; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_mad_addr_t *p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); uint8_t mad_buf[MAD_BLOCK_SIZE]; ib_mad_t *p_mad = (ib_mad_t *) mad_buf; uint64_t key = 0; OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(p_madw->mad_size <= MAD_BLOCK_SIZE); memset(p_mad, 0, MAD_BLOCK_SIZE); memcpy(p_mad, osm_madw_get_mad_ptr(p_madw), p_madw->mad_size); if (NULL != p_txn) { /* Push a fake txn id to the MAD */ key = osmv_txn_get_key(p_txn); p_mad->trans_id = cl_hton64(key); } /* Add call for packet drop randomizer. This is a testing feature. If run_randomizer flag is set to TRUE, the randomizer will be called, and randomally will drop a packet. This is used for simulating unstable fabric. */ if (p_bo->p_vendor->run_randomizer == TRUE) { /* Try the randomizer */ if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log, p_bo->p_vendor-> p_pkt_randomizer, p_mad) == TRUE) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The MAD will not be sent. \n"); ret = IB_SUCCESS; } else { ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr); } } else { ret = osmv_transport_mad_send(h_bind, p_mad, p_mad_addr); } if ((IB_SUCCESS == ret) && (NULL != p_txn) && (!is_retry)) { /* Set the timeout for receiving the response MAD */ ret = osmv_txn_set_timeout_ev(h_bind, key, p_bo->p_vendor->resp_timeout); } OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; } /***** OSM Vendor/osmv_rmpp_send_madw * NAME * osmv_rmpp_send_madw * * DESCRIPTION * Send a single message (MAD wrapper of arbitrary length). * Follow the RMPP semantics * (segmentation, send window, timeouts etc). * * The function call returns either when the whole message * has been acknowledged, or upon error. * * ASSUMPTIONS * The RMPP sender context is set up */ ib_api_status_t osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds) { ib_api_status_t ret = IB_SUCCESS; uint32_t i, total_segs; osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx); CL_ASSERT(total_segs >= 1); /* In the double-sided transfer, wait for ACK 0 */ for (;;) { if (p_send_ctx->window_first > total_segs) { /* Every segment is acknowledged */ break; } /* Send the next burst. */ for (i = p_send_ctx->window_first; i <= p_send_ctx->window_last; i++) { /* Send a segment and setup a timeout timer */ ret = __osmv_rmpp_send_segment(h_bind, p_txn, i); if (IB_SUCCESS != ret) { goto send_done; } } /* Set the Response Timeout for the ACK on the last DATA segment */ ret = osmv_txn_set_timeout_ev(h_bind, osmv_txn_get_key(p_txn), p_bo->p_vendor->resp_timeout); if (IB_SUCCESS != ret) { goto send_done; } /* Going to sleep. Let the others access the transaction DB */ osmv_txn_unlock(p_bo); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP Sender thread (madw=%p) going to sleep ...\n", p_madw); /* Await the next event to happen */ cl_event_wait_on(&p_send_ctx->event, EVENT_NO_TIMEOUT, TRUE /* interruptible */ ); /* Got a signal from the MAD dispatcher/timeout handler */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP Sender thread (madw=%p) waking up on a signal ...\n", p_madw); /* Let's see what changed... Make this atomic - re-acquire the lock. */ osmv_txn_lock(p_bo); if (TRUE == p_bo->is_closing) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_rmpp_send_madw: ERR 6601: " "The bind handle %p is being closed. " "Stopping the RMPP Send of MADW %p\n", h_bind, p_madw); ret = IB_TIMEOUT; return IB_INTERRUPTED; } /* STOP? ABORT? TIMEOUT? */ if (IB_SUCCESS != p_send_ctx->status) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_rmpp_send_madw: ERR 6602: " "An error (%s) happened during the RMPP send of %p. Bailing out.\n", ib_get_err_str(p_send_ctx->status), p_madw); ret = p_send_ctx->status; goto send_done; } } if (TRUE == is_rmpp_ds) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Double-sided RMPP - switching to be the receiver.\n"); ret = osmv_txn_init_rmpp_receiver(h_bind, p_txn, FALSE /*Send was initiated by me */ ); if (IB_SUCCESS == ret) { /* Send ACK on the 0 segment */ ret = __osmv_rmpp_send_segment(h_bind, p_txn, 0); } } send_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; } /* * NAME osmv_rmpp_send_ack * * DESCRIPTION * */ ib_api_status_t osmv_rmpp_send_ack(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN uint32_t seg_num, IN uint32_t nwl, IN const osm_mad_addr_t * p_mad_addr) { uint8_t resp_mad[MAD_BLOCK_SIZE]; ib_rmpp_mad_t *p_resp_mad = (ib_rmpp_mad_t *) resp_mad; #ifdef OSMV_RANDOM_DROP if (TRUE == osmv_random_drop()) { osm_log(((osmv_bind_obj_t *) h_bind)->p_vendor->p_log, OSM_LOG_DEBUG, "Error injection - dropping the RMPP ACK\n"); return IB_SUCCESS; } #endif memcpy(p_resp_mad, p_req_mad, MAD_BLOCK_SIZE); p_resp_mad->common_hdr.method = osmv_invert_method(p_req_mad->method); p_resp_mad->rmpp_type = IB_RMPP_TYPE_ACK; p_resp_mad->seg_num = cl_hton32(seg_num); p_resp_mad->paylen_newwin = cl_hton32(nwl); p_resp_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; return osmv_transport_mad_send(h_bind, p_resp_mad, p_mad_addr); } /* * NAME osmv_rmpp_send_nak * * DESCRIPTION Send the RMPP ABORT or STOP packet */ ib_api_status_t osmv_rmpp_send_nak(IN osm_bind_handle_t h_bind, IN const ib_mad_t * p_req_mad, IN const osm_mad_addr_t * p_mad_addr, IN uint8_t nak_type, IN uint8_t status) { uint8_t resp_mad[MAD_BLOCK_SIZE]; ib_rmpp_mad_t *p_resp_mad = (ib_rmpp_mad_t *) resp_mad; memcpy(p_resp_mad, p_req_mad, MAD_BLOCK_SIZE); p_resp_mad->common_hdr.method = osmv_invert_method(p_req_mad->method); p_resp_mad->rmpp_type = nak_type; p_resp_mad->rmpp_status = status; return osmv_transport_mad_send(h_bind, p_resp_mad, p_mad_addr); } /* * NAME __osmv_rmpp_send_segment * * DESCRIPTION Build a MAD for a specific segment and send it */ static ib_api_status_t __osmv_rmpp_send_segment(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN uint32_t seg_num) { ib_api_status_t ret; osmv_rmpp_send_ctx_t *p_send_ctx; uint8_t mad_buf[MAD_BLOCK_SIZE]; ib_mad_t *p_mad = (ib_mad_t *) mad_buf; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_mad_addr_t *p_mad_addr = osm_madw_get_mad_addr_ptr(osmv_txn_get_madw(p_txn)); uint32_t timeout = p_bo->p_vendor->resp_timeout; uint64_t key; OSM_LOG_ENTER(p_bo->p_vendor->p_log); #ifdef OSMV_RANDOM_DROP if (TRUE == osmv_random_drop()) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Error injection - simulating the RMPP segment drop\n"); return IB_SUCCESS; } #endif p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); key = osmv_txn_get_key(p_txn); if (0 != seg_num) { ret = osmv_rmpp_send_ctx_get_seg(p_send_ctx, seg_num, timeout, p_mad); CL_ASSERT(IB_SUCCESS == ret); /* Put the segment to the wire ! */ p_mad->trans_id = cl_hton64(key); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Sending RMPP segment #%d, on-wire TID=0x%" PRIx64 "\n", seg_num, p_mad->trans_id); /* Add call for packet drop randomizer. This is a testing feature. If run_randomizer flag is set to TRUE, the randomizer will be called, and randomally will drop a packet. This is used for simulating unstable fabric. */ if (p_bo->p_vendor->run_randomizer == TRUE) { /* Try the randomizer */ if (osm_pkt_randomizer_mad_drop(p_bo->p_vendor->p_log, p_bo->p_vendor-> p_pkt_randomizer, p_mad) == TRUE) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "The MAD will not be sent. \n"); ret = IB_SUCCESS; } else { ret = osmv_transport_mad_send((osm_bind_handle_t) p_bo, p_mad, p_mad_addr); } } else { ret = osmv_transport_mad_send((osm_bind_handle_t) p_bo, p_mad, p_mad_addr); } } else { /* This is an ACK for double-sided handshake. Give it a special treatment. */ /* It doesn't really matter which data to put. Only the header matters. */ ret = osmv_rmpp_send_ctx_get_seg(p_send_ctx, 1, timeout, p_mad); CL_ASSERT(IB_SUCCESS == ret); p_mad->trans_id = cl_hton64(key); ret = osmv_rmpp_send_ack((osm_bind_handle_t) p_bo, p_mad, 0 /* segnum */ , OSMV_RMPP_RECV_WIN /* NWL */ , p_mad_addr); } OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; } opensm-3.3.20/libvendor/osm_vendor_mlx_ts.c0000644000205000001450000003430412104655724015713 00000000000000/* * Copyright (c) 2004-2008 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. * */ /* AUTHOR Edward Bortnikov * * DESCRIPTION * The lower-level MAD transport interface implementation * that allows sending a single MAD/receiving a callback * when a single MAD is received. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _osmv_TOPSPIN_transport_mgr_ { int device_fd; osm_ts_user_mad_filter filter; cl_thread_t receiver; } osmv_TOPSPIN_transport_mgr_t; static void __osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend, IN struct ib_mad *p_mad, IN uint8_t is_smi, OUT osm_mad_addr_t * p_mad_addr); static void __osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr, IN uint8_t is_smi, OUT struct ib_mad *p_mad); void __osmv_TOPSPIN_receiver_thr(void *p_ctx) { int ts_ret_code; struct ib_mad mad; osm_mad_addr_t mad_addr; osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_bo->p_vendor->p_log); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; /* we set the type of cancelation for this thread */ /* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); */ while (1) { /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; /* we read one mad at a time and pass it to the read callback function */ ts_ret_code = read(((osmv_TOPSPIN_transport_mgr_t *) (p_bo-> p_transp_mgr))-> device_fd, &mad, sizeof(mad)); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; if (ts_ret_code != sizeof(mad)) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_TOPSPIN_receiver_thr: ERR 6803: " "error with read, bytes = %d, errno = %d\n", ts_ret_code, errno); break; } else { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_TOPSPIN_receiver_thr: " "MAD QPN:%d SLID:0x%04x class:0x%02x " "method:0x%02x attr:0x%04x status:0x%04x " "tid:0x%016" PRIx64 "\n", mad.dqpn, cl_ntoh16(mad.slid), mad.mgmt_class, mad.r_method, cl_ntoh16(mad.attribute_id), cl_ntoh16(mad.status), cl_ntoh64(mad.transaction_id)); /* first arrange an address */ __osmv_TOPSPIN_mad_addr_to_osm_addr(p_bo->p_vendor, &mad, (((ib_mad_t *) & mad)-> mgmt_class == IB_MCLASS_SUBN_LID) || (((ib_mad_t *) & mad)-> mgmt_class == IB_MCLASS_SUBN_DIR), &mad_addr); /* call the receiver callback */ status = osmv_dispatch_mad((osm_bind_handle_t) p_bo, (void *)&mad, &mad_addr); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; if (IB_INTERRUPTED == status) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_TOPSPIN_receiver_thr: " "The bind handle %p is being closed. " "Breaking the loop.\n", p_bo); break; } } } OSM_LOG_EXIT(p_bo->p_vendor->p_log); } /* * NAME * osmv_transport_init * * DESCRIPTION * Setup the MAD transport infrastructure (filters, callbacks etc). */ ib_api_status_t osmv_transport_init(IN osm_bind_info_t * p_info, IN char hca_id[VENDOR_HCA_MAXNAMES], IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo) { cl_status_t cl_st; char device_file[16]; int device_fd; int ts_ioctl_ret; osmv_TOPSPIN_transport_mgr_t *p_mgr = malloc(sizeof(osmv_TOPSPIN_transport_mgr_t)); int qpn; if (!p_mgr) { return IB_INSUFFICIENT_MEMORY; } memset(p_mgr, 0, sizeof(osmv_TOPSPIN_transport_mgr_t)); /* open TopSpin file device */ /* HACK: assume last char in hostid is the HCA index */ sprintf(device_file, "/dev/ts_ua%u", hca_idx); device_fd = open(device_file, O_RDWR); if (device_fd < 0) { fprintf(stderr, "Fatal: Fail to open the file:%s err:%d\n", device_file, errno); return IB_ERROR; } /* * Create the MAD filter on this file handle. */ p_mgr->filter.port = p_bo->port_num; p_mgr->filter.direction = TS_IB_MAD_DIRECTION_IN; p_mgr->filter.mask = TS_IB_MAD_FILTER_DIRECTION | TS_IB_MAD_FILTER_PORT | TS_IB_MAD_FILTER_QPN | TS_IB_MAD_FILTER_MGMT_CLASS; switch (p_info->mad_class) { case IB_MCLASS_SUBN_LID: case IB_MCLASS_SUBN_DIR: qpn = 0; p_mgr->filter.qpn = qpn; p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_LID; ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter); if (ts_ioctl_ret < 0) { return IB_ERROR; } p_mgr->filter.mgmt_class = IB_MCLASS_SUBN_DIR; ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter); if (ts_ioctl_ret < 0) { return IB_ERROR; } break; case IB_MCLASS_SUBN_ADM: default: qpn = 1; p_mgr->filter.qpn = qpn; p_mgr->filter.mgmt_class = p_info->mad_class; ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSMADFILTADD, &p_mgr->filter); if (ts_ioctl_ret < 0) { return IB_ERROR; } break; } p_mgr->device_fd = device_fd; p_bo->p_transp_mgr = p_mgr; /* Initialize the magic_ptr to the pointer of the p_bo info. This will be used to signal when the object is being destroyed, so no real action will be done then. */ p_bo->magic_ptr = p_bo; /* init receiver thread */ cl_st = cl_thread_init(&p_mgr->receiver, __osmv_TOPSPIN_receiver_thr, (void *)p_bo, "osmv TOPSPIN rcv thr"); return (ib_api_status_t) cl_st; } /* * NAME * osmv_transport_send_mad * * DESCRIPTION * Send a single MAD (256 byte) */ ib_api_status_t osmv_transport_mad_send(IN const osm_bind_handle_t h_bind, IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; struct ib_mad ts_mad; int ret; ib_api_status_t status; const ib_mad_t *p_mad_hdr = p_mad; OSM_LOG_ENTER(p_vend->p_log); memset(&ts_mad, 0, sizeof(ts_mad)); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return IB_INVALID_CALLBACK; /* * Copy the MAD over to the sent mad */ memcpy(&ts_mad, p_mad_hdr, MAD_BLOCK_SIZE); /* * For all sends other than directed route SM MADs, * acquire an address vector for the destination. */ if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) { __osmv_TOPSPIN_osm_addr_to_mad_addr(p_mad_addr, p_mad_hdr->mgmt_class == IB_MCLASS_SUBN_LID, &ts_mad); } else { /* is a directed route - we need to construct a permissive address */ /* we do not need port number since it is part of the mad_hndl */ ts_mad.dlid = IB_LID_PERMISSIVE; ts_mad.slid = IB_LID_PERMISSIVE; ts_mad.sqpn = 0; ts_mad.dqpn = 0; } ts_mad.port = p_bo->port_num; osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_mad_send: " "Sending QPN:%d DLID:0x%04x class:0x%02x " "method:0x%02x attr:0x%04x status:0x%04x " "tid:0x%016" PRIx64 "\n", ts_mad.dqpn, cl_ntoh16(ts_mad.dlid), ts_mad.mgmt_class, ts_mad.r_method, cl_ntoh16(ts_mad.attribute_id), cl_ntoh16(ts_mad.status), cl_ntoh64(ts_mad.transaction_id) ); /* send it */ ret = write(((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))-> device_fd, &ts_mad, sizeof(ts_mad)); if (ret != sizeof(ts_mad)) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osmv_transport_mad_send: ERR 6804: " "Error sending mad (%d).\n", ret); status = IB_ERROR; goto Exit; } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } /* register a new mad type to the opened device file and send a mad through - the main idea is to make the filter catch it such that the read unblocks */ void __osm_transport_gen_dummy_mad(osmv_bind_obj_t * p_bo) { struct ib_mad ts_mad; osmv_TOPSPIN_transport_mgr_t *p_mgr = (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr); struct ib_get_port_info_ioctl port_data; int ts_ioctl_ret; /* prepare the mad fields following the stored filter on the bind */ memset(&ts_mad, 0, sizeof(ts_mad)); ts_mad.format_version = 1; ts_mad.mgmt_class = p_mgr->filter.mgmt_class; ts_mad.attribute_id = 0x2; ts_mad.class_version = 1; ts_mad.r_method = cl_ntoh16(0x2); ts_mad.port = p_bo->port_num; ts_mad.sqpn = p_mgr->filter.qpn; ts_mad.dqpn = p_mgr->filter.qpn; ts_mad.slid = 0xffff; /* we must send to our local lid ... */ port_data.port = p_bo->port_num; ts_ioctl_ret = ioctl(p_mgr->device_fd, TS_IB_IOCGPORTINFO, &port_data); ts_mad.dlid = port_data.port_info.lid; ts_mad.transaction_id = 0x9999; write(p_mgr->device_fd, &ts_mad, sizeof(ts_mad)); } void osmv_transport_done(IN const osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osmv_TOPSPIN_transport_mgr_t *p_tpot_mgr = (osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr); CL_ASSERT(p_bo); /* First of all - zero out the magic_ptr, so if a callback is called - it'll know that we are currently closing down, and will not handle the mad. */ p_bo->magic_ptr = 0; /* usleep(3000000); */ /* seems the only way to abort a blocking read is to make it read something */ __osm_transport_gen_dummy_mad(p_bo); cl_thread_destroy(&(p_tpot_mgr->receiver)); free(p_tpot_mgr); } static void __osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr, IN uint8_t is_smi, OUT struct ib_mad *p_mad) { /* For global destination or Multicast address: */ p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid); p_mad->sl = p_mad_addr->addr_type.gsi.service_level; if (is_smi) { p_mad->sqpn = 0; p_mad->dqpn = 0; } else { p_mad->sqpn = 1; p_mad->dqpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp); } /* HACK we limit to the first PKey Index assuming it will always be the default PKey */ p_mad->pkey_index = 0; } static void __osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend, IN struct ib_mad *p_mad, IN uint8_t is_smi, OUT osm_mad_addr_t * p_mad_addr) { p_mad_addr->dest_lid = cl_hton16(p_mad->slid); p_mad_addr->static_rate = 0; p_mad_addr->path_bits = 0; if (is_smi) { /* SMI */ p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid); p_mad_addr->addr_type.smi.port_num = p_mad->port; } else { /* GSI */ p_mad_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_mad->sqpn); p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY; /* There is a TAVOR limitation that only one P_KEY is supported per */ /* QP - so QP1 must use IB_DEFAULT_PKEY */ p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index; p_mad_addr->addr_type.gsi.service_level = p_mad->sl; p_mad_addr->addr_type.gsi.global_route = FALSE; /* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */ /* if (p_mad_addr->addr_type.gsi.global_route) { p_mad_addr->addr_type.gsi.grh_info.ver_class_flow = ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version, p_rcv_desc->grh.traffic_class, p_rcv_desc->grh.flow_label); p_mad_addr->addr_type.gsi.grh_info.hop_limit = p_rcv_desc->grh.hop_limit; memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw, &p_rcv_desc->grh.sgid, sizeof(ib_net64_t)); memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw, p_rcv_desc->grh.dgid, sizeof(ib_net64_t)); } */ } } /* * NAME osm_vendor_set_sm * * DESCRIPTION Modifies the port info for the bound port to set the "IS_SM" bit * according to the value given (TRUE or FALSE). */ #if (defined(OSM_VENDOR_INTF_TS_NO_VAPI) || defined(OSM_VENDOR_INTF_TS)) void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; int ts_ioctl_ret; int device_fd = ((osmv_TOPSPIN_transport_mgr_t *) (p_bo->p_transp_mgr))->device_fd; struct ib_set_port_info_ioctl set_port_data; OSM_LOG_ENTER(p_vend->p_log); memset(&set_port_data, 0, sizeof(set_port_data)); set_port_data.port = p_bo->port_num; set_port_data.port_info.valid_fields = IB_PORT_IS_SM; set_port_data.port_info.is_sm = is_sm_val; ts_ioctl_ret = ioctl(device_fd, TS_IB_IOCSPORTINFO, &set_port_data); if (ts_ioctl_ret < 0) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_set_sm: ERR 6805: " "Unable set 'IS_SM' bit to:%u in port attributes (%d).\n", is_sm_val, ts_ioctl_ret); } OSM_LOG_EXIT(p_vend->p_log); } #endif opensm-3.3.20/libvendor/osm_vendor_mlx_txn.c0000644000205000001450000004401412104655724016075 00000000000000/* * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2009 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include static ib_api_status_t __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); static ib_api_status_t __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr, IN osmv_txn_ctx_t * p_txn, IN uint64_t key); static ib_api_status_t __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn); static void __osmv_txn_all_done(osm_bind_handle_t h_bind); static uint64_t __osmv_txn_timeout_cb(IN uint64_t key, IN uint32_t num_regs, IN void *cb_context); ib_api_status_t osmv_txn_init(IN osm_bind_handle_t h_bind, IN uint64_t tid, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) { ib_api_status_t st; osmv_txn_ctx_t *p_txn; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(NULL != h_bind && NULL != pp_txn); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Starting transaction 0x%016" PRIx64 " (key=0x%016" PRIx64 ")\n", tid, key); p_txn = malloc(sizeof(osmv_txn_ctx_t)); if (!p_txn) { return IB_INSUFFICIENT_MEMORY; } memset(p_txn, 0, sizeof(osmv_txn_ctx_t)); p_txn->p_log = p_bo->txn_mgr.p_log; p_txn->tid = tid; p_txn->key = key; p_txn->p_madw = NULL; p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_NONE; /* insert into transaction manager DB */ st = __osmv_txnmgr_insert_txn(&p_bo->txn_mgr, p_txn, key); if (IB_SUCCESS != st) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_txn_init: ERR 6703: " "Failed to insert to transaction 0x%016" PRIx64 " (key=0x%016" PRIx64 ") to manager DB\n", tid, key); goto insert_txn_failed; } *pp_txn = p_txn; OSM_LOG_EXIT(p_bo->p_vendor->p_log); return IB_SUCCESS; insert_txn_failed: free(p_txn); OSM_LOG_EXIT(p_bo->p_vendor->p_log); return st; } ib_api_status_t osmv_txn_init_rmpp_sender(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN osm_madw_t * p_madw) { ib_api_status_t st; CL_ASSERT(p_txn); /* Double-Sided RMPP Direction Switch */ osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn)); p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_SENDER; p_txn->rmpp_txfr.p_rmpp_send_ctx = malloc(sizeof(osmv_rmpp_send_ctx_t)); if (!p_txn->rmpp_txfr.p_rmpp_send_ctx) { return IB_INSUFFICIENT_MEMORY; } memset(p_txn->rmpp_txfr.p_rmpp_send_ctx, 0, sizeof(osmv_rmpp_send_ctx_t)); st = osmv_rmpp_send_ctx_init(p_txn->rmpp_txfr.p_rmpp_send_ctx, (void *)p_madw->p_mad, p_madw->mad_size, p_txn->p_log); return st; } ib_api_status_t osmv_txn_init_rmpp_receiver(IN osm_bind_handle_t h_bind, IN osmv_txn_ctx_t * p_txn, IN boolean_t is_init_by_peer) { ib_api_status_t st; osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; uint64_t key = osmv_txn_get_key(p_txn); CL_ASSERT(p_txn); /* Double-Sided RMPP Direction Switch */ osmv_txn_remove_timeout_ev(h_bind, key); /* Set the Transaction Timeout value */ st = osmv_txn_set_timeout_ev(h_bind, key, p_bo->p_vendor->ttime_timeout); if (IB_SUCCESS != st) { return st; } p_txn->rmpp_txfr.rmpp_state = OSMV_TXN_RMPP_RECEIVER; p_txn->rmpp_txfr.is_rmpp_init_by_peer = is_init_by_peer; p_txn->rmpp_txfr.p_rmpp_recv_ctx = malloc(sizeof(osmv_rmpp_recv_ctx_t)); if (!p_txn->rmpp_txfr.p_rmpp_recv_ctx) { osmv_txn_remove_timeout_ev(h_bind, key); return IB_INSUFFICIENT_MEMORY; } memset(p_txn->rmpp_txfr.p_rmpp_recv_ctx, 0, sizeof(osmv_rmpp_recv_ctx_t)); st = osmv_rmpp_recv_ctx_init(p_txn->rmpp_txfr.p_rmpp_recv_ctx, p_txn->p_log); return st; } /* * NAME * osmv_txn_set_timeout_ev * * DESCRIPTION * * SEE ALSO * */ ib_api_status_t osmv_txn_set_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key, IN uint64_t msec) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; cl_event_wheel_t *p_event_wheel = p_bo->txn_mgr.p_event_wheel; cl_status_t status; status = cl_event_wheel_reg(p_event_wheel, key, cl_get_time_stamp() + 1000 * msec, /* TTL */ __osmv_txn_timeout_cb, p_bo /* The context */ ); return (ib_api_status_t) status; } /* * NAME * osmv_txn_remove_timeout_ev * * DESCRIPTION * SEE ALSO * */ void osmv_txn_remove_timeout_ev(IN osm_bind_handle_t h_bind, IN uint64_t key) { cl_event_wheel_t *p_event_wheel = ((osmv_bind_obj_t *) h_bind)->txn_mgr.p_event_wheel; cl_event_wheel_unreg(p_event_wheel, key); } void osmv_txn_done(IN osm_bind_handle_t h_bind, IN uint64_t key, IN boolean_t is_in_cb) { osmv_txn_ctx_t *p_ctx; osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) h_bind; OSM_LOG_ENTER(p_bo->p_vendor->p_log); CL_ASSERT(h_bind); /* Cancel the (single) timeout possibly outstanding for this txn * Don't do this if you are in the callback context, for 2 reasons: * (1) The event wheel will remove the context itself. * (2) If we try to, there is a deadlock in the event wheel */ if (FALSE == is_in_cb) { osmv_txn_remove_timeout_ev(h_bind, key); } /* Remove from DB */ if (IB_NOT_FOUND == __osmv_txnmgr_remove_txn(&p_bo->txn_mgr, key, &p_ctx)) { return; } /* Destroy the transaction's RMPP contexts * (can be more than one in the case of double sided transfer) */ if (p_ctx->rmpp_txfr.p_rmpp_send_ctx) { osmv_rmpp_send_ctx_done(p_ctx->rmpp_txfr.p_rmpp_send_ctx); } if (p_ctx->rmpp_txfr.p_rmpp_recv_ctx) { osmv_rmpp_recv_ctx_done(p_ctx->rmpp_txfr.p_rmpp_recv_ctx); } free(p_ctx); OSM_LOG_EXIT(p_bo->p_vendor->p_log); } ib_api_status_t osmv_txn_lookup(IN osm_bind_handle_t h_bind, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) { return __osmv_txnmgr_lookup(&(((osmv_bind_obj_t *) h_bind)->txn_mgr), key, pp_txn); } void osmv_txn_abort_rmpp_txns(osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; cl_map_item_t *p_item; cl_map_obj_t *p_obj; osmv_txn_ctx_t *p_txn; osmv_rmpp_send_ctx_t *p_send_ctx; cl_qmap_t *p_map = p_bo->txn_mgr.p_txn_map; OSM_LOG_ENTER(p_bo->p_vendor->p_log); while (FALSE == cl_is_qmap_empty(p_map)) { p_item = cl_qmap_head(p_map); p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj); p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); if (NULL != p_send_ctx) { p_send_ctx->status = IB_INTERRUPTED; /* Wake up the sender thread to let it break out */ cl_event_signal(&p_send_ctx->event); } cl_qmap_remove_item(p_map, p_item); } OSM_LOG_EXIT(p_bo->p_vendor->p_log); } ib_api_status_t osmv_txnmgr_init(IN osmv_txn_mgr_t * p_tx_mgr, IN osm_log_t * p_log, IN cl_spinlock_t * p_lock) { cl_status_t cl_st = CL_SUCCESS; p_tx_mgr->p_event_wheel = malloc(sizeof(cl_event_wheel_t)); if (!p_tx_mgr->p_event_wheel) { return IB_INSUFFICIENT_MEMORY; } memset(p_tx_mgr->p_event_wheel, 0, sizeof(cl_event_wheel_t)); cl_event_wheel_construct(p_tx_mgr->p_event_wheel); /* NOTE! We are using an extended constructor. * We tell the Event Wheel run in a non-protected manner in the reg/unreg calls, * and acquire an external lock in the asynchronous callback. */ cl_st = cl_event_wheel_init_ex(p_tx_mgr->p_event_wheel, p_lock); if (cl_st != CL_SUCCESS) { free(p_tx_mgr->p_event_wheel); return (ib_api_status_t) cl_st; } p_tx_mgr->p_txn_map = malloc(sizeof(cl_qmap_t)); if (!p_tx_mgr->p_txn_map) { cl_event_wheel_destroy(p_tx_mgr->p_event_wheel); free(p_tx_mgr->p_event_wheel); return IB_INSUFFICIENT_MEMORY; } memset(p_tx_mgr->p_txn_map, 0, sizeof(cl_qmap_t)); cl_qmap_init(p_tx_mgr->p_txn_map); p_tx_mgr->p_log = p_log; return cl_st; } void osmv_txnmgr_done(IN osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; __osmv_txn_all_done(h_bind); free(p_bo->txn_mgr.p_txn_map); cl_event_wheel_destroy(p_bo->txn_mgr.p_event_wheel); free(p_bo->txn_mgr.p_event_wheel); } ib_api_status_t __osmv_txnmgr_lookup(IN osmv_txn_mgr_t * p_tx_mgr, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) { ib_api_status_t status = IB_SUCCESS; cl_map_item_t *p_item; cl_map_obj_t *p_obj; uint64_t tmp_key; OSM_LOG_ENTER(p_tx_mgr->p_log); CL_ASSERT(p_tx_mgr); CL_ASSERT(pp_txn); osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_lookup: " "Looking for key: 0x%016" PRIx64 " in map ptr:%p\n", key, p_tx_mgr->p_txn_map); p_item = cl_qmap_head(p_tx_mgr->p_txn_map); while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) { tmp_key = cl_qmap_key(p_item); osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_lookup: " "Found key 0x%016" PRIx64 "\n", tmp_key); p_item = cl_qmap_next(p_item); } p_item = cl_qmap_get(p_tx_mgr->p_txn_map, key); if (cl_qmap_end(p_tx_mgr->p_txn_map) == p_item) { status = IB_NOT_FOUND; } else { p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); *pp_txn = cl_qmap_obj(p_obj); } OSM_LOG_EXIT(p_tx_mgr->p_log); return status; } ib_api_status_t __osmv_txnmgr_insert_txn(IN osmv_txn_mgr_t * p_tx_mgr, IN osmv_txn_ctx_t * p_txn, IN uint64_t key) { cl_map_obj_t *p_obj = NULL; cl_map_item_t *p_item; uint64_t tmp_key; CL_ASSERT(p_tx_mgr); CL_ASSERT(p_txn); key = osmv_txn_get_key(p_txn); p_obj = malloc(sizeof(cl_map_obj_t)); if (NULL == p_obj) return IB_INSUFFICIENT_MEMORY; osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_insert_txn: " "Inserting key: 0x%016" PRIx64 " to map ptr:%p\n", key, p_tx_mgr->p_txn_map); memset(p_obj, 0, sizeof(cl_map_obj_t)); cl_qmap_set_obj(p_obj, p_txn); /* assuming lookup with this key was made and the result was IB_NOT_FOUND */ cl_qmap_insert(p_tx_mgr->p_txn_map, key, &p_obj->item); p_item = cl_qmap_head(p_tx_mgr->p_txn_map); while (p_item != cl_qmap_end(p_tx_mgr->p_txn_map)) { tmp_key = cl_qmap_key(p_item); osm_log(p_tx_mgr->p_log, OSM_LOG_DEBUG, "__osmv_txnmgr_insert_txn: " "Found key 0x%016" PRIx64 "\n", tmp_key); p_item = cl_qmap_next(p_item); } return IB_SUCCESS; } ib_api_status_t __osmv_txnmgr_remove_txn(IN osmv_txn_mgr_t * p_tx_mgr, IN uint64_t key, OUT osmv_txn_ctx_t ** pp_txn) { cl_map_obj_t *p_obj; cl_map_item_t *p_item; OSM_LOG_ENTER(p_tx_mgr->p_log); CL_ASSERT(p_tx_mgr); CL_ASSERT(pp_txn); p_item = cl_qmap_remove(p_tx_mgr->p_txn_map, key); if (p_item == cl_qmap_end(p_tx_mgr->p_txn_map)) { osm_log(p_tx_mgr->p_log, OSM_LOG_ERROR, "__osmv_txnmgr_remove_txn: ERR 6701: " "Could not remove the transaction 0x%016" PRIx64 " - " "something is really wrong!\n", key); OSM_LOG_EXIT(p_tx_mgr->p_log); return IB_NOT_FOUND; } p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); *pp_txn = cl_qmap_obj(p_obj); free(p_obj); OSM_LOG_EXIT(p_tx_mgr->p_log); return IB_SUCCESS; } void __osmv_txn_all_done(osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; cl_map_item_t *p_item; cl_map_obj_t *p_obj; osmv_txn_ctx_t *p_txn; OSM_LOG_ENTER(p_bo->p_vendor->p_log); p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map); while (p_item != cl_qmap_end(p_bo->txn_mgr.p_txn_map)) { p_obj = PARENT_STRUCT(p_item, cl_map_obj_t, item); p_txn = (osmv_txn_ctx_t *) cl_qmap_obj(p_obj); osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE); free(p_obj); /* assuming osmv_txn_done has removed the txn from the map */ p_item = cl_qmap_head(p_bo->txn_mgr.p_txn_map); } OSM_LOG_EXIT(p_bo->p_vendor->p_log); } /******************************************************************************/ void osmv_txn_lock(IN osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "--> Acquiring lock %p on bind handle %p\n", &p_bo->lock, p_bo); cl_spinlock_acquire(&p_bo->lock); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "--> Acquired lock %p on bind handle %p\n", &p_bo->lock, p_bo); } void osmv_txn_unlock(IN osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; cl_spinlock_t *p_lock = &p_bo->lock; osm_log_t *p_log = p_bo->p_vendor->p_log; osm_log(p_log, OSM_LOG_DEBUG, "<-- Releasing lock %p on bind handle %p\n", p_lock, p_bo); cl_spinlock_release(&p_bo->lock); /* We'll use the saved ptrs, since now the p_bo can be destroyed already */ osm_log(p_log, OSM_LOG_DEBUG, "<-- Released lock %p on bind handle %p\n", p_lock, p_bo); } static uint64_t __osmv_txn_timeout_cb(IN uint64_t key, IN uint32_t num_regs, IN void *cb_context) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) cb_context; uint64_t ret = 0; osmv_txn_ctx_t *p_txn; osmv_rmpp_send_ctx_t *p_send_ctx; osm_madw_t *p_madw = NULL; ib_mad_t *p_mad; osm_mad_addr_t *p_mad_addr; boolean_t invoke_err_cb = FALSE; OSM_LOG_ENTER(p_bo->p_vendor->p_log); /* Don't try to acquire a lock on the Bind Object - * it's taken by the mechanism that drives the timeout based events! * (Recall the special constructor that the Event Wheel is applied with) */ if (p_bo->is_closing) { goto txn_done; } ret = osmv_txn_lookup(p_bo, key, &p_txn); if (IB_NOT_FOUND == ret) { /* Prevent a race - the transaction is already destroyed */ goto txn_done; } p_madw = p_txn->p_madw; switch (osmv_txn_get_rmpp_state(p_txn)) { case OSMV_TXN_RMPP_NONE: if (num_regs <= OSM_DEFAULT_RETRY_COUNT) { /* We still did not exceed the limit of retransmissions. * Set the next timeout's value. */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_txn_timeout_cb: " "The transaction request (tid=0x%016" PRIx64 ")" " timed out %d times. Retrying the send.\n", osmv_txn_get_tid(p_txn), num_regs); /* resend this mad */ ret = osmv_simple_send_madw((osm_bind_handle_t *) p_bo, p_madw, p_txn, TRUE); if (ret != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_txn_timeout_cb: " "Fail to send retry for transaction" "request (tid=0x%016" PRIx64 ").\n", osmv_txn_get_tid(p_txn)); osmv_txn_done((osm_bind_handle_t) p_bo, key, TRUE /*in timeout callback */ ); /* This is a requester. Always apply the callback */ invoke_err_cb = TRUE; } else { uint64_t next_timeout_ms; next_timeout_ms = p_bo->p_vendor->resp_timeout * (num_regs + 1) * (num_regs + 1); /* when do we need to timeout again */ ret = cl_get_time_stamp() + (uint64_t) (1000 * next_timeout_ms); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_txn_timeout_cb: " "Retry request timout in : %lu [msec].\n", next_timeout_ms); } } else { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "__osmv_txn_timeout_cb: ERR 6702: " "The transaction request (0x%016" PRIx64 ") " "timed out (after %d retries). " "Invoking the error callback.\n", osmv_txn_get_tid(p_txn), num_regs); osmv_txn_done((osm_bind_handle_t) p_bo, key, TRUE /*in timeout callback */ ); /* This is a requester. Always apply the callback */ invoke_err_cb = TRUE; } break; case OSMV_TXN_RMPP_SENDER: osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "RMPP sender (tid=0x%016" PRIx64 ") did not receive ACK " "on every segment in the current send window.\n", osmv_txn_get_tid(p_txn)); p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn); if (num_regs <= OSM_DEFAULT_RETRY_COUNT) { /* We still did not exceed the limit of retransmissions. * Set the next timeout's value. */ ret = cl_get_time_stamp() + 1000 * p_bo->p_vendor->resp_timeout; } else { p_send_ctx->status = IB_TIMEOUT; p_mad = osm_madw_get_mad_ptr(p_madw); p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); /* Send an ABORT to the other side */ osmv_rmpp_send_nak((osm_bind_handle_t) p_bo, p_mad, p_mad_addr, IB_RMPP_TYPE_ABORT, IB_RMPP_STATUS_T2L); } /* Wake the RMPP sender thread up */ cl_event_signal(&p_send_ctx->event); break; case OSMV_TXN_RMPP_RECEIVER: osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "Transaction timeout on an RMPP receiver " "(tid=0x%016" PRIx64 "). Dropping the transaction.\n", osmv_txn_get_tid(p_txn)); osmv_txn_done((osm_bind_handle_t) p_bo, key, TRUE /*in timeout callback */ ); if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)) { /* This is a requester, still waiting for the reply. Apply the callback */ invoke_err_cb = TRUE; } break; default: CL_ASSERT(FALSE); } if (TRUE == invoke_err_cb) { CL_ASSERT(NULL != p_madw); /* update the status in the p_madw */ p_madw->status = IB_TIMEOUT; p_bo->send_err_cb(p_bo->cb_context, p_madw); /* no re-registration */ ret = 0; } txn_done: OSM_LOG_EXIT(p_bo->p_vendor->p_log); return ret; } opensm-3.3.20/libvendor/osm_vendor_mlx_sa.c0000644000205000001450000006201612104655724015671 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include /* this struct is the internal rep of the bind handle */ typedef struct _osmv_sa_bind_info { osm_bind_handle_t h_bind; osm_log_t *p_log; osm_vendor_t *p_vendor; osm_mad_pool_t *p_mad_pool; uint64_t port_guid; cl_event_t sync_event; uint64_t last_lids_update_sec; uint16_t lid; uint16_t sm_lid; } osmv_sa_bind_info_t; /* Call back on new mad received: We basically only need to set the context of the query. Or report an error. A pointer to the actual context of the request (a copy of the oriignal request structure) is attached as the p_madw->context.ni_context.node_guid */ static void __osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw, IN void *bind_context, IN osm_madw_t * p_req_madw) { osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context; osmv_query_req_t *p_query_req_copy = NULL; osmv_query_res_t query_res; ib_sa_mad_t *p_sa_mad; ib_net16_t mad_status; OSM_LOG_ENTER(p_bind->p_log); if (!p_req_madw) { OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG, "Ignoring a non-response mad\n"); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); goto Exit; } /* obtain the sent context */ p_query_req_copy = (osmv_query_req_t *) (p_req_madw->context.arb_context.context1); /* provide the context of the original request in the result */ query_res.query_context = p_query_req_copy->query_context; /* provide the resulting madw */ query_res.p_result_madw = p_madw; /* update the req fields */ p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad; /* if we got a remote error track it in the status */ mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK); if (mad_status != IB_SUCCESS) { OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 0501: " "Remote error:0x%04X\n", cl_ntoh16(mad_status)); query_res.status = IB_REMOTE_ERROR; } else query_res.status = IB_SUCCESS; /* what if we have got back an empty mad ? */ if (!p_madw->mad_size) { OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 0502: " "Got an empty mad\n"); query_res.status = IB_ERROR; } if (IB_SUCCESS == mad_status) { /* if we are in not in a method response of an rmpp nature we must get only 1 */ /* HACK: in the future we might need to be smarter for other methods... */ if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) { query_res.result_cnt = 1; } else { #ifndef VENDOR_RMPP_SUPPORT if (mad_status != IB_SUCCESS) query_res.result_cnt = 0; else query_res.result_cnt = 1; #else /* we used the offset value to calculate the number of records in here */ if (ib_get_attr_size(p_sa_mad->attr_offset) == 0) { query_res.result_cnt = 0; OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG, "Count = 0\n"); } else { query_res.result_cnt = (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) / ib_get_attr_size(p_sa_mad->attr_offset); OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG, "Count = %u = %zu / %u (%zu)\n", query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE, ib_get_attr_size(p_sa_mad->attr_offset), (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) % ib_get_attr_size(p_sa_mad->attr_offset)); } #endif } } query_res.query_type = p_query_req_copy->query_type; p_query_req_copy->pfn_query_cb(&query_res); if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) cl_event_signal(&p_bind->sync_event); Exit: /* free the copied query request if found */ if (p_query_req_copy) free(p_query_req_copy); /* put back the request madw */ if (p_req_madw) osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw); OSM_LOG_EXIT(p_bind->p_log); } /* Send Error Callback: Only report the error and get rid of the mad wrapper */ static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw) { osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context; osmv_query_req_t *p_query_req_copy = NULL; osmv_query_res_t query_res; OSM_LOG_ENTER(p_bind->p_log); /* Obtain the sent context etc */ p_query_req_copy = (osmv_query_req_t *) (p_madw->context.arb_context.context1); /* provide the context of the original request in the result */ query_res.query_context = p_query_req_copy->query_context; query_res.p_result_madw = p_madw; query_res.status = IB_TIMEOUT; query_res.result_cnt = 0; query_res.p_result_madw->status = IB_TIMEOUT; p_madw->status = IB_TIMEOUT; query_res.query_type = p_query_req_copy->query_type; p_query_req_copy->pfn_query_cb(&query_res); if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) cl_event_signal(&p_bind->sync_event); free(p_query_req_copy); OSM_LOG_EXIT(p_bind->p_log); } /***************************************************************************** This routine needs to be invoked on every send - since the SM LID and Local lid might change. To do that without any major perfoermance impact we cache the results and time they were obtained. Refresh only twice a minute. To avoid the need to use statics and risk a race - we require the refresh time to be stored in the context of the results. Also this coveres cases were we query for multiple guids. *****************************************************************************/ static ib_api_status_t __osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend, IN ib_net64_t port_guid, IN OUT uint64_t * p_lids_update_time_sec, OUT uint16_t * lid, OUT uint16_t * sm_lid) { ib_api_status_t status; ib_port_attr_t *p_attr_array; uint32_t num_ports; uint32_t port_num; OSM_LOG_ENTER(p_vend->p_log); /* use prevous values if current time is close enough to previous query */ if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30) { OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Using previously stored lid:0x%04x sm_lid:0x%04x\n", *lid, *sm_lid); status = IB_SUCCESS; goto Exit; } /* obtain the number of available ports */ num_ports = 0; status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports); if (status != IB_INSUFFICIENT_MEMORY) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 0503: " "Expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n", num_ports, cl_ntoh64(port_guid)); /* allocate the attributes */ p_attr_array = (ib_port_attr_t *) malloc(sizeof(ib_port_attr_t) * num_ports); /* obtain the attributes */ status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports); if (status != IB_SUCCESS) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 0504: " "Failed to get port attributes (error: %s)\n", ib_get_err_str(status)); free(p_attr_array); goto Exit; } status = IB_ERROR; /* find the port requested in the list */ for (port_num = 0; (port_num < num_ports) && (status == IB_ERROR); port_num++) { if (p_attr_array[port_num].port_guid == port_guid) { *lid = p_attr_array[port_num].lid; *sm_lid = p_attr_array[port_num].sm_lid; *p_lids_update_time_sec = cl_get_time_stamp_sec(); status = IB_SUCCESS; OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Found guid:0x%016" PRIx64 " with idx:%d\n", cl_ntoh64(port_guid), port_num); } } free(p_attr_array); Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } osm_bind_handle_t osmv_bind_sa(IN osm_vendor_t * const p_vend, IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid) { osm_bind_info_t bind_info; osm_log_t *p_log = p_vend->p_log; ib_api_status_t status = IB_SUCCESS; osmv_sa_bind_info_t *p_sa_bind_info; cl_status_t cl_status; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); bind_info.port_guid = port_guid; bind_info.mad_class = IB_MCLASS_SUBN_ADM; bind_info.class_version = 2; bind_info.is_responder = FALSE; bind_info.is_trap_processor = FALSE; bind_info.is_report_processor = FALSE; bind_info.send_q_size = 256; bind_info.recv_q_size = 256; /* allocate the new sa bind info */ p_sa_bind_info = (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t)); if (!p_sa_bind_info) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0505: " "Failed to allocate new bind structure\n"); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; goto Exit; } /* store some important context */ p_sa_bind_info->p_log = p_log; p_sa_bind_info->port_guid = port_guid; p_sa_bind_info->p_mad_pool = p_mad_pool; p_sa_bind_info->p_vendor = p_vend; p_sa_bind_info->last_lids_update_sec = 0; /* Bind to the lower level */ p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info); /* context provided to CBs */ if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) { free(p_sa_bind_info); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0506: " "Failed to bind to vendor GSI\n"); goto Exit; } /* obtain the sm_lid from the vendor */ status = __osmv_get_lid_and_sm_lid_by_port_guid(p_vend, port_guid, &p_sa_bind_info-> last_lids_update_sec, &p_sa_bind_info->lid, &p_sa_bind_info->sm_lid); if (status != IB_SUCCESS) { free(p_sa_bind_info); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0507: " "Failed to obtain the SM lid\n"); goto Exit; } /* initialize the sync_event */ cl_event_construct(&p_sa_bind_info->sync_event); cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE); if (cl_status != CL_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0508: " "cl_init_event failed: %s\n", ib_get_err_str(cl_status)); free(p_sa_bind_info); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; } Exit: OSM_LOG_EXIT(p_log); return (p_sa_bind_info); } /****t* OSM Vendor SA Client/osmv_sa_mad_data * NAME * osmv_sa_mad_data * * DESCRIPTION * Extra fields required to perform a mad query * This struct is passed to the actual send method * * SYNOPSIS */ typedef struct _osmv_sa_mad_data { /* MAD data. */ uint8_t method; ib_net16_t attr_id; ib_net16_t attr_offset; ib_net32_t attr_mod; ib_net64_t comp_mask; void *p_attr; } osmv_sa_mad_data_t; /* * method * The method of the mad to be sent * * attr_id * Attribute ID * * attr_offset * Offset as defined by RMPP * * attr_mod * Attribute modifier * * comp_mask * The component mask of the query * * p_attr * A pointer to the record of the attribute to be sent. * *****/ /* Send a MAD out on the GSI interface */ static ib_api_status_t __osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind, IN const osmv_sa_mad_data_t * const p_sa_mad_data, IN const osmv_query_req_t * const p_query_req) { ib_api_status_t status; ib_mad_t *p_mad_hdr; ib_sa_mad_t *p_sa_mad; osm_madw_t *p_madw; osm_log_t *p_log = p_bind->p_log; static atomic32_t trans_id; boolean_t sync; osmv_query_req_t *p_query_req_copy; uint32_t sa_size; OSM_LOG_ENTER(p_log); /* since the sm_lid might change we obtain it every send (actually it is cached in the bind object and refreshed every 30sec by this proc) */ status = __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor, p_bind->port_guid, &p_bind-> last_lids_update_sec, &p_bind->lid, &p_bind->sm_lid); if (status != IB_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0509: " "Failed to obtain the SM lid\n"); goto Exit; } /* Get a MAD wrapper for the send */ p_madw = osm_mad_pool_get(p_bind->p_mad_pool, p_bind->h_bind, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0510: " "Unable to acquire MAD\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } /* Initialize the Sent MAD: */ /* Initialize the MAD buffer for the send operation. */ p_mad_hdr = osm_madw_get_mad_ptr(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); /* Get a new transaction Id */ cl_atomic_inc(&trans_id); /* Cleanup the MAD from any residue */ memset(p_sa_mad, 0, MAD_BLOCK_SIZE); /* Initialize the standard MAD header. */ ib_mad_init_new(p_mad_hdr, /* mad pointer */ IB_MCLASS_SUBN_ADM, /* class */ (uint8_t) 2, /* version */ p_sa_mad_data->method, /* method */ cl_hton64((uint64_t) trans_id), /* tid */ p_sa_mad_data->attr_id, /* attr id */ p_sa_mad_data->attr_mod /* attr mod */); /* Set the query information. */ p_sa_mad->sm_key = p_query_req->sm_key; p_sa_mad->attr_offset = 0; p_sa_mad->comp_mask = p_sa_mad_data->comp_mask; if (p_sa_mad->comp_mask) { p_sa_mad_data->attr_offset ? (sa_size = ib_get_attr_size(p_sa_mad_data->attr_offset)) : (sa_size = IB_SA_DATA_SIZE); memcpy(p_sa_mad->data, p_sa_mad_data->p_attr, sa_size); } /* Provide the address to send to */ /* Patch to handle IBAL - host order , where it should take destination lid in network order */ #ifdef OSM_VENDOR_INTF_AL p_madw->mad_addr.dest_lid = p_bind->sm_lid; #else p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid); #endif p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid); p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1); p_madw->resp_expected = TRUE; p_madw->fail_msg = CL_DISP_MSGID_NONE; /* Provide MAD context such that the call back will know what to do. We have to keep the entire request structure so we know the CB. Since we can not rely on the client to keep it around until the response - we duplicate it and will later dispose it (in CB). To store on the MADW we cast it into what opensm has: p_madw->context.arb_context.context1 */ p_query_req_copy = malloc(sizeof(*p_query_req_copy)); if (!p_query_req_copy) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0511: " "Unable to acquire memory for query copy\n"); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } *p_query_req_copy = *p_query_req; p_madw->context.arb_context.context1 = p_query_req_copy; /* we can support async as well as sync calls */ sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC); /* send the mad asynchronously */ status = osm_vendor_send(osm_madw_get_bind_handle(p_madw), p_madw, p_madw->resp_expected); /* if synchronous - wait on the event */ if (sync) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n"); cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE); cl_event_reset(&p_bind->sync_event); status = p_madw->status; } Exit: OSM_LOG_EXIT(p_log); return status; } /* * Query the SA based on the user's request. */ ib_api_status_t osmv_query_sa(IN osm_bind_handle_t h_bind, IN const osmv_query_req_t * const p_query_req) { union { ib_service_record_t svc_rec; ib_node_record_t node_rec; ib_portinfo_record_t port_info; ib_path_rec_t path_rec; #ifdef DUAL_SIDED_RMPP ib_multipath_rec_t multipath_rec; #endif ib_class_port_info_t class_port_info; } u; osmv_sa_mad_data_t sa_mad_data; osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind; osmv_user_query_t *p_user_query; #ifdef DUAL_SIDED_RMPP osmv_multipath_req_t *p_mpr_req; int i, j; #endif osm_log_t *p_log = p_bind->p_log; ib_api_status_t status; OSM_LOG_ENTER(p_log); /* Set the request information. */ sa_mad_data.method = IB_MAD_METHOD_GETTABLE; sa_mad_data.attr_mod = 0; sa_mad_data.attr_offset = 0; /* Set the MAD attributes and component mask correctly. */ switch (p_query_req->query_type) { case OSMV_QUERY_USER_DEFINED: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 USER_DEFINED\n"); p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; if (p_user_query->method) sa_mad_data.method = p_user_query->method; #ifdef DUAL_SIDED_RMPP if (sa_mad_data.method == IB_MAD_METHOD_GETMULTI || sa_mad_data.method == IB_MAD_METHOD_GETTRACETABLE) sa_mad_data.attr_offset = p_user_query->attr_offset; #endif sa_mad_data.attr_id = p_user_query->attr_id; sa_mad_data.attr_mod = p_user_query->attr_mod; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_ALL_SVC_RECS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = 0; sa_mad_data.p_attr = &u.svc_rec; break; case OSMV_QUERY_SVC_REC_BY_NAME: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n"); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME; sa_mad_data.p_attr = &u.svc_rec; memcpy(u.svc_rec.service_name, p_query_req->p_query_input, sizeof(ib_svc_name_t)); break; case OSMV_QUERY_SVC_REC_BY_ID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_ID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = IB_SR_COMPMASK_SID; sa_mad_data.p_attr = &u.svc_rec; u.svc_rec.service_id = *(ib_net64_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_CLASS_PORT_INFO: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 CLASS_PORT_INFO\n"); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO; sa_mad_data.comp_mask = 0; sa_mad_data.p_attr = &u.class_port_info; break; case OSMV_QUERY_NODE_REC_BY_NODE_GUID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 NODE_REC_BY_NODE_GUID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD; sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID; sa_mad_data.p_attr = &u.node_rec; u.node_rec.node_info.node_guid = *(ib_net64_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_PORT_REC_BY_LID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID; sa_mad_data.p_attr = &u.port_info; u.port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID_AND_NUM\n"); sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n"); sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD; sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_SLVL_BY_LID_AND_PORTS: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD; sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_PORT_GUIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH); u.path_rec.num_path = 0x7f; sa_mad_data.p_attr = &u.path_rec; ib_gid_set_default(&u.path_rec.dgid, ((osmv_guid_pair_t *) (p_query_req-> p_query_input))-> dest_guid); ib_gid_set_default(&u.path_rec.sgid, ((osmv_guid_pair_t *) (p_query_req-> p_query_input))-> src_guid); break; case OSMV_QUERY_PATH_REC_BY_GIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_GIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH); u.path_rec.num_path = 0x7f; sa_mad_data.p_attr = &u.path_rec; memcpy(&u.path_rec.dgid, &((osmv_gid_pair_t *) (p_query_req->p_query_input))-> dest_gid, sizeof(ib_gid_t)); memcpy(&u.path_rec.sgid, &((osmv_gid_pair_t *) (p_query_req->p_query_input))-> src_gid, sizeof(ib_gid_t)); break; case OSMV_QUERY_PATH_REC_BY_LIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_LIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID); sa_mad_data.p_attr = &u.path_rec; u.path_rec.dlid = ((osmv_lid_pair_t *) (p_query_req->p_query_input))-> dest_lid; u.path_rec.slid = ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid; break; case OSMV_QUERY_UD_MULTICAST_SET: sa_mad_data.method = IB_MAD_METHOD_SET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_SET\n"); sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_UD_MULTICAST_DELETE: sa_mad_data.method = IB_MAD_METHOD_DELETE; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_DELETE\n"); sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; #ifdef DUAL_SIDED_RMPP case OSMV_QUERY_MULTIPATH_REC: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n"); /* Validate sgid/dgid counts against SA client limit */ p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input; if (p_mpr_req->sgid_count + p_mpr_req->dgid_count > IB_MULTIPATH_MAX_GIDS) { OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC " "SGID count %d DGID count %d max count %d\n", p_mpr_req->sgid_count, p_mpr_req->dgid_count, IB_MULTIPATH_MAX_GIDS); CL_ASSERT(0); return IB_ERROR; } memset(&u.multipath_rec, 0, sizeof(ib_multipath_rec_t)); sa_mad_data.method = IB_MAD_METHOD_GETMULTI; sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD; sa_mad_data.attr_offset = ib_get_attr_offset(sizeof(ib_multipath_rec_t)); sa_mad_data.p_attr = &u.multipath_rec; sa_mad_data.comp_mask = p_mpr_req->comp_mask; u.multipath_rec.num_path = p_mpr_req->num_path; if (p_mpr_req->reversible) u.multipath_rec.num_path |= 0x80; else u.multipath_rec.num_path &= ~0x80; u.multipath_rec.pkey = p_mpr_req->pkey; ib_multipath_rec_set_sl(&u.multipath_rec, p_mpr_req->sl); ib_multipath_rec_set_qos_class(&u.multipath_rec, 0); u.multipath_rec.independence = p_mpr_req->independence; u.multipath_rec.sgid_count = p_mpr_req->sgid_count; u.multipath_rec.dgid_count = p_mpr_req->dgid_count; j = 0; for (i = 0; i < p_mpr_req->sgid_count; i++, j++) u.multipath_rec.gids[j] = p_mpr_req->gids[j]; for (i = 0; i < p_mpr_req->dgid_count; i++, j++) u.multipath_rec.gids[j] = p_mpr_req->gids[j]; break; #endif default: OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n"); CL_ASSERT(0); return IB_ERROR; } status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req); OSM_LOG_EXIT(p_log); return status; } opensm-3.3.20/libvendor/osm_vendor_ibumad.c0000644000205000001450000010566312374421064015652 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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 osm_vendor_t (for umad). * This object represents the OpenIB vendor layer. * This object is part of the opensm family of objects. * * Environment: * Linux User Mode * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef OSM_VENDOR_INTF_OPENIB #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_VENDOR_IBUMAD_C #include #include #include #include #include /****s* OpenSM: Vendor UMAD/osm_umad_bind_info_t * NAME * osm_umad_bind_info_t * * DESCRIPTION * Structure containing bind information. * * SYNOPSIS */ typedef struct _osm_umad_bind_info { osm_vendor_t *p_vend; void *client_context; osm_mad_pool_t *p_mad_pool; osm_vend_mad_recv_callback_t mad_recv_callback; osm_vend_mad_send_err_callback_t send_err_callback; ib_net64_t port_guid; int port_id; int agent_id; int agent_id1; /* SMI requires two agents */ int timeout; int max_retries; } osm_umad_bind_info_t; typedef struct _umad_receiver { pthread_t tid; osm_vendor_t *p_vend; osm_log_t *p_log; } umad_receiver_t; static void osm_vendor_close_port(osm_vendor_t * const p_vend); static void log_send_error(osm_vendor_t * const p_vend, osm_madw_t *p_madw) { if (p_madw->p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) { /* LID routed */ OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5410: " "Send completed with error (%s) -- dropping\n" "\t\t\tClass 0x%x, Method 0x%X, Attr 0x%X, " "TID 0x%" PRIx64 ", LID %u\n", ib_get_err_str(p_madw->status), p_madw->p_mad->mgmt_class, p_madw->p_mad->method, cl_ntoh16(p_madw->p_mad->attr_id), cl_ntoh64(p_madw->p_mad->trans_id), cl_ntoh16(p_madw->mad_addr.dest_lid)); } else { ib_smp_t *p_smp; /* Direct routed SMP */ p_smp = osm_madw_get_smp_ptr(p_madw); OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5411: " "DR SMP Send completed with error (%s) -- dropping\n" "\t\t\tMethod 0x%X, Attr 0x%X, TID 0x%" PRIx64 "\n", ib_get_err_str(p_madw->status), p_madw->p_mad->method, cl_ntoh16(p_madw->p_mad->attr_id), cl_ntoh64(p_madw->p_mad->trans_id)); osm_dump_smp_dr_path(p_vend->p_log, p_smp, OSM_LOG_ERROR); } } static void clear_madw(osm_vendor_t * p_vend) { umad_match_t *m, *e, *old_m; ib_net64_t old_tid; uint8_t old_mgmt_class; OSM_LOG_ENTER(p_vend->p_log); pthread_mutex_lock(&p_vend->match_tbl_mutex); for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) { if (m->tid) { old_m = m; old_tid = m->tid; old_mgmt_class = m->mgmt_class; m->tid = 0; osm_mad_pool_put(((osm_umad_bind_info_t *) ((osm_madw_t *) m->v)->h_bind)-> p_mad_pool, m->v); pthread_mutex_unlock(&p_vend->match_tbl_mutex); OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5401: " "evicting entry %p (tid was 0x%" PRIx64 " mgmt class 0x%x)\n", old_m, cl_ntoh64(old_tid), old_mgmt_class); goto Exit; } } pthread_mutex_unlock(&p_vend->match_tbl_mutex); Exit: OSM_LOG_EXIT(p_vend->p_log); } static osm_madw_t *get_madw(osm_vendor_t * p_vend, ib_net64_t * tid, uint8_t mgmt_class) { umad_match_t *m, *e; ib_net64_t mtid = (*tid & CL_HTON64(0x00000000ffffffffULL)); osm_madw_t *res; /* * Since mtid == 0 is the empty key, we should not * waste time looking for it */ if (mtid == 0 || mgmt_class == 0) return 0; pthread_mutex_lock(&p_vend->match_tbl_mutex); for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) { if (m->tid == mtid && m->mgmt_class == mgmt_class) { m->tid = 0; m->mgmt_class = 0; *tid = mtid; res = m->v; pthread_mutex_unlock(&p_vend->match_tbl_mutex); return res; } } pthread_mutex_unlock(&p_vend->match_tbl_mutex); return 0; } /* * If match table full, evict LRU (least recently used) transaction. * Maintain 2 LRUs: one for SMPs, and one for others (GS). * Evict LRU GS transaction if one is available and only evict LRU SMP * transaction if no other choice. */ static void put_madw(osm_vendor_t * p_vend, osm_madw_t * p_madw, ib_net64_t tid, uint8_t mgmt_class) { umad_match_t *m, *e, *old_lru, *lru = 0, *lru_smp = 0; osm_madw_t *p_req_madw; osm_umad_bind_info_t *p_bind; ib_net64_t old_tid; uint32_t oldest = ~0, oldest_smp = ~0; uint8_t old_mgmt_class; pthread_mutex_lock(&p_vend->match_tbl_mutex); for (m = p_vend->mtbl.tbl, e = m + p_vend->mtbl.max; m < e; m++) { if (m->tid == 0 && m->mgmt_class == 0) { m->tid = tid; m->mgmt_class = mgmt_class; m->v = p_madw; m->version = cl_atomic_inc((atomic32_t *) & p_vend->mtbl. last_version); pthread_mutex_unlock(&p_vend->match_tbl_mutex); return; } if (m->mgmt_class == IB_MCLASS_SUBN_DIR || m->mgmt_class == IB_MCLASS_SUBN_LID) { if (oldest_smp >= m->version) { oldest_smp = m->version; lru_smp = m; } } else { if (oldest >= m->version) { oldest = m->version; lru = m; } } } if (oldest != ~0) { old_lru = lru; old_tid = lru->tid; old_mgmt_class = lru->mgmt_class; } else { CL_ASSERT(oldest_smp != ~0); old_lru = lru_smp; old_tid = lru_smp->tid; old_mgmt_class = lru_smp->mgmt_class; } p_req_madw = old_lru->v; p_bind = p_req_madw->h_bind; p_req_madw->status = IB_CANCELED; log_send_error(p_vend, p_req_madw); pthread_mutex_lock(&p_vend->cb_mutex); (*p_bind->send_err_callback) (p_bind->client_context, p_req_madw); pthread_mutex_unlock(&p_vend->cb_mutex); if (mgmt_class == IB_MCLASS_SUBN_DIR || mgmt_class == IB_MCLASS_SUBN_LID) { lru_smp->tid = tid; lru_smp->mgmt_class = mgmt_class; lru_smp->v = p_madw; lru_smp->version = cl_atomic_inc((atomic32_t *) & p_vend->mtbl.last_version); } else { lru->tid = tid; lru->mgmt_class = mgmt_class; lru->v = p_madw; lru->version = cl_atomic_inc((atomic32_t *) & p_vend->mtbl.last_version); } pthread_mutex_unlock(&p_vend->match_tbl_mutex); OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5402: " "evicting entry %p (tid was 0x%" PRIx64 " mgmt class 0x%x)\n", old_lru, cl_ntoh64(old_tid), old_mgmt_class); } static void ib_mad_addr_conv(ib_user_mad_t * umad, osm_mad_addr_t * osm_mad_addr, int is_smi) { ib_mad_addr_t *ib_mad_addr = umad_get_mad_addr(umad); memset(osm_mad_addr, 0, sizeof(osm_mad_addr_t)); osm_mad_addr->dest_lid = ib_mad_addr->lid; osm_mad_addr->path_bits = ib_mad_addr->path_bits; if (is_smi) { osm_mad_addr->addr_type.smi.source_lid = osm_mad_addr->dest_lid; osm_mad_addr->addr_type.smi.port_num = 255; /* not used */ return; } osm_mad_addr->addr_type.gsi.remote_qp = ib_mad_addr->qpn; osm_mad_addr->addr_type.gsi.remote_qkey = ib_mad_addr->qkey; osm_mad_addr->addr_type.gsi.pkey_ix = umad_get_pkey(umad); osm_mad_addr->addr_type.gsi.service_level = ib_mad_addr->sl; if (ib_mad_addr->grh_present) { osm_mad_addr->addr_type.gsi.global_route = 1; osm_mad_addr->addr_type.gsi.grh_info.hop_limit = ib_mad_addr->hop_limit; osm_mad_addr->addr_type.gsi.grh_info.ver_class_flow = ib_grh_set_ver_class_flow(6, /* GRH version */ ib_mad_addr->traffic_class, ib_mad_addr->flow_label); memcpy(&osm_mad_addr->addr_type.gsi.grh_info.dest_gid, &ib_mad_addr->gid, 16); } } static void *swap_mad_bufs(osm_madw_t * p_madw, void *umad) { void *old; old = p_madw->vend_wrap.umad; p_madw->vend_wrap.umad = umad; p_madw->p_mad = umad_get_mad(umad); return old; } static void unlock_mutex(void *arg) { pthread_mutex_unlock(arg); } static void *umad_receiver(void *p_ptr) { umad_receiver_t *const p_ur = (umad_receiver_t *) p_ptr; osm_vendor_t *p_vend = p_ur->p_vend; osm_umad_bind_info_t *p_bind; osm_mad_addr_t osm_addr; osm_madw_t *p_madw, *p_req_madw; ib_mad_t *p_mad, *p_req_mad; void *umad = 0; int mad_agent, length; OSM_LOG_ENTER(p_ur->p_log); for (;;) { if (!umad && !(umad = umad_alloc(1, umad_size() + MAD_BLOCK_SIZE))) { OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5403: " "can't alloc MAD sized umad\n"); break; } length = MAD_BLOCK_SIZE; if ((mad_agent = umad_recv(p_vend->umad_port_id, umad, &length, -1)) < 0) { if (length <= MAD_BLOCK_SIZE) { OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5404: " "recv error on MAD sized umad (%m)\n"); continue; } else { umad_free(umad); /* Need a larger buffer for RMPP */ umad = umad_alloc(1, umad_size() + length); if (!umad) { OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5405: " "can't alloc umad length %d\n", length); continue; } if ((mad_agent = umad_recv(p_vend->umad_port_id, umad, &length, -1)) < 0) { OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5406: " "recv error on umad length %d (%m)\n", length); continue; } } } if (mad_agent >= OSM_UMAD_MAX_AGENTS || !(p_bind = p_vend->agents[mad_agent])) { OSM_LOG(p_ur->p_log, OSM_LOG_ERROR, "ERR 5407: " "invalid mad agent %d - dropping\n", mad_agent); continue; } p_mad = (ib_mad_t *) umad_get_mad(umad); ib_mad_addr_conv(umad, &osm_addr, p_mad->mgmt_class == IB_MCLASS_SUBN_LID || p_mad->mgmt_class == IB_MCLASS_SUBN_DIR); if (!(p_madw = osm_mad_pool_get(p_bind->p_mad_pool, (osm_bind_handle_t) p_bind, MAX(length, MAD_BLOCK_SIZE), &osm_addr))) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5408: " "request for a new madw failed -- dropping packet\n"); continue; } /* Need to fix up MAD size if short RMPP packet */ if (length < MAD_BLOCK_SIZE) p_madw->mad_size = length; /* * Avoid copying by swapping mad buf pointers. * Do not use umad after this line of code. */ umad = swap_mad_bufs(p_madw, umad); /* if status != 0 then we are handling recv timeout on send */ if (umad_status(p_madw->vend_wrap.umad)) { if (!(p_req_madw = get_madw(p_vend, &p_mad->trans_id, p_mad->mgmt_class))) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5412: " "Failed to obtain request madw for timed out MAD" " (class=0x%X method=0x%X attr=0x%X tid=0x%"PRIx64") -- dropping\n", p_mad->mgmt_class, p_mad->method, cl_ntoh16(p_mad->attr_id), cl_ntoh64(p_mad->trans_id)); } else { p_req_madw->status = IB_TIMEOUT; log_send_error(p_vend, p_req_madw); /* cb frees req_madw */ pthread_mutex_lock(&p_vend->cb_mutex); pthread_cleanup_push(unlock_mutex, &p_vend->cb_mutex); (*p_bind->send_err_callback) (p_bind-> client_context, p_req_madw); pthread_cleanup_pop(1); } osm_mad_pool_put(p_bind->p_mad_pool, p_madw); continue; } p_req_madw = 0; if (ib_mad_is_response(p_mad)) { p_req_madw = get_madw(p_vend, &p_mad->trans_id, p_mad->mgmt_class); if (PF(!p_req_madw)) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5413: Failed to obtain request " "madw for received MAD " "(class=0x%X method=0x%X attr=0x%X " "tid=0x%"PRIx64") -- dropping\n", p_mad->mgmt_class, p_mad->method, cl_ntoh16(p_mad->attr_id), cl_ntoh64(p_mad->trans_id)); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); continue; } /* * Check that request MAD was really a request, * and make sure that attribute ID, attribute * modifier and transaction ID are the same in * request and response. * * Exception for o15-0.2-1.11: * SA response to a SubnAdmGetMulti() containing a * MultiPathRecord shall have PathRecord attribute ID. */ p_req_mad = osm_madw_get_mad_ptr(p_req_madw); if (PF(ib_mad_is_response(p_req_mad) || (p_mad->attr_id != p_req_mad->attr_id && !(p_mad->mgmt_class == IB_MCLASS_SUBN_ADM && p_req_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD && p_mad->attr_id == IB_MAD_ATTR_PATH_RECORD)) || p_mad->attr_mod != p_req_mad->attr_mod || p_mad->trans_id != p_req_mad->trans_id)) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 541A: " "Response MAD validation failed " "(request attr=0x%X modif=0x%X " "tid=0x%"PRIx64", " "response attr=0x%X modif=0x%X " "tid=0x%"PRIx64") -- dropping\n", cl_ntoh16(p_req_mad->attr_id), cl_ntoh32(p_req_mad->attr_mod), cl_ntoh64(p_req_mad->trans_id), cl_ntoh16(p_mad->attr_id), cl_ntoh32(p_mad->attr_mod), cl_ntoh64(p_mad->trans_id)); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); continue; } } #ifndef VENDOR_RMPP_SUPPORT if ((p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) && (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) && (ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_mad, IB_RMPP_FLAG_ACTIVE))) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5414: " "class 0x%x method 0x%x RMPP version %d type " "%d flags 0x%x received -- dropping\n", p_mad->mgmt_class, p_mad->method, ((ib_rmpp_mad_t *) p_mad)->rmpp_version, ((ib_rmpp_mad_t *) p_mad)->rmpp_type, ((ib_rmpp_mad_t *) p_mad)->rmpp_flags); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); continue; } #endif /* call the CB */ pthread_mutex_lock(&p_vend->cb_mutex); pthread_cleanup_push(unlock_mutex, &p_vend->cb_mutex); (*p_bind->mad_recv_callback) (p_madw, p_bind->client_context, p_req_madw); pthread_cleanup_pop(1); } OSM_LOG_EXIT(p_vend->p_log); return NULL; } static int umad_receiver_start(osm_vendor_t * p_vend) { umad_receiver_t *p_ur = p_vend->receiver; p_ur->p_vend = p_vend; p_ur->p_log = p_vend->p_log; if (pthread_create(&p_ur->tid, NULL, umad_receiver, p_ur) != 0) return -1; return 0; } static void umad_receiver_stop(umad_receiver_t * p_ur) { pthread_cancel(p_ur->tid); pthread_join(p_ur->tid, NULL); p_ur->tid = 0; p_ur->p_vend = NULL; p_ur->p_log = NULL; } ib_api_status_t osm_vendor_init(IN osm_vendor_t * const p_vend, IN osm_log_t * const p_log, IN const uint32_t timeout) { char *max = NULL; int r, n_cas; OSM_LOG_ENTER(p_log); p_vend->p_log = p_log; p_vend->timeout = timeout; p_vend->max_retries = OSM_DEFAULT_RETRY_COUNT; pthread_mutex_init(&p_vend->cb_mutex, NULL); pthread_mutex_init(&p_vend->match_tbl_mutex, NULL); p_vend->umad_port_id = -1; p_vend->issmfd = -1; /* * Open our instance of UMAD. */ if ((r = umad_init()) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5415: Error opening UMAD\n"); } if ((n_cas = umad_get_cas_names(p_vend->ca_names, OSM_UMAD_MAX_CAS)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5416: umad_get_cas_names failed\n"); r = n_cas; goto Exit; } p_vend->ca_count = n_cas; p_vend->mtbl.max = DEFAULT_OSM_UMAD_MAX_PENDING; if ((max = getenv("OSM_UMAD_MAX_PENDING")) != NULL) { int tmp = strtol(max, NULL, 0); if (tmp > 0) p_vend->mtbl.max = tmp; else OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:" "OSM_UMAD_MAX_PENDING=%d is invalid\n", tmp); } OSM_LOG(p_vend->p_log, OSM_LOG_INFO, "%d pending umads specified\n", p_vend->mtbl.max); p_vend->mtbl.tbl = calloc(p_vend->mtbl.max, sizeof(*(p_vend->mtbl.tbl))); if (!p_vend->mtbl.tbl) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "Error:" "failed to allocate vendor match table\n"); r = IB_INSUFFICIENT_MEMORY; goto Exit; } Exit: OSM_LOG_EXIT(p_log); return (r); } osm_vendor_t *osm_vendor_new(IN osm_log_t * const p_log, IN const uint32_t timeout) { osm_vendor_t *p_vend = NULL; OSM_LOG_ENTER(p_log); if (!timeout) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5433: " "transaction timeout cannot be 0\n"); goto Exit; } p_vend = malloc(sizeof(*p_vend)); if (p_vend == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5417: " "Unable to allocate vendor object\n"); goto Exit; } memset(p_vend, 0, sizeof(*p_vend)); if (osm_vendor_init(p_vend, p_log, timeout) != IB_SUCCESS) { free(p_vend); p_vend = NULL; } Exit: OSM_LOG_EXIT(p_log); return (p_vend); } void osm_vendor_delete(IN osm_vendor_t ** const pp_vend) { osm_vendor_close_port(*pp_vend); clear_madw(*pp_vend); /* make sure all ports are closed */ umad_done(); pthread_mutex_destroy(&(*pp_vend)->cb_mutex); pthread_mutex_destroy(&(*pp_vend)->match_tbl_mutex); free((*pp_vend)->mtbl.tbl); free(*pp_vend); *pp_vend = NULL; } ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports) { umad_ca_t ca; ib_port_attr_t *attr = p_attr_array; unsigned done = 0; int r = 0, i, j, k; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend && p_num_ports); if (!*p_num_ports) { r = IB_INVALID_PARAMETER; OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5418: " "Ports in should be > 0\n"); goto Exit; } if (!p_attr_array) { r = IB_INSUFFICIENT_MEMORY; *p_num_ports = 0; goto Exit; } for (i = 0; i < p_vend->ca_count && !done; i++) { /* For each CA, retrieve the port attributes */ if (umad_get_ca(p_vend->ca_names[i], &ca) == 0) { if (ca.node_type < 1 || ca.node_type > 3) continue; for (j = 0; j <= ca.numports; j++) { if (!ca.ports[j]) continue; attr->port_guid = ca.ports[j]->port_guid; attr->lid = ca.ports[j]->base_lid; attr->port_num = ca.ports[j]->portnum; attr->sm_lid = ca.ports[j]->sm_lid; attr->sm_sl = ca.ports[j]->sm_sl; attr->link_state = ca.ports[j]->state; if (attr->num_pkeys && attr->p_pkey_table) { if (attr->num_pkeys > ca.ports[j]->pkeys_size) attr->num_pkeys = ca.ports[j]->pkeys_size; for (k = 0; k < attr->num_pkeys; k++) attr->p_pkey_table[k] = cl_hton16(ca.ports[j]->pkeys[k]); } attr->num_pkeys = ca.ports[j]->pkeys_size; if (attr->num_gids && attr->p_gid_table) { attr->p_gid_table[0].unicast.prefix = cl_hton64(ca.ports[j]->gid_prefix); attr->p_gid_table[0].unicast.interface_id = cl_hton64(ca.ports[j]->port_guid); attr->num_gids = 1; } attr++; if (attr - p_attr_array > *p_num_ports) { done = 1; break; } } umad_release_ca(&ca); } } *p_num_ports = attr - p_attr_array; Exit: OSM_LOG_EXIT(p_vend->p_log); return r; } static int osm_vendor_open_port(IN osm_vendor_t * const p_vend, IN const ib_net64_t port_guid) { ib_net64_t portguids[OSM_UMAD_MAX_PORTS_PER_CA + 1]; umad_ca_t umad_ca; int i = 0, umad_port_id = -1; char *name; int ca, r; CL_ASSERT(p_vend); OSM_LOG_ENTER(p_vend->p_log); if (p_vend->umad_port_id >= 0) { umad_port_id = p_vend->umad_port_id; goto Exit; } if (!port_guid) { name = NULL; i = 0; goto _found; } for (ca = 0; ca < p_vend->ca_count; ca++) { if ((r = umad_get_ca_portguids(p_vend->ca_names[ca], portguids, OSM_UMAD_MAX_PORTS_PER_CA + 1)) < 0) { #ifdef __WIN__ OSM_LOG(p_vend->p_log, OSM_LOG_VERBOSE, #else OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5421: " #endif "Unable to get CA %s port guids (%s)\n", p_vend->ca_names[ca], strerror(r)); continue; } for (i = 0; i < r; i++) if (port_guid == portguids[i]) { name = p_vend->ca_names[ca]; goto _found; } } /* * No local CA owns this guid! */ OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5422: " "Unable to find requested CA guid 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); goto Exit; _found: /* Validate that node is an IB node type (not iWARP) */ if (umad_get_ca(name, &umad_ca) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542A: " "umad_get_ca() failed\n"); goto Exit; } if (umad_ca.node_type < 1 || umad_ca.node_type > 3) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542D: " "Type %d of node \'%s\' is not an IB node type\n", umad_ca.node_type, umad_ca.ca_name); fprintf(stderr, "Type %d of node \'%s\' is not an IB node type\n", umad_ca.node_type, umad_ca.ca_name); umad_release_ca(&umad_ca); goto Exit; } umad_release_ca(&umad_ca); /* Port found, try to open it */ if (umad_get_port(name, i, &p_vend->umad_port) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542B: " "umad_get_port() failed\n"); goto Exit; } if ((umad_port_id = umad_open_port(p_vend->umad_port.ca_name, p_vend->umad_port.portnum)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542C: " "umad_open_port() failed\n"); goto Exit; } p_vend->umad_port_id = umad_port_id; /* start receiver thread */ if (!(p_vend->receiver = calloc(1, sizeof(umad_receiver_t)))) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5423: " "Unable to alloc receiver struct\n"); umad_close_port(umad_port_id); umad_release_port(&p_vend->umad_port); p_vend->umad_port.port_guid = 0; p_vend->umad_port_id = umad_port_id = -1; goto Exit; } if (umad_receiver_start(p_vend) != 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5420: " "umad_receiver_init failed\n"); umad_close_port(umad_port_id); umad_release_port(&p_vend->umad_port); p_vend->umad_port.port_guid = 0; p_vend->umad_port_id = umad_port_id = -1; } Exit: OSM_LOG_EXIT(p_vend->p_log); return umad_port_id; } static void osm_vendor_close_port(osm_vendor_t * const p_vend) { umad_receiver_t *p_ur; int i; p_ur = p_vend->receiver; p_vend->receiver = NULL; if (p_ur) { umad_receiver_stop(p_ur); free(p_ur); } if (p_vend->umad_port_id >= 0) { for (i = 0; i < OSM_UMAD_MAX_AGENTS; i++) if (p_vend->agents[i]) umad_unregister(p_vend->umad_port_id, i); umad_close_port(p_vend->umad_port_id); umad_release_port(&p_vend->umad_port); p_vend->umad_port.port_guid = 0; p_vend->umad_port_id = -1; } } static int set_bit(int nr, void *method_mask) { long mask, *addr = method_mask; int retval; addr += nr / (8 * sizeof(long)); mask = 1L << (nr % (8 * sizeof(long))); retval = (mask & *addr) != 0; *addr |= mask; return retval; } osm_bind_handle_t osm_vendor_bind(IN osm_vendor_t * const p_vend, IN osm_bind_info_t * const p_user_bind, IN osm_mad_pool_t * const p_mad_pool, IN osm_vend_mad_recv_callback_t mad_recv_callback, IN osm_vend_mad_send_err_callback_t send_err_callback, IN void *context) { ib_net64_t port_guid; osm_umad_bind_info_t *p_bind = 0; long method_mask[16 / sizeof(long)]; int umad_port_id; uint8_t rmpp_version; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_user_bind); CL_ASSERT(p_mad_pool); CL_ASSERT(mad_recv_callback); CL_ASSERT(send_err_callback); port_guid = p_user_bind->port_guid; OSM_LOG(p_vend->p_log, OSM_LOG_INFO, "Mgmt class 0x%02x binding to port GUID 0x%" PRIx64 "\n", p_user_bind->mad_class, cl_ntoh64(port_guid)); if ((umad_port_id = osm_vendor_open_port(p_vend, port_guid)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5424: " "Unable to open port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); goto Exit; } if (umad_get_issm_path(p_vend->umad_port.ca_name, p_vend->umad_port.portnum, p_vend->issm_path, sizeof(p_vend->issm_path)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 542E: " "Cannot resolve issm path for port %s:%u\n", p_vend->umad_port.ca_name, p_vend->umad_port.portnum); goto Exit; } if (!(p_bind = malloc(sizeof(*p_bind)))) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5425: " "Unable to allocate internal bind object\n"); goto Exit; } memset(p_bind, 0, sizeof(*p_bind)); p_bind->p_vend = p_vend; p_bind->port_id = umad_port_id; p_bind->client_context = context; p_bind->mad_recv_callback = mad_recv_callback; p_bind->send_err_callback = send_err_callback; p_bind->p_mad_pool = p_mad_pool; p_bind->port_guid = port_guid; p_bind->timeout = p_user_bind->timeout ? p_user_bind->timeout : p_vend->timeout; p_bind->max_retries = p_user_bind->retries ? p_user_bind->retries : p_vend->max_retries; memset(method_mask, 0, sizeof method_mask); if (p_user_bind->is_responder) { set_bit(IB_MAD_METHOD_GET, &method_mask); set_bit(IB_MAD_METHOD_SET, &method_mask); if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM) { set_bit(IB_MAD_METHOD_GETTABLE, &method_mask); set_bit(IB_MAD_METHOD_DELETE, &method_mask); #ifdef DUAL_SIDED_RMPP set_bit(IB_MAD_METHOD_GETMULTI, &method_mask); #endif /* Add in IB_MAD_METHOD_GETTRACETABLE */ /* when supported by OpenSM */ } } if (p_user_bind->is_report_processor) set_bit(IB_MAD_METHOD_REPORT, &method_mask); if (p_user_bind->is_trap_processor) { set_bit(IB_MAD_METHOD_TRAP, &method_mask); set_bit(IB_MAD_METHOD_TRAP_REPRESS, &method_mask); } #ifndef VENDOR_RMPP_SUPPORT rmpp_version = 0; #else /* If SA class, set rmpp_version */ if (p_user_bind->mad_class == IB_MCLASS_SUBN_ADM) rmpp_version = 1; else rmpp_version = 0; #endif if ((p_bind->agent_id = umad_register(p_vend->umad_port_id, p_user_bind->mad_class, p_user_bind->class_version, rmpp_version, method_mask)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5426: " "Unable to register class %u version %u\n", p_user_bind->mad_class, p_user_bind->class_version); free(p_bind); p_bind = 0; goto Exit; } if (p_bind->agent_id >= OSM_UMAD_MAX_AGENTS || p_vend->agents[p_bind->agent_id]) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5427: " "bad agent id %u or duplicate agent for class %u vers %u\n", p_bind->agent_id, p_user_bind->mad_class, p_user_bind->class_version); free(p_bind); p_bind = 0; goto Exit; } p_vend->agents[p_bind->agent_id] = p_bind; /* If Subn Directed Route class, register Subn LID routed class */ if (p_user_bind->mad_class == IB_MCLASS_SUBN_DIR) { if ((p_bind->agent_id1 = umad_register(p_vend->umad_port_id, IB_MCLASS_SUBN_LID, p_user_bind-> class_version, 0, method_mask)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5428: " "Unable to register class 1 version %u\n", p_user_bind->class_version); free(p_bind); p_bind = 0; goto Exit; } if (p_bind->agent_id1 >= OSM_UMAD_MAX_AGENTS || p_vend->agents[p_bind->agent_id1]) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5429: " "bad agent id %u or duplicate agent for class 1 vers %u\n", p_bind->agent_id1, p_user_bind->class_version); free(p_bind); p_bind = 0; goto Exit; } p_vend->agents[p_bind->agent_id1] = p_bind; } Exit: OSM_LOG_EXIT(p_vend->p_log); return ((osm_bind_handle_t) p_bind); } static void __osm_vendor_recv_dummy_cb(IN osm_madw_t * p_madw, IN void *bind_context, IN osm_madw_t * p_req_madw) { #ifdef _DEBUG_ fprintf(stderr, "__osm_vendor_recv_dummy_cb: Ignoring received MAD after osm_vendor_unbind\n"); #endif } static void __osm_vendor_send_err_dummy_cb(IN void *bind_context, IN osm_madw_t * p_req_madw) { #ifdef _DEBUG_ fprintf(stderr, "__osm_vendor_send_err_dummy_cb: Ignoring send error after osm_vendor_unbind\n"); #endif } void osm_vendor_unbind(IN osm_bind_handle_t h_bind) { osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind; osm_vendor_t *p_vend = p_bind->p_vend; OSM_LOG_ENTER(p_vend->p_log); pthread_mutex_lock(&p_vend->cb_mutex); p_bind->mad_recv_callback = __osm_vendor_recv_dummy_cb; p_bind->send_err_callback = __osm_vendor_send_err_dummy_cb; pthread_mutex_unlock(&p_vend->cb_mutex); OSM_LOG_EXIT(p_vend->p_log); } ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind, IN const uint32_t mad_size, IN osm_vend_wrap_t * const p_vw) { osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind; osm_vendor_t *p_vend = p_bind->p_vend; OSM_LOG_ENTER(p_vend->p_log); OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Acquiring UMAD for p_madw = %p, size = %u\n", p_vw, mad_size); CL_ASSERT(p_vw); p_vw->size = mad_size; p_vw->umad = umad_alloc(1, mad_size + umad_size()); /* track locally */ p_vw->h_bind = h_bind; OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Acquired UMAD %p, size = %u\n", p_vw->umad, p_vw->size); OSM_LOG_EXIT(p_vend->p_log); return (p_vw->umad ? umad_get_mad(p_vw->umad) : NULL); } void osm_vendor_put(IN osm_bind_handle_t h_bind, IN osm_vend_wrap_t * const p_vw) { osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind; osm_vendor_t *p_vend = p_bind->p_vend; osm_madw_t *p_madw; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vw); OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Retiring UMAD %p\n", p_vw->umad); /* * We moved the removal of the transaction to immediately after * it was looked up. */ /* free the mad but the wrapper is part of the madw object */ umad_free(p_vw->umad); p_vw->umad = 0; p_madw = PARENT_STRUCT(p_vw, osm_madw_t, vend_wrap); p_madw->p_mad = NULL; OSM_LOG_EXIT(p_vend->p_log); } ib_api_status_t osm_vendor_send(IN osm_bind_handle_t h_bind, IN osm_madw_t * const p_madw, IN boolean_t const resp_expected) { osm_umad_bind_info_t *const p_bind = h_bind; osm_vendor_t *const p_vend = p_bind->p_vend; osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw); osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw); ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw); ib_sa_mad_t *const p_sa = (ib_sa_mad_t *) p_mad; ib_mad_addr_t mad_addr; int ret = -1; int __attribute__((__unused__)) is_rmpp = 0; uint32_t sent_mad_size; uint64_t tid; #ifndef VENDOR_RMPP_SUPPORT uint32_t paylen = 0; #endif OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vw->h_bind == h_bind); CL_ASSERT(p_mad == umad_get_mad(p_vw->umad)); if (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) { umad_set_addr_net(p_vw->umad, 0xffff, 0, 0, 0); umad_set_grh(p_vw->umad, NULL); goto Resp; } if (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) { umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid, 0, 0, 0); umad_set_grh(p_vw->umad, NULL); goto Resp; } /* GS classes */ umad_set_addr_net(p_vw->umad, p_mad_addr->dest_lid, p_mad_addr->addr_type.gsi.remote_qp, p_mad_addr->addr_type.gsi.service_level, IB_QP1_WELL_KNOWN_Q_KEY); if (p_mad_addr->addr_type.gsi.global_route) { mad_addr.grh_present = 1; mad_addr.gid_index = 0; mad_addr.hop_limit = p_mad_addr->addr_type.gsi.grh_info.hop_limit; ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi.grh_info.ver_class_flow, NULL, &mad_addr.traffic_class, &mad_addr.flow_label); memcpy(&mad_addr.gid, &p_mad_addr->addr_type.gsi.grh_info.dest_gid, 16); umad_set_grh(p_vw->umad, &mad_addr); } else umad_set_grh(p_vw->umad, NULL); umad_set_pkey(p_vw->umad, p_mad_addr->addr_type.gsi.pkey_ix); if (ib_class_is_rmpp(p_mad->mgmt_class)) { /* RMPP GS classes */ if (!ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa, IB_RMPP_FLAG_ACTIVE)) { /* Clear RMPP header when RMPP not ACTIVE */ p_sa->rmpp_version = 0; p_sa->rmpp_type = 0; p_sa->rmpp_flags = 0; p_sa->rmpp_status = 0; #ifdef VENDOR_RMPP_SUPPORT } else is_rmpp = 1; OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "RMPP %d length %d\n", ib_rmpp_is_flag_set((ib_rmpp_mad_t *) p_sa, IB_RMPP_FLAG_ACTIVE), p_madw->mad_size); #else } else { p_sa->rmpp_version = 1; p_sa->seg_num = cl_ntoh32(1); /* first DATA is seg 1 */ p_sa->rmpp_flags |= (uint8_t) 0x70; /* RRespTime of 14 (high 5 bits) */ p_sa->rmpp_status = 0; paylen = p_madw->mad_size - IB_SA_MAD_HDR_SIZE; paylen += (IB_SA_MAD_HDR_SIZE - MAD_RMPP_HDR_SIZE); p_sa->paylen_newwin = cl_ntoh32(paylen); } #endif } Resp: if (resp_expected) put_madw(p_vend, p_madw, p_mad->trans_id, p_mad->mgmt_class); #ifdef VENDOR_RMPP_SUPPORT sent_mad_size = p_madw->mad_size; #else sent_mad_size = is_rmpp ? p_madw->mad_size - IB_SA_MAD_HDR_SIZE : p_madw->mad_size; #endif tid = cl_ntoh64(p_mad->trans_id); if ((ret = umad_send(p_bind->port_id, p_bind->agent_id, p_vw->umad, sent_mad_size, resp_expected ? p_bind->timeout : 0, p_bind->max_retries)) < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5430: " "Send p_madw = %p of size %d, Class 0x%x, Method 0x%X, " "Attr 0x%X, TID 0x%" PRIx64 " failed %d (%m)\n", p_madw, sent_mad_size, p_mad->mgmt_class, p_mad->method, cl_ntoh16(p_mad->attr_id), tid, ret); if (resp_expected) { get_madw(p_vend, &p_mad->trans_id, p_mad->mgmt_class); /* remove from aging table */ p_madw->status = IB_ERROR; pthread_mutex_lock(&p_vend->cb_mutex); (*p_bind->send_err_callback) (p_bind->client_context, p_madw); /* cb frees madw */ pthread_mutex_unlock(&p_vend->cb_mutex); } else osm_mad_pool_put(p_bind->p_mad_pool, p_madw); goto Exit; } if (!resp_expected) osm_mad_pool_put(p_bind->p_mad_pool, p_madw); OSM_LOG(p_vend->p_log, OSM_LOG_DEBUG, "Completed sending %s TID 0x%" PRIx64 "\n", resp_expected ? "request" : "response or unsolicited", tid); Exit: OSM_LOG_EXIT(p_vend->p_log); return (ret); } ib_api_status_t osm_vendor_local_lid_change(IN osm_bind_handle_t h_bind) { osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind; osm_vendor_t *p_vend = p_bind->p_vend; OSM_LOG_ENTER(p_vend->p_log); ; OSM_LOG_EXIT(p_vend->p_log); return (0); } void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val) { osm_umad_bind_info_t *p_bind = (osm_umad_bind_info_t *) h_bind; osm_vendor_t *p_vend = p_bind->p_vend; OSM_LOG_ENTER(p_vend->p_log); if (TRUE == is_sm_val) { p_vend->issmfd = open(p_vend->issm_path, O_NONBLOCK); if (p_vend->issmfd < 0) { OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5431: " "setting IS_SM capmask: cannot open file " "\'%s\': %s\n", p_vend->issm_path, strerror(errno)); p_vend->issmfd = -1; } } else if (p_vend->issmfd != -1) { if (0 != close(p_vend->issmfd)) OSM_LOG(p_vend->p_log, OSM_LOG_ERROR, "ERR 5432: " "clearing IS_SM capmask: cannot close: %s\n", strerror(errno)); p_vend->issmfd = -1; } OSM_LOG_EXIT(p_vend->p_log); } void osm_vendor_set_debug(IN osm_vendor_t * const p_vend, IN int32_t level) { umad_debug(level); } #endif /* OSM_VENDOR_INTF_OPENIB */ opensm-3.3.20/libvendor/osm_vendor_ibumad_sa.c0000644000205000001450000005566012560662556016350 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include /* this struct is the internal rep of the bind handle */ typedef struct _osmv_sa_bind_info { osm_bind_handle_t h_bind; osm_log_t *p_log; osm_vendor_t *p_vendor; osm_mad_pool_t *p_mad_pool; cl_event_t sync_event; time_t last_lids_update_sec; } osmv_sa_bind_info_t; /* Call back on new mad received: We basically only need to set the context of the query. Or report an error. A pointer to the actual context of the request (a copy of the oriignal request structure) is attached as the p_madw->context.ni_context.node_guid */ static void __osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw, IN void *bind_context, IN osm_madw_t * p_req_madw) { osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context; osmv_query_req_t *p_query_req_copy = NULL; osmv_query_res_t query_res; ib_sa_mad_t *p_sa_mad; ib_net16_t mad_status; OSM_LOG_ENTER(p_bind->p_log); if (!p_req_madw) { OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG, "Ignoring a non-response mad\n"); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); goto Exit; } /* obtain the sent context since we store it during send in the ni_ctx */ p_query_req_copy = (osmv_query_req_t *) (uintptr_t)(osm_madw_get_ni_context_ptr(p_req_madw)->node_guid); /* provide the context of the original request in the result */ query_res.query_context = p_query_req_copy->query_context; /* provide the resulting madw */ query_res.p_result_madw = p_madw; /* update the req fields */ p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad; /* if we got a remote error track it in the status */ mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK); if (mad_status != IB_SUCCESS) { OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: " "Remote error: 0x%04X\n", cl_ntoh16(mad_status)); query_res.status = IB_REMOTE_ERROR; } else query_res.status = IB_SUCCESS; /* what if we have got back an empty mad ? */ if (!p_madw->mad_size) { OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: " "Got an empty mad\n"); query_res.status = IB_ERROR; } if (IB_SUCCESS == mad_status) { /* if we are in not in a method response of an rmpp nature we must get only 1 */ /* HACK: in the future we might need to be smarter for other methods... */ if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) { query_res.result_cnt = 1; } else { #ifndef VENDOR_RMPP_SUPPORT if (mad_status != IB_SUCCESS) query_res.result_cnt = 0; else query_res.result_cnt = 1; #else if (ib_get_attr_size(p_sa_mad->attr_offset)) { /* we used the offset value to calculate the number of records in here */ query_res.result_cnt = (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) / ib_get_attr_size(p_sa_mad->attr_offset); OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG, "Count = %u = %zu / %u (%zu)\n", query_res.result_cnt, p_madw->mad_size - IB_SA_MAD_HDR_SIZE, ib_get_attr_size(p_sa_mad->attr_offset), (p_madw->mad_size - IB_SA_MAD_HDR_SIZE) % ib_get_attr_size(p_sa_mad->attr_offset)); } else query_res.result_cnt = 0; #endif } } query_res.query_type = p_query_req_copy->query_type; p_query_req_copy->pfn_query_cb(&query_res); if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) cl_event_signal(&p_bind->sync_event); Exit: /* free the copied query request if found */ if (p_query_req_copy) free(p_query_req_copy); /* put back the request madw */ if (p_req_madw) osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw); OSM_LOG_EXIT(p_bind->p_log); } /* Send Error Callback: Only report the error and get rid of the mad wrapper */ static void __osmv_sa_mad_err_cb(IN void *bind_context, IN osm_madw_t * p_madw) { osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context; osmv_query_req_t *p_query_req_copy = NULL; osmv_query_res_t query_res; OSM_LOG_ENTER(p_bind->p_log); /* Obtain the sent context etc */ p_query_req_copy = (osmv_query_req_t *) (uintptr_t)(osm_madw_get_ni_context_ptr(p_madw)->node_guid); /* provide the context of the original request in the result */ query_res.query_context = p_query_req_copy->query_context; query_res.p_result_madw = p_madw; query_res.status = IB_TIMEOUT; query_res.result_cnt = 0; query_res.query_type = p_query_req_copy->query_type; p_query_req_copy->pfn_query_cb(&query_res); if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC) cl_event_signal(&p_bind->sync_event); free(p_query_req_copy); OSM_LOG_EXIT(p_bind->p_log); } /***************************************************************************** Update lids of vendor umad_port. *****************************************************************************/ static ib_api_status_t update_umad_port(osm_vendor_t * p_vend) { umad_port_t port; if (umad_get_port(p_vend->umad_port.ca_name, p_vend->umad_port.portnum, &port) < 0) return IB_ERROR; p_vend->umad_port.base_lid = port.base_lid; p_vend->umad_port.sm_lid = port.sm_lid; umad_release_port(&port); return IB_SUCCESS; } osm_bind_handle_t osmv_bind_sa(IN osm_vendor_t * const p_vend, IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid) { osm_bind_info_t bind_info; osm_log_t *p_log = p_vend->p_log; osmv_sa_bind_info_t *p_sa_bind_info; cl_status_t cl_status; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); bind_info.port_guid = port_guid; bind_info.mad_class = IB_MCLASS_SUBN_ADM; bind_info.class_version = 2; bind_info.is_responder = FALSE; bind_info.is_trap_processor = FALSE; bind_info.is_report_processor = FALSE; bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE; bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE; bind_info.timeout = p_vend->timeout; bind_info.retries = OSM_DEFAULT_RETRY_COUNT; /* allocate the new sa bind info */ p_sa_bind_info = (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t)); if (!p_sa_bind_info) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: " "Failed to allocate new bind structure\n"); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; goto Exit; } /* store some important context */ p_sa_bind_info->p_log = p_log; p_sa_bind_info->p_mad_pool = p_mad_pool; p_sa_bind_info->p_vendor = p_vend; /* Bind to the lower level */ p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info); /* context provided to CBs */ if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) { free(p_sa_bind_info); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: " "Failed to bind to vendor GSI\n"); goto Exit; } /* update time umad_port is initilized now */ p_sa_bind_info->last_lids_update_sec = time(NULL); /* initialize the sync_event */ cl_event_construct(&p_sa_bind_info->sync_event); cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE); if (cl_status != CL_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: " "cl_init_event failed: %s\n", ib_get_err_str(cl_status)); free(p_sa_bind_info); p_sa_bind_info = OSM_BIND_INVALID_HANDLE; } Exit: OSM_LOG_EXIT(p_log); return (p_sa_bind_info); } /****t* OSM Vendor SA Client/osmv_sa_mad_data * NAME * osmv_sa_mad_data * * DESCRIPTION * Extra fields required to perform a mad query * This struct is passed to the actual send method * * SYNOPSIS */ typedef struct _osmv_sa_mad_data { /* MAD data. */ uint8_t method; ib_net16_t attr_id; ib_net16_t attr_offset; ib_net32_t attr_mod; ib_net64_t comp_mask; void *p_attr; } osmv_sa_mad_data_t; /* * method * The method of the mad to be sent * * attr_id * Attribute ID * * attr_offset * Offset as defined by RMPP * * attr_mod * Attribute modifier * * comp_mask * The component mask of the query * * p_attr * A pointer to the record of the attribute to be sent. * *****/ /* Send a MAD out on the GSI interface */ static ib_api_status_t __osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind, IN const osmv_sa_mad_data_t * const p_sa_mad_data, IN const osmv_query_req_t * const p_query_req) { ib_api_status_t status; ib_mad_t *p_mad_hdr; ib_sa_mad_t *p_sa_mad; osm_madw_t *p_madw; osm_log_t *p_log = p_bind->p_log; static atomic32_t trans_id; boolean_t sync; osmv_query_req_t *p_query_req_copy; uint32_t sa_size; OSM_LOG_ENTER(p_log); /* since the sm_lid might change we obtain it every send (actually it is cached in the bind object and refreshed every 30sec by this proc) */ if (time(NULL) > p_bind->last_lids_update_sec + 30) { status = update_umad_port(p_bind->p_vendor); if (status != IB_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: " "Failed to obtain the SM lid\n"); goto Exit; } p_bind->last_lids_update_sec = time(NULL); } /* Get a MAD wrapper for the send */ p_madw = osm_mad_pool_get(p_bind->p_mad_pool, p_bind->h_bind, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: " "Unable to acquire MAD\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } /* Initialize the Sent MAD: */ /* Initialize the MAD buffer for the send operation. */ p_mad_hdr = osm_madw_get_mad_ptr(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); /* Get a new transaction Id */ cl_atomic_inc(&trans_id); /* Cleanup the MAD from any residue */ memset(p_sa_mad, 0, MAD_BLOCK_SIZE); /* Initialize the standard MAD header. */ ib_mad_init_new(p_mad_hdr, /* mad pointer */ IB_MCLASS_SUBN_ADM, /* class */ (uint8_t) 2, /* version */ p_sa_mad_data->method, /* method */ cl_hton64((uint64_t) trans_id), /* tid */ p_sa_mad_data->attr_id, /* attr id */ p_sa_mad_data->attr_mod /* attr mod */); /* Set the query information. */ p_sa_mad->sm_key = p_query_req->sm_key; p_sa_mad->attr_offset = 0; p_sa_mad->comp_mask = p_sa_mad_data->comp_mask; #ifdef DUAL_SIDED_RMPP if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI) p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; #endif if (p_sa_mad->comp_mask) { p_sa_mad_data->attr_offset ? (sa_size = ib_get_attr_size(p_sa_mad_data->attr_offset)) : (sa_size = IB_SA_DATA_SIZE); memcpy(p_sa_mad->data, p_sa_mad_data->p_attr, sa_size); } /* Provide the address to send to */ p_madw->mad_addr.dest_lid = cl_hton16(p_bind->p_vendor->umad_port.sm_lid); p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->p_vendor->umad_port.base_lid); p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1); p_madw->resp_expected = TRUE; p_madw->fail_msg = CL_DISP_MSGID_NONE; /* add grh */ if (p_query_req->with_grh) { OSM_LOG(p_log, OSM_LOG_DEBUG, "sending sa query with GRH " "GID 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh64(p_query_req->gid.unicast.prefix), cl_ntoh64(p_query_req->gid.unicast.interface_id)); p_madw->mad_addr.addr_type.gsi.global_route = 1; memset(&p_madw->mad_addr.addr_type.gsi.grh_info, 0, sizeof(p_madw->mad_addr.addr_type.gsi.grh_info)); memcpy(&p_madw->mad_addr.addr_type.gsi.grh_info.dest_gid, &(p_query_req->gid), 16); } /* Provide MAD context such that the call back will know what to do. We have to keep the entire request structure so we know the CB. Since we can not rely on the client to keep it around until the response - we duplicate it and will later dispose it (in CB). To store on the MADW we cast it into what opensm has: p_madw->context.ni_context.node_guid */ p_query_req_copy = malloc(sizeof(*p_query_req_copy)); if (!p_query_req_copy) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5511: " "Unable to acquire memory for query copy\n"); osm_mad_pool_put(p_bind->p_mad_pool, p_madw); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } *p_query_req_copy = *p_query_req; osm_madw_get_ni_context_ptr(p_madw)->node_guid = (ib_net64_t) (uintptr_t)p_query_req_copy; /* we can support async as well as sync calls */ sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC); /* send the mad asynchronously */ status = osm_vendor_send(osm_madw_get_bind_handle(p_madw), p_madw, p_madw->resp_expected); /* if synchronous - wait on the event */ if (sync) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n"); cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE); cl_event_reset(&p_bind->sync_event); status = p_madw->status; } Exit: OSM_LOG_EXIT(p_log); return status; } /* * Query the SA based on the user's request. */ ib_api_status_t osmv_query_sa(IN osm_bind_handle_t h_bind, IN const osmv_query_req_t * const p_query_req) { union { ib_service_record_t svc_rec; ib_node_record_t node_rec; ib_portinfo_record_t port_info; ib_path_rec_t path_rec; #ifdef DUAL_SIDED_RMPP ib_multipath_rec_t multipath_rec; #endif ib_class_port_info_t class_port_info; } u; osmv_sa_mad_data_t sa_mad_data; osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) h_bind; osmv_user_query_t *p_user_query; #ifdef DUAL_SIDED_RMPP osmv_multipath_req_t *p_mpr_req; int i, j; #endif osm_log_t *p_log = p_bind->p_log; ib_api_status_t status; OSM_LOG_ENTER(p_log); /* Set the request information. */ sa_mad_data.method = IB_MAD_METHOD_GETTABLE; sa_mad_data.attr_mod = 0; sa_mad_data.attr_offset = 0; /* Set the MAD attributes and component mask correctly. */ switch (p_query_req->query_type) { case OSMV_QUERY_USER_DEFINED: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 USER_DEFINED\n"); p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; if (p_user_query->method) sa_mad_data.method = p_user_query->method; #ifdef DUAL_SIDED_RMPP if (sa_mad_data.method == IB_MAD_METHOD_GETMULTI || sa_mad_data.method == IB_MAD_METHOD_GETTRACETABLE) sa_mad_data.attr_offset = p_user_query->attr_offset; #endif sa_mad_data.attr_id = p_user_query->attr_id; sa_mad_data.attr_mod = p_user_query->attr_mod; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_ALL_SVC_RECS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = 0; sa_mad_data.p_attr = &u.svc_rec; break; case OSMV_QUERY_SVC_REC_BY_NAME: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_NAME\n"); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = IB_SR_COMPMASK_SNAME; sa_mad_data.p_attr = &u.svc_rec; memcpy(u.svc_rec.service_name, p_query_req->p_query_input, sizeof(ib_svc_name_t)); break; case OSMV_QUERY_SVC_REC_BY_ID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 SVC_REC_BY_ID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD; sa_mad_data.comp_mask = IB_SR_COMPMASK_SID; sa_mad_data.p_attr = &u.svc_rec; u.svc_rec.service_id = *(ib_net64_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_CLASS_PORT_INFO: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 CLASS_PORT_INFO\n"); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_CLASS_PORT_INFO; sa_mad_data.comp_mask = 0; sa_mad_data.p_attr = &u.class_port_info; break; case OSMV_QUERY_NODE_REC_BY_NODE_GUID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 NODE_REC_BY_NODE_GUID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD; sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID; sa_mad_data.p_attr = &u.node_rec; u.node_rec.node_info.node_guid = *(ib_net64_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_PORT_REC_BY_LID: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID\n"); sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID; sa_mad_data.p_attr = &u.port_info; u.port_info.lid = *(ib_net16_t *) (p_query_req->p_query_input); break; case OSMV_QUERY_PORT_REC_BY_LID_AND_NUM: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PORT_REC_BY_LID_AND_NUM\n"); sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_PORTNUM; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n"); sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD; sa_mad_data.comp_mask = IB_VLA_COMPMASK_LID | IB_VLA_COMPMASK_OUT_PORT | IB_VLA_COMPMASK_BLOCK; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_SLVL_BY_LID_AND_PORTS: sa_mad_data.method = IB_MAD_METHOD_GET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n"); sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD; sa_mad_data.comp_mask = IB_SLVL_COMPMASK_LID | IB_SLVL_COMPMASK_OUT_PORT | IB_SLVL_COMPMASK_IN_PORT; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_PATH_REC_BY_PORT_GUIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_PORT_GUIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH); u.path_rec.num_path = 0x7f; sa_mad_data.p_attr = &u.path_rec; ib_gid_set_default(&u.path_rec.dgid, ((osmv_guid_pair_t *) (p_query_req-> p_query_input))-> dest_guid); ib_gid_set_default(&u.path_rec.sgid, ((osmv_guid_pair_t *) (p_query_req-> p_query_input))-> src_guid); break; case OSMV_QUERY_PATH_REC_BY_GIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_GIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH); u.path_rec.num_path = 0x7f; sa_mad_data.p_attr = &u.path_rec; memcpy(&u.path_rec.dgid, &((osmv_gid_pair_t *) (p_query_req->p_query_input))-> dest_gid, sizeof(ib_gid_t)); memcpy(&u.path_rec.sgid, &((osmv_gid_pair_t *) (p_query_req->p_query_input))-> src_gid, sizeof(ib_gid_t)); break; case OSMV_QUERY_PATH_REC_BY_LIDS: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 PATH_REC_BY_LIDS\n"); memset(&u.path_rec, 0, sizeof(ib_path_rec_t)); sa_mad_data.method = IB_MAD_METHOD_GET; sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD; sa_mad_data.comp_mask = (IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID); sa_mad_data.p_attr = &u.path_rec; u.path_rec.dlid = ((osmv_lid_pair_t *) (p_query_req->p_query_input))->dest_lid; u.path_rec.slid = ((osmv_lid_pair_t *) (p_query_req->p_query_input))->src_lid; break; case OSMV_QUERY_UD_MULTICAST_SET: sa_mad_data.method = IB_MAD_METHOD_SET; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_SET\n"); sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; case OSMV_QUERY_UD_MULTICAST_DELETE: sa_mad_data.method = IB_MAD_METHOD_DELETE; p_user_query = (osmv_user_query_t *) p_query_req->p_query_input; OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 OSMV_QUERY_UD_MULTICAST_DELETE\n"); sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; break; #ifdef DUAL_SIDED_RMPP case OSMV_QUERY_MULTIPATH_REC: OSM_LOG(p_log, OSM_LOG_DEBUG, "DBG:001 MULTIPATH_REC\n"); /* Validate sgid/dgid counts against SA client limit */ p_mpr_req = (osmv_multipath_req_t *) p_query_req->p_query_input; if (p_mpr_req->sgid_count + p_mpr_req->dgid_count > IB_MULTIPATH_MAX_GIDS) { OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 MULTIPATH_REC " "SGID count %d DGID count %d max count %d\n", p_mpr_req->sgid_count, p_mpr_req->dgid_count, IB_MULTIPATH_MAX_GIDS); CL_ASSERT(0); return IB_ERROR; } memset(&u.multipath_rec, 0, sizeof(ib_multipath_rec_t)); sa_mad_data.method = IB_MAD_METHOD_GETMULTI; sa_mad_data.attr_id = IB_MAD_ATTR_MULTIPATH_RECORD; sa_mad_data.attr_offset = ib_get_attr_offset(sizeof(ib_multipath_rec_t)); sa_mad_data.p_attr = &u.multipath_rec; sa_mad_data.comp_mask = p_mpr_req->comp_mask; u.multipath_rec.num_path = p_mpr_req->num_path; if (p_mpr_req->reversible) u.multipath_rec.num_path |= 0x80; else u.multipath_rec.num_path &= ~0x80; u.multipath_rec.pkey = p_mpr_req->pkey; ib_multipath_rec_set_sl(&u.multipath_rec, p_mpr_req->sl); ib_multipath_rec_set_qos_class(&u.multipath_rec, 0); u.multipath_rec.independence = p_mpr_req->independence; u.multipath_rec.sgid_count = p_mpr_req->sgid_count; u.multipath_rec.dgid_count = p_mpr_req->dgid_count; j = 0; for (i = 0; i < p_mpr_req->sgid_count; i++, j++) u.multipath_rec.gids[j] = p_mpr_req->gids[j]; for (i = 0; i < p_mpr_req->dgid_count; i++, j++) u.multipath_rec.gids[j] = p_mpr_req->gids[j]; break; #endif default: OSM_LOG(p_log, OSM_LOG_ERROR, "DBG:001 UNKNOWN\n"); CL_ASSERT(0); return IB_ERROR; } status = __osmv_send_sa_req(h_bind, &sa_mad_data, p_query_req); OSM_LOG_EXIT(p_log); return status; } opensm-3.3.20/libvendor/osm_vendor_mlx_sim.c0000644000205000001450000003021312104655724016050 00000000000000/* * Copyright (c) 2004-2008 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. * */ /* AUTHOR Eitan Zahavi * * DESCRIPTION * The lower-level MAD transport interface implementation * that allows sending a single MAD/receiving a callback * when a single MAD is received. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include /* the simulator messages definition */ #include typedef struct _osmv_ibms_transport_mgr { ibms_conn_handle_t conHdl; /* the connection handle we talk to */ ibms_bind_msg_t filter; /* the bind message defining the filtering */ cl_thread_t receiver; /* the thread waiting for incomming messages */ } osmv_ibms_transport_mgr_t; static void __osmv_ibms_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend, IN struct _ibms_mad_addr *p_ibms_addr, IN uint8_t is_smi, OUT osm_mad_addr_t * p_osm_addr); static void __osmv_ibms_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_osm_addr, IN uint8_t is_smi, OUT struct _ibms_mad_addr *p_ibms_addr); /* this is the callback function the "server" will call on incoming messages */ void __osmv_ibms_receiver_callback(void *p_ctx, ibms_mad_msg_t * p_mad) { osm_mad_addr_t mad_addr; osmv_bind_obj_t *const p_bo = (osmv_bind_obj_t *) p_ctx; ib_api_status_t status = IB_SUCCESS; /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; { OSM_LOG_ENTER(p_bo->p_vendor->p_log); /* some logging */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "__osmv_ibms_receiver_callback: " "MAD QPN:%d SLID:0x%04x class:0x%02x " "method:0x%02x attr:0x%04x status:0x%04x " "tid:0x%016" PRIx64 "\n", p_mad->addr.dqpn, cl_ntoh16(p_mad->addr.slid), p_mad->header.mgmt_class, p_mad->header.method, cl_ntoh16(p_mad->header.attr_id), cl_ntoh16(p_mad->header.status), cl_ntoh64(p_mad->header.trans_id)); /* first arrange an address */ __osmv_ibms_mad_addr_to_osm_addr(p_bo->p_vendor, &p_mad->addr, (((ib_mad_t *) & p_mad-> header)->mgmt_class == IB_MCLASS_SUBN_LID) || (((ib_mad_t *) & p_mad-> header)->mgmt_class == IB_MCLASS_SUBN_DIR), &mad_addr); /* call the receiver callback */ status = osmv_dispatch_mad((osm_bind_handle_t) p_bo, (void *)&p_mad->header, &mad_addr); OSM_LOG_EXIT(p_bo->p_vendor->p_log); } } ib_api_status_t osm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend, IN char *hca_id, IN uint32_t port_num, OUT uint64_t * p_port_guid); /* * NAME * osmv_transport_init * * DESCRIPTION * Setup the MAD transport infrastructure (filters, callbacks etc). */ ib_api_status_t osmv_transport_init(IN osm_bind_info_t * p_info, IN char hca_id[VENDOR_HCA_MAXNAMES], IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo) { ibms_conn_handle_t conHdl; /* the connection we talk to the simulator through */ osmv_ibms_transport_mgr_t *p_mgr = malloc(sizeof(osmv_ibms_transport_mgr_t)); int qpn; int ibms_status; uint64_t port_guid; if (!p_mgr) { return IB_INSUFFICIENT_MEMORY; } memset(p_mgr, 0, sizeof(osmv_ibms_transport_mgr_t)); /* create the client socket connected to the simulator */ /* also perform the "connect" message - such that we validate the target guid */ if (osm_vendor_get_guid_by_ca_and_port (p_bo->p_vendor, hca_id, p_bo->port_num, &port_guid)) { return IB_INVALID_GUID; } conHdl = ibms_connect(port_guid, __osmv_ibms_receiver_callback, (void *)p_bo); if (!conHdl) { printf("fail to connect to the server.\n"); exit(1); } /* * Create the MAD filter on this file handle. */ p_mgr->filter.port = p_bo->port_num; p_mgr->filter.only_input = 1; p_mgr->filter.mask = IBMS_BIND_MASK_PORT | IBMS_BIND_MASK_INPUT | IBMS_BIND_MASK_QP | IBMS_BIND_MASK_CLASS; switch (p_info->mad_class) { case IB_MCLASS_SUBN_LID: case IB_MCLASS_SUBN_DIR: qpn = 0; p_mgr->filter.qpn = qpn; p_mgr->filter.mgt_class = IB_MCLASS_SUBN_LID; ibms_status = ibms_bind(conHdl, &p_mgr->filter); if (ibms_status) { return IB_ERROR; } p_mgr->filter.mgt_class = IB_MCLASS_SUBN_DIR; ibms_status = ibms_bind(conHdl, &p_mgr->filter); if (ibms_status) { return IB_ERROR; } break; case IB_MCLASS_SUBN_ADM: default: qpn = 1; p_mgr->filter.qpn = qpn; p_mgr->filter.mgt_class = p_info->mad_class; ibms_status = ibms_bind(conHdl, &p_mgr->filter); if (ibms_status) { return IB_ERROR; } break; } p_mgr->conHdl = conHdl; p_bo->p_transp_mgr = p_mgr; /* Initialize the magic_ptr to the pointer of the p_bo info. This will be used to signal when the object is being destroyed, so no real action will be done then. */ p_bo->magic_ptr = p_bo; return IB_SUCCESS; } /* * NAME * osmv_transport_send_mad * * DESCRIPTION * Send a single MAD (256 byte) */ ib_api_status_t osmv_transport_mad_send(IN const osm_bind_handle_t h_bind, IN void *p_mad, IN const osm_mad_addr_t * p_mad_addr) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; int ret; ibms_mad_msg_t mad_msg; ib_api_status_t status; const ib_mad_t *p_mad_hdr = p_mad; OSM_LOG_ENTER(p_vend->p_log); memset(&mad_msg, 0, sizeof(mad_msg)); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return IB_INVALID_CALLBACK; /* * Copy the MAD over to the sent mad */ memcpy(&mad_msg.header, p_mad_hdr, MAD_BLOCK_SIZE); /* * For all sends other than directed route SM MADs, * acquire an address vector for the destination. */ if (p_mad_hdr->mgmt_class != IB_MCLASS_SUBN_DIR) { __osmv_ibms_osm_addr_to_mad_addr(p_mad_addr, p_mad_hdr->mgmt_class == IB_MCLASS_SUBN_LID, &mad_msg.addr); } else { /* is a directed route - we need to construct a permissive address */ /* we do not need port number since it is part of the mad_hndl */ mad_msg.addr.dlid = IB_LID_PERMISSIVE; mad_msg.addr.slid = IB_LID_PERMISSIVE; mad_msg.addr.sqpn = 0; mad_msg.addr.dqpn = 0; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_mad_send: " "Sending QPN:%d DLID:0x%04x class:0x%02x " "method:0x%02x attr:0x%04x status:0x%04x " "tid:0x%016" PRIx64 "\n", mad_msg.addr.dqpn, cl_ntoh16(mad_msg.addr.dlid), mad_msg.header.mgmt_class, mad_msg.header.method, cl_ntoh16(mad_msg.header.attr_id), cl_ntoh16(mad_msg.header.status), cl_ntoh64(mad_msg.header.trans_id) ); /* send it */ ret = ibms_send(((osmv_ibms_transport_mgr_t *) (p_bo->p_transp_mgr))-> conHdl, &mad_msg); if (ret) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osmv_transport_mad_send: ERR 5304: " "Error sending mad (%d).\n", ret); status = IB_ERROR; goto Exit; } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } void osmv_transport_done(IN const osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osmv_ibms_transport_mgr_t *p_tpot_mgr = (osmv_ibms_transport_mgr_t *) (p_bo->p_transp_mgr); CL_ASSERT(p_bo); /* First of all - zero out the magic_ptr, so if a callback is called - it'll know that we are currently closing down, and will not handle the mad. */ p_bo->magic_ptr = 0; /* usleep(3000000); */ ibms_disconnect(p_tpot_mgr->conHdl); /* seems the only way to abort a blocking read is to make it read something */ free(p_tpot_mgr); } static void __osmv_ibms_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_osm_addr, IN uint8_t is_smi, OUT struct _ibms_mad_addr *p_ibms_addr) { /* For global destination or Multicast address: */ p_ibms_addr->dlid = cl_ntoh16(p_osm_addr->dest_lid); p_ibms_addr->sl = p_osm_addr->addr_type.gsi.service_level; if (is_smi) { p_ibms_addr->sqpn = 0; p_ibms_addr->dqpn = 0; } else { p_ibms_addr->sqpn = 1; p_ibms_addr->dqpn = cl_ntoh32(p_osm_addr->addr_type.gsi.remote_qp); } /* HACK we limit to the first PKey Index assuming it will always be the default PKey */ p_ibms_addr->pkey_index = 0; } static void __osmv_ibms_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend, IN struct _ibms_mad_addr *p_ibms_addr, IN uint8_t is_smi, OUT osm_mad_addr_t * p_osm_addr) { memset(p_osm_addr, 0, sizeof(osm_mad_addr_t)); p_osm_addr->dest_lid = cl_hton16(p_ibms_addr->slid); p_osm_addr->static_rate = 0; p_osm_addr->path_bits = 0; if (is_smi) { /* SMI */ p_osm_addr->addr_type.smi.source_lid = cl_hton16(p_ibms_addr->slid); p_osm_addr->addr_type.smi.port_num = 1; /* TODO add if required p_ibms_addr->port; */ } else { /* GSI */ p_osm_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_ibms_addr->sqpn); p_osm_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY; p_osm_addr->addr_type.gsi.pkey_ix = p_ibms_addr->pkey_index; p_osm_addr->addr_type.gsi.service_level = p_ibms_addr->sl; p_osm_addr->addr_type.gsi.global_route = FALSE; /* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */ /* if (p_osm_addr->addr_type.gsi.global_route) { p_osm_addr->addr_type.gsi.grh_info.ver_class_flow = ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version, p_rcv_desc->grh.traffic_class, p_rcv_desc->grh.flow_label); p_osm_addr->addr_type.gsi.grh_info.hop_limit = p_rcv_desc->grh.hop_limit; memcpy(&p_osm_addr->addr_type.gsi.grh_info.src_gid.raw, &p_rcv_desc->grh.sgid, sizeof(ib_net64_t)); memcpy(&p_osm_addr->addr_type.gsi.grh_info.dest_gid.raw, p_rcv_desc->grh.dgid, sizeof(ib_net64_t)); } */ } } /* * NAME osm_vendor_set_sm * * DESCRIPTION Modifies the port info for the bound port to set the "IS_SM" bit * according to the value given (TRUE or FALSE). */ void osm_vendor_set_sm(IN osm_bind_handle_t h_bind, IN boolean_t is_sm_val) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_vendor_t const *p_vend = p_bo->p_vendor; int ret; ibms_cap_msg_t cap_msg; OSM_LOG_ENTER(p_vend->p_log); cap_msg.mask = IB_PORT_CAP_IS_SM; if (is_sm_val) cap_msg.capabilities = IB_PORT_CAP_IS_SM; else cap_msg.capabilities = 0; ret = ibms_set_cap(((osmv_ibms_transport_mgr_t *) (p_bo-> p_transp_mgr))-> conHdl, &cap_msg); if (ret) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_set_sm: ERR 5312: " "Unable set 'IS_SM' bit to:%u in port attributes.\n", is_sm_val); } OSM_LOG_EXIT(p_vend->p_log); } opensm-3.3.20/libvendor/osm_vendor_mlx_hca_sim.c0000644000205000001450000005715612104655724016702 00000000000000/* * Copyright (c) 2004-2008 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #if defined(OSM_VENDOR_INTF_SIM) #undef IN #undef OUT #include #include #include #include #include #include #include #include #include #include #include /****************************************************************************** * * Provides the functionality for selecting an HCA Port and Obtaining it's guid. * This version is based on $IBMGTSIM_DIR/$IBMGTSIM_NODE file system. * This is a mimic of the OpenIB gen1 file system * ******************************************************************************/ char *__get_simulator_dir(void) { static char *ibmgtSimDir = NULL; static char *defaultIbmgtSimDir = "/tmp/ibmgtsim"; static char *ibmgtSimNode = NULL; static char dirName[1024]; /* we use the first pointer to know if we were here */ if (ibmgtSimDir == NULL) { /* obtain the simulator directory */ ibmgtSimDir = getenv("IBMGTSIM_DIR"); if (ibmgtSimDir == NULL) { printf ("-W- Environment variable: IBMGTSIM_DIR does not exist.\n"); printf (" Please create one used by the simulator.\n"); printf(" Using /tmp/ibmgtsim as default.\n"); ibmgtSimDir = defaultIbmgtSimDir; } /* obtain the node name we simulate */ ibmgtSimNode = getenv("IBMGTSIM_NODE"); if (ibmgtSimNode == NULL) { printf ("-W- Environment variable: IBMGTSIM_NODE does not exist.\n"); printf (" This variable should be the name of the node you wish to simulate.\n"); printf(" Using H-1 as default.\n"); ibmgtSimNode = "H-1"; } sprintf(dirName, "%s/%s", ibmgtSimDir, ibmgtSimNode); } return dirName; } typedef struct _osm_ca_info { ib_net64_t guid; size_t attr_size; ib_ca_attr_t *p_attr; } osm_ca_info_t; /********************************************************************** * Returns a pointer to the port attribute of the specified port * owned by this CA. ************************************************************************/ static ib_port_attr_t *__osm_ca_info_get_port_attr_ptr(IN const osm_ca_info_t * const p_ca_info, IN const uint8_t index) { return (&p_ca_info->p_attr->p_port_attr[index]); } /********************************************************************** * Obtain the number of local CAs by scanning /proc/infiniband/core **********************************************************************/ int __hca_sim_get_num_cas(void) { int num_cas = 0; DIR *dp; struct dirent *ep; dp = opendir(__get_simulator_dir()); if (dp != NULL) { while ((ep = readdir(dp))) { /* CAs are directories with the format ca[1-9][0-9]* */ /* if ((ep->d_type == DT_DIR) && !strncmp(ep->d_name, "ca", 2)) */ if (!strncmp(ep->d_name, "ca", 2)) { num_cas++; } } closedir(dp); } else { printf("__hca_sim_get_num_cas: ERROR : ail to open dir %s\n", __get_simulator_dir()); exit(1); } if (!num_cas) exit(1); return num_cas; } /* name: InfiniHost0 provider: tavor node GUID: 0002:c900:0120:3470 ports: 2 vendor ID: 0x2c9 device ID: 0x5a44 HW revision: 0xa1 FW revision: 0x300020080 */ typedef struct _sim_ca_info { char name[32]; char provider[32]; uint64_t guid; uint8_t num_ports; uint32_t vend_id; uint16_t dev_id; uint16_t rev_id; uint64_t fw_rev; } sim_ca_info_t; /********************************************************************** * Parse the CA Info file available in ibmgtSimDir/caN/info **********************************************************************/ static ib_api_status_t __parse_ca_info_file(IN osm_vendor_t * const p_vend, IN uint32_t idx, OUT sim_ca_info_t * sim_ca_info) { ib_api_status_t status = IB_ERROR; int info_file; char file_name[256]; char file_buffer[3200]; char *p_ch; int g1, g2, g3, g4; int num_ports; uint32_t len; OSM_LOG_ENTER(p_vend->p_log); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__parse_ca_info_file: " "Querying CA %d.\n", idx); /* we use the proc file system so we must be able to open the info file .. */ sprintf(file_name, "%s/ca%d/info", __get_simulator_dir(), idx); info_file = open(file_name, O_RDONLY); if (!info_file) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5105: " "Fail to open HCA:%d info file:(%s).\n", idx, file_name); goto Exit; } /* read in the file */ len = read(info_file, file_buffer, 3200); close(info_file); file_buffer[len] = '\0'; /* parse the file ... name: InfiniHost0 provider: tavor node GUID: 0002:c900:0120:3470 ports: 2 vendor ID: 0x2c9 device ID: 0x5a44 HW revision: 0xa1 FW revision: 0x300020080 */ if (!(p_ch = strstr(file_buffer, "name:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5106: " "Fail to obtain HCA name. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "name: %s", sim_ca_info->name) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5107: " "Fail to parse name in info file:(%s).\n", p_ch); goto Exit; } /* get the guid of the HCA */ if (!(p_ch = strstr(file_buffer, "node GUID:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5108: " "Fail to obtain GUID in info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "node GUID: %x:%x:%x:%x", &g1, &g2, &g3, &g4) != 4) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5109: " "Fail to parse GUID in info file:(%s).\n", p_ch); goto Exit; } sim_ca_info->guid = (uint64_t) g1 << 48 | (uint64_t) g1 << 32 | (uint64_t) g1 << 16 | (uint64_t) g3; /* obtain number of ports */ if (!(p_ch = strstr(file_buffer, "ports:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5110: " "Fail to obtain number of ports in info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "ports: %d", &num_ports) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_ca_info_file: ERR 5111: " "Fail to parse num ports in info file:(%s).\n", p_ch); goto Exit; } sim_ca_info->num_ports = num_ports; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__parse_ca_info_file: " "CA1 = name:%s guid:0x%" PRIx64 " ports:%d\n", sim_ca_info->name, sim_ca_info->guid, sim_ca_info->num_ports); status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return status; } /* state: ACTIVE LID: 0x0001 LMC: 0x0000 SM LID: 0x0001 SM SL: 0x0000 Capabilities: IsSM IsTrapSupported IsAutomaticMigrationSupported IsSLMappingSupported IsLEDInfoSupported IsSystemImageGUIDSupported IsVendorClassSupported IsCapabilityMaskNoticeSupported */ typedef struct _sim_port_info { uint8_t state; uint16_t lid; uint8_t lmc; uint16_t sm_lid; uint8_t sm_sl; } sim_port_info_t; /********************************************************************** * Parse the Port Info file available in ibmgtSimDir/caN/portM/info * Port num is 1..N **********************************************************************/ static ib_api_status_t __parse_port_info_file(IN osm_vendor_t * const p_vend, IN uint32_t hca_idx, IN uint8_t port_num, OUT sim_port_info_t * sim_port_info) { ib_api_status_t status = IB_ERROR; int info_file; char file_name[256]; char file_buffer[3200]; char state[12]; char *p_ch; int lid, sm_lid, lmc, sm_sl; uint32_t len; OSM_LOG_ENTER(p_vend->p_log); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__parse_port_info_file: " "Parsing Proc File System Port Info CA %d Port %d.\n", hca_idx, port_num); /* we use the proc file system so we must be able to open the info file .. */ sprintf(file_name, "%s/ca%d/port%d/info", __get_simulator_dir(), hca_idx, port_num); info_file = open(file_name, O_RDONLY); if (!info_file) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5112: " "Fail to open HCA:%d Port:%d info file:(%s).\n", hca_idx, port_num, file_name); goto Exit; } /* read in the file */ len = read(info_file, file_buffer, 3200); close(info_file); file_buffer[len] = '\0'; /* parse the file ... state: ACTIVE LID: 0x0001 LMC: 0x0000 SM LID: 0x0001 SM SL: 0x0000 ... */ if (!(p_ch = strstr(file_buffer, "state:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5113: " "Fail to obtain port state. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "state: %s", state) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5114: " "Fail to parse state from info file:(%s).\n", p_ch); goto Exit; } if (!strcmp(state, "ACTIVE")) sim_port_info->state = IB_LINK_ACTIVE; else if (!strcmp(state, "DOWN")) sim_port_info->state = IB_LINK_DOWN; else if (!strcmp(state, "INIT")) sim_port_info->state = IB_LINK_INIT; else if (!strcmp(state, "ARMED")) sim_port_info->state = IB_LINK_ARMED; else sim_port_info->state = 0; /* get lid */ if (!(p_ch = strstr(file_buffer, "LID:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5115: " "Fail to obtain port lid. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "LID: %x", &lid) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5116: " "Fail to parse lid from info file:(%s).\n", p_ch); goto Exit; } sim_port_info->lid = lid; /* get LMC */ if (!(p_ch = strstr(file_buffer, "LMC:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5117: " "Fail to obtain port LMC. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "LMC: %x", &lmc) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5118: " "Fail to parse LMC from info file:(%s).\n", p_ch); goto Exit; } sim_port_info->lmc = lmc; /* get SM LID */ if (!(p_ch = strstr(file_buffer, "SM LID:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5119: " "Fail to obtain port SM LID. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "SM LID: %x", &sm_lid) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5120: " "Fail to parse SM LID from info file:(%s).\n", p_ch); goto Exit; } sim_port_info->sm_lid = sm_lid; /* get SM LID */ if (!(p_ch = strstr(file_buffer, "SM SL:"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5121: " "Fail to obtain port SM SL. In info file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch, "SM SL: %x", &sm_sl) != 1) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__parse_port_info_file: ERR 5122: " "Fail to parse SM SL from info file:(%s).\n", p_ch); goto Exit; } sim_port_info->sm_sl = sm_sl; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__parse_port_info_file: " "Obtained Port:%d = state:%d, lid:0x%04X, lmc:%d, sm_lid:0x%04X, sm_sl:%d\n", port_num, sim_port_info->state, sim_port_info->lid, sim_port_info->lmc, sim_port_info->sm_lid, sim_port_info->sm_sl); status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return status; } /********************************************************************** * Parse the port guid_tbl file to obtain the port guid. * File format is: * [ 0] fe80:0000:0000:0000:0002:c900:0120:3472 **********************************************************************/ static ib_api_status_t __get_port_guid_from_port_gid_tbl(IN osm_vendor_t * const p_vend, IN uint32_t hca_idx, IN uint8_t port_num, OUT uint64_t * port_guid) { ib_api_status_t status = IB_ERROR; int info_file; char file_name[256]; char file_buffer[3200]; char *p_ch; int g[8]; uint32_t len; OSM_LOG_ENTER(p_vend->p_log); osm_log(p_vend->p_log, OSM_LOG_DEBUG, "__get_port_guid_from_port_gid_tbl: " "Parsing Proc File System Port Guid Table CA %d Port %d.\n", hca_idx, port_num); /* we use the proc file system so we must be able to open the info file .. */ sprintf(file_name, "%s/ca%d/port%d/gid_table", __get_simulator_dir(), hca_idx, port_num); info_file = open(file_name, O_RDONLY); if (!info_file) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__get_port_guid_from_port_gid_tbl: ERR 5123: " "Fail to open HCA:%d Port:%d gid_table file:(%s).\n", hca_idx, port_num, file_name); goto Exit; } /* read in the file */ len = read(info_file, file_buffer, 3200); close(info_file); file_buffer[len] = '\0'; /* parse the file ... [ 0] fe80:0000:0000:0000:0002:c900:0120:3472 ... */ if (!(p_ch = strstr(file_buffer, "[ 0]"))) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__get_port_guid_from_port_gid_tbl: ERR 5124: " "Fail to obtain first gid index. In gid_table file:(%s).\n", file_buffer); goto Exit; } if (sscanf(p_ch + 6, "%x:%x:%x:%x:%x:%x:%x:%x", &g[7], &g[6], &g[5], &g[4], &g[3], &g[2], &g[1], &g[0]) != 8) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__get_port_guid_from_port_gid_tbl: ERR 5125: " "Fail to parse gid from gid_table file:(%s).\n", p_ch); goto Exit; } *port_guid = (uint64_t) g[3] << 48 | (uint64_t) g[2] << 32 | (uint64_t) g[1] << 16 | g[0]; status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return status; } /********************************************************************** * Initialize an Info Struct for the Given HCA by its index 1..N **********************************************************************/ static ib_api_status_t __osm_ca_info_init(IN osm_vendor_t * const p_vend, IN uint32_t const idx, OUT osm_ca_info_t * const p_ca_info) { ib_api_status_t status = IB_ERROR; uint8_t port_num; uint64_t port_guid; sim_ca_info_t sim_ca_info; OSM_LOG_ENTER(p_vend->p_log); /* parse the CA info file */ if (__parse_ca_info_file(p_vend, idx, &sim_ca_info) != IB_SUCCESS) goto Exit; p_ca_info->guid = cl_hton64(sim_ca_info.guid); /* set size of attributes and allocate them */ p_ca_info->attr_size = 1; p_ca_info->p_attr = (ib_ca_attr_t *) malloc(sizeof(ib_ca_attr_t)); p_ca_info->p_attr->ca_guid = p_ca_info->guid; p_ca_info->p_attr->num_ports = sim_ca_info.num_ports; /* now obtain the attributes of the ports */ p_ca_info->p_attr->p_port_attr = (ib_port_attr_t *) malloc(sim_ca_info.num_ports * sizeof(ib_port_attr_t)); /* get all the ports info */ for (port_num = 1; port_num <= sim_ca_info.num_ports; port_num++) { sim_port_info_t sim_port_info; /* query the port attributes */ if (__parse_port_info_file (p_vend, idx, port_num, &sim_port_info)) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 5126: " "Fail to get HCA:%d Port:%d Attributes.\n", idx, port_num); goto Exit; } /* HACK: the lids should have been converted to network but the rest of the code is wrong and provdes them as is (host order) - so we stick with it. */ p_ca_info->p_attr->p_port_attr[port_num - 1].lid = sim_port_info.lid; p_ca_info->p_attr->p_port_attr[port_num - 1].link_state = sim_port_info.state; p_ca_info->p_attr->p_port_attr[port_num - 1].sm_lid = sim_port_info.sm_lid; /* get the port guid */ if (__get_port_guid_from_port_gid_tbl (p_vend, idx, port_num, &port_guid)) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "__osm_ca_info_init: ERR 5127: " "Fail to get HCA:%d Port:%d Guid.\n", idx, port_num); goto Exit; } p_ca_info->p_attr->p_port_attr[port_num - 1].port_guid = cl_hton64(port_guid); } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } void osm_ca_info_destroy(IN osm_vendor_t * const p_vend, IN osm_ca_info_t * const p_ca_info, IN uint8_t num_ca) { osm_ca_info_t *p_ca; uint8_t i; OSM_LOG_ENTER(p_vend->p_log); for (i = 0; i < num_ca; i++) { p_ca = &p_ca_info[i]; if (NULL != p_ca->p_attr) { if (0 != p_ca->p_attr->num_ports) { free(p_ca->p_attr->p_port_attr); } free(p_ca->p_attr); } } free(p_ca_info); OSM_LOG_EXIT(p_vend->p_log); } /********************************************************************** * Fill in the array of port_attr with all available ports on ALL the * avilable CAs on this machine. **********************************************************************/ ib_api_status_t osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend, IN ib_port_attr_t * const p_attr_array, IN uint32_t * const p_num_ports) { ib_api_status_t status = IB_SUCCESS; uint32_t caIdx; uint32_t ca_count = 0; uint32_t port_count = 0; uint8_t port_num; uint32_t total_ports = 0; osm_ca_info_t *p_ca_infos = NULL; uint32_t attr_array_sz = *p_num_ports; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend); /* determine the number of CA's */ ca_count = __hca_sim_get_num_cas(); if (!ca_count) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 5128: " "Fail to get Any CA Ids.\n"); goto Exit; } /* Allocate an array big enough to hold the ca info objects */ p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t)); if (p_ca_infos == NULL) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 5129: " "Unable to allocate CA information array.\n"); goto Exit; } memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t)); /* * For each CA, retrieve the CA info attributes */ for (caIdx = 1; caIdx <= ca_count; caIdx++) { status = __osm_ca_info_init(p_vend, caIdx, &p_ca_infos[caIdx - 1]); if (status != IB_SUCCESS) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_all_port_attr: ERR 5130: " "Unable to initialize CA Info object (%s).\n", ib_get_err_str(status)); goto Exit; } total_ports += p_ca_infos[caIdx - 1].p_attr->num_ports; } *p_num_ports = total_ports; osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get_all_port_attr: total ports:%u \n", total_ports); /* * If the user supplied enough storage, return the port guids, * otherwise, return the appropriate error. */ if (attr_array_sz >= total_ports) { for (caIdx = 1; caIdx <= ca_count; caIdx++) { uint32_t num_ports; num_ports = p_ca_infos[caIdx - 1].p_attr->num_ports; for (port_num = 0; port_num < num_ports; port_num++) { p_attr_array[port_count] = *__osm_ca_info_get_port_attr_ptr(&p_ca_infos [caIdx - 1], port_num); port_count++; } } } else { status = IB_INSUFFICIENT_MEMORY; goto Exit; } status = IB_SUCCESS; Exit: if (p_ca_infos) { osm_ca_info_destroy(p_vend, p_ca_infos, ca_count); } OSM_LOG_EXIT(p_vend->p_log); return (status); } /********************************************************************** * Given the vendor obj and a port guid * return the ca id and port number that have that guid **********************************************************************/ ib_api_status_t osm_vendor_get_guid_ca_and_port(IN osm_vendor_t * const p_vend, IN ib_net64_t const guid, OUT uint32_t * p_hca_hndl, OUT char *p_hca_id, OUT uint8_t * p_hca_idx, OUT uint32_t * p_port_num) { uint32_t caIdx; uint32_t ca_count = 0; uint8_t port_num; ib_api_status_t status = IB_ERROR; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend); /* determine the number of CA's */ ca_count = __hca_sim_get_num_cas(); if (!ca_count) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 5131: " "Fail to get Any CA Ids.\n"); goto Exit; } /* * For each CA, retrieve the CA info attributes */ for (caIdx = 1; caIdx <= ca_count; caIdx++) { sim_ca_info_t sim_ca_info; if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) == IB_SUCCESS) { /* get all the ports info */ for (port_num = 1; port_num <= sim_ca_info.num_ports; port_num++) { uint64_t port_guid; if (!__get_port_guid_from_port_gid_tbl (p_vend, caIdx, port_num, &port_guid)) { if (cl_hton64(port_guid) == guid) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get_guid_ca_and_port: " "Found Matching guid on HCA:%d Port:%d.\n", caIdx, port_num); strcpy(p_hca_id, sim_ca_info.name); *p_port_num = port_num; *p_hca_idx = caIdx - 1; *p_hca_hndl = 0; status = IB_SUCCESS; goto Exit; } } } } } osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_ca_and_port: ERR 5132: " "Fail to find HCA and Port for Port Guid 0x%" PRIx64 "\n", cl_ntoh64(guid)); status = IB_INVALID_GUID; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } /********************************************************************** * Given the vendor obj HCA ID and Port Num * update the given port guid if found. Return 0 on success. **********************************************************************/ ib_api_status_t osm_vendor_get_guid_by_ca_and_port(IN osm_vendor_t * const p_vend, IN char *hca_id, IN uint32_t port_num, OUT uint64_t * p_port_guid) { uint32_t caIdx; uint32_t ca_count = 0; ib_api_status_t status = IB_ERROR; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_vend); /* determine the number of CA's */ ca_count = __hca_sim_get_num_cas(); if (!ca_count) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_by_ca_and_port: ERR 5133: " "Fail to get Any CA Ids.\n"); goto Exit; } /* * For each CA, retrieve the CA info attributes */ for (caIdx = 1; caIdx <= ca_count; caIdx++) { sim_ca_info_t sim_ca_info; if (__parse_ca_info_file(p_vend, caIdx, &sim_ca_info) == IB_SUCCESS) { /* if not identical by id - go to next one */ if (strcmp(sim_ca_info.name, hca_id)) continue; if ((port_num < 1) || (port_num > sim_ca_info.num_ports)) { return 1; } if (!__get_port_guid_from_port_gid_tbl (p_vend, caIdx, port_num, p_port_guid)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osm_vendor_get_guid_by_ca_and_port: " "Found Matching guid on HCA:%d Port:%d.\n", caIdx, port_num); status = IB_SUCCESS; goto Exit; } } } osm_log(p_vend->p_log, OSM_LOG_ERROR, "osm_vendor_get_guid_by_ca_and_port: ERR 5134: " "Fail to find HCA:%s\n", hca_id); status = IB_INVALID_GUID; Exit: OSM_LOG_EXIT(p_vend->p_log); return (status); } #endif opensm-3.3.20/libvendor/osm_vendor_mlx_ibmgt.c0000644000205000001450000005564212104655724016377 00000000000000/* * Copyright (c) 2004-2008 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. * */ /* AUTHOR Edward Bortnikov * * DESCRIPTION * The lower-level MAD transport interface implementation * that allows sending a single MAD/receiving a callback * when a single MAD is received. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include typedef struct _osmv_IBMGT_transport_mgr_ { IB_MGT_mad_type_t mad_type; uint8_t mgmt_class; /* for gsi */ /* for communication between send call back and send mad */ boolean_t is_send_ok; cl_event_t send_done; } osmv_IBMGT_transport_mgr_t; typedef struct _osmv_IBMGT_transport_info_ { IB_MGT_mad_hndl_t smi_h; cl_qlist_t *p_smi_list; IB_MGT_mad_hndl_t gsi_h; /* holds bind object list for every binded mgmt class */ cl_qlist_t *gsi_mgmt_lists[15]; } osmv_IBMGT_transport_info_t; static void __osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc, IN uint8_t is_smi, OUT osm_mad_addr_t * p_mad_addr); static void __osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr, IN uint8_t is_smi, OUT IB_ud_av_t * p_av); void __osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl, IN u_int64_t wrid, IN IB_comp_status_t status, IN void *private_ctx_p); void __osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl, IN void *private_ctx_p, IN void *payload_p, IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p); /* * NAME * osmv_transport_init * * DESCRIPTION * Setup the MAD transport infrastructure (filters, callbacks etc). */ ib_api_status_t osmv_transport_init(IN osm_bind_info_t * p_info, IN char hca_id[VENDOR_HCA_MAXNAMES], IN uint8_t hca_idx, IN osmv_bind_obj_t * p_bo) { ib_api_status_t st = IB_SUCCESS; IB_MGT_ret_t ret; IB_MGT_mad_type_t mad_type; osmv_IBMGT_transport_mgr_t *p_mgr; osmv_IBMGT_transport_info_t *p_tpot_info; cl_list_obj_t *p_obj = NULL; osm_log_t *p_log = p_bo->p_vendor->p_log; int i; UNUSED_PARAM(hca_idx); /* if first bind, allocate tranport_info at vendor */ if (NULL == p_bo->p_vendor->p_transport_info) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: first bind() for the vendor\n"); p_bo->p_vendor->p_transport_info = (osmv_IBMGT_transport_info_t *) malloc(sizeof(osmv_IBMGT_transport_info_t)); if (NULL == p_bo->p_vendor->p_transport_info) { return IB_INSUFFICIENT_MEMORY; } memset(p_bo->p_vendor->p_transport_info, 0, sizeof(osmv_IBMGT_transport_info_t)); p_tpot_info = (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor-> p_transport_info); p_tpot_info->smi_h = 0xffffffff; p_tpot_info->p_smi_list = NULL; p_tpot_info->gsi_h = 0xffffffff; for (i = 0; i < 15; i++) { p_tpot_info->gsi_mgmt_lists[i] = NULL; } } else { p_tpot_info = (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor-> p_transport_info); } /* Initialize the magic_ptr to the pointer of the p_bo info. This will be used to signal when the object is being destroyed, so no real action will be done then. */ p_bo->magic_ptr = p_bo; /* allocate transport mgr */ p_mgr = malloc(sizeof(osmv_IBMGT_transport_mgr_t)); if (NULL == p_mgr) { free(p_tpot_info); osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7201: " "alloc failed \n"); return IB_INSUFFICIENT_MEMORY; } memset(p_mgr, 0, sizeof(osmv_IBMGT_transport_mgr_t)); p_bo->p_transp_mgr = p_mgr; switch (p_info->mad_class) { case IB_MCLASS_SUBN_LID: case IB_MCLASS_SUBN_DIR: mad_type = IB_MGT_SMI; break; case IB_MCLASS_SUBN_ADM: default: mad_type = IB_MGT_GSI; break; } /* we only support one class registration per SMI/GSI !!! */ switch (mad_type) { case IB_MGT_SMI: /* we do not need to bind the handle if already available */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: SMI bind\n"); if (p_tpot_info->smi_h == 0xffffffff) { ret = IB_MGT_get_handle(hca_id, p_bo->port_num, IB_MGT_SMI, &(p_tpot_info->smi_h)); if (IB_MGT_OK != ret) { osm_log(p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7202: " "IB_MGT_get_handle for smi failed \n"); st = IB_ERROR; free(p_mgr); goto Exit; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: got smi handle:%d \n", p_tpot_info->smi_h); ret = IB_MGT_bind_sm(p_tpot_info->smi_h); if (IB_MGT_OK != ret) { osm_log(p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7203: " "IB_MGT_bind_sm failed \n"); st = IB_ERROR; free(p_mgr); goto Exit; } /* init smi list */ p_tpot_info->p_smi_list = malloc(sizeof(cl_qlist_t)); if (NULL == p_tpot_info->p_smi_list) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7204: " "alloc failed \n"); IB_MGT_unbind_sm(p_tpot_info->smi_h); IB_MGT_release_handle(p_tpot_info->smi_h); free(p_mgr); return IB_INSUFFICIENT_MEMORY; } memset(p_tpot_info->p_smi_list, 0, sizeof(cl_qlist_t)); cl_qlist_init(p_tpot_info->p_smi_list); osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: before reg_cb\n"); ret = IB_MGT_reg_cb(p_tpot_info->smi_h, &__osmv_IBMGT_rcv_cb, p_bo, &__osmv_IBMGT_send_cb, p_tpot_info->p_smi_list, IB_MGT_RCV_CB_MASK | IB_MGT_SEND_CB_MASK); if (ret != IB_SUCCESS) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7205: " "reg_cb failed with return code:%x \n", ret); IB_MGT_unbind_sm(p_tpot_info->smi_h); IB_MGT_release_handle(p_tpot_info->smi_h); free(p_tpot_info->p_smi_list); free(p_mgr); st = IB_ERROR; goto Exit; } } /* insert to list of smi's - for raising callbacks later on */ p_obj = malloc(sizeof(cl_list_obj_t)); if (p_obj) memset(p_obj, 0, sizeof(cl_list_obj_t)); cl_qlist_set_obj(p_obj, p_bo); cl_qlist_insert_tail(p_tpot_info->p_smi_list, &p_obj->list_item); break; case IB_MGT_GSI: /* we do not need to bind the handle if already available */ osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: ERR 7206: GSI bind\n"); if (p_tpot_info->gsi_h == 0xffffffff) { ret = IB_MGT_get_handle(hca_id, p_bo->port_num, IB_MGT_GSI, &(p_tpot_info->gsi_h)); if (IB_MGT_OK != ret) { osm_log(p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7207: " "IB_MGT_get_handle for gsi failed \n"); st = IB_ERROR; free(p_mgr); goto Exit; } } /* this mgmt class was not binded yet */ if (p_tpot_info->gsi_mgmt_lists[p_info->mad_class] == NULL) { ret = IB_MGT_bind_gsi_class(p_tpot_info->gsi_h, p_info->mad_class); if (IB_MGT_OK != ret) { osm_log(p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7208: " "IB_MGT_bind_gsi_class failed \n"); st = IB_ERROR; free(p_mgr); goto Exit; } p_tpot_info->gsi_mgmt_lists[p_info->mad_class] = malloc(sizeof(cl_qlist_t)); if (NULL == p_tpot_info->gsi_mgmt_lists[p_info->mad_class]) { IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h, p_info->mad_class); free(p_mgr); return IB_INSUFFICIENT_MEMORY; } memset(p_tpot_info->gsi_mgmt_lists[p_info->mad_class], 0, sizeof(cl_qlist_t)); cl_qlist_init(p_tpot_info-> gsi_mgmt_lists[p_info->mad_class]); } /* insert to list of smi's - for raising callbacks later on */ p_obj = malloc(sizeof(cl_list_obj_t)); if (p_obj) memset(p_obj, 0, sizeof(cl_list_obj_t)); cl_qlist_set_obj(p_obj, p_bo); cl_qlist_insert_tail(p_tpot_info-> gsi_mgmt_lists[p_info->mad_class], &p_obj->list_item); p_mgr->mgmt_class = p_info->mad_class; ret = IB_MGT_reg_cb(p_tpot_info->gsi_h, &__osmv_IBMGT_rcv_cb, p_bo, &__osmv_IBMGT_send_cb, p_bo, IB_MGT_RCV_CB_MASK | IB_MGT_SEND_CB_MASK); if (ret != IB_SUCCESS) { IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h, p_mgr->mgmt_class); free(p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class]); free(p_mgr); st = IB_ERROR; goto Exit; } break; default: osm_log(p_log, OSM_LOG_ERROR, "osmv_transport_init: ERR 7209: unrecognized mgmt class \n"); st = IB_ERROR; free(p_mgr); goto Exit; } osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG, "osmv_transport_init: GSI bind\n"); cl_event_construct(&p_mgr->send_done); cl_event_init(&p_mgr->send_done, TRUE); p_mgr->is_send_ok = FALSE; p_mgr->mad_type = mad_type; Exit: /* OSM_LOG_EXIT(p_log ); */ return (ib_api_status_t) st; } /* * NAME * osmv_transport_send_mad * * DESCRIPTION * Send a single MAD (256 byte) */ ib_api_status_t osmv_transport_mad_send(IN const osm_bind_handle_t h_bind, IN void *p_ib_mad, IN const osm_mad_addr_t * p_mad_addr) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osmv_IBMGT_transport_info_t *p_tpot_info = (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info); osm_vendor_t const *p_vend = p_bo->p_vendor; ib_api_status_t status; IB_ud_av_t av; IB_MGT_ret_t ret; ib_mad_t *p_mad = p_ib_mad; OSM_LOG_ENTER(p_vend->p_log); CL_ASSERT(p_bo->p_vendor->p_transport_info); /* * For all sends other than directed route SM MADs, * acquire an address vector for the destination. */ if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) { __osmv_IBMGT_osm_addr_to_ibmgt_addr(p_mad_addr, p_mad->mgmt_class == IB_MCLASS_SUBN_LID, &av); } else { /* is a directed route - we need to construct a permissive address */ memset(&av, 0, sizeof(av)); /* we do not need port number since it is part of the mad_hndl */ av.dlid = IB_LID_PERMISSIVE; } /* send it */ if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) || (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) { /* SMI CASE */ if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osmv_transport_mad_send: " "av.dlid:0x%X, " "av.static_rate:%d, " "av.path_bits:%d.\n", cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits); } ret = IB_MGT_send_mad(p_tpot_info->smi_h, p_mad, /* actual payload */ &av, /* address vector */ (u_int64_t) CAST_P2LONG(p_bo), IB_MGT_DEFAULT_SEND_TIME); } else { /* GSI CASE - Support Remote QP */ if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) { osm_log(p_vend->p_log, OSM_LOG_DEBUG, "osmv_transport_mad_send: " "av.dlid:0x%X, av.static_rate:%d, av.path_bits:%d, remote qp:%d \n", cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits, cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp) ); } ret = IB_MGT_send_mad_to_qp(p_tpot_info->gsi_h, p_mad, /* actual payload */ &av, /* address vector */ (u_int64_t) CAST_P2LONG(p_bo), IB_MGT_DEFAULT_SEND_TIME, cl_ntoh32(p_mad_addr->addr_type.gsi. remote_qp)); } status = IB_SUCCESS; if (ret != IB_MGT_OK) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osmv_transport_mad_send: ERR 7210: " "Error sending mad (%d).\n", ret); status = IB_ERROR; } else { osmv_IBMGT_transport_mgr_t *p_mgr = (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr); /* Let the others work when I am sleeping ... */ osmv_txn_unlock(p_bo); cl_event_wait_on(&(p_mgr->send_done), 0xffffffff, TRUE); /* Re-acquire the lock */ osmv_txn_lock(p_bo); if (TRUE == p_bo->is_closing) { osm_log(p_vend->p_log, OSM_LOG_ERROR, "osmv_transport_mad_send: ERR 7211: " "The handle %p is being unbound, cannot send.\n", h_bind); status = IB_ERROR; } if (p_mgr->is_send_ok == FALSE) { status = IB_ERROR; } } OSM_LOG_EXIT(p_vend->p_log); return (status); } void osmv_transport_done(IN const osm_bind_handle_t h_bind) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind; osm_log_t *p_log = p_bo->p_vendor->p_log; osmv_IBMGT_transport_mgr_t *p_mgr; osmv_IBMGT_transport_info_t *p_tpot_info; IB_MGT_ret_t ret; cl_list_obj_t *p_obj = NULL; cl_list_item_t *p_item, *p_item_tmp; int i; cl_qlist_t *p_list = NULL; OSM_LOG_ENTER(p_log); CL_ASSERT(p_bo); /* First of all - zero out the magic_ptr, so if a callback is called - it'll know that we are currently closing down, and will not handle the mad. */ p_bo->magic_ptr = 0; p_mgr = (osmv_IBMGT_transport_mgr_t *) (p_bo->p_transp_mgr); p_tpot_info = (osmv_IBMGT_transport_info_t *) (p_bo->p_vendor->p_transport_info); switch (p_mgr->mad_type) { case IB_MGT_SMI: p_list = p_tpot_info->p_smi_list; /* remove from the bindings list */ p_item = cl_qlist_head(p_list); while (p_item != cl_qlist_end(p_list)) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); if (cl_qlist_obj(p_obj) == h_bind) { break; } p_item_tmp = cl_qlist_next(p_item); p_item = p_item_tmp; } CL_ASSERT(p_item != cl_qlist_end(p_list)); cl_qlist_remove_item(p_list, p_item); if (p_obj) free(p_obj); /* no one is binded to smi anymore - we can free the list, unbind & realease the hndl */ if (cl_is_qlist_empty(p_list) == TRUE) { free(p_list); p_list = NULL; ret = IB_MGT_unbind_sm(p_tpot_info->smi_h); if (ret != IB_MGT_OK) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_done: ERR 7212: " "Failed to unbind sm\n"); } ret = IB_MGT_release_handle(p_tpot_info->smi_h); if (ret != IB_MGT_OK) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_done: ERR 7213: " "Failed to release smi handle\n"); } p_tpot_info->smi_h = 0xffffffff; } break; case IB_MGT_GSI: p_list = p_tpot_info->gsi_mgmt_lists[p_mgr->mgmt_class]; /* remove from the bindings list */ p_item = cl_qlist_head(p_list); while (p_item != cl_qlist_end(p_list)) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); if (cl_qlist_obj(p_obj) == h_bind) { break; } p_item_tmp = cl_qlist_next(p_item); p_item = p_item_tmp; } CL_ASSERT(p_item != cl_qlist_end(p_list)); cl_qlist_remove_item(p_list, p_item); if (p_obj) free(p_obj); /* no one is binded to this class anymore - we can free the list and unbind this class */ if (cl_is_qlist_empty(p_list) == TRUE) { free(p_list); p_list = NULL; ret = IB_MGT_unbind_gsi_class(p_tpot_info->gsi_h, p_mgr->mgmt_class); if (ret != IB_MGT_OK) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_done: ERR 7214: " "Failed to unbind gsi class\n"); } } /* all the mgmt classes are unbinded - release gsi handle */ for (i = 0; i < 15; i++) { if (p_tpot_info->gsi_mgmt_lists[i] != NULL) { break; } } if (i == 15) { ret = IB_MGT_release_handle(p_tpot_info->gsi_h); if (ret != IB_MGT_OK) { osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR, "osmv_transport_done: ERR 7215: " "Failed to release gsi handle\n"); } p_tpot_info->gsi_h = 0xffffffff; } } /* end switch */ free(p_mgr); } /********************************************************************** * IB_MGT Receive callback : invoked after each receive **********************************************************************/ void __osmv_IBMGT_rcv_cb(IN IB_MGT_mad_hndl_t mad_hndl, IN void *private_ctx_p, IN void *payload_p, IN IB_MGT_mad_rcv_desc_t * rcv_remote_info_p) { osmv_bind_obj_t *p_bo; osm_mad_addr_t mad_addr; cl_list_item_t *p_item; cl_list_obj_t *p_obj; cl_qlist_t *p_list; ib_mad_t *p_mad = (ib_mad_t *) payload_p; osm_vendor_t *p_vendor; osmv_IBMGT_transport_info_t *p_tinfo; __osmv_IBMGT_rcv_desc_to_osm_addr(rcv_remote_info_p, ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) || (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)), &mad_addr); /* different handling of SMI and GSI */ if ((p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) || (p_mad->mgmt_class == IB_MCLASS_SUBN_LID)) { /* SMI CASE */ p_bo = (osmv_bind_obj_t *) private_ctx_p; /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; p_vendor = p_bo->p_vendor; p_tinfo = (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info; p_list = p_tinfo->p_smi_list; } else { /* GSI CASE */ p_bo = (osmv_bind_obj_t *) private_ctx_p; /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; p_vendor = p_bo->p_vendor; p_tinfo = (osmv_IBMGT_transport_info_t *) p_vendor->p_transport_info; p_list = p_tinfo->gsi_mgmt_lists[p_mad->mgmt_class]; } /* go over the bindings list and send the mad, one of them will accept it, the others will drope */ p_item = cl_qlist_head(p_list); while (p_item != cl_qlist_end(p_list)) { p_obj = PARENT_STRUCT(p_item, cl_list_obj_t, list_item); p_bo = cl_qlist_obj(p_obj); /* give upper layer the mad */ osmv_dispatch_mad((osm_bind_handle_t) p_bo, payload_p, &mad_addr); /* Make sure the p_bo object is still relevant */ if ((p_bo->magic_ptr != p_bo) || p_bo->is_closing) return; p_item = cl_qlist_next(p_item); } } /********************************************************************** * IB_MGT Send callback : invoked after each send **********************************************************************/ void __osmv_IBMGT_send_cb(IN IB_MGT_mad_hndl_t mad_hndl, IN u_int64_t wrid, IN IB_comp_status_t status, IN void *private_ctx_p) { osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) CAST_P2LONG(wrid); osmv_IBMGT_transport_mgr_t *p_mgr = (osmv_IBMGT_transport_mgr_t *) p_bo->p_transp_mgr; /* Make sure the p_bo object is still relevant */ if (p_bo->magic_ptr != p_bo) return; /* we assume that each send on a bind object is synchronized, and no paralel sends from diffrent threads with same object can be made */ if (status == IB_COMP_SUCCESS) { p_mgr->is_send_ok = TRUE; } else p_mgr->is_send_ok = FALSE; cl_event_signal(&p_mgr->send_done); } /********************************************************************** * IB_MGT to OSM ADDRESS VECTOR **********************************************************************/ static void __osmv_IBMGT_rcv_desc_to_osm_addr(IN IB_MGT_mad_rcv_desc_t * p_rcv_desc, IN uint8_t is_smi, OUT osm_mad_addr_t * p_mad_addr) { /* p_mad_addr->dest_lid = p_osm->subn.sm_base_lid; - for resp we use the dest lid ... */ p_mad_addr->dest_lid = cl_hton16(p_rcv_desc->remote_lid); p_mad_addr->static_rate = 0; /* HACK - we do not know the rate ! */ p_mad_addr->path_bits = p_rcv_desc->local_path_bits; /* Clear the grh any way to avoid unset fields */ memset(&p_mad_addr->addr_type.gsi.grh_info, 0, sizeof(p_mad_addr->addr_type.gsi.grh_info)); if (is_smi) { /* SMI */ p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_rcv_desc->remote_lid); p_mad_addr->addr_type.smi.port_num = 99; /* HACK - if used - should fail */ } else { /* GSI */ /* seems to me there is a IBMGT bug reversing the QPN ... */ /* Does IBMGT supposed to provide the QPN is network or HOST ? */ p_mad_addr->addr_type.gsi.remote_qp = cl_hton32(p_rcv_desc->qp); p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY; /* we do have the p_mad_addr->pkey_ix but how to get the PKey by index ? */ /* the only way seems to be to use VAPI_query_hca_pkey_tbl and obtain */ /* the full PKey table - than go by the index. */ /* since this does not seem reasonable to me I simply use the default */ /* There is a TAVOR limitation that only one P_KEY is supported per */ /* QP - so QP1 must use IB_DEFAULT_PKEY */ p_mad_addr->addr_type.gsi.pkey_ix = 0; p_mad_addr->addr_type.gsi.service_level = p_rcv_desc->sl; p_mad_addr->addr_type.gsi.global_route = p_rcv_desc->grh_flag; /* copy the GRH data if relevant */ if (p_mad_addr->addr_type.gsi.global_route) { p_mad_addr->addr_type.gsi.grh_info.ver_class_flow = ib_grh_set_ver_class_flow(p_rcv_desc->grh. IP_version, p_rcv_desc->grh. traffic_class, p_rcv_desc->grh. flow_label); p_mad_addr->addr_type.gsi.grh_info.hop_limit = p_rcv_desc->grh.hop_limit; memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw, &p_rcv_desc->grh.sgid, sizeof(ib_net64_t)); memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw, p_rcv_desc->grh.dgid, sizeof(ib_net64_t)); } } } /********************************************************************** * OSM ADDR VECTOR TO IB_MGT **********************************************************************/ void __osmv_IBMGT_osm_addr_to_ibmgt_addr(IN const osm_mad_addr_t * p_mad_addr, IN uint8_t is_smi, OUT IB_ud_av_t * p_av) { /* For global destination or Multicast address: */ u_int8_t ver; memset(p_av, 0, sizeof(IB_ud_av_t)); p_av->src_path_bits = p_mad_addr->path_bits; p_av->static_rate = p_mad_addr->static_rate; p_av->dlid = cl_ntoh16(p_mad_addr->dest_lid); if (is_smi) { p_av->sl = 0; /* Just to note we use 0 here. */ } else { p_av->sl = p_mad_addr->addr_type.gsi.service_level; p_av->grh_flag = p_mad_addr->addr_type.gsi.global_route; if (p_mad_addr->addr_type.gsi.global_route) { ib_grh_get_ver_class_flow(p_mad_addr->addr_type.gsi. grh_info.ver_class_flow, &ver, &p_av->traffic_class, &p_av->flow_label); p_av->hop_limit = p_mad_addr->addr_type.gsi.grh_info.hop_limit; p_av->sgid_index = 0; /* we always use source GID 0 */ memcpy(&p_av->dgid, &p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw, sizeof(ib_net64_t)); } } } opensm-3.3.20/libvendor/libosmvendor.map0000644000205000001450000000060112104655724015201 00000000000000OSMVENDOR_2.0 { global: umad_receiver; osm_vendor_init; osm_vendor_new; osm_vendor_delete; osm_vendor_get_all_port_attr; osm_vendor_bind; osm_vendor_unbind; osm_vendor_get; osm_vendor_put; osm_vendor_send; osm_vendor_local_lid_change; osm_vendor_set_sm; osm_vendor_set_debug; osmv_bind_sa; osmv_query_sa; osm_vendor_get_guid_ca_and_port; local: *; }; opensm-3.3.20/libvendor/libosmvendor.ver0000644000205000001450000000052412726304124015217 00000000000000# In this file we track the current API version # of the vendor interface (and libraries) # The version is built of the following # tree numbers: # API_REV:RUNNING_REV:AGE # API_REV - advance on any added API # RUNNING_REV - advance any change to the vendor files # AGE - number of backward versions the API still supports LIBVERSION=4:2:0 opensm-3.3.20/opensm/0000755000205000001450000000000012726324775011410 500000000000000opensm-3.3.20/opensm/Makefile.am0000644000205000001450000001314412272264653013361 00000000000000 INCLUDES = $(OSMV_INCLUDES) AM_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 lib_LTLIBRARIES = libopensm.la if DEBUG DBGFLAGS = -ggdb -D_DEBUG_ else DBGFLAGS = -g endif if HAVE_LD_VERSION_SCRIPT libopensm_version_script = -Wl,--version-script=$(srcdir)/libopensm.map else libopensm_version_script = endif opensm_api_version=$(shell grep LIBVERSION= $(srcdir)/libopensm.ver | sed 's/LIBVERSION=//') libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c libopensm_la_LDFLAGS = -version-info $(opensm_api_version) \ -export-dynamic $(libopensm_version_script) libopensm_la_DEPENDENCIES = $(srcdir)/libopensm.map sbin_PROGRAMS = opensm opensm_LDFLAGS = -rdynamic opensm_DEPENDENCIES = libopensm.la opensm_SOURCES = main.c osm_console_io.c osm_console.c osm_db_files.c \ osm_db_pack.c osm_drop_mgr.c osm_guid_info_rcv.c \ osm_guid_mgr.c osm_inform.c osm_lid_mgr.c osm_lin_fwd_rcv.c \ osm_link_mgr.c osm_mcast_fwd_rcv.c \ osm_mcast_mgr.c osm_mcast_tbl.c \ osm_mcm_port.c osm_mesh.c osm_mtree.c osm_multicast.c osm_node.c \ osm_node_desc_rcv.c osm_node_info_rcv.c \ osm_opensm.c osm_pkey.c osm_pkey_mgr.c osm_pkey_rcv.c \ osm_port.c osm_port_info_rcv.c osm_mlnx_ext_port_info_rcv.c \ osm_remote_sm.c osm_req.c \ osm_resp.c osm_sa.c osm_sa_class_port_info.c \ osm_sa_informinfo.c osm_sa_lft_record.c osm_sa_mft_record.c \ osm_sa_link_record.c osm_sa_mad_ctrl.c \ osm_sa_mcmember_record.c osm_sa_node_record.c \ osm_sa_path_record.c osm_sa_pkey_record.c \ osm_sa_portinfo_record.c osm_sa_guidinfo_record.c \ osm_sa_multipath_record.c \ osm_sa_service_record.c osm_sa_slvl_record.c \ osm_sa_sminfo_record.c osm_sa_vlarb_record.c \ osm_sa_sw_info_record.c osm_service.c \ osm_slvl_map_rcv.c osm_sm.c osm_sminfo_rcv.c \ osm_sm_mad_ctrl.c osm_sm_state_mgr.c osm_state_mgr.c \ osm_subnet.c osm_sw_info_rcv.c osm_switch.c \ osm_prtn.c osm_prtn_config.c osm_qos.c osm_router.c \ osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_updn.c \ osm_ucast_lash.c osm_ucast_file.c osm_ucast_ftree.c \ osm_torus.c osm_ucast_dnup.c \ osm_ucast_dfsssp.c osm_vl15intf.c \ osm_vl_arb_rcv.c st.c osm_perfmgr.c osm_perfmgr_db.c \ osm_event_plugin.c osm_dump.c osm_ucast_cache.c \ osm_qos_parser_y.y osm_qos_parser_l.l osm_qos_policy.c \ osm_congestion_control.c AM_YFLAGS:= -d # we need to be able to load libraries from local build subtree before make install # we always give precedence to local tree libs and then use the pre-installed ones. opensm_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L. -lopensm $(OSMV_LDADD) opensmincludedir = $(includedir)/infiniband/opensm opensminclude_HEADERS = \ $(srcdir)/../include/opensm/osm_attrib_req.h \ $(srcdir)/../include/opensm/osm_base.h \ $(srcdir)/../include/opensm/osm_console.h \ $(srcdir)/../include/opensm/osm_console_io.h \ $(srcdir)/../include/opensm/osm_db.h \ $(srcdir)/../include/opensm/osm_db_pack.h \ $(srcdir)/../include/opensm/osm_event_plugin.h \ $(srcdir)/../include/opensm/osm_errors.h \ $(srcdir)/../include/opensm/osm_file_ids.h \ $(srcdir)/../include/opensm/osm_guid.h \ $(srcdir)/../include/opensm/osm_helper.h \ $(srcdir)/../include/opensm/osm_inform.h \ $(srcdir)/../include/opensm/osm_ucast_lash.h \ $(srcdir)/../include/opensm/osm_lid_mgr.h \ $(srcdir)/../include/opensm/osm_log.h \ $(srcdir)/../include/opensm/osm_mad_pool.h \ $(srcdir)/../include/opensm/osm_madw.h \ $(srcdir)/../include/opensm/osm_mcast_tbl.h \ $(srcdir)/../include/opensm/osm_mcm_port.h \ $(srcdir)/../include/opensm/osm_mesh.h \ $(srcdir)/../include/opensm/osm_mtree.h \ $(srcdir)/../include/opensm/osm_multicast.h \ $(srcdir)/../include/opensm/osm_msgdef.h \ $(srcdir)/../include/opensm/osm_node.h \ $(srcdir)/../include/opensm/osm_opensm.h \ $(srcdir)/../include/opensm/osm_partition.h \ $(srcdir)/../include/opensm/osm_path.h \ $(srcdir)/../include/opensm/osm_perfmgr.h \ $(srcdir)/../include/opensm/osm_perfmgr_db.h \ $(srcdir)/../include/opensm/osm_pkey.h \ $(srcdir)/../include/opensm/osm_port.h \ $(srcdir)/../include/opensm/osm_port_profile.h \ $(srcdir)/../include/opensm/osm_prefix_route.h \ $(srcdir)/../include/opensm/osm_qos_policy.h \ $(srcdir)/../include/opensm/osm_congestion_control.h \ $(srcdir)/../include/opensm/osm_remote_sm.h \ $(srcdir)/../include/opensm/osm_router.h \ $(srcdir)/../include/opensm/osm_sa.h \ $(srcdir)/../include/opensm/osm_sa_mad_ctrl.h \ $(srcdir)/../include/opensm/osm_service.h \ $(srcdir)/../include/opensm/osm_sm.h \ $(srcdir)/../include/opensm/osm_sm_mad_ctrl.h \ $(srcdir)/../include/opensm/st.h \ $(srcdir)/../include/opensm/osm_stats.h \ $(srcdir)/../include/opensm/osm_subnet.h \ $(srcdir)/../include/opensm/osm_switch.h \ $(srcdir)/../include/opensm/osm_ucast_mgr.h \ $(srcdir)/../include/opensm/osm_mcast_mgr.h \ $(srcdir)/../include/opensm/osm_ucast_cache.h \ $(srcdir)/../include/opensm/osm_vl15intf.h \ $(top_builddir)/include/opensm/osm_version.h \ $(top_builddir)/include/opensm/osm_config.h BUILT_SOURCES = osm_version osm_qos_parser_y.h osm_version: if [ -x $(top_srcdir)/gen_ver.sh ] ; then \ ver_file=$(top_builddir)/include/opensm/osm_version.h ; \ osm_ver=`cat $$ver_file | sed -ne '/#define OSM_VERSION /s/^.*\"OpenSM \(.*\)\"$$/\1/p'` ; \ ver=`$(top_srcdir)/gen_ver.sh $(PACKAGE)` ; \ if [ $$ver != $$osm_ver ] ; then \ cat $$ver_file | sed -e '/#define OSM_VERSION /s/\"OpenSM .*\"/\"OpenSM '$$ver'\"/' > tmp_new_version ; \ cat tmp_new_version > $$ver_file && rm -f tmp_new_version ; \ fi ; \ fi # files distributed as part of the srcdir EXTRA_DIST = $(srcdir)/libopensm.map $(srcdir)/libopensm.ver \ $(srcdir)/ChangeLog opensm-3.3.20/opensm/Makefile.in0000644000205000001450000010770612726323425013377 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = opensm$(EXEEXT) subdir = opensm DIST_COMMON = $(opensminclude_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in ChangeLog osm_qos_parser_l.c \ osm_qos_parser_y.c osm_qos_parser_y.h ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" \ "$(DESTDIR)$(opensmincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) libopensm_la_LIBADD = am_libopensm_la_OBJECTS = osm_log.lo osm_mad_pool.lo osm_helper.lo libopensm_la_OBJECTS = $(am_libopensm_la_OBJECTS) libopensm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libopensm_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(sbin_PROGRAMS) am_opensm_OBJECTS = main.$(OBJEXT) osm_console_io.$(OBJEXT) \ osm_console.$(OBJEXT) osm_db_files.$(OBJEXT) \ osm_db_pack.$(OBJEXT) osm_drop_mgr.$(OBJEXT) \ osm_guid_info_rcv.$(OBJEXT) osm_guid_mgr.$(OBJEXT) \ osm_inform.$(OBJEXT) osm_lid_mgr.$(OBJEXT) \ osm_lin_fwd_rcv.$(OBJEXT) osm_link_mgr.$(OBJEXT) \ osm_mcast_fwd_rcv.$(OBJEXT) osm_mcast_mgr.$(OBJEXT) \ osm_mcast_tbl.$(OBJEXT) osm_mcm_port.$(OBJEXT) \ osm_mesh.$(OBJEXT) osm_mtree.$(OBJEXT) osm_multicast.$(OBJEXT) \ osm_node.$(OBJEXT) osm_node_desc_rcv.$(OBJEXT) \ osm_node_info_rcv.$(OBJEXT) osm_opensm.$(OBJEXT) \ osm_pkey.$(OBJEXT) osm_pkey_mgr.$(OBJEXT) \ osm_pkey_rcv.$(OBJEXT) osm_port.$(OBJEXT) \ osm_port_info_rcv.$(OBJEXT) \ osm_mlnx_ext_port_info_rcv.$(OBJEXT) osm_remote_sm.$(OBJEXT) \ osm_req.$(OBJEXT) osm_resp.$(OBJEXT) osm_sa.$(OBJEXT) \ osm_sa_class_port_info.$(OBJEXT) osm_sa_informinfo.$(OBJEXT) \ osm_sa_lft_record.$(OBJEXT) osm_sa_mft_record.$(OBJEXT) \ osm_sa_link_record.$(OBJEXT) osm_sa_mad_ctrl.$(OBJEXT) \ osm_sa_mcmember_record.$(OBJEXT) osm_sa_node_record.$(OBJEXT) \ osm_sa_path_record.$(OBJEXT) osm_sa_pkey_record.$(OBJEXT) \ osm_sa_portinfo_record.$(OBJEXT) \ osm_sa_guidinfo_record.$(OBJEXT) \ osm_sa_multipath_record.$(OBJEXT) \ osm_sa_service_record.$(OBJEXT) osm_sa_slvl_record.$(OBJEXT) \ osm_sa_sminfo_record.$(OBJEXT) osm_sa_vlarb_record.$(OBJEXT) \ osm_sa_sw_info_record.$(OBJEXT) osm_service.$(OBJEXT) \ osm_slvl_map_rcv.$(OBJEXT) osm_sm.$(OBJEXT) \ osm_sminfo_rcv.$(OBJEXT) osm_sm_mad_ctrl.$(OBJEXT) \ osm_sm_state_mgr.$(OBJEXT) osm_state_mgr.$(OBJEXT) \ osm_subnet.$(OBJEXT) osm_sw_info_rcv.$(OBJEXT) \ osm_switch.$(OBJEXT) osm_prtn.$(OBJEXT) \ osm_prtn_config.$(OBJEXT) osm_qos.$(OBJEXT) \ osm_router.$(OBJEXT) osm_trap_rcv.$(OBJEXT) \ osm_ucast_mgr.$(OBJEXT) osm_ucast_updn.$(OBJEXT) \ osm_ucast_lash.$(OBJEXT) osm_ucast_file.$(OBJEXT) \ osm_ucast_ftree.$(OBJEXT) osm_torus.$(OBJEXT) \ osm_ucast_dnup.$(OBJEXT) osm_ucast_dfsssp.$(OBJEXT) \ osm_vl15intf.$(OBJEXT) osm_vl_arb_rcv.$(OBJEXT) st.$(OBJEXT) \ osm_perfmgr.$(OBJEXT) osm_perfmgr_db.$(OBJEXT) \ osm_event_plugin.$(OBJEXT) osm_dump.$(OBJEXT) \ osm_ucast_cache.$(OBJEXT) osm_qos_parser_y.$(OBJEXT) \ osm_qos_parser_l.$(OBJEXT) osm_qos_policy.$(OBJEXT) \ osm_congestion_control.$(OBJEXT) opensm_OBJECTS = $(am_opensm_OBJECTS) am__DEPENDENCIES_1 = opensm_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(opensm_LDFLAGS) \ $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS) YLWRAP = $(top_srcdir)/config/ylwrap YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS) SOURCES = $(libopensm_la_SOURCES) $(opensm_SOURCES) DIST_SOURCES = $(libopensm_la_SOURCES) $(opensm_SOURCES) HEADERS = $(opensminclude_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = $(OSMV_INCLUDES) AM_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 lib_LTLIBRARIES = libopensm.la @DEBUG_FALSE@DBGFLAGS = -g @DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_ @HAVE_LD_VERSION_SCRIPT_FALSE@libopensm_version_script = @HAVE_LD_VERSION_SCRIPT_TRUE@libopensm_version_script = -Wl,--version-script=$(srcdir)/libopensm.map opensm_api_version = $(shell grep LIBVERSION= $(srcdir)/libopensm.ver | sed 's/LIBVERSION=//') libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c libopensm_la_LDFLAGS = -version-info $(opensm_api_version) \ -export-dynamic $(libopensm_version_script) libopensm_la_DEPENDENCIES = $(srcdir)/libopensm.map opensm_LDFLAGS = -rdynamic opensm_DEPENDENCIES = libopensm.la opensm_SOURCES = main.c osm_console_io.c osm_console.c osm_db_files.c \ osm_db_pack.c osm_drop_mgr.c osm_guid_info_rcv.c \ osm_guid_mgr.c osm_inform.c osm_lid_mgr.c osm_lin_fwd_rcv.c \ osm_link_mgr.c osm_mcast_fwd_rcv.c \ osm_mcast_mgr.c osm_mcast_tbl.c \ osm_mcm_port.c osm_mesh.c osm_mtree.c osm_multicast.c osm_node.c \ osm_node_desc_rcv.c osm_node_info_rcv.c \ osm_opensm.c osm_pkey.c osm_pkey_mgr.c osm_pkey_rcv.c \ osm_port.c osm_port_info_rcv.c osm_mlnx_ext_port_info_rcv.c \ osm_remote_sm.c osm_req.c \ osm_resp.c osm_sa.c osm_sa_class_port_info.c \ osm_sa_informinfo.c osm_sa_lft_record.c osm_sa_mft_record.c \ osm_sa_link_record.c osm_sa_mad_ctrl.c \ osm_sa_mcmember_record.c osm_sa_node_record.c \ osm_sa_path_record.c osm_sa_pkey_record.c \ osm_sa_portinfo_record.c osm_sa_guidinfo_record.c \ osm_sa_multipath_record.c \ osm_sa_service_record.c osm_sa_slvl_record.c \ osm_sa_sminfo_record.c osm_sa_vlarb_record.c \ osm_sa_sw_info_record.c osm_service.c \ osm_slvl_map_rcv.c osm_sm.c osm_sminfo_rcv.c \ osm_sm_mad_ctrl.c osm_sm_state_mgr.c osm_state_mgr.c \ osm_subnet.c osm_sw_info_rcv.c osm_switch.c \ osm_prtn.c osm_prtn_config.c osm_qos.c osm_router.c \ osm_trap_rcv.c osm_ucast_mgr.c osm_ucast_updn.c \ osm_ucast_lash.c osm_ucast_file.c osm_ucast_ftree.c \ osm_torus.c osm_ucast_dnup.c \ osm_ucast_dfsssp.c osm_vl15intf.c \ osm_vl_arb_rcv.c st.c osm_perfmgr.c osm_perfmgr_db.c \ osm_event_plugin.c osm_dump.c osm_ucast_cache.c \ osm_qos_parser_y.y osm_qos_parser_l.l osm_qos_policy.c \ osm_congestion_control.c AM_YFLAGS := -d # we need to be able to load libraries from local build subtree before make install # we always give precedence to local tree libs and then use the pre-installed ones. opensm_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L. -lopensm $(OSMV_LDADD) opensmincludedir = $(includedir)/infiniband/opensm opensminclude_HEADERS = \ $(srcdir)/../include/opensm/osm_attrib_req.h \ $(srcdir)/../include/opensm/osm_base.h \ $(srcdir)/../include/opensm/osm_console.h \ $(srcdir)/../include/opensm/osm_console_io.h \ $(srcdir)/../include/opensm/osm_db.h \ $(srcdir)/../include/opensm/osm_db_pack.h \ $(srcdir)/../include/opensm/osm_event_plugin.h \ $(srcdir)/../include/opensm/osm_errors.h \ $(srcdir)/../include/opensm/osm_file_ids.h \ $(srcdir)/../include/opensm/osm_guid.h \ $(srcdir)/../include/opensm/osm_helper.h \ $(srcdir)/../include/opensm/osm_inform.h \ $(srcdir)/../include/opensm/osm_ucast_lash.h \ $(srcdir)/../include/opensm/osm_lid_mgr.h \ $(srcdir)/../include/opensm/osm_log.h \ $(srcdir)/../include/opensm/osm_mad_pool.h \ $(srcdir)/../include/opensm/osm_madw.h \ $(srcdir)/../include/opensm/osm_mcast_tbl.h \ $(srcdir)/../include/opensm/osm_mcm_port.h \ $(srcdir)/../include/opensm/osm_mesh.h \ $(srcdir)/../include/opensm/osm_mtree.h \ $(srcdir)/../include/opensm/osm_multicast.h \ $(srcdir)/../include/opensm/osm_msgdef.h \ $(srcdir)/../include/opensm/osm_node.h \ $(srcdir)/../include/opensm/osm_opensm.h \ $(srcdir)/../include/opensm/osm_partition.h \ $(srcdir)/../include/opensm/osm_path.h \ $(srcdir)/../include/opensm/osm_perfmgr.h \ $(srcdir)/../include/opensm/osm_perfmgr_db.h \ $(srcdir)/../include/opensm/osm_pkey.h \ $(srcdir)/../include/opensm/osm_port.h \ $(srcdir)/../include/opensm/osm_port_profile.h \ $(srcdir)/../include/opensm/osm_prefix_route.h \ $(srcdir)/../include/opensm/osm_qos_policy.h \ $(srcdir)/../include/opensm/osm_congestion_control.h \ $(srcdir)/../include/opensm/osm_remote_sm.h \ $(srcdir)/../include/opensm/osm_router.h \ $(srcdir)/../include/opensm/osm_sa.h \ $(srcdir)/../include/opensm/osm_sa_mad_ctrl.h \ $(srcdir)/../include/opensm/osm_service.h \ $(srcdir)/../include/opensm/osm_sm.h \ $(srcdir)/../include/opensm/osm_sm_mad_ctrl.h \ $(srcdir)/../include/opensm/st.h \ $(srcdir)/../include/opensm/osm_stats.h \ $(srcdir)/../include/opensm/osm_subnet.h \ $(srcdir)/../include/opensm/osm_switch.h \ $(srcdir)/../include/opensm/osm_ucast_mgr.h \ $(srcdir)/../include/opensm/osm_mcast_mgr.h \ $(srcdir)/../include/opensm/osm_ucast_cache.h \ $(srcdir)/../include/opensm/osm_vl15intf.h \ $(top_builddir)/include/opensm/osm_version.h \ $(top_builddir)/include/opensm/osm_config.h BUILT_SOURCES = osm_version osm_qos_parser_y.h # files distributed as part of the srcdir EXTRA_DIST = $(srcdir)/libopensm.map $(srcdir)/libopensm.ver \ $(srcdir)/ChangeLog all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .l .lo .o .obj .y $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign opensm/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign opensm/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libopensm.la: $(libopensm_la_OBJECTS) $(libopensm_la_DEPENDENCIES) $(libopensm_la_LINK) -rpath $(libdir) $(libopensm_la_OBJECTS) $(libopensm_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list osm_qos_parser_y.h: osm_qos_parser_y.c @if test ! -f $@; then \ rm -f osm_qos_parser_y.c; \ $(MAKE) $(AM_MAKEFLAGS) osm_qos_parser_y.c; \ else :; fi opensm$(EXEEXT): $(opensm_OBJECTS) $(opensm_DEPENDENCIES) @rm -f opensm$(EXEEXT) $(opensm_LINK) $(opensm_OBJECTS) $(opensm_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_congestion_control.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_console.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_console_io.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_db_files.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_db_pack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_drop_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_event_plugin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_guid_info_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_guid_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_helper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_inform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_lid_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_lin_fwd_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_link_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mad_pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mcast_fwd_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mcast_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mcast_tbl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mcm_port.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mesh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mlnx_ext_port_info_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_mtree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_multicast.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_node.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_node_desc_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_node_info_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_opensm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_perfmgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_perfmgr_db.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_pkey.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_pkey_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_pkey_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_port.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_port_info_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_prtn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_prtn_config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_qos.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_qos_parser_l.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_qos_parser_y.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_qos_policy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_remote_sm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_req.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_resp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_router.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_class_port_info.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_guidinfo_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_informinfo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_lft_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_link_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_mad_ctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_mcmember_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_mft_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_multipath_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_node_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_path_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_pkey_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_portinfo_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_service_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_slvl_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_sminfo_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_sw_info_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sa_vlarb_record.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_slvl_map_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sm_mad_ctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sm_state_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sminfo_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_state_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_subnet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_sw_info_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_switch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_torus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_trap_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_cache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_dfsssp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_dnup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_ftree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_lash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_ucast_updn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_vl15intf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osm_vl_arb_rcv.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/st.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< .l.c: $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-opensmincludeHEADERS: $(opensminclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(opensmincludedir)" || $(MKDIR_P) "$(DESTDIR)$(opensmincludedir)" @list='$(opensminclude_HEADERS)'; test -n "$(opensmincludedir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(opensmincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(opensmincludedir)" || exit $$?; \ done uninstall-opensmincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(opensminclude_HEADERS)'; test -n "$(opensmincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(opensmincludedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(opensmincludedir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(opensmincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -rm -f osm_qos_parser_l.c -rm -f osm_qos_parser_y.c -rm -f osm_qos_parser_y.h -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-opensmincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-opensmincludeHEADERS \ uninstall-sbinPROGRAMS .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS ctags \ distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man \ install-opensmincludeHEADERS install-pdf install-pdf-am \ install-ps install-ps-am install-sbinPROGRAMS install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-libLTLIBRARIES \ uninstall-opensmincludeHEADERS uninstall-sbinPROGRAMS osm_version: if [ -x $(top_srcdir)/gen_ver.sh ] ; then \ ver_file=$(top_builddir)/include/opensm/osm_version.h ; \ osm_ver=`cat $$ver_file | sed -ne '/#define OSM_VERSION /s/^.*\"OpenSM \(.*\)\"$$/\1/p'` ; \ ver=`$(top_srcdir)/gen_ver.sh $(PACKAGE)` ; \ if [ $$ver != $$osm_ver ] ; then \ cat $$ver_file | sed -e '/#define OSM_VERSION /s/\"OpenSM .*\"/\"OpenSM '$$ver'\"/' > tmp_new_version ; \ cat tmp_new_version > $$ver_file && rm -f tmp_new_version ; \ fi ; \ fi # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/opensm/ChangeLog0000644000205000001450000000606412104655724013077 000000000000002007-07-11 Hal Rosenstock * configure.in: Bump to version 2.2.1 2007-06-20 Hal Rosenstock * osm_helper.c: Add 3LeafNetworks and Xsigo to osm_get_manufacturer_str 2007-06-15 Sasha Khapyorsky * osm_helper.c: Fix PortInfo:CapMask printing when CapMask is 0 2007-06-11 Sasha Khapyorsky * osm_helper.c: Remove OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED from __osm_sm_mgr_signal_str 2007-06-06 Sasha Khapyorsky * osm_helper.c: More optimally deal with manufacturer strings 2007-06-06 Hal Rosenstock * osm_helper.c: Add Sun to osm_get_manufacturer_str 2007-06-04 Hal Rosenstock * osm_helper.c: Add 8x to __osm_lwa_str_fixed_width 2007-05-07 Sasha Khapyorsky * osm_helper.c: Remove repeated strlen() calls 2007-04-27 Ira K. Weiny * osm_helper.c: In osm_dump_notice, use ib_get_producer_type_str for printing producer type 2007-04-26 Hal Rosenstock * osm_helper.c: Clarify the proper usage of osm_get_node_type_str_fixed_width to take uint8_t rather than uint32_t for node_type argument 2007-04-25 Yevgeny Kliteynik * osm_helper.c: Fix problematic usage of sprintf() when source and destination strings overlap. 2007-04-24 Albert L. Chu * osm_helper.c: In osm_get_node_type_str_fixed_width, fix both range limit and endian of node type check 2007-03-29 Hal Rosenstock * configure.in: Bump version to 2.2.0 2007-03-21 Sasha Khapyorsky * osm_log.c: Changed to support daemon mode 2007-03-01 Hal Rosenstock * configure.in: Bump version to 2.1.2 * osm_helper.c: Eliminate extraneous comma in __osm_disp_msg_ string for OSM_MSG_MAD_PORT_INFO 2007-02-26 Sasha Khapyorsky * osm_log.c: Minor optimization to previous change to osm_log for also flushing on OSM_LOG_SYS 2007-02-26 Yevgeny Kliteynik * osm_log.c: In osm_log, flush log on OSM_LOG_SYS (as well as OSM_LOG_ERROR) 2007-02-20 Hal Rosenstock * configure.in: Bump version to 2.1.1 * osm_helper.c: In osm_dbg_get_capabilities_str, only display Capability Mask if there are capabilities present 2007-01-22 Hal Rosenstock * osm_helper.c: Change DR path format from [%X] to %d, 2007-01-08 Sasha Khapyorsky * osm_log.c: Add osm_log_reopen_file API 2006-12-22 Hal Rosenstock * osm_helper.c: Add osm_dump_switch_info_record API 2006-11-03 Sasha Khapyorsky * osm_log.c: Add osm_log_printf API 2006-10-30 Sasha Khapyorsky * osm_helper.c: Fix seg fault with strings which might not be null terminated 2006-10-18 Yevgeny Kliteynik * osm_log.c: Windows porting changes 2006-09-19 Yevgeny Kliteynik * osm_log.c: Windows porting changes opensm-3.3.20/opensm/osm_qos_parser_l.c0000644000205000001450000025011612110766521015032 00000000000000 #line 3 "osm_qos_parser_l.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 84 #define YY_END_OF_BUFFER 85 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[582] = { 0, 0, 0, 85, 83, 3, 4, 83, 83, 81, 80, 78, 77, 77, 79, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 3, 2, 0, 82, 0, 1, 77, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 67, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 39, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 71, 0, 0, 69, 0, 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0, 33, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 71, 0, 56, 0, 0, 58, 0, 0, 0, 0, 0, 0, 40, 0, 35, 0, 33, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 32, 0, 0, 31, 0, 49, 9, 0, 29, 0, 30, 0, 50, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 32, 0, 31, 49, 7, 29, 30, 50, 0, 0, 0, 47, 0, 53, 19, 0, 0, 0, 36, 37, 15, 0, 0, 0, 0, 0, 0, 70, 68, 0, 0, 42, 0, 52, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 48, 0, 0, 47, 53, 0, 44, 17, 0, 36, 13, 0, 0, 0, 0, 72, 0, 42, 52, 0, 24, 0, 12, 0, 0, 0, 0, 48, 0, 0, 44, 0, 62, 0, 0, 0, 0, 10, 22, 0, 0, 0, 0, 0, 0, 27, 0, 38, 0, 0, 0, 0, 8, 0, 20, 0, 16, 0, 0, 55, 25, 38, 0, 0, 0, 0, 0, 18, 14, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 26, 65, 0, 64, 73, 0, 0, 0, 0, 0, 0, 66, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 4, 5, 1, 1, 1, 1, 1, 1, 6, 1, 7, 8, 1, 1, 9, 10, 11, 10, 10, 10, 10, 10, 10, 10, 12, 1, 1, 1, 1, 1, 1, 13, 14, 15, 16, 17, 18, 1, 19, 20, 1, 1, 21, 1, 22, 23, 24, 1, 25, 26, 27, 28, 1, 29, 30, 31, 1, 1, 1, 1, 1, 1, 1, 32, 33, 34, 35, 36, 37, 38, 39, 40, 1, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 30, 54, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[55] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int16_t yy_base[585] = { 0, 0, 0, 790, 791, 53, 791, 785, 785, 791, 791, 791, 48, 51, 791, 42, 53, 51, 43, 56, 77, 54, 54, 743, 738, 737, 734, 38, 63, 738, 84, 115, 737, 732, 738, 71, 791, 775, 791, 775, 791, 71, 0, 76, 68, 791, 87, 88, 92, 77, 86, 93, 94, 96, 101, 729, 109, 741, 730, 729, 722, 729, 736, 104, 734, 721, 719, 717, 113, 154, 715, 133, 729, 115, 0, 791, 141, 140, 129, 134, 168, 135, 169, 146, 171, 140, 719, 713, 754, 718, 709, 751, 722, 721, 715, 705, 715, 699, 702, 743, 714, 697, 172, 696, 745, 698, 175, 743, 177, 705, 695, 184, 186, 164, 179, 192, 193, 194, 740, 180, 196, 199, 739, 791, 200, 204, 194, 691, 699, 171, 209, 692, 695, 212, 728, 699, 694, 725, 217, 724, 188, 723, 690, 687, 726, 693, 724, 231, 723, 684, 690, 211, 681, 189, 689, 205, 239, 246, 225, 718, 236, 674, 716, 217, 242, 672, 714, 247, 683, 231, 665, 669, 667, 666, 668, 667, 250, 706, 254, 667, 257, 704, 655, 654, 653, 669, 261, 699, 230, 658, 663, 666, 661, 654, 653, 660, 685, 656, 689, 652, 681, 652, 639, 635, 637, 228, 265, 262, 682, 273, 638, 680, 633, 791, 632, 631, 791, 277, 646, 629, 627, 664, 642, 671, 274, 670, 628, 668, 615, 660, 627, 626, 663, 232, 632, 631, 610, 611, 610, 613, 618, 621, 241, 282, 617, 253, 601, 602, 605, 614, 294, 279, 610, 648, 601, 598, 597, 608, 297, 250, 643, 594, 593, 634, 589, 592, 637, 598, 591, 594, 590, 584, 588, 592, 588, 581, 593, 594, 576, 577, 582, 616, 589, 590, 299, 619, 612, 579, 573, 583, 584, 791, 575, 580, 577, 302, 610, 575, 560, 601, 600, 571, 558, 560, 602, 563, 594, 273, 559, 567, 549, 562, 557, 552, 546, 543, 558, 556, 542, 548, 550, 542, 791, 547, 546, 540, 551, 581, 540, 543, 527, 534, 545, 543, 540, 525, 572, 519, 564, 527, 526, 519, 523, 305, 522, 528, 529, 532, 527, 520, 553, 552, 308, 311, 522, 316, 319, 512, 324, 325, 327, 285, 549, 791, 506, 520, 508, 511, 512, 512, 328, 504, 507, 512, 539, 538, 791, 501, 493, 492, 534, 498, 330, 538, 495, 490, 485, 486, 485, 488, 294, 296, 336, 531, 339, 530, 495, 345, 528, 347, 527, 479, 348, 525, 350, 524, 351, 523, 480, 791, 475, 352, 353, 486, 485, 477, 354, 356, 517, 482, 481, 508, 321, 469, 463, 470, 469, 465, 367, 508, 368, 464, 472, 473, 455, 456, 470, 471, 468, 469, 498, 497, 370, 496, 495, 791, 494, 493, 492, 461, 441, 371, 489, 372, 488, 791, 373, 449, 374, 486, 485, 791, 437, 445, 439, 451, 437, 438, 791, 791, 435, 375, 477, 376, 476, 426, 434, 436, 428, 791, 428, 439, 426, 437, 379, 467, 425, 425, 464, 463, 387, 462, 791, 413, 460, 791, 426, 412, 411, 410, 791, 409, 454, 453, 408, 404, 444, 791, 405, 408, 403, 406, 445, 410, 409, 442, 388, 791, 393, 404, 391, 390, 390, 791, 390, 401, 400, 399, 398, 390, 384, 391, 430, 423, 394, 421, 420, 791, 376, 791, 372, 791, 371, 392, 417, 791, 416, 379, 366, 377, 376, 371, 791, 791, 410, 360, 402, 358, 357, 371, 366, 359, 361, 358, 348, 361, 350, 326, 300, 791, 791, 285, 791, 791, 262, 297, 260, 159, 70, 42, 791, 791, 422, 424, 63 } ; static yyconst flex_int16_t yy_def[585] = { 0, 581, 1, 581, 581, 581, 581, 582, 583, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 582, 581, 583, 581, 581, 584, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 584, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 0, 581, 581, 581 } ; static yyconst flex_int16_t yy_nxt[846] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 13, 14, 15, 4, 16, 17, 4, 4, 4, 18, 4, 4, 4, 4, 19, 20, 4, 4, 4, 4, 4, 21, 4, 16, 22, 23, 24, 25, 4, 18, 4, 4, 26, 27, 4, 28, 29, 30, 31, 32, 33, 34, 4, 4, 35, 36, 41, 41, 41, 41, 41, 41, 43, 44, 74, 45, 47, 46, 48, 61, 46, 49, 35, 36, 43, 44, 580, 42, 50, 41, 41, 41, 62, 43, 45, 44, 46, 55, 47, 56, 49, 48, 51, 52, 63, 43, 75, 44, 76, 49, 50, 53, 80, 64, 77, 54, 50, 65, 79, 579, 78, 51, 52, 81, 83, 67, 82, 75, 49, 84, 85, 76, 109, 77, 53, 80, 77, 79, 50, 54, 51, 52, 78, 83, 106, 83, 81, 94, 82, 53, 85, 84, 111, 54, 107, 77, 110, 112, 114, 51, 68, 95, 113, 96, 83, 102, 69, 87, 115, 70, 101, 119, 53, 123, 103, 104, 126, 54, 114, 116, 120, 113, 124, 102, 117, 121, 106, 125, 147, 118, 122, 115, 123, 104, 119, 111, 107, 151, 148, 126, 112, 155, 156, 157, 116, 160, 163, 120, 158, 117, 164, 124, 121, 159, 118, 167, 125, 122, 169, 578, 176, 156, 151, 180, 155, 163, 172, 173, 186, 174, 177, 189, 175, 181, 202, 205, 209, 169, 187, 190, 191, 152, 147, 203, 153, 154, 192, 160, 193, 161, 206, 213, 148, 164, 165, 207, 205, 157, 167, 216, 208, 176, 158, 168, 250, 224, 152, 159, 180, 153, 154, 177, 186, 251, 213, 225, 206, 233, 181, 216, 210, 207, 187, 234, 209, 224, 208, 250, 258, 272, 251, 161, 273, 284, 259, 225, 302, 165, 260, 282, 283, 287, 408, 285, 288, 295, 168, 577, 258, 303, 284, 289, 290, 295, 576, 296, 382, 252, 260, 392, 285, 575, 394, 296, 346, 347, 383, 397, 210, 393, 399, 348, 395, 349, 252, 402, 404, 398, 406, 417, 400, 382, 574, 409, 573, 403, 405, 392, 407, 418, 394, 383, 436, 437, 438, 439, 397, 393, 399, 402, 395, 404, 406, 451, 453, 458, 398, 417, 400, 403, 572, 405, 407, 452, 454, 459, 464, 418, 471, 473, 465, 484, 451, 453, 490, 458, 471, 473, 472, 474, 484, 485, 452, 454, 491, 459, 472, 474, 490, 531, 485, 543, 531, 543, 571, 570, 569, 568, 491, 532, 567, 544, 532, 544, 566, 565, 564, 563, 562, 561, 560, 554, 559, 558, 557, 556, 555, 546, 554, 553, 552, 492, 37, 37, 39, 39, 551, 550, 549, 548, 547, 546, 545, 542, 541, 540, 539, 538, 537, 536, 535, 534, 533, 515, 530, 529, 512, 528, 527, 526, 525, 524, 523, 522, 503, 502, 521, 520, 519, 518, 517, 494, 516, 515, 489, 488, 514, 513, 512, 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, 495, 460, 494, 493, 489, 488, 487, 486, 448, 447, 446, 444, 443, 441, 440, 483, 482, 481, 480, 479, 478, 477, 476, 475, 429, 470, 469, 468, 467, 466, 463, 462, 461, 460, 457, 456, 455, 450, 449, 448, 447, 446, 445, 444, 443, 442, 441, 440, 435, 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, 424, 423, 422, 421, 420, 419, 416, 415, 414, 413, 412, 411, 410, 401, 396, 391, 390, 389, 388, 387, 386, 385, 384, 381, 380, 379, 378, 377, 376, 336, 375, 374, 373, 372, 371, 370, 369, 368, 327, 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, 354, 353, 352, 351, 350, 345, 344, 304, 343, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 266, 309, 308, 307, 306, 305, 304, 301, 300, 299, 298, 253, 297, 294, 293, 292, 291, 286, 281, 280, 279, 278, 277, 276, 275, 274, 232, 271, 270, 269, 268, 227, 267, 266, 223, 265, 264, 263, 262, 261, 257, 256, 255, 211, 254, 253, 249, 248, 247, 246, 245, 244, 198, 243, 242, 241, 240, 239, 238, 237, 236, 235, 232, 231, 230, 229, 228, 227, 226, 223, 222, 221, 220, 219, 218, 217, 215, 166, 214, 162, 212, 211, 204, 201, 200, 199, 198, 146, 197, 144, 196, 195, 194, 188, 185, 184, 183, 182, 179, 178, 171, 170, 166, 162, 150, 149, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 108, 105, 100, 99, 98, 97, 93, 92, 91, 90, 89, 88, 86, 40, 38, 73, 72, 71, 66, 60, 59, 58, 57, 40, 38, 581, 3, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581 } ; static yyconst flex_int16_t yy_chk[846] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 12, 12, 12, 13, 13, 13, 15, 15, 584, 16, 18, 17, 18, 27, 22, 19, 35, 35, 21, 21, 579, 12, 19, 41, 41, 41, 27, 15, 16, 15, 17, 21, 18, 22, 19, 18, 20, 20, 28, 21, 43, 21, 44, 30, 19, 20, 49, 28, 46, 20, 30, 28, 48, 578, 47, 20, 20, 50, 52, 30, 51, 43, 30, 53, 54, 44, 73, 46, 20, 49, 56, 48, 30, 20, 31, 31, 47, 68, 71, 52, 50, 63, 51, 31, 54, 53, 76, 31, 71, 56, 73, 76, 78, 31, 31, 63, 77, 63, 68, 69, 31, 56, 79, 31, 68, 81, 31, 83, 69, 69, 85, 31, 78, 80, 82, 77, 84, 102, 80, 82, 106, 84, 108, 80, 82, 79, 83, 102, 81, 111, 106, 112, 108, 85, 111, 113, 114, 115, 116, 117, 119, 120, 115, 116, 121, 124, 120, 115, 116, 125, 124, 120, 126, 577, 130, 114, 151, 133, 113, 119, 129, 129, 138, 129, 130, 140, 129, 133, 153, 155, 158, 126, 138, 140, 140, 112, 147, 153, 112, 112, 140, 160, 140, 117, 156, 163, 147, 164, 121, 156, 155, 157, 167, 169, 156, 176, 157, 125, 205, 178, 151, 157, 180, 151, 151, 176, 186, 207, 163, 178, 206, 188, 180, 169, 158, 206, 186, 188, 209, 224, 206, 205, 217, 233, 251, 160, 233, 243, 217, 224, 259, 164, 217, 242, 242, 245, 361, 243, 245, 250, 167, 576, 258, 259, 284, 245, 245, 295, 575, 250, 343, 207, 258, 352, 284, 574, 353, 295, 307, 307, 343, 355, 209, 352, 356, 307, 353, 307, 251, 358, 359, 355, 360, 370, 356, 382, 571, 361, 568, 358, 359, 392, 360, 370, 394, 382, 390, 390, 391, 391, 397, 392, 399, 402, 394, 404, 406, 411, 412, 416, 397, 417, 399, 402, 567, 404, 406, 411, 412, 416, 422, 417, 428, 430, 422, 442, 451, 453, 456, 458, 471, 473, 428, 430, 484, 442, 451, 453, 456, 458, 471, 473, 490, 516, 484, 529, 531, 543, 566, 565, 564, 563, 490, 516, 562, 529, 531, 543, 561, 560, 559, 558, 557, 556, 555, 554, 551, 550, 549, 548, 547, 546, 544, 542, 540, 456, 582, 582, 583, 583, 538, 536, 535, 534, 533, 532, 530, 528, 527, 526, 525, 524, 522, 521, 520, 519, 518, 515, 514, 513, 512, 511, 510, 509, 508, 506, 505, 504, 503, 502, 501, 499, 498, 497, 496, 494, 493, 491, 489, 488, 487, 486, 485, 483, 482, 481, 480, 478, 477, 476, 475, 474, 472, 470, 467, 466, 465, 464, 463, 462, 460, 459, 457, 454, 452, 450, 449, 448, 447, 446, 444, 443, 441, 440, 439, 438, 437, 436, 435, 434, 433, 432, 431, 429, 427, 426, 425, 424, 423, 421, 420, 419, 418, 415, 414, 413, 410, 408, 407, 405, 403, 401, 400, 398, 396, 395, 393, 389, 388, 387, 386, 385, 384, 383, 381, 380, 379, 378, 377, 375, 374, 373, 372, 371, 369, 368, 367, 366, 365, 364, 362, 357, 354, 351, 350, 349, 348, 347, 346, 345, 344, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 323, 321, 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 306, 305, 304, 303, 302, 301, 300, 299, 298, 297, 296, 294, 293, 292, 290, 289, 288, 287, 286, 285, 283, 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260, 257, 256, 255, 254, 253, 252, 249, 248, 247, 246, 244, 241, 240, 239, 238, 237, 236, 235, 234, 232, 231, 230, 229, 228, 227, 226, 225, 223, 222, 221, 220, 219, 218, 215, 214, 212, 211, 210, 208, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 187, 185, 184, 183, 182, 181, 179, 177, 175, 174, 173, 172, 171, 170, 168, 166, 165, 162, 161, 159, 154, 152, 150, 149, 148, 146, 145, 144, 143, 142, 141, 139, 137, 136, 135, 134, 132, 131, 128, 127, 122, 118, 110, 109, 107, 105, 104, 103, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 72, 70, 67, 66, 65, 64, 62, 61, 60, 59, 58, 57, 55, 39, 37, 34, 33, 32, 29, 26, 25, 24, 23, 8, 7, 3, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581, 581 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "osm_qos_parser_l.l" #line 2 "osm_qos_parser_l.l" /* * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 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: * Lexer of OSM QoS parser. * * Environment: * Linux User Mode * * Author: * Yevgeny Kliteynik, Mellanox */ #include #define FILE_ID OSM_FILE_QOS_PARSER_L_L #include #include "osm_qos_parser_y.h" #define HANDLE_IF_IN_DESCRIPTION if (in_description) { yylval = strdup(yytext); return TK_TEXT; } #define SAVE_POS save_pos() static void save_pos(); extern int column_num; extern int line_num; extern FILE * yyin; extern YYSTYPE yylval; boolean_t in_description = FALSE; boolean_t in_list_of_hex_num_ranges = FALSE; boolean_t in_node_type = FALSE; boolean_t in_list_of_numbers = FALSE; boolean_t in_list_of_strings = FALSE; boolean_t in_list_of_num_pairs = FALSE; boolean_t in_asterisk_or_list_of_numbers = FALSE; boolean_t in_list_of_num_ranges = FALSE; boolean_t in_single_string = FALSE; boolean_t in_single_number = FALSE; static void reset_new_line_flags(); #define RESET_NEW_LINE_FLAGS reset_new_line_flags() #define START_USE {in_description = TRUE;} /* list of strings including whitespace (description) */ #define START_PORT_GUID {in_list_of_hex_num_ranges = TRUE;} /* comma-separated list of hex num ranges */ #define START_PORT_NAME {in_list_of_strings = TRUE;} /* comma-separated list of following strings: ../../.. */ #define START_PARTITION {in_single_string = TRUE;} /* single string w/o whitespaces (partition name) */ #define START_NAME {in_single_string = TRUE;} /* single string w/o whitespaces (port group name) */ #define START_QOS_LEVEL_NAME {in_single_string = TRUE;} /* single string w/o whitespaces (qos level name in match rule) */ #define START_NODE_TYPE {in_node_type = TRUE;} /* comma-separated list of node types (ROUTER,CA,...) */ #define START_SL2VL_TABLE {in_list_of_numbers = TRUE;} /* comma-separated list of hex or dec numbers */ #define START_GROUP {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS_TO {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS_FROM {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_SOURCE {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_DESTINATION {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_VLARB_HIGH {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */ #define START_VLARB_LOW {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */ #define START_TO {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */ #define START_FROM {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */ #define START_PATH_BITS {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_QOS_CLASS {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_SERVICE_ID {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_PKEY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_SL {in_single_number = TRUE;} /* single number */ #define START_VLARB_HIGH_LIMIT {in_single_number = TRUE;} /* single number */ #define START_MTU_LIMIT {in_single_number = TRUE;} /* single number */ #define START_RATE_LIMIT {in_single_number = TRUE;} /* single number */ #define START_PACKET_LIFE {in_single_number = TRUE;} /* single number */ #define START_ULP_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_ANY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_SDP_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_SDP_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_RDS_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_RDS_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_ISER_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_ISER_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_SRP_GUID {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_IPOIB_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_IPOIB_PKEY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define YY_NO_INPUT 1 #line 951 "osm_qos_parser_l.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); int yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ unsigned n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 205 "osm_qos_parser_l.l" #line 1135 "osm_qos_parser_l.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 582 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 791 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: /* rule 1 can match eol */ YY_RULE_SETUP #line 208 "osm_qos_parser_l.l" { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* swallow comment */ YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 209 "osm_qos_parser_l.l" { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* trailing blanks with new line */ YY_BREAK case 3: YY_RULE_SETUP #line 210 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; } YY_BREAK case 4: /* rule 4 can match eol */ YY_RULE_SETUP #line 211 "osm_qos_parser_l.l" { SAVE_POS; RESET_NEW_LINE_FLAGS; } YY_BREAK case 5: YY_RULE_SETUP #line 213 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_START; } YY_BREAK case 6: YY_RULE_SETUP #line 214 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_END; } YY_BREAK case 7: YY_RULE_SETUP #line 216 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_START; } YY_BREAK case 8: YY_RULE_SETUP #line 217 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_END; } YY_BREAK case 9: YY_RULE_SETUP #line 218 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_START; } YY_BREAK case 10: YY_RULE_SETUP #line 219 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_END; } YY_BREAK case 11: YY_RULE_SETUP #line 221 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_START; } YY_BREAK case 12: YY_RULE_SETUP #line 222 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_END; } YY_BREAK case 13: YY_RULE_SETUP #line 223 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_START; } YY_BREAK case 14: YY_RULE_SETUP #line 224 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_END; } YY_BREAK case 15: YY_RULE_SETUP #line 225 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_START; } YY_BREAK case 16: YY_RULE_SETUP #line 226 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_END; } YY_BREAK case 17: YY_RULE_SETUP #line 228 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_START; } YY_BREAK case 18: YY_RULE_SETUP #line 229 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_END; } YY_BREAK case 19: YY_RULE_SETUP #line 230 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_START; } YY_BREAK case 20: YY_RULE_SETUP #line 231 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_END; } YY_BREAK case 21: YY_RULE_SETUP #line 233 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_START; } YY_BREAK case 22: YY_RULE_SETUP #line 234 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_END; } YY_BREAK case 23: YY_RULE_SETUP #line 235 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_START; } YY_BREAK case 24: YY_RULE_SETUP #line 236 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_END; } YY_BREAK case 25: YY_RULE_SETUP #line 238 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_START; } YY_BREAK case 26: YY_RULE_SETUP #line 239 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_END; } YY_BREAK case 27: YY_RULE_SETUP #line 240 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_START; } YY_BREAK case 28: YY_RULE_SETUP #line 241 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_END; } YY_BREAK case 29: YY_RULE_SETUP #line 243 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_GUID; return TK_PORT_GUID; } YY_BREAK case 30: YY_RULE_SETUP #line 244 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_NAME; return TK_PORT_NAME; } YY_BREAK case 31: YY_RULE_SETUP #line 245 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PARTITION; return TK_PARTITION; } YY_BREAK case 32: YY_RULE_SETUP #line 246 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NODE_TYPE; return TK_NODE_TYPE; } YY_BREAK case 33: YY_RULE_SETUP #line 247 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NAME; return TK_NAME; } YY_BREAK case 34: YY_RULE_SETUP #line 248 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_USE; return TK_USE; } YY_BREAK case 35: YY_RULE_SETUP #line 249 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_GROUP; return TK_GROUP; } YY_BREAK case 36: YY_RULE_SETUP #line 250 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH; return TK_VLARB_HIGH; } YY_BREAK case 37: YY_RULE_SETUP #line 251 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_LOW; return TK_VLARB_LOW; } YY_BREAK case 38: YY_RULE_SETUP #line 252 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH_LIMIT; return TK_VLARB_HIGH_LIMIT;} YY_BREAK case 39: YY_RULE_SETUP #line 253 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_TO; return TK_TO; } YY_BREAK case 40: YY_RULE_SETUP #line 254 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_FROM; return TK_FROM; } YY_BREAK case 41: YY_RULE_SETUP #line 255 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_TO; return TK_ACROSS_TO; } YY_BREAK case 42: YY_RULE_SETUP #line 256 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_FROM; return TK_ACROSS_FROM;} YY_BREAK case 43: YY_RULE_SETUP #line 257 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS; return TK_ACROSS; } YY_BREAK case 44: YY_RULE_SETUP #line 258 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL2VL_TABLE; return TK_SL2VL_TABLE;} YY_BREAK case 45: YY_RULE_SETUP #line 259 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL; return TK_SL; } YY_BREAK case 46: YY_RULE_SETUP #line 260 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_MTU_LIMIT; return TK_MTU_LIMIT; } YY_BREAK case 47: YY_RULE_SETUP #line 261 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_RATE_LIMIT; return TK_RATE_LIMIT; } YY_BREAK case 48: YY_RULE_SETUP #line 262 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PACKET_LIFE; return TK_PACKET_LIFE;} YY_BREAK case 49: YY_RULE_SETUP #line 263 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PATH_BITS; return TK_PATH_BITS; } YY_BREAK case 50: YY_RULE_SETUP #line 264 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_CLASS; return TK_QOS_CLASS; } YY_BREAK case 51: YY_RULE_SETUP #line 265 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SOURCE; return TK_SOURCE; } YY_BREAK case 52: YY_RULE_SETUP #line 266 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_DESTINATION; return TK_DESTINATION;} YY_BREAK case 53: YY_RULE_SETUP #line 267 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SERVICE_ID; return TK_SERVICE_ID; } YY_BREAK case 54: YY_RULE_SETUP #line 268 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PKEY; return TK_PKEY; } YY_BREAK case 55: YY_RULE_SETUP #line 269 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_LEVEL_NAME; return TK_QOS_LEVEL_NAME;} YY_BREAK case 56: YY_RULE_SETUP #line 271 "osm_qos_parser_l.l" { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ROUTER; yylval = strdup(yytext); return TK_TEXT; } YY_BREAK case 57: YY_RULE_SETUP #line 272 "osm_qos_parser_l.l" { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_CA; yylval = strdup(yytext); return TK_TEXT; } YY_BREAK case 58: YY_RULE_SETUP #line 273 "osm_qos_parser_l.l" { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SWITCH; yylval = strdup(yytext); return TK_TEXT; } YY_BREAK case 59: YY_RULE_SETUP #line 274 "osm_qos_parser_l.l" { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SELF; yylval = strdup(yytext); return TK_TEXT; } YY_BREAK case 60: YY_RULE_SETUP #line 275 "osm_qos_parser_l.l" { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ALL; yylval = strdup(yytext); return TK_TEXT; } YY_BREAK case 61: YY_RULE_SETUP #line 277 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_DEFAULT; return TK_ULP_DEFAULT; } YY_BREAK case 62: YY_RULE_SETUP #line 278 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SERVICE_ID; } YY_BREAK case 63: YY_RULE_SETUP #line 279 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_PKEY; } YY_BREAK case 64: YY_RULE_SETUP #line 280 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_TARGET_PORT_GUID; } YY_BREAK case 65: YY_RULE_SETUP #line 281 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SOURCE_PORT_GUID; } YY_BREAK case 66: YY_RULE_SETUP #line 282 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SOURCE_TARGET_PORT_GUID; } YY_BREAK case 67: YY_RULE_SETUP #line 284 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_SDP_DEFAULT; } YY_BREAK case 68: YY_RULE_SETUP #line 285 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_SDP_PORT; } YY_BREAK case 69: YY_RULE_SETUP #line 287 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_DEFAULT; return TK_ULP_RDS_DEFAULT; } YY_BREAK case 70: YY_RULE_SETUP #line 288 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_PORT; return TK_ULP_RDS_PORT; } YY_BREAK case 71: YY_RULE_SETUP #line 290 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_ISER_DEFAULT; } YY_BREAK case 72: YY_RULE_SETUP #line 291 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_ISER_PORT; } YY_BREAK case 73: YY_RULE_SETUP #line 293 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SRP_GUID; return TK_ULP_SRP_GUID; } YY_BREAK case 74: YY_RULE_SETUP #line 295 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_DEFAULT; return TK_ULP_IPOIB_DEFAULT; } YY_BREAK case 75: YY_RULE_SETUP #line 296 "osm_qos_parser_l.l" { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_PKEY; return TK_ULP_IPOIB_PKEY; } YY_BREAK case 76: YY_RULE_SETUP #line 298 "osm_qos_parser_l.l" { SAVE_POS; yylval = strdup(yytext); if (in_description || in_list_of_strings || in_single_string) return TK_TEXT; return TK_NUMBER; } YY_BREAK case 77: YY_RULE_SETUP #line 306 "osm_qos_parser_l.l" { SAVE_POS; yylval = strdup(yytext); if (in_description || in_list_of_strings || in_single_string) return TK_TEXT; return TK_NUMBER; } YY_BREAK case 78: YY_RULE_SETUP #line 315 "osm_qos_parser_l.l" { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_DASH; } YY_BREAK case 79: YY_RULE_SETUP #line 325 "osm_qos_parser_l.l" { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_DOTDOT; } YY_BREAK case 80: YY_RULE_SETUP #line 335 "osm_qos_parser_l.l" { SAVE_POS; if (in_description) { yylval = strdup(yytext); return TK_TEXT; } return TK_COMMA; } YY_BREAK case 81: YY_RULE_SETUP #line 345 "osm_qos_parser_l.l" { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_ASTERISK; } YY_BREAK case 82: /* rule 82 can match eol */ YY_RULE_SETUP #line 355 "osm_qos_parser_l.l" { SAVE_POS; yylval = strdup(&yytext[1]); yylval[strlen(yylval)-1] = '\0'; return TK_TEXT; } YY_BREAK case 83: YY_RULE_SETUP #line 362 "osm_qos_parser_l.l" { SAVE_POS; yylval = strdup(yytext); return TK_TEXT;} YY_BREAK case YY_STATE_EOF(INITIAL): #line 364 "osm_qos_parser_l.l" { YY_NEW_FILE; yyterminate(); } YY_BREAK case 84: YY_RULE_SETUP #line 368 "osm_qos_parser_l.l" ECHO; YY_BREAK #line 1698 "osm_qos_parser_l.c" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 582 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 582 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 581); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 368 "osm_qos_parser_l.l" /********************************************* *********************************************/ static void save_pos() { int i; for (i = 0; i < yyleng; i++) { if (yytext[i] == '\n') { line_num ++; column_num = 1; } else column_num ++; } } /********************************************* *********************************************/ static void reset_new_line_flags() { in_description = FALSE; in_list_of_hex_num_ranges = FALSE; in_node_type = FALSE; in_list_of_numbers = FALSE; in_list_of_strings = FALSE; in_list_of_num_pairs = FALSE; in_asterisk_or_list_of_numbers = FALSE; in_list_of_num_ranges = FALSE; in_single_string = FALSE; in_single_number = FALSE; } opensm-3.3.20/opensm/osm_qos_parser_y.c0000644000205000001450000055403712314013174015053 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.4.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ /* Line 189 of yacc.c */ #line 1 "osm_qos_parser_y.y" /* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 HNR Consulting. 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: * Grammar of OSM QoS parser. * * Environment: * Linux User Mode * * Author: * Yevgeny Kliteynik, Mellanox */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_QOS_PARSER_Y_Y #include #include #define OSM_QOS_POLICY_MAX_LINE_LEN 1024*10 #define OSM_QOS_POLICY_SL2VL_TABLE_LEN IB_MAX_NUM_VLS #define OSM_QOS_POLICY_MAX_VL_NUM IB_MAX_NUM_VLS #define OSM_QOS_POLICY_MAX_RATE IB_MAX_RATE #define OSM_QOS_POLICY_MIN_RATE IB_MIN_RATE #define OSM_QOS_POLICY_MAX_MTU IB_MAX_MTU #define OSM_QOS_POLICY_MIN_MTU IB_MIN_MTU typedef struct tmp_parser_struct_t_ { char str[OSM_QOS_POLICY_MAX_LINE_LEN]; uint64_t num_pair[2]; cl_list_t str_list; cl_list_t num_list; cl_list_t num_pair_list; } tmp_parser_struct_t; static void __parser_tmp_struct_init(); static void __parser_tmp_struct_reset(); static void __parser_tmp_struct_destroy(); static char * __parser_strip_white(char * str); static void __parser_str2uint64(uint64_t * p_val, char * str); static void __parser_port_group_start(); static int __parser_port_group_end(); static void __parser_sl2vl_scope_start(); static int __parser_sl2vl_scope_end(); static void __parser_vlarb_scope_start(); static int __parser_vlarb_scope_end(); static void __parser_qos_level_start(); static int __parser_qos_level_end(); static void __parser_match_rule_start(); static int __parser_match_rule_end(); static void __parser_ulp_match_rule_start(); static int __parser_ulp_match_rule_end(); static void __pkey_rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len); static void __rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len); static void __merge_rangearr( uint64_t ** range_arr_1, unsigned range_len_1, uint64_t ** range_arr_2, unsigned range_len_2, uint64_t ** * p_arr, unsigned * p_arr_len ); static void __parser_add_port_to_port_map( cl_qmap_t * p_map, osm_physp_t * p_physp); static void __parser_add_guid_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len); static void __parser_add_pkey_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len); static void __parser_add_partition_list_to_port_map( cl_qmap_t * p_map, cl_list_t * p_list); static void __parser_add_map_to_port_map( cl_qmap_t * p_dmap, cl_map_t * p_smap); static int __validate_pkeys( uint64_t ** range_arr, unsigned range_len, boolean_t is_ipoib); static void __setup_simple_qos_levels(); static void __clear_simple_qos_levels(); static void __setup_ulp_match_rules(); static void __process_ulp_match_rules(); static void yyerror(const char *format, ...); extern char * yytext; extern int yylex (void); extern FILE * yyin; extern int errno; extern void yyrestart(FILE *input_file); int yyparse(); #define RESET_BUFFER __parser_tmp_struct_reset() tmp_parser_struct_t tmp_parser_struct; int column_num; int line_num; osm_qos_policy_t * p_qos_policy = NULL; osm_qos_port_group_t * p_current_port_group = NULL; osm_qos_sl2vl_scope_t * p_current_sl2vl_scope = NULL; osm_qos_vlarb_scope_t * p_current_vlarb_scope = NULL; osm_qos_level_t * p_current_qos_level = NULL; osm_qos_match_rule_t * p_current_qos_match_rule = NULL; osm_log_t * p_qos_parser_osm_log; /* 16 Simple QoS Levels - one for each SL */ static osm_qos_level_t osm_qos_policy_simple_qos_levels[16]; /* Default Simple QoS Level */ osm_qos_level_t __default_simple_qos_level; /* * List of match rules that will be generated by the * qos-ulp section. These rules are concatenated to * the end of the usual matching rules list at the * end of parsing. */ static cl_list_t __ulp_match_rules; /***************************************************/ /* Line 189 of yacc.c */ #line 267 "osm_qos_parser_y.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { TK_NUMBER = 258, TK_DASH = 259, TK_DOTDOT = 260, TK_COMMA = 261, TK_ASTERISK = 262, TK_TEXT = 263, TK_QOS_ULPS_START = 264, TK_QOS_ULPS_END = 265, TK_PORT_GROUPS_START = 266, TK_PORT_GROUPS_END = 267, TK_PORT_GROUP_START = 268, TK_PORT_GROUP_END = 269, TK_QOS_SETUP_START = 270, TK_QOS_SETUP_END = 271, TK_VLARB_TABLES_START = 272, TK_VLARB_TABLES_END = 273, TK_VLARB_SCOPE_START = 274, TK_VLARB_SCOPE_END = 275, TK_SL2VL_TABLES_START = 276, TK_SL2VL_TABLES_END = 277, TK_SL2VL_SCOPE_START = 278, TK_SL2VL_SCOPE_END = 279, TK_QOS_LEVELS_START = 280, TK_QOS_LEVELS_END = 281, TK_QOS_LEVEL_START = 282, TK_QOS_LEVEL_END = 283, TK_QOS_MATCH_RULES_START = 284, TK_QOS_MATCH_RULES_END = 285, TK_QOS_MATCH_RULE_START = 286, TK_QOS_MATCH_RULE_END = 287, TK_NAME = 288, TK_USE = 289, TK_PORT_GUID = 290, TK_PORT_NAME = 291, TK_PARTITION = 292, TK_NODE_TYPE = 293, TK_GROUP = 294, TK_ACROSS = 295, TK_VLARB_HIGH = 296, TK_VLARB_LOW = 297, TK_VLARB_HIGH_LIMIT = 298, TK_TO = 299, TK_FROM = 300, TK_ACROSS_TO = 301, TK_ACROSS_FROM = 302, TK_SL2VL_TABLE = 303, TK_SL = 304, TK_MTU_LIMIT = 305, TK_RATE_LIMIT = 306, TK_PACKET_LIFE = 307, TK_PATH_BITS = 308, TK_QOS_CLASS = 309, TK_SOURCE = 310, TK_DESTINATION = 311, TK_SERVICE_ID = 312, TK_QOS_LEVEL_NAME = 313, TK_PKEY = 314, TK_NODE_TYPE_ROUTER = 315, TK_NODE_TYPE_CA = 316, TK_NODE_TYPE_SWITCH = 317, TK_NODE_TYPE_SELF = 318, TK_NODE_TYPE_ALL = 319, TK_ULP_DEFAULT = 320, TK_ULP_ANY_SERVICE_ID = 321, TK_ULP_ANY_PKEY = 322, TK_ULP_ANY_TARGET_PORT_GUID = 323, TK_ULP_ANY_SOURCE_PORT_GUID = 324, TK_ULP_ANY_SOURCE_TARGET_PORT_GUID = 325, TK_ULP_SDP_DEFAULT = 326, TK_ULP_SDP_PORT = 327, TK_ULP_RDS_DEFAULT = 328, TK_ULP_RDS_PORT = 329, TK_ULP_ISER_DEFAULT = 330, TK_ULP_ISER_PORT = 331, TK_ULP_SRP_GUID = 332, TK_ULP_IPOIB_DEFAULT = 333, TK_ULP_IPOIB_PKEY = 334 }; #endif /* Tokens. */ #define TK_NUMBER 258 #define TK_DASH 259 #define TK_DOTDOT 260 #define TK_COMMA 261 #define TK_ASTERISK 262 #define TK_TEXT 263 #define TK_QOS_ULPS_START 264 #define TK_QOS_ULPS_END 265 #define TK_PORT_GROUPS_START 266 #define TK_PORT_GROUPS_END 267 #define TK_PORT_GROUP_START 268 #define TK_PORT_GROUP_END 269 #define TK_QOS_SETUP_START 270 #define TK_QOS_SETUP_END 271 #define TK_VLARB_TABLES_START 272 #define TK_VLARB_TABLES_END 273 #define TK_VLARB_SCOPE_START 274 #define TK_VLARB_SCOPE_END 275 #define TK_SL2VL_TABLES_START 276 #define TK_SL2VL_TABLES_END 277 #define TK_SL2VL_SCOPE_START 278 #define TK_SL2VL_SCOPE_END 279 #define TK_QOS_LEVELS_START 280 #define TK_QOS_LEVELS_END 281 #define TK_QOS_LEVEL_START 282 #define TK_QOS_LEVEL_END 283 #define TK_QOS_MATCH_RULES_START 284 #define TK_QOS_MATCH_RULES_END 285 #define TK_QOS_MATCH_RULE_START 286 #define TK_QOS_MATCH_RULE_END 287 #define TK_NAME 288 #define TK_USE 289 #define TK_PORT_GUID 290 #define TK_PORT_NAME 291 #define TK_PARTITION 292 #define TK_NODE_TYPE 293 #define TK_GROUP 294 #define TK_ACROSS 295 #define TK_VLARB_HIGH 296 #define TK_VLARB_LOW 297 #define TK_VLARB_HIGH_LIMIT 298 #define TK_TO 299 #define TK_FROM 300 #define TK_ACROSS_TO 301 #define TK_ACROSS_FROM 302 #define TK_SL2VL_TABLE 303 #define TK_SL 304 #define TK_MTU_LIMIT 305 #define TK_RATE_LIMIT 306 #define TK_PACKET_LIFE 307 #define TK_PATH_BITS 308 #define TK_QOS_CLASS 309 #define TK_SOURCE 310 #define TK_DESTINATION 311 #define TK_SERVICE_ID 312 #define TK_QOS_LEVEL_NAME 313 #define TK_PKEY 314 #define TK_NODE_TYPE_ROUTER 315 #define TK_NODE_TYPE_CA 316 #define TK_NODE_TYPE_SWITCH 317 #define TK_NODE_TYPE_SELF 318 #define TK_NODE_TYPE_ALL 319 #define TK_ULP_DEFAULT 320 #define TK_ULP_ANY_SERVICE_ID 321 #define TK_ULP_ANY_PKEY 322 #define TK_ULP_ANY_TARGET_PORT_GUID 323 #define TK_ULP_ANY_SOURCE_PORT_GUID 324 #define TK_ULP_ANY_SOURCE_TARGET_PORT_GUID 325 #define TK_ULP_SDP_DEFAULT 326 #define TK_ULP_SDP_PORT 327 #define TK_ULP_RDS_DEFAULT 328 #define TK_ULP_RDS_PORT 329 #define TK_ULP_ISER_DEFAULT 330 #define TK_ULP_ISER_PORT 331 #define TK_ULP_SRP_GUID 332 #define TK_ULP_IPOIB_DEFAULT 333 #define TK_ULP_IPOIB_PKEY 334 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 264 of yacc.c */ #line 467 "osm_qos_parser_y.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 275 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 80 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 169 /* YYNRULES -- Number of rules. */ #define YYNRULES 244 /* YYNRULES -- Number of states. */ #define YYNSTATES 340 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 334 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 5, 6, 9, 11, 13, 15, 17, 19, 23, 25, 28, 32, 34, 37, 41, 43, 45, 46, 49, 51, 53, 55, 57, 59, 61, 63, 67, 68, 71, 74, 78, 79, 82, 86, 88, 90, 91, 94, 96, 98, 100, 102, 104, 108, 109, 112, 116, 118, 120, 121, 124, 126, 128, 130, 132, 134, 136, 138, 142, 143, 146, 150, 152, 154, 155, 158, 160, 162, 164, 166, 168, 170, 172, 174, 178, 179, 182, 186, 188, 190, 191, 194, 196, 198, 200, 202, 204, 206, 208, 211, 212, 218, 219, 225, 226, 232, 233, 239, 240, 246, 247, 251, 252, 258, 259, 263, 264, 270, 271, 275, 276, 282, 283, 289, 290, 294, 295, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323, 325, 327, 329, 331, 334, 336, 339, 341, 344, 346, 349, 351, 354, 356, 359, 361, 364, 366, 368, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 395, 397, 400, 402, 405, 407, 410, 412, 415, 417, 420, 422, 425, 427, 430, 432, 435, 437, 440, 442, 445, 447, 449, 451, 453, 455, 457, 459, 461, 463, 466, 468, 471, 473, 476, 478, 481, 483, 486, 488, 491, 493, 496, 498, 501, 503, 506, 508, 511, 513, 516, 518, 521, 523, 526, 528, 531, 533, 536, 538, 541, 543, 545, 547, 550, 552, 554, 558, 560, 562, 566, 568, 572, 578, 580, 582, 584, 586, 590, 596, 600, 602, 604 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 81, 0, -1, 82, -1, -1, 82, 83, -1, 84, -1, 86, -1, 93, -1, 109, -1, 116, -1, 9, 85, 10, -1, 123, -1, 85, 123, -1, 11, 87, 12, -1, 88, -1, 87, 88, -1, 89, 91, 90, -1, 13, -1, 14, -1, -1, 91, 92, -1, 153, -1, 155, -1, 159, -1, 157, -1, 161, -1, 163, -1, 165, -1, 15, 94, 16, -1, -1, 94, 95, -1, 94, 102, -1, 17, 96, 18, -1, -1, 96, 97, -1, 98, 100, 99, -1, 19, -1, 20, -1, -1, 100, 101, -1, 174, -1, 176, -1, 180, -1, 182, -1, 178, -1, 21, 103, 22, -1, -1, 103, 104, -1, 105, 107, 106, -1, 23, -1, 24, -1, -1, 107, 108, -1, 184, -1, 186, -1, 188, -1, 190, -1, 192, -1, 194, -1, 202, -1, 25, 110, 26, -1, -1, 110, 111, -1, 112, 114, 113, -1, 27, -1, 28, -1, -1, 114, 115, -1, 204, -1, 206, -1, 208, -1, 210, -1, 212, -1, 214, -1, 216, -1, 218, -1, 29, 117, 30, -1, -1, 117, 118, -1, 119, 121, 120, -1, 31, -1, 32, -1, -1, 121, 122, -1, 220, -1, 222, -1, 228, -1, 224, -1, 226, -1, 230, -1, 232, -1, 65, 238, -1, -1, 138, 244, 5, 124, 152, -1, -1, 139, 244, 5, 125, 152, -1, -1, 140, 244, 5, 126, 152, -1, -1, 141, 244, 5, 127, 152, -1, -1, 142, 244, 5, 128, 152, -1, -1, 143, 129, 152, -1, -1, 144, 244, 5, 130, 152, -1, -1, 145, 131, 152, -1, -1, 146, 244, 5, 132, 152, -1, -1, 147, 133, 152, -1, -1, 148, 244, 5, 134, 152, -1, -1, 149, 244, 5, 135, 152, -1, -1, 150, 136, 152, -1, -1, 151, 244, 5, 137, 152, -1, 66, -1, 67, -1, 68, -1, 69, -1, 70, -1, 71, -1, 72, -1, 73, -1, 74, -1, 75, -1, 76, -1, 77, -1, 78, -1, 79, -1, 238, -1, 154, 234, -1, 33, -1, 156, 234, -1, 34, -1, 158, 237, -1, 36, -1, 160, 244, -1, 35, -1, 162, 244, -1, 59, -1, 164, 237, -1, 37, -1, 166, 167, -1, 38, -1, 168, -1, 167, 6, 168, -1, 169, -1, 170, -1, 171, -1, 172, -1, 173, -1, 61, -1, 62, -1, 60, -1, 64, -1, 63, -1, 175, 237, -1, 39, -1, 177, 237, -1, 40, -1, 179, 238, -1, 43, -1, 181, 241, -1, 41, -1, 183, 241, -1, 42, -1, 185, 237, -1, 39, -1, 187, 237, -1, 40, -1, 189, 237, -1, 47, -1, 191, 237, -1, 46, -1, 193, 196, -1, 45, -1, 195, 198, -1, 44, -1, 197, -1, 200, -1, 7, -1, 199, -1, 201, -1, 7, -1, 244, -1, 244, -1, 203, 239, -1, 48, -1, 205, 234, -1, 33, -1, 207, 234, -1, 34, -1, 209, 238, -1, 49, -1, 211, 238, -1, 50, -1, 213, 238, -1, 51, -1, 215, 238, -1, 52, -1, 217, 244, -1, 53, -1, 219, 244, -1, 59, -1, 221, 234, -1, 34, -1, 223, 244, -1, 54, -1, 225, 237, -1, 55, -1, 227, 237, -1, 56, -1, 229, 234, -1, 58, -1, 231, 244, -1, 57, -1, 233, 244, -1, 59, -1, 235, -1, 236, -1, 235, 236, -1, 8, -1, 234, -1, 237, 6, 234, -1, 240, -1, 240, -1, 239, 6, 240, -1, 3, -1, 242, 5, 243, -1, 241, 6, 242, 5, 243, -1, 3, -1, 3, -1, 245, -1, 246, -1, 247, 4, 248, -1, 245, 6, 247, 4, 248, -1, 245, 6, 246, -1, 3, -1, 3, -1, 3, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 285, 285, 288, 289, 292, 293, 294, 295, 296, 322, 325, 326, 355, 358, 359, 362, 365, 370, 376, 377, 380, 381, 382, 383, 384, 385, 386, 413, 416, 417, 418, 423, 426, 427, 430, 433, 438, 444, 445, 460, 461, 462, 463, 464, 469, 472, 473, 476, 479, 484, 490, 491, 510, 511, 512, 513, 514, 515, 516, 540, 543, 544, 547, 550, 555, 561, 562, 565, 566, 567, 568, 569, 570, 571, 572, 594, 597, 598, 601, 604, 609, 615, 616, 619, 620, 621, 622, 623, 624, 625, 649, 667, 667, 688, 688, 709, 709, 744, 744, 779, 779, 817, 817, 830, 830, 864, 864, 877, 877, 911, 911, 924, 924, 958, 958, 994, 994, 1014, 1014, 1047, 1050, 1053, 1056, 1059, 1062, 1065, 1068, 1071, 1074, 1077, 1080, 1083, 1086, 1090, 1129, 1152, 1157, 1180, 1185, 1251, 1256, 1276, 1281, 1301, 1306, 1314, 1319, 1324, 1329, 1330, 1333, 1334, 1335, 1336, 1337, 1340, 1346, 1352, 1358, 1366, 1388, 1405, 1410, 1427, 1432, 1450, 1455, 1472, 1477, 1494, 1510, 1527, 1532, 1551, 1556, 1573, 1578, 1596, 1601, 1606, 1611, 1616, 1621, 1622, 1625, 1632, 1633, 1636, 1643, 1674, 1706, 1749, 1766, 1789, 1794, 1817, 1822, 1842, 1847, 1874, 1880, 1907, 1913, 1933, 1939, 1974, 1979, 2012, 2029, 2052, 2057, 2091, 2096, 2113, 2118, 2135, 2140, 2163, 2168, 2201, 2206, 2239, 2250, 2257, 2258, 2261, 2268, 2269, 2274, 2277, 2278, 2281, 2289, 2295, 2303, 2309, 2315, 2318, 2324, 2336, 2348, 2356, 2363, 2369 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "TK_NUMBER", "TK_DASH", "TK_DOTDOT", "TK_COMMA", "TK_ASTERISK", "TK_TEXT", "TK_QOS_ULPS_START", "TK_QOS_ULPS_END", "TK_PORT_GROUPS_START", "TK_PORT_GROUPS_END", "TK_PORT_GROUP_START", "TK_PORT_GROUP_END", "TK_QOS_SETUP_START", "TK_QOS_SETUP_END", "TK_VLARB_TABLES_START", "TK_VLARB_TABLES_END", "TK_VLARB_SCOPE_START", "TK_VLARB_SCOPE_END", "TK_SL2VL_TABLES_START", "TK_SL2VL_TABLES_END", "TK_SL2VL_SCOPE_START", "TK_SL2VL_SCOPE_END", "TK_QOS_LEVELS_START", "TK_QOS_LEVELS_END", "TK_QOS_LEVEL_START", "TK_QOS_LEVEL_END", "TK_QOS_MATCH_RULES_START", "TK_QOS_MATCH_RULES_END", "TK_QOS_MATCH_RULE_START", "TK_QOS_MATCH_RULE_END", "TK_NAME", "TK_USE", "TK_PORT_GUID", "TK_PORT_NAME", "TK_PARTITION", "TK_NODE_TYPE", "TK_GROUP", "TK_ACROSS", "TK_VLARB_HIGH", "TK_VLARB_LOW", "TK_VLARB_HIGH_LIMIT", "TK_TO", "TK_FROM", "TK_ACROSS_TO", "TK_ACROSS_FROM", "TK_SL2VL_TABLE", "TK_SL", "TK_MTU_LIMIT", "TK_RATE_LIMIT", "TK_PACKET_LIFE", "TK_PATH_BITS", "TK_QOS_CLASS", "TK_SOURCE", "TK_DESTINATION", "TK_SERVICE_ID", "TK_QOS_LEVEL_NAME", "TK_PKEY", "TK_NODE_TYPE_ROUTER", "TK_NODE_TYPE_CA", "TK_NODE_TYPE_SWITCH", "TK_NODE_TYPE_SELF", "TK_NODE_TYPE_ALL", "TK_ULP_DEFAULT", "TK_ULP_ANY_SERVICE_ID", "TK_ULP_ANY_PKEY", "TK_ULP_ANY_TARGET_PORT_GUID", "TK_ULP_ANY_SOURCE_PORT_GUID", "TK_ULP_ANY_SOURCE_TARGET_PORT_GUID", "TK_ULP_SDP_DEFAULT", "TK_ULP_SDP_PORT", "TK_ULP_RDS_DEFAULT", "TK_ULP_RDS_PORT", "TK_ULP_ISER_DEFAULT", "TK_ULP_ISER_PORT", "TK_ULP_SRP_GUID", "TK_ULP_IPOIB_DEFAULT", "TK_ULP_IPOIB_PKEY", "$accept", "head", "qos_policy_entries", "qos_policy_entry", "qos_ulps_section", "qos_ulps", "port_groups_section", "port_groups", "port_group", "port_group_start", "port_group_end", "port_group_entries", "port_group_entry", "qos_setup_section", "qos_setup_items", "vlarb_tables", "vlarb_scope_items", "vlarb_scope", "vlarb_scope_start", "vlarb_scope_end", "vlarb_scope_entries", "vlarb_scope_entry", "sl2vl_tables", "sl2vl_scope_items", "sl2vl_scope", "sl2vl_scope_start", "sl2vl_scope_end", "sl2vl_scope_entries", "sl2vl_scope_entry", "qos_levels_section", "qos_levels", "qos_level", "qos_level_start", "qos_level_end", "qos_level_entries", "qos_level_entry", "qos_match_rules_section", "qos_match_rules", "qos_match_rule", "qos_match_rule_start", "qos_match_rule_end", "qos_match_rule_entries", "qos_match_rule_entry", "qos_ulp", "$@1", "$@2", "$@3", "$@4", "$@5", "$@6", "$@7", "$@8", "$@9", "$@10", "$@11", "$@12", "$@13", "$@14", "qos_ulp_type_any_service", "qos_ulp_type_any_pkey", "qos_ulp_type_any_target_port_guid", "qos_ulp_type_any_source_port_guid", "qos_ulp_type_any_source_target_port_guid", "qos_ulp_type_sdp_default", "qos_ulp_type_sdp_port", "qos_ulp_type_rds_default", "qos_ulp_type_rds_port", "qos_ulp_type_iser_default", "qos_ulp_type_iser_port", "qos_ulp_type_srp_guid", "qos_ulp_type_ipoib_default", "qos_ulp_type_ipoib_pkey", "qos_ulp_sl", "port_group_name", "port_group_name_start", "port_group_use", "port_group_use_start", "port_group_port_name", "port_group_port_name_start", "port_group_port_guid", "port_group_port_guid_start", "port_group_pkey", "port_group_pkey_start", "port_group_partition", "port_group_partition_start", "port_group_node_type", "port_group_node_type_start", "port_group_node_type_list", "node_type_item", "node_type_ca", "node_type_switch", "node_type_router", "node_type_all", "node_type_self", "vlarb_scope_group", "vlarb_scope_group_start", "vlarb_scope_across", "vlarb_scope_across_start", "vlarb_scope_vlarb_high_limit", "vlarb_scope_vlarb_high_limit_start", "vlarb_scope_vlarb_high", "vlarb_scope_vlarb_high_start", "vlarb_scope_vlarb_low", "vlarb_scope_vlarb_low_start", "sl2vl_scope_group", "sl2vl_scope_group_start", "sl2vl_scope_across", "sl2vl_scope_across_start", "sl2vl_scope_across_from", "sl2vl_scope_across_from_start", "sl2vl_scope_across_to", "sl2vl_scope_across_to_start", "sl2vl_scope_from", "sl2vl_scope_from_start", "sl2vl_scope_to", "sl2vl_scope_to_start", "sl2vl_scope_from_list_or_asterisk", "sl2vl_scope_from_asterisk", "sl2vl_scope_to_list_or_asterisk", "sl2vl_scope_to_asterisk", "sl2vl_scope_from_list_of_ranges", "sl2vl_scope_to_list_of_ranges", "sl2vl_scope_sl2vl_table", "sl2vl_scope_sl2vl_table_start", "qos_level_name", "qos_level_name_start", "qos_level_use", "qos_level_use_start", "qos_level_sl", "qos_level_sl_start", "qos_level_mtu_limit", "qos_level_mtu_limit_start", "qos_level_rate_limit", "qos_level_rate_limit_start", "qos_level_packet_life", "qos_level_packet_life_start", "qos_level_path_bits", "qos_level_path_bits_start", "qos_level_pkey", "qos_level_pkey_start", "qos_match_rule_use", "qos_match_rule_use_start", "qos_match_rule_qos_class", "qos_match_rule_qos_class_start", "qos_match_rule_source", "qos_match_rule_source_start", "qos_match_rule_destination", "qos_match_rule_destination_start", "qos_match_rule_qos_level_name", "qos_match_rule_qos_level_name_start", "qos_match_rule_service_id", "qos_match_rule_service_id_start", "qos_match_rule_pkey", "qos_match_rule_pkey_start", "single_string", "single_string_elems", "single_string_element", "string_list", "single_number", "num_list", "number", "num_list_with_dotdot", "number_from_pair_1", "number_from_pair_2", "list_of_ranges", "num_list_with_dash", "single_number_from_range", "number_from_range_1", "number_from_range_2", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 80, 81, 82, 82, 83, 83, 83, 83, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 91, 91, 92, 92, 92, 92, 92, 92, 92, 93, 94, 94, 94, 95, 96, 96, 97, 98, 99, 100, 100, 101, 101, 101, 101, 101, 102, 103, 103, 104, 105, 106, 107, 107, 108, 108, 108, 108, 108, 108, 108, 109, 110, 110, 111, 112, 113, 114, 114, 115, 115, 115, 115, 115, 115, 115, 115, 116, 117, 117, 118, 119, 120, 121, 121, 122, 122, 122, 122, 122, 122, 122, 123, 124, 123, 125, 123, 126, 123, 127, 123, 128, 123, 129, 123, 130, 123, 131, 123, 132, 123, 133, 123, 134, 123, 135, 123, 136, 123, 137, 123, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 167, 168, 168, 168, 168, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 196, 197, 198, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 235, 236, 237, 237, 238, 239, 239, 240, 241, 241, 242, 243, 244, 245, 245, 245, 245, 246, 247, 248 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 3, 1, 2, 3, 1, 2, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 3, 0, 2, 2, 3, 0, 2, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 3, 0, 2, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 3, 0, 2, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 0, 2, 3, 1, 1, 0, 2, 1, 1, 1, 1, 1, 1, 1, 2, 0, 5, 0, 5, 0, 5, 0, 5, 0, 5, 0, 3, 0, 5, 0, 3, 0, 5, 0, 3, 0, 5, 0, 5, 0, 3, 0, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 3, 1, 1, 3, 1, 3, 5, 1, 1, 1, 1, 3, 5, 3, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 3, 0, 2, 1, 0, 0, 29, 61, 77, 4, 5, 6, 7, 8, 9, 0, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 0, 11, 0, 0, 0, 0, 0, 102, 0, 106, 0, 110, 0, 0, 116, 0, 17, 0, 14, 19, 0, 0, 0, 232, 91, 229, 10, 12, 242, 0, 237, 238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 15, 0, 28, 33, 46, 30, 31, 60, 64, 62, 66, 76, 80, 78, 82, 92, 0, 0, 94, 96, 98, 100, 103, 134, 104, 107, 108, 111, 112, 114, 117, 118, 18, 136, 138, 142, 140, 146, 148, 144, 16, 20, 21, 0, 22, 0, 24, 0, 23, 0, 25, 0, 26, 0, 27, 0, 0, 0, 0, 0, 0, 241, 0, 244, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 135, 223, 224, 137, 227, 139, 141, 143, 145, 158, 156, 157, 160, 159, 147, 149, 151, 152, 153, 154, 155, 32, 36, 34, 38, 45, 49, 47, 51, 65, 194, 196, 198, 200, 202, 204, 206, 208, 63, 67, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0, 81, 210, 212, 214, 216, 220, 218, 222, 79, 83, 84, 0, 85, 0, 87, 0, 88, 0, 86, 0, 89, 0, 90, 0, 93, 0, 95, 97, 99, 101, 105, 109, 113, 115, 119, 225, 0, 0, 0, 0, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 240, 228, 150, 37, 162, 164, 168, 170, 166, 35, 39, 40, 0, 41, 0, 44, 0, 42, 0, 43, 0, 50, 172, 174, 182, 180, 178, 176, 192, 48, 52, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 161, 163, 165, 235, 167, 0, 169, 171, 173, 175, 177, 185, 179, 183, 184, 189, 188, 181, 186, 187, 190, 191, 230, 0, 0, 0, 0, 236, 233, 231, 0, 234 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 1, 2, 9, 10, 30, 11, 47, 48, 49, 117, 78, 118, 12, 50, 82, 133, 175, 176, 272, 246, 273, 83, 134, 179, 180, 292, 247, 293, 13, 51, 86, 87, 190, 135, 191, 14, 52, 90, 91, 216, 136, 217, 31, 137, 142, 143, 144, 145, 67, 146, 69, 147, 71, 148, 149, 74, 150, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 99, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 166, 167, 168, 169, 170, 171, 172, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 320, 321, 325, 326, 322, 327, 306, 307, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 156, 153, 154, 157, 100, 329, 55, 312, 313, 336, 59, 60, 61, 62, 141 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -294 static const yytype_int16 yypact[] = { -294, 18, 13, -294, 87, 7, -294, -294, -294, -294, -294, -294, -294, -294, -294, 20, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 66, -294, 26, 26, 26, 26, 26, -294, 26, -294, 26, -294, 26, 26, -294, 26, -294, 41, -294, -294, 0, 29, 35, -294, -294, -294, -294, -294, 27, 52, 53, -294, 69, 70, 72, 73, 75, 20, 79, 20, 80, 20, 81, 89, 20, 91, -294, -294, -1, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 26, 71, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, -294, 90, -294, 90, -294, 26, -294, 26, -294, 90, -294, 116, 50, 49, 11, -7, 20, -294, 88, -294, -294, 20, 20, 20, 20, 20, 20, 20, 20, 20, -294, -294, 90, -294, -294, -294, 94, -294, -294, 94, -294, -294, -294, -294, -294, 95, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, -294, 90, -294, 20, -294, 20, -294, 20, -294, 20, -294, 26, -294, 26, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, -294, 26, -294, 90, -294, 90, -294, 90, -294, 26, -294, 26, -294, 71, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, 116, 84, 43, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 94, 94, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, -294, 90, -294, 20, -294, 99, -294, 99, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 90, -294, 90, -294, 90, -294, 90, -294, 12, -294, 23, -294, 20, 94, 94, -294, -294, 97, 101, 97, 94, 94, 94, 94, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 102, -294, 99, 104, 20, 105, -294, -294, -294, 104, -294 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -294, -294, -294, -294, -294, -294, -294, -294, 64, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, 82, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -28, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -117, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -294, -114, -294, -24, -126, -4, -294, -293, -137, -184, -190, -33, -294, 57, 74, -65 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -244 static const yytype_int16 yytable[] = { 63, 64, 65, 66, 160, 68, 152, 70, 155, 72, 73, 54, 75, 109, 330, 58, 79, 80, 3, 319, 46, 81, 4, 53, 5, 208, 58, 209, 6, 58, 324, -243, 110, 111, 112, 113, 114, 115, 7, 181, 337, 102, 8, 104, 182, 183, 107, 210, 211, 212, 213, 214, 215, 76, 46, 84, 85, 92, 116, 93, 184, 185, 186, 187, 188, 88, 89, 284, 173, 174, 189, 177, 178, 94, 140, 95, 56, 96, 97, 248, 98, 249, 285, 286, 101, 103, 105, 287, 288, 289, 290, 291, 233, 158, 106, 159, 108, 258, 151, 259, 244, 245, 311, 331, 266, 256, 332, 335, 333, 232, 338, 77, 57, 260, 234, 235, 236, 237, 238, 239, 240, 241, 242, 267, 268, 269, 270, 271, 265, 243, 264, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 314, 334, 339, 308, 138, 309, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 139, 263, 315, 0, 316, 254, 317, 255, 318, 161, 162, 163, 164, 165, 0, 0, 0, 0, 0, 0, 0, 257, 0, 0, 0, 0, 250, 0, 251, 261, 252, 262, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 323, 0, 328, 0, 0, 310 }; static const yytype_int16 yycheck[] = { 33, 34, 35, 36, 130, 38, 120, 40, 122, 42, 43, 15, 45, 14, 307, 3, 16, 17, 0, 7, 13, 21, 9, 3, 11, 32, 3, 34, 15, 3, 7, 4, 33, 34, 35, 36, 37, 38, 25, 28, 333, 69, 29, 71, 33, 34, 74, 54, 55, 56, 57, 58, 59, 12, 13, 26, 27, 5, 59, 6, 49, 50, 51, 52, 53, 30, 31, 24, 18, 19, 59, 22, 23, 4, 3, 5, 10, 5, 5, 193, 5, 195, 39, 40, 5, 5, 5, 44, 45, 46, 47, 48, 4, 126, 5, 128, 5, 223, 8, 225, 6, 6, 3, 6, 20, 219, 5, 3, 6, 137, 5, 47, 30, 227, 142, 143, 144, 145, 146, 147, 148, 149, 150, 39, 40, 41, 42, 43, 245, 153, 244, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 283, 331, 338, 275, 93, 277, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 93, 233, 295, -1, 297, 205, 299, 207, 301, 60, 61, 62, 63, 64, -1, -1, -1, -1, -1, -1, -1, 221, -1, -1, -1, -1, 197, -1, 199, 229, 201, 231, 203, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 303, -1, 305, -1, -1, 279 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 81, 82, 0, 9, 11, 15, 25, 29, 83, 84, 86, 93, 109, 116, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 85, 123, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 13, 87, 88, 89, 94, 110, 117, 3, 238, 240, 10, 123, 3, 244, 245, 246, 247, 244, 244, 244, 244, 129, 244, 131, 244, 133, 244, 244, 136, 244, 12, 88, 91, 16, 17, 21, 95, 102, 26, 27, 111, 112, 30, 31, 118, 119, 5, 6, 4, 5, 5, 5, 5, 152, 238, 5, 152, 5, 152, 5, 5, 152, 5, 14, 33, 34, 35, 36, 37, 38, 59, 90, 92, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 96, 103, 114, 121, 124, 246, 247, 3, 248, 125, 126, 127, 128, 130, 132, 134, 135, 137, 8, 234, 235, 236, 234, 234, 237, 244, 244, 237, 60, 61, 62, 63, 64, 167, 168, 169, 170, 171, 172, 173, 18, 19, 97, 98, 22, 23, 104, 105, 28, 33, 34, 49, 50, 51, 52, 53, 59, 113, 115, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 32, 34, 54, 55, 56, 57, 58, 59, 120, 122, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 152, 4, 152, 152, 152, 152, 152, 152, 152, 152, 152, 236, 6, 6, 100, 107, 234, 234, 238, 238, 238, 238, 244, 244, 234, 244, 237, 237, 234, 244, 244, 248, 234, 168, 20, 39, 40, 41, 42, 43, 99, 101, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 24, 39, 40, 44, 45, 46, 47, 48, 106, 108, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 202, 203, 237, 237, 238, 3, 241, 242, 241, 237, 237, 237, 237, 7, 196, 197, 200, 244, 7, 198, 199, 201, 244, 239, 240, 6, 5, 6, 242, 3, 243, 240, 5, 243 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*-------------------------. | yyparse or yypush_parse. | `-------------------------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 17: /* Line 1455 of yacc.c */ #line 365 "osm_qos_parser_y.y" { __parser_port_group_start(); } break; case 18: /* Line 1455 of yacc.c */ #line 370 "osm_qos_parser_y.y" { if ( __parser_port_group_end() ) return 1; } break; case 36: /* Line 1455 of yacc.c */ #line 433 "osm_qos_parser_y.y" { __parser_vlarb_scope_start(); } break; case 37: /* Line 1455 of yacc.c */ #line 438 "osm_qos_parser_y.y" { if ( __parser_vlarb_scope_end() ) return 1; } break; case 49: /* Line 1455 of yacc.c */ #line 479 "osm_qos_parser_y.y" { __parser_sl2vl_scope_start(); } break; case 50: /* Line 1455 of yacc.c */ #line 484 "osm_qos_parser_y.y" { if ( __parser_sl2vl_scope_end() ) return 1; } break; case 64: /* Line 1455 of yacc.c */ #line 550 "osm_qos_parser_y.y" { __parser_qos_level_start(); } break; case 65: /* Line 1455 of yacc.c */ #line 555 "osm_qos_parser_y.y" { if ( __parser_qos_level_end() ) return 1; } break; case 80: /* Line 1455 of yacc.c */ #line 604 "osm_qos_parser_y.y" { __parser_match_rule_start(); } break; case 81: /* Line 1455 of yacc.c */ #line 609 "osm_qos_parser_y.y" { if ( __parser_match_rule_end() ) return 1; } break; case 91: /* Line 1455 of yacc.c */ #line 649 "osm_qos_parser_y.y" { /* parsing default ulp rule: "default: num" */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_tmp_num > 15) { yyerror("illegal SL value"); return 1; } __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num); __default_simple_qos_level.sl_set = TRUE; free(p_tmp_num); cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 92: /* Line 1455 of yacc.c */ #line 667 "osm_qos_parser_y.y" { /* "any, service-id ... : sl" - one instance of list of ranges */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have service ids"); return 1; } /* get all the service id ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } break; case 94: /* Line 1455 of yacc.c */ #line 688 "osm_qos_parser_y.y" { /* "any, pkey ... : sl" - one instance of list of ranges */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have pkeys"); return 1; } /* get all the pkey ranges */ __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } break; case 96: /* Line 1455 of yacc.c */ #line 709 "osm_qos_parser_y.y" { /* any, target-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } break; case 98: /* Line 1455 of yacc.c */ #line 744 "osm_qos_parser_y.y" { /* any, source-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Sources_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the source groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->source_group_list, p_current_port_group); __parser_port_group_end(); } break; case 100: /* Line 1455 of yacc.c */ #line 779 "osm_qos_parser_y.y" { /* any, source-target-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Sources_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the source and destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->source_group_list, p_current_port_group); cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } break; case 102: /* Line 1455 of yacc.c */ #line 817 "osm_qos_parser_y.y" { /* "sdp : sl" - default SL for SDP */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } break; case 104: /* Line 1455 of yacc.c */ #line 830 "osm_qos_parser_y.y" { /* sdp with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("SDP ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } break; case 106: /* Line 1455 of yacc.c */ #line 864 "osm_qos_parser_y.y" { /* "rds : sl" - default SL for RDS */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + OSM_QOS_POLICY_ULP_RDS_PORT; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } break; case 108: /* Line 1455 of yacc.c */ #line 877 "osm_qos_parser_y.y" { /* rds with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("RDS ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } break; case 110: /* Line 1455 of yacc.c */ #line 911 "osm_qos_parser_y.y" { /* "iSER : sl" - default SL for iSER */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } break; case 112: /* Line 1455 of yacc.c */ #line 924 "osm_qos_parser_y.y" { /* iser with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("iSER ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } break; case 114: /* Line 1455 of yacc.c */ #line 958 "osm_qos_parser_y.y" { /* srp with target guids - this rule is similar to writing 'any' ulp with target port guids */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("SRP ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_SRP_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } break; case 116: /* Line 1455 of yacc.c */ #line 994 "osm_qos_parser_y.y" { /* ipoib w/o any pkeys (default pkey) */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = 0x7fff; /* * Although we know that the default partition exists, * we still need to validate it by checking that it has * at least two full members. Otherwise IPoIB won't work. */ if (__validate_pkeys(range_arr, 1, TRUE)) return 1; p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = 1; } break; case 118: /* Line 1455 of yacc.c */ #line 1014 "osm_qos_parser_y.y" { /* ipoib with pkeys */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("IPoIB ULP rule doesn't have pkeys"); return 1; } /* get all the pkey ranges */ __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* * Validate pkeys. * For IPoIB pkeys the validation is strict. * If some problem would be found, parsing will * be aborted with a proper error messages. */ if (__validate_pkeys(range_arr, range_len, TRUE)) { free(range_arr); return 1; } p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } break; case 120: /* Line 1455 of yacc.c */ #line 1048 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 121: /* Line 1455 of yacc.c */ #line 1051 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 122: /* Line 1455 of yacc.c */ #line 1054 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 123: /* Line 1455 of yacc.c */ #line 1057 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 124: /* Line 1455 of yacc.c */ #line 1060 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 125: /* Line 1455 of yacc.c */ #line 1063 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 126: /* Line 1455 of yacc.c */ #line 1066 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 127: /* Line 1455 of yacc.c */ #line 1069 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 128: /* Line 1455 of yacc.c */ #line 1072 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 129: /* Line 1455 of yacc.c */ #line 1075 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 130: /* Line 1455 of yacc.c */ #line 1078 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 131: /* Line 1455 of yacc.c */ #line 1081 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 132: /* Line 1455 of yacc.c */ #line 1084 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 133: /* Line 1455 of yacc.c */ #line 1087 "osm_qos_parser_y.y" { __parser_ulp_match_rule_start(); } break; case 134: /* Line 1455 of yacc.c */ #line 1090 "osm_qos_parser_y.y" { /* get the SL for ULP rules */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; uint8_t sl; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_tmp_num > 15) { yyerror("illegal SL value"); return 1; } sl = (uint8_t)(*p_tmp_num); free(p_tmp_num); cl_list_remove_all(&tmp_parser_struct.num_list); p_current_qos_match_rule->p_qos_level = &osm_qos_policy_simple_qos_levels[sl]; p_current_qos_match_rule->qos_level_name = strdup(osm_qos_policy_simple_qos_levels[sl].name); if (__parser_ulp_match_rule_end()) return 1; } break; case 135: /* Line 1455 of yacc.c */ #line 1129 "osm_qos_parser_y.y" { /* 'name' of 'port-group' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_port_group->name) { yyerror("port-group has multiple 'name' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_port_group->name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 136: /* Line 1455 of yacc.c */ #line 1152 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 137: /* Line 1455 of yacc.c */ #line 1157 "osm_qos_parser_y.y" { /* 'use' of 'port-group' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_port_group->use) { yyerror("port-group has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_port_group->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 138: /* Line 1455 of yacc.c */ #line 1180 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 139: /* Line 1455 of yacc.c */ #line 1185 "osm_qos_parser_y.y" { /* 'port-name' in 'port-group' - any num of instances */ cl_list_iterator_t list_iterator; osm_node_t * p_node; osm_physp_t * p_physp; unsigned port_num; char * tmp_str; char * port_str; /* parsing port name strings */ for (list_iterator = cl_list_head(&tmp_parser_struct.str_list); list_iterator != cl_list_end(&tmp_parser_struct.str_list); list_iterator = cl_list_next(list_iterator)) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { /* last slash in port name string is a separator between node name and port number */ port_str = strrchr(tmp_str, '/'); if (!port_str || (strlen(port_str) < 3) || (port_str[1] != 'p' && port_str[1] != 'P')) { yyerror("'%s' - illegal port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } if (!(port_num = strtoul(&port_str[2],NULL,0))) { yyerror( "'%s' - illegal port number in port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } /* separate node name from port number */ port_str[0] = '\0'; if (st_lookup(p_qos_policy->p_node_hash, (st_data_t)tmp_str, (void *)&p_node)) { /* we found the node, now get the right port */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { yyerror( "'%s' - port number out of range in port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } /* we found the port, now add it to guid table */ __parser_add_port_to_port_map(&p_current_port_group->port_map, p_physp); } free(tmp_str); } } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 140: /* Line 1455 of yacc.c */ #line 1251 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 141: /* Line 1455 of yacc.c */ #line 1256 "osm_qos_parser_y.y" { /* 'port-guid' in 'port-group' - any num of instances */ /* list of guid ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); } } break; case 142: /* Line 1455 of yacc.c */ #line 1276 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 143: /* Line 1455 of yacc.c */ #line 1281 "osm_qos_parser_y.y" { /* 'pkey' in 'port-group' - any num of instances */ /* list of pkey ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_pkey_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); } } break; case 144: /* Line 1455 of yacc.c */ #line 1301 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 145: /* Line 1455 of yacc.c */ #line 1306 "osm_qos_parser_y.y" { /* 'partition' in 'port-group' - any num of instances */ __parser_add_partition_list_to_port_map( &p_current_port_group->port_map, &tmp_parser_struct.str_list); } break; case 146: /* Line 1455 of yacc.c */ #line 1314 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 147: /* Line 1455 of yacc.c */ #line 1319 "osm_qos_parser_y.y" { /* 'node-type' in 'port-group' - any num of instances */ } break; case 148: /* Line 1455 of yacc.c */ #line 1324 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 156: /* Line 1455 of yacc.c */ #line 1340 "osm_qos_parser_y.y" { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_CA; } break; case 157: /* Line 1455 of yacc.c */ #line 1346 "osm_qos_parser_y.y" { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_SWITCH; } break; case 158: /* Line 1455 of yacc.c */ #line 1352 "osm_qos_parser_y.y" { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_ROUTER; } break; case 159: /* Line 1455 of yacc.c */ #line 1358 "osm_qos_parser_y.y" { p_current_port_group->node_types |= (OSM_QOS_POLICY_NODE_TYPE_CA | OSM_QOS_POLICY_NODE_TYPE_SWITCH | OSM_QOS_POLICY_NODE_TYPE_ROUTER); } break; case 160: /* Line 1455 of yacc.c */ #line 1366 "osm_qos_parser_y.y" { osm_port_t * p_osm_port = osm_get_port_by_guid(p_qos_policy->p_subn, p_qos_policy->p_subn->sm_port_guid); if (p_osm_port) __parser_add_port_to_port_map( &p_current_port_group->port_map, p_osm_port->p_physp); } break; case 161: /* Line 1455 of yacc.c */ #line 1388 "osm_qos_parser_y.y" { /* 'group' in 'vlarb-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_vlarb_scope->group_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 162: /* Line 1455 of yacc.c */ #line 1405 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 163: /* Line 1455 of yacc.c */ #line 1410 "osm_qos_parser_y.y" { /* 'across' in 'vlarb-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_vlarb_scope->across_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 164: /* Line 1455 of yacc.c */ #line 1427 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 165: /* Line 1455 of yacc.c */ #line 1432 "osm_qos_parser_y.y" { /* 'vl-high-limit' in 'vlarb-scope' - one instance of one number */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (p_tmp_num) { p_current_vlarb_scope->vl_high_limit = (uint32_t)(*p_tmp_num); p_current_vlarb_scope->vl_high_limit_set = TRUE; free(p_tmp_num); } cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 166: /* Line 1455 of yacc.c */ #line 1450 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 167: /* Line 1455 of yacc.c */ #line 1455 "osm_qos_parser_y.y" { /* 'vlarb-high' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */ cl_list_iterator_t list_iterator; uint64_t * num_pair; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) cl_list_insert_tail(&p_current_vlarb_scope->vlarb_high_list,num_pair); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } break; case 168: /* Line 1455 of yacc.c */ #line 1472 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 169: /* Line 1455 of yacc.c */ #line 1477 "osm_qos_parser_y.y" { /* 'vlarb-low' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */ cl_list_iterator_t list_iterator; uint64_t * num_pair; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) cl_list_insert_tail(&p_current_vlarb_scope->vlarb_low_list,num_pair); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } break; case 170: /* Line 1455 of yacc.c */ #line 1494 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 171: /* Line 1455 of yacc.c */ #line 1510 "osm_qos_parser_y.y" { /* 'group' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_sl2vl_scope->group_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 172: /* Line 1455 of yacc.c */ #line 1527 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 173: /* Line 1455 of yacc.c */ #line 1532 "osm_qos_parser_y.y" { /* 'across' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str); cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,strdup(tmp_str)); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 174: /* Line 1455 of yacc.c */ #line 1551 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 175: /* Line 1455 of yacc.c */ #line 1556 "osm_qos_parser_y.y" { /* 'across-from' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 176: /* Line 1455 of yacc.c */ #line 1573 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 177: /* Line 1455 of yacc.c */ #line 1578 "osm_qos_parser_y.y" { /* 'across-to' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,tmp_str); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 178: /* Line 1455 of yacc.c */ #line 1596 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 179: /* Line 1455 of yacc.c */ #line 1601 "osm_qos_parser_y.y" { /* 'from' in 'sl2vl-scope' - any num of instances */ } break; case 180: /* Line 1455 of yacc.c */ #line 1606 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 181: /* Line 1455 of yacc.c */ #line 1611 "osm_qos_parser_y.y" { /* 'to' in 'sl2vl-scope' - any num of instances */ } break; case 182: /* Line 1455 of yacc.c */ #line 1616 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 185: /* Line 1455 of yacc.c */ #line 1625 "osm_qos_parser_y.y" { int i; for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++) p_current_sl2vl_scope->from[i] = TRUE; } break; case 188: /* Line 1455 of yacc.c */ #line 1636 "osm_qos_parser_y.y" { int i; for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++) p_current_sl2vl_scope->to[i] = TRUE; } break; case 189: /* Line 1455 of yacc.c */ #line 1643 "osm_qos_parser_y.y" { int i; cl_list_iterator_t list_iterator; uint64_t * num_pair; uint8_t num1, num2; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) { if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH ) { yyerror("port number out of range 'from' list"); free(num_pair); cl_list_remove_all(&tmp_parser_struct.num_pair_list); return 1; } num1 = (uint8_t)num_pair[0]; num2 = (uint8_t)num_pair[1]; free(num_pair); for (i = num1; i <= num2; i++) p_current_sl2vl_scope->from[i] = TRUE; } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } break; case 190: /* Line 1455 of yacc.c */ #line 1674 "osm_qos_parser_y.y" { int i; cl_list_iterator_t list_iterator; uint64_t * num_pair; uint8_t num1, num2; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) { if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH ) { yyerror("port number out of range 'to' list"); free(num_pair); cl_list_remove_all(&tmp_parser_struct.num_pair_list); return 1; } num1 = (uint8_t)num_pair[0]; num2 = (uint8_t)num_pair[1]; free(num_pair); for (i = num1; i <= num2; i++) p_current_sl2vl_scope->to[i] = TRUE; } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } break; case 191: /* Line 1455 of yacc.c */ #line 1706 "osm_qos_parser_y.y" { /* 'sl2vl-table' - one instance of exactly OSM_QOS_POLICY_SL2VL_TABLE_LEN numbers */ cl_list_iterator_t list_iterator; uint64_t num; uint64_t * p_num; int i = 0; if (p_current_sl2vl_scope->sl2vl_table_set) { yyerror("sl2vl-scope has more than one sl2vl-table"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } if (cl_list_count(&tmp_parser_struct.num_list) != OSM_QOS_POLICY_SL2VL_TABLE_LEN) { yyerror("wrong number of values in 'sl2vl-table' (should be 16)"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_list) ) { p_num = (uint64_t*)cl_list_obj(list_iterator); num = *p_num; free(p_num); if (num >= OSM_QOS_POLICY_MAX_VL_NUM) { yyerror("wrong VL value in 'sl2vl-table' (should be 0 to 15)"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_sl2vl_scope->sl2vl_table[i++] = (uint8_t)num; list_iterator = cl_list_next(list_iterator); } p_current_sl2vl_scope->sl2vl_table_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 192: /* Line 1455 of yacc.c */ #line 1749 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 193: /* Line 1455 of yacc.c */ #line 1766 "osm_qos_parser_y.y" { /* 'name' of 'qos-level' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_level->name) { yyerror("qos-level has multiple 'name' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_level->name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 194: /* Line 1455 of yacc.c */ #line 1789 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 195: /* Line 1455 of yacc.c */ #line 1794 "osm_qos_parser_y.y" { /* 'use' of 'qos-level' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_level->use) { yyerror("qos-level has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_level->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 196: /* Line 1455 of yacc.c */ #line 1817 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 197: /* Line 1455 of yacc.c */ #line 1822 "osm_qos_parser_y.y" { /* 'sl' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->sl_set) { yyerror("'qos-level' has multiple 'sl' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); p_current_qos_level->sl = (uint8_t)(*p_num); free(p_num); p_current_qos_level->sl_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 198: /* Line 1455 of yacc.c */ #line 1842 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 199: /* Line 1455 of yacc.c */ #line 1847 "osm_qos_parser_y.y" { /* 'mtu-limit' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->mtu_limit_set) { yyerror("'qos-level' has multiple 'mtu-limit' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_num > OSM_QOS_POLICY_MAX_MTU || *p_num < OSM_QOS_POLICY_MIN_MTU) { yyerror("mtu limit is out of range, value: %d", *p_num); free(p_num); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_qos_level->mtu_limit = (uint8_t)(*p_num); free(p_num); p_current_qos_level->mtu_limit_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 200: /* Line 1455 of yacc.c */ #line 1874 "osm_qos_parser_y.y" { /* 'mtu-limit' in 'qos-level' - one instance */ RESET_BUFFER; } break; case 201: /* Line 1455 of yacc.c */ #line 1880 "osm_qos_parser_y.y" { /* 'rate-limit' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->rate_limit_set) { yyerror("'qos-level' has multiple 'rate-limit' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_num > OSM_QOS_POLICY_MAX_RATE || *p_num < OSM_QOS_POLICY_MIN_RATE) { yyerror("rate limit is out of range, value: %d", *p_num); free(p_num); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_qos_level->rate_limit = (uint8_t)(*p_num); free(p_num); p_current_qos_level->rate_limit_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 202: /* Line 1455 of yacc.c */ #line 1907 "osm_qos_parser_y.y" { /* 'rate-limit' in 'qos-level' - one instance */ RESET_BUFFER; } break; case 203: /* Line 1455 of yacc.c */ #line 1913 "osm_qos_parser_y.y" { /* 'packet-life' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->pkt_life_set) { yyerror("'qos-level' has multiple 'packet-life' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); p_current_qos_level->pkt_life = (uint8_t)(*p_num); free(p_num); p_current_qos_level->pkt_life_set= TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } break; case 204: /* Line 1455 of yacc.c */ #line 1933 "osm_qos_parser_y.y" { /* 'packet-life' in 'qos-level' - one instance */ RESET_BUFFER; } break; case 205: /* Line 1455 of yacc.c */ #line 1939 "osm_qos_parser_y.y" { /* 'path-bits' in 'qos-level' - any num of instances */ /* list of path bit ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_level->path_bits_range_len ) { p_current_qos_level->path_bits_range_arr = range_arr; p_current_qos_level->path_bits_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_level->path_bits_range_arr, p_current_qos_level->path_bits_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_level->path_bits_range_arr = new_range_arr; p_current_qos_level->path_bits_range_len = new_range_len; } } } break; case 206: /* Line 1455 of yacc.c */ #line 1974 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 207: /* Line 1455 of yacc.c */ #line 1979 "osm_qos_parser_y.y" { /* 'pkey' in 'qos-level' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_level->pkey_range_len ) { p_current_qos_level->pkey_range_arr = range_arr; p_current_qos_level->pkey_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_level->pkey_range_arr, p_current_qos_level->pkey_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_level->pkey_range_arr = new_range_arr; p_current_qos_level->pkey_range_len = new_range_len; } } } break; case 208: /* Line 1455 of yacc.c */ #line 2012 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 209: /* Line 1455 of yacc.c */ #line 2029 "osm_qos_parser_y.y" { /* 'use' of 'qos-match-rule' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_match_rule->use) { yyerror("'qos-match-rule' has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_match_rule->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 210: /* Line 1455 of yacc.c */ #line 2052 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 211: /* Line 1455 of yacc.c */ #line 2057 "osm_qos_parser_y.y" { /* 'qos-class' in 'qos-match-rule' - num of instances of list of ranges */ /* list of class ranges (QoS Class is 12-bit value) */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->qos_class_range_len ) { p_current_qos_match_rule->qos_class_range_arr = range_arr; p_current_qos_match_rule->qos_class_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->qos_class_range_arr, p_current_qos_match_rule->qos_class_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->qos_class_range_arr = new_range_arr; p_current_qos_match_rule->qos_class_range_len = new_range_len; } } } break; case 212: /* Line 1455 of yacc.c */ #line 2091 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 213: /* Line 1455 of yacc.c */ #line 2096 "osm_qos_parser_y.y" { /* 'source' in 'qos-match-rule' - text */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_qos_match_rule->source_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 214: /* Line 1455 of yacc.c */ #line 2113 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 215: /* Line 1455 of yacc.c */ #line 2118 "osm_qos_parser_y.y" { /* 'destination' in 'qos-match-rule' - text */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_qos_match_rule->destination_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 216: /* Line 1455 of yacc.c */ #line 2135 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 217: /* Line 1455 of yacc.c */ #line 2140 "osm_qos_parser_y.y" { /* 'qos-level-name' in 'qos-match-rule' - single string */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_match_rule->qos_level_name) { yyerror("qos-match-rule has multiple 'qos-level-name' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_match_rule->qos_level_name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } break; case 218: /* Line 1455 of yacc.c */ #line 2163 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 219: /* Line 1455 of yacc.c */ #line 2168 "osm_qos_parser_y.y" { /* 'service-id' in 'qos-match-rule' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->service_id_range_len ) { p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->service_id_range_arr, p_current_qos_match_rule->service_id_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->service_id_range_arr = new_range_arr; p_current_qos_match_rule->service_id_range_len = new_range_len; } } } break; case 220: /* Line 1455 of yacc.c */ #line 2201 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 221: /* Line 1455 of yacc.c */ #line 2206 "osm_qos_parser_y.y" { /* 'pkey' in 'qos-match-rule' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->pkey_range_len ) { p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->pkey_range_arr, p_current_qos_match_rule->pkey_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->pkey_range_arr = new_range_arr; p_current_qos_match_rule->pkey_range_len = new_range_len; } } } break; case 222: /* Line 1455 of yacc.c */ #line 2239 "osm_qos_parser_y.y" { RESET_BUFFER; } break; case 223: /* Line 1455 of yacc.c */ #line 2250 "osm_qos_parser_y.y" { cl_list_insert_tail(&tmp_parser_struct.str_list, strdup(__parser_strip_white(tmp_parser_struct.str))); tmp_parser_struct.str[0] = '\0'; } break; case 226: /* Line 1455 of yacc.c */ #line 2261 "osm_qos_parser_y.y" { strcat(tmp_parser_struct.str,(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; case 232: /* Line 1455 of yacc.c */ #line 2281 "osm_qos_parser_y.y" { uint64_t * p_num = (uint64_t*)malloc(sizeof(uint64_t)); __parser_str2uint64(p_num,(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); cl_list_insert_tail(&tmp_parser_struct.num_list, p_num); } break; case 233: /* Line 1455 of yacc.c */ #line 2289 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 234: /* Line 1455 of yacc.c */ #line 2295 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 235: /* Line 1455 of yacc.c */ #line 2303 "osm_qos_parser_y.y" { __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; case 236: /* Line 1455 of yacc.c */ #line 2309 "osm_qos_parser_y.y" { __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; case 238: /* Line 1455 of yacc.c */ #line 2318 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 239: /* Line 1455 of yacc.c */ #line 2324 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) { num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; } else { num_pair[1] = tmp_parser_struct.num_pair[0]; num_pair[0] = tmp_parser_struct.num_pair[1]; } cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 240: /* Line 1455 of yacc.c */ #line 2336 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) { num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; } else { num_pair[1] = tmp_parser_struct.num_pair[0]; num_pair[0] = tmp_parser_struct.num_pair[1]; } cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 241: /* Line 1455 of yacc.c */ #line 2348 "osm_qos_parser_y.y" { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } break; case 242: /* Line 1455 of yacc.c */ #line 2356 "osm_qos_parser_y.y" { __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)])); __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; case 243: /* Line 1455 of yacc.c */ #line 2363 "osm_qos_parser_y.y" { __parser_str2uint64(&tmp_parser_struct.num_pair[0],(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; case 244: /* Line 1455 of yacc.c */ #line 2369 "osm_qos_parser_y.y" { __parser_str2uint64(&tmp_parser_struct.num_pair[1],(yyvsp[(1) - (1)])); free((yyvsp[(1) - (1)])); } break; /* Line 1455 of yacc.c */ #line 4305 "osm_qos_parser_y.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined(yyoverflow) || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } /* Line 1675 of yacc.c */ #line 2375 "osm_qos_parser_y.y" /*************************************************** ***************************************************/ int osm_qos_parse_policy_file(IN osm_subn_t * p_subn) { int res = 0; static boolean_t first_time = TRUE; p_qos_parser_osm_log = &p_subn->p_osm->log; OSM_LOG_ENTER(p_qos_parser_osm_log); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; yyin = fopen (p_subn->opt.qos_policy_file, "r"); if (!yyin) { if (strcmp(p_subn->opt.qos_policy_file,OSM_DEFAULT_QOS_POLICY_FILE)) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC01: " "Failed opening QoS policy file %s - %s\n", p_subn->opt.qos_policy_file, strerror(errno)); res = 1; } else OSM_LOG(p_qos_parser_osm_log, OSM_LOG_VERBOSE, "QoS policy file not found (%s)\n", p_subn->opt.qos_policy_file); goto Exit; } if (first_time) { first_time = FALSE; __setup_simple_qos_levels(); __setup_ulp_match_rules(); OSM_LOG(p_qos_parser_osm_log, OSM_LOG_INFO, "Loading QoS policy file (%s)\n", p_subn->opt.qos_policy_file); } else /* * ULP match rules list was emptied at the end of * previous parsing iteration. * What's left is to clear simple QoS levels. */ __clear_simple_qos_levels(); column_num = 1; line_num = 1; p_subn->p_qos_policy = osm_qos_policy_create(p_subn); __parser_tmp_struct_init(); p_qos_policy = p_subn->p_qos_policy; res = yyparse(); __parser_tmp_struct_destroy(); if (res != 0) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC03: " "Failed parsing QoS policy file (%s)\n", p_subn->opt.qos_policy_file); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; res = 1; goto Exit; } /* add generated ULP match rules to the usual match rules */ __process_ulp_match_rules(); if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log)) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC04: " "Error(s) in QoS policy file (%s)\n", p_subn->opt.qos_policy_file); fprintf(stderr, "Error(s) in QoS policy file (%s)\n", p_subn->opt.qos_policy_file); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; res = 1; goto Exit; } Exit: if (yyin) { yyrestart(yyin); fclose(yyin); } OSM_LOG_EXIT(p_qos_parser_osm_log); return res; } /*************************************************** ***************************************************/ int yywrap() { return(1); } /*************************************************** ***************************************************/ static void yyerror(const char *format, ...) { char s[256]; va_list pvar; OSM_LOG_ENTER(p_qos_parser_osm_log); va_start(pvar, format); vsnprintf(s, sizeof(s), format, pvar); va_end(pvar); OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC05: " "Syntax error (line %d:%d): %s\n", line_num, column_num, s); fprintf(stderr, "Error in QoS Policy File (line %d:%d): %s.\n", line_num, column_num, s); OSM_LOG_EXIT(p_qos_parser_osm_log); } /*************************************************** ***************************************************/ static char * __parser_strip_white(char * str) { char *p; while (isspace(*str)) str++; if (!*str) return str; p = str + strlen(str) - 1; while (isspace(*p)) *p-- = '\0'; return str; } /*************************************************** ***************************************************/ static void __parser_str2uint64(uint64_t * p_val, char * str) { *p_val = strtoull(str, NULL, 0); } /*************************************************** ***************************************************/ static void __parser_port_group_start() { p_current_port_group = osm_qos_policy_port_group_create(); } /*************************************************** ***************************************************/ static int __parser_port_group_end() { if(!p_current_port_group->name) { yyerror("port-group validation failed - no port group name specified"); return -1; } cl_list_insert_tail(&p_qos_policy->port_groups, p_current_port_group); p_current_port_group = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_vlarb_scope_start() { p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create(); } /*************************************************** ***************************************************/ static int __parser_vlarb_scope_end() { if ( !cl_list_count(&p_current_vlarb_scope->group_list) && !cl_list_count(&p_current_vlarb_scope->across_list) ) { yyerror("vlarb-scope validation failed - no port groups specified by 'group' or by 'across'"); return -1; } cl_list_insert_tail(&p_qos_policy->vlarb_tables, p_current_vlarb_scope); p_current_vlarb_scope = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_sl2vl_scope_start() { p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create(); } /*************************************************** ***************************************************/ static int __parser_sl2vl_scope_end() { if (!p_current_sl2vl_scope->sl2vl_table_set) { yyerror("sl2vl-scope validation failed - no sl2vl table specified"); return -1; } if ( !cl_list_count(&p_current_sl2vl_scope->group_list) && !cl_list_count(&p_current_sl2vl_scope->across_to_list) && !cl_list_count(&p_current_sl2vl_scope->across_from_list) ) { yyerror("sl2vl-scope validation failed - no port groups specified by 'group', 'across-to' or 'across-from'"); return -1; } cl_list_insert_tail(&p_qos_policy->sl2vl_tables, p_current_sl2vl_scope); p_current_sl2vl_scope = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_qos_level_start() { p_current_qos_level = osm_qos_policy_qos_level_create(); } /*************************************************** ***************************************************/ static int __parser_qos_level_end() { if (!p_current_qos_level->sl_set) { yyerror("qos-level validation failed - no 'sl' specified"); return -1; } if (!p_current_qos_level->name) { yyerror("qos-level validation failed - no 'name' specified"); return -1; } cl_list_insert_tail(&p_qos_policy->qos_levels, p_current_qos_level); p_current_qos_level = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_match_rule_start() { p_current_qos_match_rule = osm_qos_policy_match_rule_create(); } /*************************************************** ***************************************************/ static int __parser_match_rule_end() { if (!p_current_qos_match_rule->qos_level_name) { yyerror("match-rule validation failed - no 'qos-level-name' specified"); return -1; } cl_list_insert_tail(&p_qos_policy->qos_match_rules, p_current_qos_match_rule); p_current_qos_match_rule = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_ulp_match_rule_start() { p_current_qos_match_rule = osm_qos_policy_match_rule_create(); } /*************************************************** ***************************************************/ static int __parser_ulp_match_rule_end() { CL_ASSERT(p_current_qos_match_rule->p_qos_level); cl_list_insert_tail(&__ulp_match_rules, p_current_qos_match_rule); p_current_qos_match_rule = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_tmp_struct_init() { tmp_parser_struct.str[0] = '\0'; cl_list_construct(&tmp_parser_struct.str_list); cl_list_init(&tmp_parser_struct.str_list, 10); cl_list_construct(&tmp_parser_struct.num_list); cl_list_init(&tmp_parser_struct.num_list, 10); cl_list_construct(&tmp_parser_struct.num_pair_list); cl_list_init(&tmp_parser_struct.num_pair_list, 10); } /*************************************************** ***************************************************/ /* * Do NOT free objects from the temp struct. * Either they are inserted into the parse tree data * structure, or they are already freed when copying * their values to the parse tree data structure. */ static void __parser_tmp_struct_reset() { tmp_parser_struct.str[0] = '\0'; cl_list_remove_all(&tmp_parser_struct.str_list); cl_list_remove_all(&tmp_parser_struct.num_list); cl_list_remove_all(&tmp_parser_struct.num_pair_list); } /*************************************************** ***************************************************/ static void __parser_tmp_struct_destroy() { __parser_tmp_struct_reset(); cl_list_destroy(&tmp_parser_struct.str_list); cl_list_destroy(&tmp_parser_struct.num_list); cl_list_destroy(&tmp_parser_struct.num_pair_list); } /*************************************************** ***************************************************/ #define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL" #define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT" static void __setup_simple_qos_levels() { uint8_t i; char tmp_buf[30]; memset(osm_qos_policy_simple_qos_levels, 0, sizeof(osm_qos_policy_simple_qos_levels)); for (i = 0; i < 16; i++) { osm_qos_policy_simple_qos_levels[i].sl = i; osm_qos_policy_simple_qos_levels[i].sl_set = TRUE; sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i); osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf); } memset(&__default_simple_qos_level, 0, sizeof(__default_simple_qos_level)); __default_simple_qos_level.name = strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME); } /*************************************************** ***************************************************/ static void __clear_simple_qos_levels() { /* * Simple QoS levels are static. * What's left is to invalidate default simple QoS level. */ __default_simple_qos_level.sl_set = FALSE; } /*************************************************** ***************************************************/ static void __setup_ulp_match_rules() { cl_list_construct(&__ulp_match_rules); cl_list_init(&__ulp_match_rules, 10); } /*************************************************** ***************************************************/ static void __process_ulp_match_rules() { cl_list_iterator_t list_iterator; osm_qos_match_rule_t *p_qos_match_rule = NULL; list_iterator = cl_list_head(&__ulp_match_rules); while (list_iterator != cl_list_end(&__ulp_match_rules)) { p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator); if (p_qos_match_rule) cl_list_insert_tail(&p_qos_policy->qos_match_rules, p_qos_match_rule); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&__ulp_match_rules); } /*************************************************** ***************************************************/ static int __cmp_num_range(const void * p1, const void * p2) { uint64_t * pair1 = *((uint64_t **)p1); uint64_t * pair2 = *((uint64_t **)p2); if (pair1[0] < pair2[0]) return -1; if (pair1[0] > pair2[0]) return 1; if (pair1[1] < pair2[1]) return -1; if (pair1[1] > pair2[1]) return 1; return 0; } /*************************************************** ***************************************************/ static void __sort_reduce_rangearr( uint64_t ** arr, unsigned arr_len, uint64_t ** * p_res_arr, unsigned * p_res_arr_len ) { unsigned i = 0; unsigned j = 0; unsigned last_valid_ind = 0; unsigned valid_cnt = 0; uint64_t ** res_arr; boolean_t * is_valid_arr; *p_res_arr = NULL; *p_res_arr_len = 0; qsort(arr, arr_len, sizeof(uint64_t*), __cmp_num_range); is_valid_arr = (boolean_t *)malloc(arr_len * sizeof(boolean_t)); is_valid_arr[last_valid_ind] = TRUE; valid_cnt++; for (i = 1; i < arr_len; i++) { if (arr[i][0] <= arr[last_valid_ind][1]) { if (arr[i][1] > arr[last_valid_ind][1]) arr[last_valid_ind][1] = arr[i][1]; free(arr[i]); arr[i] = NULL; is_valid_arr[i] = FALSE; } else if ((arr[i][0] - 1) == arr[last_valid_ind][1]) { arr[last_valid_ind][1] = arr[i][1]; free(arr[i]); arr[i] = NULL; is_valid_arr[i] = FALSE; } else { is_valid_arr[i] = TRUE; last_valid_ind = i; valid_cnt++; } } res_arr = (uint64_t **)malloc(valid_cnt * sizeof(uint64_t *)); for (i = 0; i < arr_len; i++) { if (is_valid_arr[i]) res_arr[j++] = arr[i]; } free(is_valid_arr); free(arr); *p_res_arr = res_arr; *p_res_arr_len = valid_cnt; } /*************************************************** ***************************************************/ static void __pkey_rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len) { uint64_t tmp_pkey; uint64_t * p_pkeys; cl_list_iterator_t list_iterator; list_iterator= cl_list_head(p_list); while( list_iterator != cl_list_end(p_list) ) { p_pkeys = (uint64_t *)cl_list_obj(list_iterator); p_pkeys[0] &= 0x7fff; p_pkeys[1] &= 0x7fff; if (p_pkeys[0] > p_pkeys[1]) { tmp_pkey = p_pkeys[1]; p_pkeys[1] = p_pkeys[0]; p_pkeys[0] = tmp_pkey; } list_iterator = cl_list_next(list_iterator); } __rangelist2rangearr(p_list, p_arr, p_arr_len); } /*************************************************** ***************************************************/ static void __rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len) { cl_list_iterator_t list_iterator; unsigned len = cl_list_count(p_list); unsigned i = 0; uint64_t ** tmp_arr; uint64_t ** res_arr = NULL; unsigned res_arr_len = 0; tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *)); list_iterator = cl_list_head(p_list); while( list_iterator != cl_list_end(p_list) ) { tmp_arr[i++] = (uint64_t *)cl_list_obj(list_iterator); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(p_list); __sort_reduce_rangearr( tmp_arr, len, &res_arr, &res_arr_len ); *p_arr = res_arr; *p_arr_len = res_arr_len; } /*************************************************** ***************************************************/ static void __merge_rangearr( uint64_t ** range_arr_1, unsigned range_len_1, uint64_t ** range_arr_2, unsigned range_len_2, uint64_t ** * p_arr, unsigned * p_arr_len ) { unsigned i = 0; unsigned j = 0; unsigned len = range_len_1 + range_len_2; uint64_t ** tmp_arr; uint64_t ** res_arr = NULL; unsigned res_arr_len = 0; *p_arr = NULL; *p_arr_len = 0; tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *)); for (i = 0; i < range_len_1; i++) tmp_arr[j++] = range_arr_1[i]; for (i = 0; i < range_len_2; i++) tmp_arr[j++] = range_arr_2[i]; free(range_arr_1); free(range_arr_2); __sort_reduce_rangearr( tmp_arr, len, &res_arr, &res_arr_len ); *p_arr = res_arr; *p_arr_len = res_arr_len; } /*************************************************** ***************************************************/ static void __parser_add_port_to_port_map( cl_qmap_t * p_map, osm_physp_t * p_physp) { if (cl_qmap_get(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp))) == cl_qmap_end(p_map)) { osm_qos_port_t * p_port = osm_qos_policy_port_create(p_physp); if (p_port) cl_qmap_insert(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp)), &p_port->map_item); } } /*************************************************** ***************************************************/ static void __parser_add_guid_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len) { unsigned i; uint64_t guid_ho; osm_port_t * p_osm_port; if (!range_arr || !range_len) return; for (i = 0; i < range_len; i++) { for (guid_ho = range_arr[i][0]; guid_ho <= range_arr[i][1]; guid_ho++) { p_osm_port = osm_get_port_by_guid(p_qos_policy->p_subn, cl_hton64(guid_ho)); if (p_osm_port) __parser_add_port_to_port_map(p_map, p_osm_port->p_physp); } free(range_arr[i]); } free(range_arr); } /*************************************************** ***************************************************/ static void __parser_add_pkey_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len) { unsigned i; uint64_t pkey_64; ib_net16_t pkey; osm_prtn_t * p_prtn; if (!range_arr || !range_len) return; for (i = 0; i < range_len; i++) { for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) { pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); p_prtn = (osm_prtn_t *) cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey); if (p_prtn != (osm_prtn_t *)cl_qmap_end( &p_qos_policy->p_subn->prtn_pkey_tbl)) { __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl); __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl); } } free(range_arr[i]); } free(range_arr); } /*************************************************** ***************************************************/ static void __parser_add_partition_list_to_port_map( cl_qmap_t * p_map, cl_list_t * p_list) { cl_list_iterator_t list_iterator; char * tmp_str; osm_prtn_t * p_prtn; /* extract all the ports from the partition to the port map of this port group */ list_iterator = cl_list_head(p_list); while(list_iterator != cl_list_end(p_list)) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { p_prtn = osm_prtn_find_by_name(p_qos_policy->p_subn, tmp_str); if (p_prtn) { __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl); __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl); } free(tmp_str); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(p_list); } /*************************************************** ***************************************************/ static void __parser_add_map_to_port_map( cl_qmap_t * p_dmap, cl_map_t * p_smap) { cl_map_iterator_t map_iterator; osm_physp_t * p_physp; if (!p_dmap || !p_smap) return; map_iterator = cl_map_head(p_smap); while (map_iterator != cl_map_end(p_smap)) { p_physp = (osm_physp_t*)cl_map_obj(map_iterator); __parser_add_port_to_port_map(p_dmap, p_physp); map_iterator = cl_map_next(map_iterator); } } /*************************************************** ***************************************************/ static int __validate_pkeys( uint64_t ** range_arr, unsigned range_len, boolean_t is_ipoib) { unsigned i; uint64_t pkey_64; ib_net16_t pkey; osm_prtn_t * p_prtn; if (!range_arr || !range_len) return 0; for (i = 0; i < range_len; i++) { for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) { pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); p_prtn = (osm_prtn_t *) cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey); if (p_prtn == (osm_prtn_t *)cl_qmap_end( &p_qos_policy->p_subn->prtn_pkey_tbl)) p_prtn = NULL; if (is_ipoib) { /* * Be very strict for IPoIB partition: * - the partition for the pkey have to exist * - it has to have at least 2 full members */ if (!p_prtn) { yyerror("IPoIB partition, pkey 0x%04X - " "partition doesn't exist", cl_ntoh16(pkey)); return 1; } else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) { yyerror("IPoIB partition, pkey 0x%04X - " "partition has less than two full members", cl_ntoh16(pkey)); return 1; } } else if (!p_prtn) { /* * For non-IPoIB pkey we just want to check that * the relevant partition exists. * And even if it doesn't, don't exit - just print * error message and continue. */ OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC02: " "pkey 0x%04X - partition doesn't exist", cl_ntoh16(pkey)); } } } return 0; } /*************************************************** ***************************************************/ opensm-3.3.20/opensm/osm_qos_parser_y.h0000644000205000001450000001437612110765712015063 00000000000000 /* A Bison parser, made by GNU Bison 2.4.1. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { TK_NUMBER = 258, TK_DASH = 259, TK_DOTDOT = 260, TK_COMMA = 261, TK_ASTERISK = 262, TK_TEXT = 263, TK_QOS_ULPS_START = 264, TK_QOS_ULPS_END = 265, TK_PORT_GROUPS_START = 266, TK_PORT_GROUPS_END = 267, TK_PORT_GROUP_START = 268, TK_PORT_GROUP_END = 269, TK_QOS_SETUP_START = 270, TK_QOS_SETUP_END = 271, TK_VLARB_TABLES_START = 272, TK_VLARB_TABLES_END = 273, TK_VLARB_SCOPE_START = 274, TK_VLARB_SCOPE_END = 275, TK_SL2VL_TABLES_START = 276, TK_SL2VL_TABLES_END = 277, TK_SL2VL_SCOPE_START = 278, TK_SL2VL_SCOPE_END = 279, TK_QOS_LEVELS_START = 280, TK_QOS_LEVELS_END = 281, TK_QOS_LEVEL_START = 282, TK_QOS_LEVEL_END = 283, TK_QOS_MATCH_RULES_START = 284, TK_QOS_MATCH_RULES_END = 285, TK_QOS_MATCH_RULE_START = 286, TK_QOS_MATCH_RULE_END = 287, TK_NAME = 288, TK_USE = 289, TK_PORT_GUID = 290, TK_PORT_NAME = 291, TK_PARTITION = 292, TK_NODE_TYPE = 293, TK_GROUP = 294, TK_ACROSS = 295, TK_VLARB_HIGH = 296, TK_VLARB_LOW = 297, TK_VLARB_HIGH_LIMIT = 298, TK_TO = 299, TK_FROM = 300, TK_ACROSS_TO = 301, TK_ACROSS_FROM = 302, TK_SL2VL_TABLE = 303, TK_SL = 304, TK_MTU_LIMIT = 305, TK_RATE_LIMIT = 306, TK_PACKET_LIFE = 307, TK_PATH_BITS = 308, TK_QOS_CLASS = 309, TK_SOURCE = 310, TK_DESTINATION = 311, TK_SERVICE_ID = 312, TK_QOS_LEVEL_NAME = 313, TK_PKEY = 314, TK_NODE_TYPE_ROUTER = 315, TK_NODE_TYPE_CA = 316, TK_NODE_TYPE_SWITCH = 317, TK_NODE_TYPE_SELF = 318, TK_NODE_TYPE_ALL = 319, TK_ULP_DEFAULT = 320, TK_ULP_ANY_SERVICE_ID = 321, TK_ULP_ANY_PKEY = 322, TK_ULP_ANY_TARGET_PORT_GUID = 323, TK_ULP_ANY_SOURCE_PORT_GUID = 324, TK_ULP_ANY_SOURCE_TARGET_PORT_GUID = 325, TK_ULP_SDP_DEFAULT = 326, TK_ULP_SDP_PORT = 327, TK_ULP_RDS_DEFAULT = 328, TK_ULP_RDS_PORT = 329, TK_ULP_ISER_DEFAULT = 330, TK_ULP_ISER_PORT = 331, TK_ULP_SRP_GUID = 332, TK_ULP_IPOIB_DEFAULT = 333, TK_ULP_IPOIB_PKEY = 334 }; #endif /* Tokens. */ #define TK_NUMBER 258 #define TK_DASH 259 #define TK_DOTDOT 260 #define TK_COMMA 261 #define TK_ASTERISK 262 #define TK_TEXT 263 #define TK_QOS_ULPS_START 264 #define TK_QOS_ULPS_END 265 #define TK_PORT_GROUPS_START 266 #define TK_PORT_GROUPS_END 267 #define TK_PORT_GROUP_START 268 #define TK_PORT_GROUP_END 269 #define TK_QOS_SETUP_START 270 #define TK_QOS_SETUP_END 271 #define TK_VLARB_TABLES_START 272 #define TK_VLARB_TABLES_END 273 #define TK_VLARB_SCOPE_START 274 #define TK_VLARB_SCOPE_END 275 #define TK_SL2VL_TABLES_START 276 #define TK_SL2VL_TABLES_END 277 #define TK_SL2VL_SCOPE_START 278 #define TK_SL2VL_SCOPE_END 279 #define TK_QOS_LEVELS_START 280 #define TK_QOS_LEVELS_END 281 #define TK_QOS_LEVEL_START 282 #define TK_QOS_LEVEL_END 283 #define TK_QOS_MATCH_RULES_START 284 #define TK_QOS_MATCH_RULES_END 285 #define TK_QOS_MATCH_RULE_START 286 #define TK_QOS_MATCH_RULE_END 287 #define TK_NAME 288 #define TK_USE 289 #define TK_PORT_GUID 290 #define TK_PORT_NAME 291 #define TK_PARTITION 292 #define TK_NODE_TYPE 293 #define TK_GROUP 294 #define TK_ACROSS 295 #define TK_VLARB_HIGH 296 #define TK_VLARB_LOW 297 #define TK_VLARB_HIGH_LIMIT 298 #define TK_TO 299 #define TK_FROM 300 #define TK_ACROSS_TO 301 #define TK_ACROSS_FROM 302 #define TK_SL2VL_TABLE 303 #define TK_SL 304 #define TK_MTU_LIMIT 305 #define TK_RATE_LIMIT 306 #define TK_PACKET_LIFE 307 #define TK_PATH_BITS 308 #define TK_QOS_CLASS 309 #define TK_SOURCE 310 #define TK_DESTINATION 311 #define TK_SERVICE_ID 312 #define TK_QOS_LEVEL_NAME 313 #define TK_PKEY 314 #define TK_NODE_TYPE_ROUTER 315 #define TK_NODE_TYPE_CA 316 #define TK_NODE_TYPE_SWITCH 317 #define TK_NODE_TYPE_SELF 318 #define TK_NODE_TYPE_ALL 319 #define TK_ULP_DEFAULT 320 #define TK_ULP_ANY_SERVICE_ID 321 #define TK_ULP_ANY_PKEY 322 #define TK_ULP_ANY_TARGET_PORT_GUID 323 #define TK_ULP_ANY_SOURCE_PORT_GUID 324 #define TK_ULP_ANY_SOURCE_TARGET_PORT_GUID 325 #define TK_ULP_SDP_DEFAULT 326 #define TK_ULP_SDP_PORT 327 #define TK_ULP_RDS_DEFAULT 328 #define TK_ULP_RDS_PORT 329 #define TK_ULP_ISER_DEFAULT 330 #define TK_ULP_ISER_PORT 331 #define TK_ULP_SRP_GUID 332 #define TK_ULP_IPOIB_DEFAULT 333 #define TK_ULP_IPOIB_PKEY 334 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; opensm-3.3.20/opensm/osm_log.c0000644000205000001450000003174412330204334013117 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 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 osm_log_t. * This object represents the log file. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #define FILE_ID OSM_FILE_LOG_C #include #include #include #include #include #include #include #include static int log_exit_count = 0; #ifndef __WIN__ #include #include #include static const char *month_str[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; #else void OsmReportState(IN const char *p_str); #endif /* ndef __WIN__ */ #ifndef __WIN__ static void truncate_log_file(osm_log_t * p_log) { int fd = fileno(p_log->out_port); if (ftruncate(fd, 0) < 0) fprintf(stderr, "truncate_log_file: cannot truncate: %s\n", strerror(errno)); if (lseek(fd, 0, SEEK_SET) < 0) fprintf(stderr, "truncate_log_file: cannot rewind: %s\n", strerror(errno)); p_log->count = 0; } #else /* Windows */ static void truncate_log_file(osm_log_t * p_log) { int fd = _fileno(p_log->out_port); HANDLE hFile = (HANDLE) _get_osfhandle(fd); if (_lseek(fd, 0, SEEK_SET) < 0) fprintf(stderr, "truncate_log_file: cannot rewind: %s\n", strerror(errno)); SetEndOfFile(hFile); p_log->count = 0; } #endif /* ndef __WIN__ */ void osm_log(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const char *p_str, ...) { char buffer[LOG_ENTRY_SIZE_MAX]; va_list args; int ret; #ifdef __WIN__ SYSTEMTIME st; uint32_t pid = GetCurrentThreadId(); #else pid_t pid; time_t tim; struct tm result; uint64_t time_usecs; uint32_t usecs; #endif /* __WIN__ */ /* If this is a call to syslog - always print it */ if (!(verbosity & p_log->level)) return; va_start(args, p_str); #ifndef __WIN__ if (p_log->log_prefix == NULL) vsprintf(buffer, p_str, args); else { int n = snprintf(buffer, sizeof(buffer), "%s: ", p_log->log_prefix); vsprintf(buffer + n, p_str, args); } #else if (p_log->log_prefix == NULL) _vsnprintf(buffer, 1024, (LPSTR)p_str, args); else { int n = snprintf(buffer, sizeof(buffer), "%s: ", p_log->log_prefix); _vsnprintf(buffer + n, (1024 - n), (LPSTR)p_str, args); } #endif va_end(args); /* this is a call to the syslog */ if (verbosity & OSM_LOG_SYS) { syslog(LOG_INFO, "%s\n", buffer); /* SYSLOG should go to stdout too */ if (p_log->out_port != stdout) { printf("%s\n", buffer); fflush(stdout); } #ifdef __WIN__ OsmReportState(buffer); #endif /* __WIN__ */ } /* regular log to default out_port */ cl_spinlock_acquire(&p_log->lock); if (p_log->max_size && p_log->count > p_log->max_size) { /* truncate here */ fprintf(stderr, "osm_log: log file exceeds the limit %lu. Truncating.\n", p_log->max_size); truncate_log_file(p_log); } #ifdef __WIN__ GetLocalTime(&st); _retry: ret = fprintf(p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] 0x%02x -> %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, pid, verbosity, buffer); #else time_usecs = cl_get_time_stamp(); tim = time_usecs / 1000000; usecs = time_usecs % 1000000; localtime_r(&tim, &result); pid = pthread_self(); _retry: ret = fprintf(p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] 0x%02x -> %s", (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"), result.tm_mday, result.tm_hour, result.tm_min, result.tm_sec, usecs, pid, verbosity, buffer); #endif /* flush log */ if (ret > 0 && (p_log->flush || (verbosity & (OSM_LOG_ERROR | OSM_LOG_SYS))) && fflush(p_log->out_port) < 0) ret = -1; if (ret >= 0) { log_exit_count = 0; p_log->count += ret; } else if (log_exit_count < 3) { log_exit_count++; if (errno == ENOSPC && p_log->max_size) { fprintf(stderr, "osm_log: write failed: %s. Truncating log file.\n", strerror(errno)); truncate_log_file(p_log); goto _retry; } fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno)); } cl_spinlock_release(&p_log->lock); } void osm_log_v2(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const int file_id, IN const char *p_str, ...) { char buffer[LOG_ENTRY_SIZE_MAX]; va_list args; int ret; #ifdef __WIN__ SYSTEMTIME st; uint32_t pid = GetCurrentThreadId(); #else struct timeval tv; pid_t pid = 0; time_t tim; struct tm result; uint64_t time_usecs; uint32_t usecs; #endif /* __WIN__ */ /* If this is a call to syslog - always print it */ if (!(verbosity & p_log->level)) { if (!(verbosity & p_log->per_mod_log_tbl[file_id])) return; } va_start(args, p_str); #ifndef __WIN__ if (p_log->log_prefix == NULL) vsprintf(buffer, p_str, args); else { int n = snprintf(buffer, sizeof(buffer), "%s: ", p_log->log_prefix); vsprintf(buffer + n, p_str, args); } #else if (p_log->log_prefix == NULL) _vsnprintf(buffer, 1024, (LPSTR)p_str, args); else { int n = snprintf(buffer, sizeof(buffer), "%s: ", p_log->log_prefix); _vsnprintf(buffer + n, (1024 - n), (LPSTR)p_str, args); } #endif va_end(args); /* this is a call to the syslog */ if (verbosity & OSM_LOG_SYS) { syslog(LOG_INFO, "%s\n", buffer); /* SYSLOG should go to stdout too */ if (p_log->out_port != stdout) { printf("%s\n", buffer); fflush(stdout); } #ifdef __WIN__ OsmReportState(buffer); #endif /* __WIN__ */ } /* regular log to default out_port */ cl_spinlock_acquire(&p_log->lock); if (p_log->max_size && p_log->count > p_log->max_size) { /* truncate here */ fprintf(stderr, "osm_log: log file exceeds the limit %lu. Truncating.\n", p_log->max_size); truncate_log_file(p_log); } #ifdef __WIN__ GetLocalTime(&st); _retry: ret = fprintf(p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] 0x%02x -> %s", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, pid, verbosity, buffer); #else gettimeofday(&tv, NULL); /* Convert the time of day into a microsecond timestamp */ time_usecs = ((uint64_t) tv.tv_sec * 1000000) + (uint64_t) tv.tv_usec; tim = time_usecs / 1000000; usecs = time_usecs % 1000000; localtime_r(&tim, &result); pid = pthread_self(); _retry: ret = fprintf(p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] 0x%02x -> %s", (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"), result.tm_mday, result.tm_hour, result.tm_min, result.tm_sec, usecs, pid, verbosity, buffer); #endif /* flush log */ if (ret > 0 && (p_log->flush || (verbosity & (OSM_LOG_ERROR | OSM_LOG_SYS))) && fflush(p_log->out_port) < 0) ret = -1; if (ret >= 0) { log_exit_count = 0; p_log->count += ret; } else if (log_exit_count < 3) { log_exit_count++; if (errno == ENOSPC && p_log->max_size) { fprintf(stderr, "osm_log: write failed: %s. Truncating log file.\n", strerror(errno)); truncate_log_file(p_log); goto _retry; } fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno)); } cl_spinlock_release(&p_log->lock); } void osm_log_raw(IN osm_log_t * p_log, IN osm_log_level_t verbosity, IN const char *p_buf) { if (p_log->level & verbosity) { cl_spinlock_acquire(&p_log->lock); printf("%s", p_buf); cl_spinlock_release(&p_log->lock); /* Flush log on errors too. */ if (p_log->flush || (verbosity & OSM_LOG_ERROR)) fflush(stdout); } } void osm_log_msg_box(IN osm_log_t * log, osm_log_level_t level, const char *func_name, const char *msg) { #define MSG_BOX_LENGTH 66 char buf[MSG_BOX_LENGTH + 1]; int i, n; if (!osm_log_is_active(log, level)) return; n = (MSG_BOX_LENGTH - strlen(msg)) / 2 - 1; if (n < 0) n = 0; for (i = 0; i < n; i++) sprintf(buf + i, "*"); n += snprintf(buf + n, sizeof(buf) - n, " %s ", msg); for (i = n; i < MSG_BOX_LENGTH; i++) buf[i] = '*'; buf[i] = '\0'; osm_log(log, level, "%s:\n\n\n" "*********************************************" "*********************\n%s\n" "*********************************************" "*********************\n\n\n", func_name, buf); } void osm_log_msg_box_v2(IN osm_log_t * log, osm_log_level_t level, const int file_id, const char *func_name, const char *msg) { #define MSG_BOX_LENGTH 66 char buf[MSG_BOX_LENGTH + 1]; int i, n; if (!osm_log_is_active_v2(log, level, file_id)) return; n = (MSG_BOX_LENGTH - strlen(msg)) / 2 - 1; if (n < 0) n = 0; for (i = 0; i < n; i++) sprintf(buf + i, "*"); n += snprintf(buf + n, sizeof(buf) - n, " %s ", msg); for (i = n; i < MSG_BOX_LENGTH; i++) buf[i] = '*'; buf[i] = '\0'; osm_log_v2(log, level, file_id, "%s:\n\n\n" "*********************************************" "*********************\n%s\n" "*********************************************" "*********************\n\n\n", func_name, buf); } boolean_t osm_is_debug(void) { #if defined( _DEBUG_ ) return TRUE; #else return FALSE; #endif /* defined( _DEBUG_ ) */ } static int open_out_port(IN osm_log_t * p_log) { struct stat st; if (p_log->accum_log_file) p_log->out_port = fopen(p_log->log_file_name, "a+"); else p_log->out_port = fopen(p_log->log_file_name, "w+"); if (!p_log->out_port) { syslog(LOG_CRIT, "Cannot open file \'%s\' for %s: %s\n", p_log->log_file_name, p_log->accum_log_file ? "appending" : "writing", strerror(errno)); fprintf(stderr, "Cannot open file \'%s\': %s\n", p_log->log_file_name, strerror(errno)); return -1; } if (fstat(fileno(p_log->out_port), &st) == 0) p_log->count = st.st_size; syslog(LOG_NOTICE, "%s log file opened\n", p_log->log_file_name); if (p_log->daemon) { dup2(fileno(p_log->out_port), 0); dup2(fileno(p_log->out_port), 1); dup2(fileno(p_log->out_port), 2); } return 0; } int osm_log_reopen_file(osm_log_t * p_log) { int ret; if (p_log->out_port == stdout || p_log->out_port == stderr) return 0; cl_spinlock_acquire(&p_log->lock); fclose(p_log->out_port); ret = open_out_port(p_log); cl_spinlock_release(&p_log->lock); return ret; } ib_api_status_t osm_log_init_v2(IN osm_log_t * p_log, IN boolean_t flush, IN uint8_t log_flags, IN const char *log_file, IN unsigned long max_size, IN boolean_t accum_log_file) { p_log->level = log_flags | OSM_LOG_SYS; p_log->flush = flush; p_log->count = 0; p_log->max_size = max_size << 20; /* convert size in MB to bytes */ p_log->accum_log_file = accum_log_file; p_log->log_file_name = (char *)log_file; memset(p_log->per_mod_log_tbl, 0, sizeof(p_log->per_mod_log_tbl)); openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER); if (log_file == NULL || !strcmp(log_file, "-") || !strcmp(log_file, "stdout")) p_log->out_port = stdout; else if (!strcmp(log_file, "stderr")) p_log->out_port = stderr; else if (open_out_port(p_log)) return IB_ERROR; if (cl_spinlock_init(&p_log->lock) == CL_SUCCESS) return IB_SUCCESS; else return IB_ERROR; } ib_api_status_t osm_log_init(IN osm_log_t * p_log, IN boolean_t flush, IN uint8_t log_flags, IN const char *log_file, IN boolean_t accum_log_file) { return osm_log_init_v2(p_log, flush, log_flags, log_file, 0, accum_log_file); } osm_log_level_t osm_get_log_per_module(IN osm_log_t * p_log, IN const int file_id) { return p_log->per_mod_log_tbl[file_id]; } void osm_set_log_per_module(IN osm_log_t * p_log, IN const int file_id, IN osm_log_level_t level) { p_log->per_mod_log_tbl[file_id] = level; } void osm_reset_log_per_module(IN osm_log_t * p_log) { memset(p_log->per_mod_log_tbl, 0, sizeof(p_log->per_mod_log_tbl)); } opensm-3.3.20/opensm/osm_mad_pool.c0000644000205000001450000001062312104655724014135 00000000000000/* * Copyright (c) 2004-2009 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 osm_mad_pool_t. * This object represents a pool of management datagram (MAD) objects. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_MAD_POOL_C #include #include #include void osm_mad_pool_construct(IN osm_mad_pool_t * p_pool) { CL_ASSERT(p_pool); memset(p_pool, 0, sizeof(*p_pool)); } void osm_mad_pool_destroy(IN osm_mad_pool_t * p_pool) { CL_ASSERT(p_pool); } ib_api_status_t osm_mad_pool_init(IN osm_mad_pool_t * p_pool) { p_pool->mads_out = 0; return IB_SUCCESS; } osm_madw_t *osm_mad_pool_get(IN osm_mad_pool_t * p_pool, IN osm_bind_handle_t h_bind, IN uint32_t total_size, IN const osm_mad_addr_t * p_mad_addr) { osm_madw_t *p_madw; ib_mad_t *p_mad; CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE); CL_ASSERT(total_size); /* First, acquire a mad wrapper from the mad wrapper pool. */ p_madw = malloc(sizeof(*p_madw)); if (p_madw == NULL) goto Exit; osm_madw_init(p_madw, h_bind, total_size, p_mad_addr); /* Next, acquire a wire mad of the specified size. */ p_mad = osm_vendor_get(h_bind, total_size, &p_madw->vend_wrap); if (p_mad == NULL) { /* Don't leak wrappers! */ free(p_madw); p_madw = NULL; goto Exit; } cl_atomic_inc(&p_pool->mads_out); /* Finally, attach the wire MAD to this wrapper. */ osm_madw_set_mad(p_madw, p_mad); Exit: return p_madw; } osm_madw_t *osm_mad_pool_get_wrapper(IN osm_mad_pool_t * p_pool, IN osm_bind_handle_t h_bind, IN uint32_t total_size, IN const ib_mad_t * p_mad, IN const osm_mad_addr_t * p_mad_addr) { osm_madw_t *p_madw; CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE); CL_ASSERT(total_size); CL_ASSERT(p_mad); /* First, acquire a mad wrapper from the mad wrapper pool. */ p_madw = malloc(sizeof(*p_madw)); if (p_madw == NULL) goto Exit; /* Finally, initialize the wrapper object. */ cl_atomic_inc(&p_pool->mads_out); osm_madw_init(p_madw, h_bind, total_size, p_mad_addr); osm_madw_set_mad(p_madw, p_mad); Exit: return p_madw; } osm_madw_t *osm_mad_pool_get_wrapper_raw(IN osm_mad_pool_t * p_pool) { osm_madw_t *p_madw; p_madw = malloc(sizeof(*p_madw)); if (!p_madw) return NULL; osm_madw_init(p_madw, 0, 0, 0); osm_madw_set_mad(p_madw, 0); cl_atomic_inc(&p_pool->mads_out); return p_madw; } void osm_mad_pool_put(IN osm_mad_pool_t * p_pool, IN osm_madw_t * p_madw) { CL_ASSERT(p_madw); /* First, return the wire mad to the pool */ if (p_madw->p_mad) osm_vendor_put(p_madw->h_bind, &p_madw->vend_wrap); /* Return the mad wrapper to the wrapper pool */ free(p_madw); cl_atomic_dec(&p_pool->mads_out); } opensm-3.3.20/opensm/osm_helper.c0000644000205000001450000027313612604753736013643 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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 opensm helper functions. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_HELPER_C #include #include #define LINE_LENGTH 256 #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0])) /* we use two tables - one for queries and one for responses */ static const char *ib_sa_method_str[] = { "RESERVED", /* 0 */ "SubnAdmGet", /* 1 */ "SubnAdmSet", /* 2 */ "RESERVED", /* 3 */ "RESERVED", /* 4 */ "RESERVED", /* 5 */ "SubnAdmReport", /* 6 */ "RESERVED", /* 7 */ "RESERVED", /* 8 */ "RESERVED", /* 9 */ "RESERVED", /* A */ "RESERVED", /* B */ "RESERVED", /* C */ "RESERVED", /* D */ "RESERVED", /* E */ "RESERVED", /* F */ "RESERVED", /* 10 */ "RESERVED", /* 11 */ "SubnAdmGetTable", /* 12 */ "SubnAdmGetTraceTable", /* 13 */ "SubnAdmGetMulti", /* 14 */ "SubnAdmDelete", /* 15 */ "UNKNOWN" /* 16 */ }; #define OSM_SA_METHOD_STR_UNKNOWN_VAL (ARR_SIZE(ib_sa_method_str) - 1) static const char *ib_sa_resp_method_str[] = { "RESERVED", /* 80 */ "SubnAdmGetResp", /* 81 */ "RESERVED (SetResp?)", /* 82 */ "RESERVED", /* 83 */ "RESERVED", /* 84 */ "RESERVED", /* 85 */ "SubnAdmReportResp", /* 86 */ "RESERVED", /* 87 */ "RESERVED", /* 88 */ "RESERVED", /* 89 */ "RESERVED", /* 8A */ "RESERVED", /* 8B */ "RESERVED", /* 8C */ "RESERVED", /* 8D */ "RESERVED", /* 8E */ "RESERVED", /* 8F */ "RESERVED", /* 90 */ "RESERVED", /* 91 */ "SubnAdmGetTableResp", /* 92 */ "RESERVED", /* 93 */ "SubnAdmGetMultiResp", /* 94 */ "SubnAdmDeleteResp", /* 95 */ "UNKNOWN" }; static const char *ib_sm_method_str[] = { "RESERVED0", /* 0 */ "SubnGet", /* 1 */ "SubnSet", /* 2 */ "RESERVED3", /* 3 */ "RESERVED4", /* 4 */ "SubnTrap", /* 5 */ "RESERVED6", /* 6 */ "SubnTrapRepress", /* 7 */ "RESERVED8", /* 8 */ "RESERVED9", /* 9 */ "RESERVEDA", /* A */ "RESERVEDB", /* B */ "RESERVEDC", /* C */ "RESERVEDD", /* D */ "RESERVEDE", /* E */ "RESERVEDF", /* F */ "RESERVED10", /* 10 */ "SubnGetResp", /* 11 */ "RESERVED12", /* 12 */ "RESERVED13", /* 13 */ "RESERVED14", /* 14 */ "RESERVED15", /* 15 */ "RESERVED16", /* 16 */ "RESERVED17", /* 17 */ "RESERVED18", /* 18 */ "RESERVED19", /* 19 */ "RESERVED1A", /* 1A */ "RESERVED1B", /* 1B */ "RESERVED1C", /* 1C */ "RESERVED1D", /* 1D */ "RESERVED1E", /* 1E */ "RESERVED1F", /* 1F */ "UNKNOWN" /* 20 */ }; #define OSM_SM_METHOD_STR_UNKNOWN_VAL (ARR_SIZE(ib_sm_method_str) - 1) static const char *ib_sm_attr_str[] = { "RESERVED", /* 0 */ "ClassPortInfo", /* 1 */ "Notice", /* 2 */ "InformInfo", /* 3 */ "RESERVED", /* 4 */ "RESERVED", /* 5 */ "RESERVED", /* 6 */ "RESERVED", /* 7 */ "RESERVED", /* 8 */ "RESERVED", /* 9 */ "RESERVED", /* A */ "RESERVED", /* B */ "RESERVED", /* C */ "RESERVED", /* D */ "RESERVED", /* E */ "RESERVED", /* F */ "NodeDescription", /* 10 */ "NodeInfo", /* 11 */ "SwitchInfo", /* 12 */ "UNKNOWN", /* 13 */ "GUIDInfo", /* 14 */ "PortInfo", /* 15 */ "P_KeyTable", /* 16 */ "SLtoVLMappingTable", /* 17 */ "VLArbitrationTable", /* 18 */ "LinearForwardingTable", /* 19 */ "RandomForwardingTable", /* 1A */ "MulticastForwardingTable", /* 1B */ "UNKNOWN", /* 1C */ "UNKNOWN", /* 1D */ "UNKNOWN", /* 1E */ "UNKNOWN", /* 1F */ "SMInfo", /* 20 */ "UNKNOWN" /* 21 - always highest value */ }; #define OSM_SM_ATTR_STR_UNKNOWN_VAL (ARR_SIZE(ib_sm_attr_str) - 1) static const char *ib_sa_attr_str[] = { "RESERVED", /* 0 */ "ClassPortInfo", /* 1 */ "Notice", /* 2 */ "InformInfo", /* 3 */ "RESERVED", /* 4 */ "RESERVED", /* 5 */ "RESERVED", /* 6 */ "RESERVED", /* 7 */ "RESERVED", /* 8 */ "RESERVED", /* 9 */ "RESERVED", /* A */ "RESERVED", /* B */ "RESERVED", /* C */ "RESERVED", /* D */ "RESERVED", /* E */ "RESERVED", /* F */ "RESERVED", /* 10 */ "NodeRecord", /* 11 */ "PortInfoRecord", /* 12 */ "SLtoVLMappingTableRecord", /* 13 */ "SwitchInfoRecord", /* 14 */ "LinearForwardingTableRecord", /* 15 */ "RandomForwardingTableRecord", /* 16 */ "MulticastForwardingTableRecord", /* 17 */ "SMInfoRecord", /* 18 */ "RESERVED", /* 19 */ "RandomForwardingTable", /* 1A */ "MulticastForwardingTable", /* 1B */ "UNKNOWN", /* 1C */ "UNKNOWN", /* 1D */ "UNKNOWN", /* 1E */ "UNKNOWN", /* 1F */ "LinkRecord", /* 20 */ "UNKNOWN", /* 21 */ "UNKNOWN", /* 22 */ "UNKNOWN", /* 23 */ "UNKNOWN", /* 24 */ "UNKNOWN", /* 25 */ "UNKNOWN", /* 26 */ "UNKNOWN", /* 27 */ "UNKNOWN", /* 28 */ "UNKNOWN", /* 29 */ "UNKNOWN", /* 2A */ "UNKNOWN", /* 2B */ "UNKNOWN", /* 2C */ "UNKNOWN", /* 2D */ "UNKNOWN", /* 2E */ "UNKNOWN", /* 2F */ "GuidInfoRecord", /* 30 */ "ServiceRecord", /* 31 */ "UNKNOWN", /* 32 */ "P_KeyTableRecord", /* 33 */ "UNKNOWN", /* 34 */ "PathRecord", /* 35 */ "VLArbitrationTableRecord", /* 36 */ "UNKNOWN", /* 37 */ "MCMemberRecord", /* 38 */ "TraceRecord", /* 39 */ "MultiPathRecord", /* 3A */ "ServiceAssociationRecord", /* 3B */ "UNKNOWN", /* 3C */ "UNKNOWN", /* 3D */ "UNKNOWN", /* 3E */ "UNKNOWN", /* 3F */ "UNKNOWN", /* 40 */ "UNKNOWN", /* 41 */ "UNKNOWN", /* 42 */ "UNKNOWN", /* 43 */ "UNKNOWN", /* 44 */ "UNKNOWN", /* 45 */ "UNKNOWN", /* 46 */ "UNKNOWN", /* 47 */ "UNKNOWN", /* 48 */ "UNKNOWN", /* 49 */ "UNKNOWN", /* 4A */ "UNKNOWN", /* 4B */ "UNKNOWN", /* 4C */ "UNKNOWN", /* 4D */ "UNKNOWN", /* 4E */ "UNKNOWN", /* 4F */ "UNKNOWN", /* 50 */ "UNKNOWN", /* 51 */ "UNKNOWN", /* 52 */ "UNKNOWN", /* 53 */ "UNKNOWN", /* 54 */ "UNKNOWN", /* 55 */ "UNKNOWN", /* 56 */ "UNKNOWN", /* 57 */ "UNKNOWN", /* 58 */ "UNKNOWN", /* 59 */ "UNKNOWN", /* 5A */ "UNKNOWN", /* 5B */ "UNKNOWN", /* 5C */ "UNKNOWN", /* 5D */ "UNKNOWN", /* 5E */ "UNKNOWN", /* 5F */ "UNKNOWN", /* 60 */ "UNKNOWN", /* 61 */ "UNKNOWN", /* 62 */ "UNKNOWN", /* 63 */ "UNKNOWN", /* 64 */ "UNKNOWN", /* 65 */ "UNKNOWN", /* 66 */ "UNKNOWN", /* 67 */ "UNKNOWN", /* 68 */ "UNKNOWN", /* 69 */ "UNKNOWN", /* 6A */ "UNKNOWN", /* 6B */ "UNKNOWN", /* 6C */ "UNKNOWN", /* 6D */ "UNKNOWN", /* 6E */ "UNKNOWN", /* 6F */ "UNKNOWN", /* 70 */ "UNKNOWN", /* 71 */ "UNKNOWN", /* 72 */ "UNKNOWN", /* 73 */ "UNKNOWN", /* 74 */ "UNKNOWN", /* 75 */ "UNKNOWN", /* 76 */ "UNKNOWN", /* 77 */ "UNKNOWN", /* 78 */ "UNKNOWN", /* 79 */ "UNKNOWN", /* 7A */ "UNKNOWN", /* 7B */ "UNKNOWN", /* 7C */ "UNKNOWN", /* 7D */ "UNKNOWN", /* 7E */ "UNKNOWN", /* 7F */ "UNKNOWN", /* 80 */ "UNKNOWN", /* 81 */ "UNKNOWN", /* 82 */ "UNKNOWN", /* 83 */ "UNKNOWN", /* 84 */ "UNKNOWN", /* 85 */ "UNKNOWN", /* 86 */ "UNKNOWN", /* 87 */ "UNKNOWN", /* 88 */ "UNKNOWN", /* 89 */ "UNKNOWN", /* 8A */ "UNKNOWN", /* 8B */ "UNKNOWN", /* 8C */ "UNKNOWN", /* 8D */ "UNKNOWN", /* 8E */ "UNKNOWN", /* 8F */ "UNKNOWN", /* 90 */ "UNKNOWN", /* 91 */ "UNKNOWN", /* 92 */ "UNKNOWN", /* 93 */ "UNKNOWN", /* 94 */ "UNKNOWN", /* 95 */ "UNKNOWN", /* 96 */ "UNKNOWN", /* 97 */ "UNKNOWN", /* 98 */ "UNKNOWN", /* 99 */ "UNKNOWN", /* 9A */ "UNKNOWN", /* 9B */ "UNKNOWN", /* 9C */ "UNKNOWN", /* 9D */ "UNKNOWN", /* 9E */ "UNKNOWN", /* 9F */ "UNKNOWN", /* A0 */ "UNKNOWN", /* A1 */ "UNKNOWN", /* A2 */ "UNKNOWN", /* A3 */ "UNKNOWN", /* A4 */ "UNKNOWN", /* A5 */ "UNKNOWN", /* A6 */ "UNKNOWN", /* A7 */ "UNKNOWN", /* A8 */ "UNKNOWN", /* A9 */ "UNKNOWN", /* AA */ "UNKNOWN", /* AB */ "UNKNOWN", /* AC */ "UNKNOWN", /* AD */ "UNKNOWN", /* AE */ "UNKNOWN", /* AF */ "UNKNOWN", /* B0 */ "UNKNOWN", /* B1 */ "UNKNOWN", /* B2 */ "UNKNOWN", /* B3 */ "UNKNOWN", /* B4 */ "UNKNOWN", /* B5 */ "UNKNOWN", /* B6 */ "UNKNOWN", /* B7 */ "UNKNOWN", /* B8 */ "UNKNOWN", /* B9 */ "UNKNOWN", /* BA */ "UNKNOWN", /* BB */ "UNKNOWN", /* BC */ "UNKNOWN", /* BD */ "UNKNOWN", /* BE */ "UNKNOWN", /* BF */ "UNKNOWN", /* C0 */ "UNKNOWN", /* C1 */ "UNKNOWN", /* C2 */ "UNKNOWN", /* C3 */ "UNKNOWN", /* C4 */ "UNKNOWN", /* C5 */ "UNKNOWN", /* C6 */ "UNKNOWN", /* C7 */ "UNKNOWN", /* C8 */ "UNKNOWN", /* C9 */ "UNKNOWN", /* CA */ "UNKNOWN", /* CB */ "UNKNOWN", /* CC */ "UNKNOWN", /* CD */ "UNKNOWN", /* CE */ "UNKNOWN", /* CF */ "UNKNOWN", /* D0 */ "UNKNOWN", /* D1 */ "UNKNOWN", /* D2 */ "UNKNOWN", /* D3 */ "UNKNOWN", /* D4 */ "UNKNOWN", /* D5 */ "UNKNOWN", /* D6 */ "UNKNOWN", /* D7 */ "UNKNOWN", /* D8 */ "UNKNOWN", /* D9 */ "UNKNOWN", /* DA */ "UNKNOWN", /* DB */ "UNKNOWN", /* DC */ "UNKNOWN", /* DD */ "UNKNOWN", /* DE */ "UNKNOWN", /* DF */ "UNKNOWN", /* E0 */ "UNKNOWN", /* E1 */ "UNKNOWN", /* E2 */ "UNKNOWN", /* E3 */ "UNKNOWN", /* E4 */ "UNKNOWN", /* E5 */ "UNKNOWN", /* E6 */ "UNKNOWN", /* E7 */ "UNKNOWN", /* E8 */ "UNKNOWN", /* E9 */ "UNKNOWN", /* EA */ "UNKNOWN", /* EB */ "UNKNOWN", /* EC */ "UNKNOWN", /* ED */ "UNKNOWN", /* EE */ "UNKNOWN", /* EF */ "UNKNOWN", /* F0 */ "UNKNOWN", /* F1 */ "UNKNOWN", /* F2 */ "InformInfoRecord", /* F3 */ "UNKNOWN" /* F4 - always highest value */ }; #define OSM_SA_ATTR_STR_UNKNOWN_VAL (ARR_SIZE(ib_sa_attr_str) - 1) static int ordered_rates[] = { 0, 0, /* 0, 1 - reserved */ 1, /* 2 - 2.5 Gbps */ 3, /* 3 - 10 Gbps */ 6, /* 4 - 30 Gbps */ 2, /* 5 - 5 Gbps */ 5, /* 6 - 20 Gbps */ 8, /* 7 - 40 Gbps */ 9, /* 8 - 60 Gbps */ 11, /* 9 - 80 Gbps */ 12, /* 10 - 120 Gbps */ 4, /* 11 - 14 Gbps (17 Gbps equiv) */ 10, /* 12 - 56 Gbps (68 Gbps equiv) */ 14, /* 13 - 112 Gbps (136 Gbps equiv) */ 15, /* 14 - 168 Gbps (204 Gbps equiv) */ 7, /* 15 - 25 Gbps (31.25 Gbps equiv) */ 13, /* 16 - 100 Gbps (125 Gbps equiv) */ 16, /* 17 - 200 Gbps (250 Gbps equiv) */ 17 /* 18 - 300 Gbps (375 Gbps equiv) */ }; static int sprint_uint8_arr(char *buf, size_t size, const uint8_t * arr, size_t len) { int n; unsigned int i; for (i = 0, n = 0; i < len; i++) { n += snprintf(buf + n, size - n, "%s%u", i == 0 ? "" : ",", arr[i]); if (n >= size) break; } return n; } const char *ib_get_sa_method_str(IN uint8_t method) { if (method & 0x80) { method = method & 0x7f; if (method > OSM_SA_METHOD_STR_UNKNOWN_VAL) method = OSM_SA_METHOD_STR_UNKNOWN_VAL; /* it is a response - use the response table */ return ib_sa_resp_method_str[method]; } else { if (method > OSM_SA_METHOD_STR_UNKNOWN_VAL) method = OSM_SA_METHOD_STR_UNKNOWN_VAL; return ib_sa_method_str[method]; } } const char *ib_get_sm_method_str(IN uint8_t method) { if (method & 0x80) method = (method & 0x0F) | 0x10; if (method > OSM_SM_METHOD_STR_UNKNOWN_VAL) method = OSM_SM_METHOD_STR_UNKNOWN_VAL; return ib_sm_method_str[method]; } const char *ib_get_sm_attr_str(IN ib_net16_t attr) { uint16_t host_attr = cl_ntoh16(attr); if (attr == IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO) return "MLNXExtendedPortInfo"; if (host_attr > OSM_SM_ATTR_STR_UNKNOWN_VAL) host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL; return ib_sm_attr_str[host_attr]; } const char *ib_get_sa_attr_str(IN ib_net16_t attr) { uint16_t host_attr = cl_ntoh16(attr); if (host_attr > OSM_SA_ATTR_STR_UNKNOWN_VAL) host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL; return ib_sa_attr_str[host_attr]; } const char *ib_get_trap_str(ib_net16_t trap_num) { switch (cl_ntoh16(trap_num)) { case SM_GID_IN_SERVICE_TRAP: /* 64 */ return "GID in service"; case SM_GID_OUT_OF_SERVICE_TRAP: /* 65 */ return "GID out of service"; case SM_MGID_CREATED_TRAP: /* 66 */ return "New mcast group created"; case SM_MGID_DESTROYED_TRAP: /* 67 */ return "Mcast group deleted"; case SM_UNPATH_TRAP: /* 68 */ return "UnPath, Path no longer valid"; case SM_REPATH_TRAP: /* 69 */ return "RePath, Path recomputed"; case SM_LINK_STATE_CHANGED_TRAP: /* 128 */ return "Link state change"; case SM_LINK_INTEGRITY_THRESHOLD_TRAP: /* 129 */ return "Local Link integrity threshold reached"; case SM_BUFFER_OVERRUN_THRESHOLD_TRAP: /* 130 */ return "Excessive Buffer Overrun Threshold reached"; case SM_WATCHDOG_TIMER_EXPIRED_TRAP: /* 131 */ return "Flow Control Update watchdog timer expired"; case SM_LOCAL_CHANGES_TRAP: /* 144 */ return "CapabilityMask, NodeDescription, Link [Width|Speed] Enabled, SM priority changed"; case SM_SYS_IMG_GUID_CHANGED_TRAP: /* 145 */ return "System Image GUID changed"; case SM_BAD_MKEY_TRAP: /* 256 */ return "Bad M_Key"; case SM_BAD_PKEY_TRAP: /* 257 */ return "Bad P_Key"; case SM_BAD_QKEY_TRAP: /* 258 */ return "Bad Q_Key"; case SM_BAD_SWITCH_PKEY_TRAP: /* 259 */ return "Bad P_Key (switch external port)"; default: break; } return "Unknown"; } const ib_gid_t ib_zero_gid = { {0} }; static ib_api_status_t dbg_do_line(IN char **pp_local, IN uint32_t buf_size, IN const char *p_prefix_str, IN const char *p_new_str, IN uint32_t * p_total_len) { char line[LINE_LENGTH]; uint32_t len; sprintf(line, "%s%s", p_prefix_str, p_new_str); len = (uint32_t) strlen(line); *p_total_len += len; if (*p_total_len + sizeof('\0') > buf_size) return IB_INSUFFICIENT_MEMORY; strcpy(*pp_local, line); *pp_local += len; return IB_SUCCESS; } static void dbg_get_capabilities_str(IN char *p_buf, IN uint32_t buf_size, IN const char *p_prefix_str, IN const ib_port_info_t * p_pi) { uint32_t total_len = 0; char *p_local = p_buf; strcpy(p_local, "Capability Mask:\n"); p_local += strlen(p_local); if (p_pi->capability_mask & IB_PORT_CAP_RESV0) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_RESV0\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_IS_SM\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_NOTICE\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_TRAP\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_IPD) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_IPD\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_AUTO_MIG\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_SL_MAP\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_NV_MKEY\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_NV_PKEY\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_LED_INFO\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_SM_DISAB) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_SM_DISAB\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_SYS_IMG_GUID\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_RESV13) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_RESV13\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_EXT_SPEEDS\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_MASK2) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_CAP_MASK2\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_COM_MGT\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_SNMP\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_REINIT) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_REINIT\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_DEV_MGT\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_VEND_CLS\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_DR_NTC\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_CAP_NTC\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_BM) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_BM\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_LINK_RT_LATENCY\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_CLIENT_REREG\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_OTHER_LOCAL_CHANGES_NTC\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_LINK_SPEED_WIDTH_PAIRS_TBL\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_MADS) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_VEND_MADS\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_MCAST_PKEY_TRAP_SUPPRESS) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_MCAST_PKEY_TRAP_SUPPRESS\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_MCAST_FDB_TOP) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_MCAST_FDB_TOP\n", &total_len) != IB_SUCCESS) return; } if (p_pi->capability_mask & IB_PORT_CAP_HAS_HIER_INFO) { if (dbg_do_line(&p_local, buf_size, p_prefix_str, "IB_PORT_CAP_HAS_HIER_INFO\n", &total_len) != IB_SUCCESS) return; } } static void osm_dump_port_info_to_buf(IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_port_info_t * p_pi, OUT char * buf) { if (!buf || !p_pi) return; else { sprintf(buf, "PortInfo dump:\n" "\t\t\t\tport number..............%u\n" "\t\t\t\tnode_guid................0x%016" PRIx64 "\n" "\t\t\t\tport_guid................0x%016" PRIx64 "\n" "\t\t\t\tm_key....................0x%016" PRIx64 "\n" "\t\t\t\tsubnet_prefix............0x%016" PRIx64 "\n" "\t\t\t\tbase_lid.................%u\n" "\t\t\t\tmaster_sm_base_lid.......%u\n" "\t\t\t\tcapability_mask..........0x%X\n" "\t\t\t\tdiag_code................0x%X\n" "\t\t\t\tm_key_lease_period.......0x%X\n" "\t\t\t\tlocal_port_num...........%u\n" "\t\t\t\tlink_width_enabled.......0x%X\n" "\t\t\t\tlink_width_supported.....0x%X\n" "\t\t\t\tlink_width_active........0x%X\n" "\t\t\t\tlink_speed_supported.....0x%X\n" "\t\t\t\tport_state...............%s\n" "\t\t\t\tstate_info2..............0x%X\n" "\t\t\t\tm_key_protect_bits.......0x%X\n" "\t\t\t\tlmc......................0x%X\n" "\t\t\t\tlink_speed...............0x%X\n" "\t\t\t\tmtu_smsl.................0x%X\n" "\t\t\t\tvl_cap_init_type.........0x%X\n" "\t\t\t\tvl_high_limit............0x%X\n" "\t\t\t\tvl_arb_high_cap..........0x%X\n" "\t\t\t\tvl_arb_low_cap...........0x%X\n" "\t\t\t\tinit_rep_mtu_cap.........0x%X\n" "\t\t\t\tvl_stall_life............0x%X\n" "\t\t\t\tvl_enforce...............0x%X\n" "\t\t\t\tm_key_violations.........0x%X\n" "\t\t\t\tp_key_violations.........0x%X\n" "\t\t\t\tq_key_violations.........0x%X\n" "\t\t\t\tguid_cap.................0x%X\n" "\t\t\t\tclient_reregister........0x%X\n" "\t\t\t\tmcast_pkey_trap_suppr....0x%X\n" "\t\t\t\tsubnet_timeout...........0x%X\n" "\t\t\t\tresp_time_value..........0x%X\n" "\t\t\t\terror_threshold..........0x%X\n" "\t\t\t\tmax_credit_hint..........0x%X\n" "\t\t\t\tlink_round_trip_latency..0x%X\n" "\t\t\t\tcapability_mask2.........0x%X\n" "\t\t\t\tlink_speed_ext_active....0x%X\n" "\t\t\t\tlink_speed_ext_supported.0x%X\n" "\t\t\t\tlink_speed_ext_enabled...0x%X\n", port_num, cl_ntoh64(node_guid), cl_ntoh64(port_guid), cl_ntoh64(p_pi->m_key), cl_ntoh64(p_pi->subnet_prefix), cl_ntoh16(p_pi->base_lid), cl_ntoh16(p_pi->master_sm_base_lid), cl_ntoh32(p_pi->capability_mask), cl_ntoh16(p_pi->diag_code), cl_ntoh16(p_pi->m_key_lease_period), p_pi->local_port_num, p_pi->link_width_enabled, p_pi->link_width_supported, p_pi->link_width_active, ib_port_info_get_link_speed_sup(p_pi), ib_get_port_state_str(ib_port_info_get_port_state (p_pi)), p_pi->state_info2, ib_port_info_get_mpb(p_pi), ib_port_info_get_lmc(p_pi), p_pi->link_speed, p_pi->mtu_smsl, p_pi->vl_cap, p_pi->vl_high_limit, p_pi->vl_arb_high_cap, p_pi->vl_arb_low_cap, p_pi->mtu_cap, p_pi->vl_stall_life, p_pi->vl_enforce, cl_ntoh16(p_pi->m_key_violations), cl_ntoh16(p_pi->p_key_violations), cl_ntoh16(p_pi->q_key_violations), p_pi->guid_cap, ib_port_info_get_client_rereg(p_pi), ib_port_info_get_mcast_pkey_trap_suppress(p_pi), ib_port_info_get_timeout(p_pi), ib_port_info_get_resp_time_value(p_pi), p_pi->error_threshold, cl_ntoh16(p_pi->max_credit_hint), cl_ntoh32(p_pi->link_rt_latency), cl_ntoh16(p_pi->capability_mask2), ib_port_info_get_link_speed_ext_active(p_pi), ib_port_info_get_link_speed_ext_sup(p_pi), p_pi->link_speed_ext_enabled); } } void osm_dump_port_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_port_info_t * p_pi, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_port_info_to_buf(node_guid, port_guid, port_num, p_pi, buf); osm_log(p_log, log_level, "%s", buf); /* show the capabilities mask */ if (p_pi->capability_mask) { dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t", p_pi); osm_log(p_log, log_level, "%s", buf); } } } void osm_dump_port_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_port_info_t * p_pi, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_port_info_to_buf(node_guid, port_guid, port_num, p_pi, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); /* show the capabilities mask */ if (p_pi->capability_mask) { dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t", p_pi); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } } static void osm_dump_mlnx_ext_port_info_to_buf(IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_mlnx_ext_port_info_t * p_pi, OUT char * buf) { if (!buf || !p_pi) return; else { sprintf(buf, "MLNX ExtendedPortInfo dump:\n" "\t\t\t\tport number..............%u\n" "\t\t\t\tnode_guid................0x%016" PRIx64 "\n" "\t\t\t\tport_guid................0x%016" PRIx64 "\n" "\t\t\t\tStateChangeEnable........0x%X\n" "\t\t\t\tLinkSpeedSupported.......0x%X\n" "\t\t\t\tLinkSpeedEnabled.........0x%X\n" "\t\t\t\tLinkSpeedActive..........0x%X\n", port_num, cl_ntoh64(node_guid), cl_ntoh64(port_guid), p_pi->state_change_enable, p_pi->link_speed_supported, p_pi->link_speed_enabled, p_pi->link_speed_active); } } void osm_dump_mlnx_ext_port_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_mlnx_ext_port_info_t * p_pi, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_mlnx_ext_port_info_to_buf(node_guid, port_guid, port_num, p_pi, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_mlnx_ext_port_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t port_num, IN const ib_mlnx_ext_port_info_t * p_pi, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_mlnx_ext_port_info_to_buf(node_guid, port_guid, port_num, p_pi, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_portinfo_record_to_buf(IN const ib_portinfo_record_t * p_pir, OUT char * buf) { if (!buf || !p_pir) return; else { const ib_port_info_t *p_pi = &p_pir->port_info; sprintf(buf, "PortInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tEndPortLid...............%u\n" "\t\t\t\tPortNum..................%u\n" "\t\t\t\tOptions..................0x%X\n" "\t\t\t\tPortInfo dump:\n" "\t\t\t\tm_key....................0x%016" PRIx64 "\n" "\t\t\t\tsubnet_prefix............0x%016" PRIx64 "\n" "\t\t\t\tbase_lid.................%u\n" "\t\t\t\tmaster_sm_base_lid.......%u\n" "\t\t\t\tcapability_mask..........0x%X\n" "\t\t\t\tdiag_code................0x%X\n" "\t\t\t\tm_key_lease_period.......0x%X\n" "\t\t\t\tlocal_port_num...........%u\n" "\t\t\t\tlink_width_enabled.......0x%X\n" "\t\t\t\tlink_width_supported.....0x%X\n" "\t\t\t\tlink_width_active........0x%X\n" "\t\t\t\tlink_speed_supported.....0x%X\n" "\t\t\t\tport_state...............%s\n" "\t\t\t\tstate_info2..............0x%X\n" "\t\t\t\tm_key_protect_bits.......0x%X\n" "\t\t\t\tlmc......................0x%X\n" "\t\t\t\tlink_speed...............0x%X\n" "\t\t\t\tmtu_smsl.................0x%X\n" "\t\t\t\tvl_cap_init_type.........0x%X\n" "\t\t\t\tvl_high_limit............0x%X\n" "\t\t\t\tvl_arb_high_cap..........0x%X\n" "\t\t\t\tvl_arb_low_cap...........0x%X\n" "\t\t\t\tinit_rep_mtu_cap.........0x%X\n" "\t\t\t\tvl_stall_life............0x%X\n" "\t\t\t\tvl_enforce...............0x%X\n" "\t\t\t\tm_key_violations.........0x%X\n" "\t\t\t\tp_key_violations.........0x%X\n" "\t\t\t\tq_key_violations.........0x%X\n" "\t\t\t\tguid_cap.................0x%X\n" "\t\t\t\tclient_reregister........0x%X\n" "\t\t\t\tmcast_pkey_trap_suppr....0x%X\n" "\t\t\t\tsubnet_timeout...........0x%X\n" "\t\t\t\tresp_time_value..........0x%X\n" "\t\t\t\terror_threshold..........0x%X\n" "\t\t\t\tmax_credit_hint..........0x%X\n" "\t\t\t\tlink_round_trip_latency..0x%X\n" "\t\t\t\tcapability_mask2.........0x%X\n" "\t\t\t\tlink_speed_ext_active....0x%X\n" "\t\t\t\tlink_speed_ext_supported.0x%X\n" "\t\t\t\tlink_speed_ext_enabled...0x%X\n", cl_ntoh16(p_pir->lid), p_pir->port_num, p_pir->options, cl_ntoh64(p_pi->m_key), cl_ntoh64(p_pi->subnet_prefix), cl_ntoh16(p_pi->base_lid), cl_ntoh16(p_pi->master_sm_base_lid), cl_ntoh32(p_pi->capability_mask), cl_ntoh16(p_pi->diag_code), cl_ntoh16(p_pi->m_key_lease_period), p_pi->local_port_num, p_pi->link_width_enabled, p_pi->link_width_supported, p_pi->link_width_active, ib_port_info_get_link_speed_sup(p_pi), ib_get_port_state_str(ib_port_info_get_port_state (p_pi)), p_pi->state_info2, ib_port_info_get_mpb(p_pi), ib_port_info_get_lmc(p_pi), p_pi->link_speed, p_pi->mtu_smsl, p_pi->vl_cap, p_pi->vl_high_limit, p_pi->vl_arb_high_cap, p_pi->vl_arb_low_cap, p_pi->mtu_cap, p_pi->vl_stall_life, p_pi->vl_enforce, cl_ntoh16(p_pi->m_key_violations), cl_ntoh16(p_pi->p_key_violations), cl_ntoh16(p_pi->q_key_violations), p_pi->guid_cap, ib_port_info_get_client_rereg(p_pi), ib_port_info_get_mcast_pkey_trap_suppress(p_pi), ib_port_info_get_timeout(p_pi), ib_port_info_get_resp_time_value(p_pi), p_pi->error_threshold, cl_ntoh16(p_pi->max_credit_hint), cl_ntoh32(p_pi->link_rt_latency), cl_ntoh16(p_pi->capability_mask2), ib_port_info_get_link_speed_ext_active(p_pi), ib_port_info_get_link_speed_ext_sup(p_pi), p_pi->link_speed_ext_enabled); } } void osm_dump_portinfo_record(IN osm_log_t * p_log, IN const ib_portinfo_record_t * p_pir, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; const ib_port_info_t *p_pi = &p_pir->port_info; osm_dump_portinfo_record_to_buf(p_pir, buf); osm_log(p_log, log_level, "%s", buf); /* show the capabilities mask */ if (p_pi->capability_mask) { dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t", p_pi); osm_log(p_log, log_level, "%s", buf); } } } void osm_dump_portinfo_record_v2(IN osm_log_t * p_log, IN const ib_portinfo_record_t * p_pir, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; const ib_port_info_t *p_pi = &p_pir->port_info; osm_dump_portinfo_record_to_buf(p_pir, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); /* show the capabilities mask */ if (p_pi->capability_mask) { dbg_get_capabilities_str(buf, BUF_SIZE, "\t\t\t\t", p_pi); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } } static void osm_dump_guid_info_to_buf(IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t block_num, IN const ib_guid_info_t * p_gi, OUT char * buf) { if (!buf || !p_gi) return; else { sprintf(buf, "GUIDInfo dump:\n" "\t\t\t\tblock number............%u\n" "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n" "\t\t\t\tport_guid...............0x%016" PRIx64 "\n" "\t\t\t\tGUID 0..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 1..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 2..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 3..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 4..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 5..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 6..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 7..................0x%016" PRIx64 "\n", block_num, cl_ntoh64(node_guid), cl_ntoh64(port_guid), cl_ntoh64(p_gi->guid[0]), cl_ntoh64(p_gi->guid[1]), cl_ntoh64(p_gi->guid[2]), cl_ntoh64(p_gi->guid[3]), cl_ntoh64(p_gi->guid[4]), cl_ntoh64(p_gi->guid[5]), cl_ntoh64(p_gi->guid[6]), cl_ntoh64(p_gi->guid[7])); } } void osm_dump_guid_info(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t block_num, IN const ib_guid_info_t * p_gi, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_guid_info_to_buf(node_guid, port_guid, block_num, p_gi, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_guid_info_v2(IN osm_log_t * p_log, IN ib_net64_t node_guid, IN ib_net64_t port_guid, IN uint8_t block_num, IN const ib_guid_info_t * p_gi, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_guid_info_to_buf(node_guid, port_guid, block_num, p_gi, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_guidinfo_record_to_buf(IN const ib_guidinfo_record_t * p_gir, OUT char * buf) { if (!buf || !p_gir) return; else { const ib_guid_info_t *p_gi = &p_gir->guid_info; sprintf(buf, "GUIDInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tLid.....................%u\n" "\t\t\t\tBlockNum................0x%X\n" "\t\t\t\tReserved................0x%X\n" "\t\t\t\tGUIDInfo dump:\n" "\t\t\t\tReserved................0x%X\n" "\t\t\t\tGUID 0..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 1..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 2..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 3..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 4..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 5..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 6..................0x%016" PRIx64 "\n" "\t\t\t\tGUID 7..................0x%016" PRIx64 "\n", cl_ntoh16(p_gir->lid), p_gir->block_num, p_gir->resv, cl_ntoh32(p_gir->reserved), cl_ntoh64(p_gi->guid[0]), cl_ntoh64(p_gi->guid[1]), cl_ntoh64(p_gi->guid[2]), cl_ntoh64(p_gi->guid[3]), cl_ntoh64(p_gi->guid[4]), cl_ntoh64(p_gi->guid[5]), cl_ntoh64(p_gi->guid[6]), cl_ntoh64(p_gi->guid[7])); } } void osm_dump_guidinfo_record(IN osm_log_t * p_log, IN const ib_guidinfo_record_t * p_gir, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_guidinfo_record_to_buf(p_gir, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_guidinfo_record_v2(IN osm_log_t * p_log, IN const ib_guidinfo_record_t * p_gir, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_guidinfo_record_to_buf(p_gir, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_node_info_to_buf(IN const ib_node_info_t * p_ni, OUT char * buf) { if (!buf || !p_ni) return; else { sprintf(buf, "NodeInfo dump:\n" "\t\t\t\tbase_version............0x%X\n" "\t\t\t\tclass_version...........0x%X\n" "\t\t\t\tnode_type...............%s\n" "\t\t\t\tnum_ports...............%u\n" "\t\t\t\tsys_guid................0x%016" PRIx64 "\n" "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n" "\t\t\t\tport_guid...............0x%016" PRIx64 "\n" "\t\t\t\tpartition_cap...........0x%X\n" "\t\t\t\tdevice_id...............0x%X\n" "\t\t\t\trevision................0x%X\n" "\t\t\t\tport_num................%u\n" "\t\t\t\tvendor_id...............0x%X\n", p_ni->base_version, p_ni->class_version, ib_get_node_type_str(p_ni->node_type), p_ni->num_ports, cl_ntoh64(p_ni->sys_guid), cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_ni->port_guid), cl_ntoh16(p_ni->partition_cap), cl_ntoh16(p_ni->device_id), cl_ntoh32(p_ni->revision), ib_node_info_get_local_port_num(p_ni), cl_ntoh32(ib_node_info_get_vendor_id(p_ni))); } } void osm_dump_node_info(IN osm_log_t * p_log, IN const ib_node_info_t * p_ni, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_node_info_to_buf(p_ni, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_node_info_v2(IN osm_log_t * p_log, IN const ib_node_info_t * p_ni, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_node_info_to_buf(p_ni, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_node_record_to_buf(IN const ib_node_record_t * p_nr, OUT char * buf) { if (!buf || !p_nr) return; else { char desc[sizeof(p_nr->node_desc.description) + 1]; const ib_node_info_t *p_ni = &p_nr->node_info; memcpy(desc, p_nr->node_desc.description, sizeof(p_nr->node_desc.description)); desc[sizeof(desc) - 1] = '\0'; sprintf(buf, "Node Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tLid.....................%u\n" "\t\t\t\tReserved................0x%X\n" "\t\t\t\tNodeInfo dump:\n" "\t\t\t\tbase_version............0x%X\n" "\t\t\t\tclass_version...........0x%X\n" "\t\t\t\tnode_type...............%s\n" "\t\t\t\tnum_ports...............%u\n" "\t\t\t\tsys_guid................0x%016" PRIx64 "\n" "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n" "\t\t\t\tport_guid...............0x%016" PRIx64 "\n" "\t\t\t\tpartition_cap...........0x%X\n" "\t\t\t\tdevice_id...............0x%X\n" "\t\t\t\trevision................0x%X\n" "\t\t\t\tport_num................%u\n" "\t\t\t\tvendor_id...............0x%X\n" "\t\t\t\tNodeDescription\n" "\t\t\t\t%s\n", cl_ntoh16(p_nr->lid), cl_ntoh16(p_nr->resv), p_ni->base_version, p_ni->class_version, ib_get_node_type_str(p_ni->node_type), p_ni->num_ports, cl_ntoh64(p_ni->sys_guid), cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_ni->port_guid), cl_ntoh16(p_ni->partition_cap), cl_ntoh16(p_ni->device_id), cl_ntoh32(p_ni->revision), ib_node_info_get_local_port_num(p_ni), cl_ntoh32(ib_node_info_get_vendor_id(p_ni)), desc); } } void osm_dump_node_record(IN osm_log_t * p_log, IN const ib_node_record_t * p_nr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_node_record_to_buf(p_nr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_node_record_v2(IN osm_log_t * p_log, IN const ib_node_record_t * p_nr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_node_record_to_buf(p_nr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_path_record_to_buf(IN const ib_path_rec_t * p_pr, OUT char * buf) { if (!buf || !p_pr) return; else { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; sprintf(buf, "PathRecord dump:\n" "\t\t\t\tservice_id..............0x%016" PRIx64 "\n" "\t\t\t\tdgid....................%s\n" "\t\t\t\tsgid....................%s\n" "\t\t\t\tdlid....................%u\n" "\t\t\t\tslid....................%u\n" "\t\t\t\thop_flow_raw............0x%X\n" "\t\t\t\ttclass..................0x%X\n" "\t\t\t\tnum_path_revers.........0x%X\n" "\t\t\t\tpkey....................0x%X\n" "\t\t\t\tqos_class...............0x%X\n" "\t\t\t\tsl......................0x%X\n" "\t\t\t\tmtu.....................0x%X\n" "\t\t\t\trate....................0x%X\n" "\t\t\t\tpkt_life................0x%X\n" "\t\t\t\tpreference..............0x%X\n" "\t\t\t\tresv2...................0x%02X%02X%02X%02X%02X%02X\n", cl_ntoh64(p_pr->service_id), inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2), cl_ntoh16(p_pr->dlid), cl_ntoh16(p_pr->slid), cl_ntoh32(p_pr->hop_flow_raw), p_pr->tclass, p_pr->num_path, cl_ntoh16(p_pr->pkey), ib_path_rec_qos_class(p_pr), ib_path_rec_sl(p_pr), p_pr->mtu, p_pr->rate, p_pr->pkt_life, p_pr->preference, p_pr->resv2[0], p_pr->resv2[1], p_pr->resv2[2], p_pr->resv2[3], p_pr->resv2[4], p_pr->resv2[5]); } } void osm_dump_path_record(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_path_record_to_buf(p_pr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_path_record_v2(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_path_record_to_buf(p_pr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_multipath_record_to_buf(IN const ib_multipath_rec_t * p_mpr, OUT char * buf) { if (!buf || !p_mpr) return; else { char gid_str[INET6_ADDRSTRLEN]; char buf_line[1024]; ib_gid_t const *p_gid = p_mpr->gids; int i, n = 0; if (p_mpr->sgid_count) { for (i = 0; i < p_mpr->sgid_count; i++) { n += sprintf(buf_line + n, "\t\t\t\tsgid%02d.................." "%s\n", i + 1, inet_ntop(AF_INET6, p_gid->raw, gid_str, sizeof gid_str)); p_gid++; } } if (p_mpr->dgid_count) { for (i = 0; i < p_mpr->dgid_count; i++) { n += sprintf(buf_line + n, "\t\t\t\tdgid%02d.................." "%s\n", i + 1, inet_ntop(AF_INET6, p_gid->raw, gid_str, sizeof gid_str)); p_gid++; } } sprintf(buf, "MultiPath Record dump:\n" "\t\t\t\thop_flow_raw............0x%X\n" "\t\t\t\ttclass..................0x%X\n" "\t\t\t\tnum_path_revers.........0x%X\n" "\t\t\t\tpkey....................0x%X\n" "\t\t\t\tqos_class...............0x%X\n" "\t\t\t\tsl......................0x%X\n" "\t\t\t\tmtu.....................0x%X\n" "\t\t\t\trate....................0x%X\n" "\t\t\t\tpkt_life................0x%X\n" "\t\t\t\tindependence............0x%X\n" "\t\t\t\tsgid_count..............0x%X\n" "\t\t\t\tdgid_count..............0x%X\n" "\t\t\t\tservice_id..............0x%016" PRIx64 "\n" "%s\n", cl_ntoh32(p_mpr->hop_flow_raw), p_mpr->tclass, p_mpr->num_path, cl_ntoh16(p_mpr->pkey), ib_multipath_rec_qos_class(p_mpr), ib_multipath_rec_sl(p_mpr), p_mpr->mtu, p_mpr->rate, p_mpr->pkt_life, p_mpr->independence, p_mpr->sgid_count, p_mpr->dgid_count, cl_ntoh64(ib_multipath_rec_service_id(p_mpr)), buf_line); } } void osm_dump_multipath_record(IN osm_log_t * p_log, IN const ib_multipath_rec_t * p_mpr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_multipath_record_to_buf(p_mpr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_multipath_record_v2(IN osm_log_t * p_log, IN const ib_multipath_rec_t * p_mpr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_multipath_record_to_buf(p_mpr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_mc_record_to_buf(IN const ib_member_rec_t * p_mcmr, OUT char * buf) { if(!buf || !p_mcmr) return; else { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; sprintf(buf, "MCMember Record dump:\n" "\t\t\t\tMGID....................%s\n" "\t\t\t\tPortGid.................%s\n" "\t\t\t\tqkey....................0x%X\n" "\t\t\t\tmlid....................0x%X\n" "\t\t\t\tmtu.....................0x%X\n" "\t\t\t\tTClass..................0x%X\n" "\t\t\t\tpkey....................0x%X\n" "\t\t\t\trate....................0x%X\n" "\t\t\t\tpkt_life................0x%X\n" "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n" "\t\t\t\tScopeState..............0x%X\n" "\t\t\t\tProxyJoin...............0x%X\n", inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_mcmr->port_gid.raw, gid_str2, sizeof gid_str2), cl_ntoh32(p_mcmr->qkey), cl_ntoh16(p_mcmr->mlid), p_mcmr->mtu, p_mcmr->tclass, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, p_mcmr->pkt_life, cl_ntoh32(p_mcmr->sl_flow_hop), p_mcmr->scope_state, p_mcmr->proxy_join); } } void osm_dump_mc_record(IN osm_log_t * p_log, IN const ib_member_rec_t * p_mcmr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_mc_record_to_buf(p_mcmr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_mc_record_v2(IN osm_log_t * p_log, IN const ib_member_rec_t * p_mcmr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_mc_record_to_buf(p_mcmr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_service_record_to_buf(IN const ib_service_record_t * p_sr, OUT char * buf) { if (!buf || !p_sr) return; else { char gid_str[INET6_ADDRSTRLEN]; char buf_service_key[35]; char buf_service_name[65]; sprintf(buf_service_key, "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", p_sr->service_key[0], p_sr->service_key[1], p_sr->service_key[2], p_sr->service_key[3], p_sr->service_key[4], p_sr->service_key[5], p_sr->service_key[6], p_sr->service_key[7], p_sr->service_key[8], p_sr->service_key[9], p_sr->service_key[10], p_sr->service_key[11], p_sr->service_key[12], p_sr->service_key[13], p_sr->service_key[14], p_sr->service_key[15]); strncpy(buf_service_name, (char *)p_sr->service_name, 64); buf_service_name[64] = '\0'; sprintf(buf, "Service Record dump:\n" "\t\t\t\tServiceID...............0x%016" PRIx64 "\n" "\t\t\t\tServiceGID..............%s\n" "\t\t\t\tServiceP_Key............0x%X\n" "\t\t\t\tServiceLease............0x%X\n" "\t\t\t\tServiceKey..............%s\n" "\t\t\t\tServiceName.............%s\n" "\t\t\t\tServiceData8.1..........0x%X\n" "\t\t\t\tServiceData8.2..........0x%X\n" "\t\t\t\tServiceData8.3..........0x%X\n" "\t\t\t\tServiceData8.4..........0x%X\n" "\t\t\t\tServiceData8.5..........0x%X\n" "\t\t\t\tServiceData8.6..........0x%X\n" "\t\t\t\tServiceData8.7..........0x%X\n" "\t\t\t\tServiceData8.8..........0x%X\n" "\t\t\t\tServiceData8.9..........0x%X\n" "\t\t\t\tServiceData8.10.........0x%X\n" "\t\t\t\tServiceData8.11.........0x%X\n" "\t\t\t\tServiceData8.12.........0x%X\n" "\t\t\t\tServiceData8.13.........0x%X\n" "\t\t\t\tServiceData8.14.........0x%X\n" "\t\t\t\tServiceData8.15.........0x%X\n" "\t\t\t\tServiceData8.16.........0x%X\n" "\t\t\t\tServiceData16.1.........0x%X\n" "\t\t\t\tServiceData16.2.........0x%X\n" "\t\t\t\tServiceData16.3.........0x%X\n" "\t\t\t\tServiceData16.4.........0x%X\n" "\t\t\t\tServiceData16.5.........0x%X\n" "\t\t\t\tServiceData16.6.........0x%X\n" "\t\t\t\tServiceData16.7.........0x%X\n" "\t\t\t\tServiceData16.8.........0x%X\n" "\t\t\t\tServiceData32.1.........0x%X\n" "\t\t\t\tServiceData32.2.........0x%X\n" "\t\t\t\tServiceData32.3.........0x%X\n" "\t\t\t\tServiceData32.4.........0x%X\n" "\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n" "\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\n", cl_ntoh64(p_sr->service_id), inet_ntop(AF_INET6, p_sr->service_gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_sr->service_pkey), cl_ntoh32(p_sr->service_lease), buf_service_key, buf_service_name, p_sr->service_data8[0], p_sr->service_data8[1], p_sr->service_data8[2], p_sr->service_data8[3], p_sr->service_data8[4], p_sr->service_data8[5], p_sr->service_data8[6], p_sr->service_data8[7], p_sr->service_data8[8], p_sr->service_data8[9], p_sr->service_data8[10], p_sr->service_data8[11], p_sr->service_data8[12], p_sr->service_data8[13], p_sr->service_data8[14], p_sr->service_data8[15], cl_ntoh16(p_sr->service_data16[0]), cl_ntoh16(p_sr->service_data16[1]), cl_ntoh16(p_sr->service_data16[2]), cl_ntoh16(p_sr->service_data16[3]), cl_ntoh16(p_sr->service_data16[4]), cl_ntoh16(p_sr->service_data16[5]), cl_ntoh16(p_sr->service_data16[6]), cl_ntoh16(p_sr->service_data16[7]), cl_ntoh32(p_sr->service_data32[0]), cl_ntoh32(p_sr->service_data32[1]), cl_ntoh32(p_sr->service_data32[2]), cl_ntoh32(p_sr->service_data32[3]), cl_ntoh64(p_sr->service_data64[0]), cl_ntoh64(p_sr->service_data64[1])); } } void osm_dump_service_record(IN osm_log_t * p_log, IN const ib_service_record_t * p_sr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_service_record_to_buf(p_sr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_service_record_v2(IN osm_log_t * p_log, IN const ib_service_record_t * p_sr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_service_record_to_buf(p_sr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_inform_info_to_buf_generic(IN const ib_inform_info_t * p_ii, OUT char * buf) { if (!buf || !p_ii) return; else { uint32_t qpn; uint8_t resp_time_val; char gid_str[INET6_ADDRSTRLEN]; ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic. qpn_resp_time_val, &qpn, &resp_time_val); sprintf(buf, "InformInfo dump:\n" "\t\t\t\tgid.....................%s\n" "\t\t\t\tlid_range_begin.........%u\n" "\t\t\t\tlid_range_end...........%u\n" "\t\t\t\tis_generic..............0x%X\n" "\t\t\t\tsubscribe...............0x%X\n" "\t\t\t\ttrap_type...............0x%X\n" "\t\t\t\ttrap_num................%u\n" "\t\t\t\tqpn.....................0x%06X\n" "\t\t\t\tresp_time_val...........0x%X\n" "\t\t\t\tnode_type...............0x%06X\n" "", inet_ntop(AF_INET6, p_ii->gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_ii->lid_range_begin), cl_ntoh16(p_ii->lid_range_end), p_ii->is_generic, p_ii->subscribe, cl_ntoh16(p_ii->trap_type), cl_ntoh16(p_ii->g_or_v.generic.trap_num), cl_ntoh32(qpn), resp_time_val, cl_ntoh32(ib_inform_info_get_prod_type(p_ii))); } } static void osm_dump_inform_info_to_buf(IN const ib_inform_info_t * p_ii, OUT char * buf) { if (!buf || !p_ii) return; else { uint32_t qpn; uint8_t resp_time_val; char gid_str[INET6_ADDRSTRLEN]; ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic. qpn_resp_time_val, &qpn, &resp_time_val); sprintf(buf, "InformInfo dump:\n" "\t\t\t\tgid.....................%s\n" "\t\t\t\tlid_range_begin.........%u\n" "\t\t\t\tlid_range_end...........%u\n" "\t\t\t\tis_generic..............0x%X\n" "\t\t\t\tsubscribe...............0x%X\n" "\t\t\t\ttrap_type...............0x%X\n" "\t\t\t\tdev_id..................0x%X\n" "\t\t\t\tqpn.....................0x%06X\n" "\t\t\t\tresp_time_val...........0x%X\n" "\t\t\t\tvendor_id...............0x%06X\n" "", inet_ntop(AF_INET6, p_ii->gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_ii->lid_range_begin), cl_ntoh16(p_ii->lid_range_end), p_ii->is_generic, p_ii->subscribe, cl_ntoh16(p_ii->trap_type), cl_ntoh16(p_ii->g_or_v.vend.dev_id), cl_ntoh32(qpn), resp_time_val, cl_ntoh32(ib_inform_info_get_prod_type(p_ii))); } } void osm_dump_inform_info(IN osm_log_t * p_log, IN const ib_inform_info_t * p_ii, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; if (p_ii->is_generic) osm_dump_inform_info_to_buf_generic(p_ii, buf); else osm_dump_inform_info_to_buf(p_ii, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_inform_info_v2(IN osm_log_t * p_log, IN const ib_inform_info_t * p_ii, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; if (p_ii->is_generic) osm_dump_inform_info_to_buf_generic(p_ii, buf); else osm_dump_inform_info_to_buf(p_ii, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_inform_info_record_to_buf_generic(IN const ib_inform_info_record_t * p_iir, OUT char * buf) { if (!buf || p_iir) return; else { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; uint32_t qpn; uint8_t resp_time_val; ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v. generic.qpn_resp_time_val, &qpn, &resp_time_val); sprintf(buf, "InformInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tSubscriberGID...........%s\n" "\t\t\t\tSubscriberEnum..........0x%X\n" "\t\t\t\tInformInfo dump:\n" "\t\t\t\tgid.....................%s\n" "\t\t\t\tlid_range_begin.........%u\n" "\t\t\t\tlid_range_end...........%u\n" "\t\t\t\tis_generic..............0x%X\n" "\t\t\t\tsubscribe...............0x%X\n" "\t\t\t\ttrap_type...............0x%X\n" "\t\t\t\ttrap_num................%u\n" "\t\t\t\tqpn.....................0x%06X\n" "\t\t\t\tresp_time_val...........0x%X\n" "\t\t\t\tnode_type...............0x%06X\n" "", inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_iir->subscriber_enum), inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2, sizeof gid_str2), cl_ntoh16(p_iir->inform_info.lid_range_begin), cl_ntoh16(p_iir->inform_info.lid_range_end), p_iir->inform_info.is_generic, p_iir->inform_info.subscribe, cl_ntoh16(p_iir->inform_info.trap_type), cl_ntoh16(p_iir->inform_info.g_or_v.generic. trap_num), cl_ntoh32(qpn), resp_time_val, cl_ntoh32(ib_inform_info_get_prod_type (&p_iir->inform_info))); } } static void osm_dump_inform_info_record_to_buf(IN const ib_inform_info_record_t * p_iir, OUT char * buf) { if(!buf || p_iir) return; else { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; uint32_t qpn; uint8_t resp_time_val; ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v. generic.qpn_resp_time_val, &qpn, &resp_time_val); sprintf(buf, "InformInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tSubscriberGID...........%s\n" "\t\t\t\tSubscriberEnum..........0x%X\n" "\t\t\t\tInformInfo dump:\n" "\t\t\t\tgid.....................%s\n" "\t\t\t\tlid_range_begin.........%u\n" "\t\t\t\tlid_range_end...........%u\n" "\t\t\t\tis_generic..............0x%X\n" "\t\t\t\tsubscribe...............0x%X\n" "\t\t\t\ttrap_type...............0x%X\n" "\t\t\t\tdev_id..................0x%X\n" "\t\t\t\tqpn.....................0x%06X\n" "\t\t\t\tresp_time_val...........0x%X\n" "\t\t\t\tvendor_id...............0x%06X\n" "", inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_iir->subscriber_enum), inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2, sizeof gid_str2), cl_ntoh16(p_iir->inform_info.lid_range_begin), cl_ntoh16(p_iir->inform_info.lid_range_end), p_iir->inform_info.is_generic, p_iir->inform_info.subscribe, cl_ntoh16(p_iir->inform_info.trap_type), cl_ntoh16(p_iir->inform_info.g_or_v.vend. dev_id), cl_ntoh32(qpn), resp_time_val, cl_ntoh32(ib_inform_info_get_prod_type (&p_iir->inform_info))); } } void osm_dump_inform_info_record(IN osm_log_t * p_log, IN const ib_inform_info_record_t * p_iir, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; if (p_iir->inform_info.is_generic) osm_dump_inform_info_record_to_buf_generic(p_iir, buf); else osm_dump_inform_info_record_to_buf(p_iir, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_inform_info_record_v2(IN osm_log_t * p_log, IN const ib_inform_info_record_t * p_iir, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; if (p_iir->inform_info.is_generic) osm_dump_inform_info_record_to_buf_generic(p_iir, buf); else osm_dump_inform_info_record_to_buf(p_iir, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_link_record_to_buf(IN const ib_link_record_t * p_lr, OUT char * buf) { if (!buf || !p_lr) return; else { sprintf(buf, "Link Record dump:\n" "\t\t\t\tfrom_lid................%u\n" "\t\t\t\tfrom_port_num...........%u\n" "\t\t\t\tto_port_num.............%u\n" "\t\t\t\tto_lid..................%u\n", cl_ntoh16(p_lr->from_lid), p_lr->from_port_num, p_lr->to_port_num, cl_ntoh16(p_lr->to_lid)); } } void osm_dump_link_record(IN osm_log_t * p_log, IN const ib_link_record_t * p_lr, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_link_record_to_buf(p_lr, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_link_record_v2(IN osm_log_t * p_log, IN const ib_link_record_t * p_lr, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_link_record_to_buf(p_lr, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_switch_info_to_buf(IN const ib_switch_info_t * p_si, OUT char * buf) { if (!buf || !p_si) return; else { sprintf(buf, "SwitchInfo dump:\n" "\t\t\t\tlin_cap.................0x%X\n" "\t\t\t\trand_cap................0x%X\n" "\t\t\t\tmcast_cap...............0x%X\n" "\t\t\t\tlin_top.................0x%X\n" "\t\t\t\tdef_port................%u\n" "\t\t\t\tdef_mcast_pri_port......%u\n" "\t\t\t\tdef_mcast_not_port......%u\n" "\t\t\t\tlife_state..............0x%X\n" "\t\t\t\tlids_per_port...........%u\n" "\t\t\t\tpartition_enf_cap.......0x%X\n" "\t\t\t\tflags...................0x%X\n" "\t\t\t\tmcast_top...............0x%X\n", cl_ntoh16(p_si->lin_cap), cl_ntoh16(p_si->rand_cap), cl_ntoh16(p_si->mcast_cap), cl_ntoh16(p_si->lin_top), p_si->def_port, p_si->def_mcast_pri_port, p_si->def_mcast_not_port, p_si->life_state, cl_ntoh16(p_si->lids_per_port), cl_ntoh16(p_si->enforce_cap), p_si->flags, cl_ntoh16(p_si->mcast_top)); } } void osm_dump_switch_info(IN osm_log_t * p_log, IN const ib_switch_info_t * p_si, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_switch_info_to_buf(p_si, buf); osm_log(p_log, OSM_LOG_VERBOSE, "%s", buf); } } void osm_dump_switch_info_v2(IN osm_log_t * p_log, IN const ib_switch_info_t * p_si, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_switch_info_to_buf(p_si, buf); osm_log_v2(p_log, OSM_LOG_VERBOSE, file_id, "%s", buf); } } static void osm_dump_switch_info_record_to_buf(IN const ib_switch_info_record_t * p_sir, OUT char * buf) { if (!buf || !p_sir) return; else { sprintf(buf, "SwitchInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tlid.....................%u\n" "\t\t\t\tSwitchInfo dump:\n" "\t\t\t\tlin_cap.................0x%X\n" "\t\t\t\trand_cap................0x%X\n" "\t\t\t\tmcast_cap...............0x%X\n" "\t\t\t\tlin_top.................0x%X\n" "\t\t\t\tdef_port................%u\n" "\t\t\t\tdef_mcast_pri_port......%u\n" "\t\t\t\tdef_mcast_not_port......%u\n" "\t\t\t\tlife_state..............0x%X\n" "\t\t\t\tlids_per_port...........%u\n" "\t\t\t\tpartition_enf_cap.......0x%X\n" "\t\t\t\tflags...................0x%X\n", cl_ntoh16(p_sir->lid), cl_ntoh16(p_sir->switch_info.lin_cap), cl_ntoh16(p_sir->switch_info.rand_cap), cl_ntoh16(p_sir->switch_info.mcast_cap), cl_ntoh16(p_sir->switch_info.lin_top), p_sir->switch_info.def_port, p_sir->switch_info.def_mcast_pri_port, p_sir->switch_info.def_mcast_not_port, p_sir->switch_info.life_state, cl_ntoh16(p_sir->switch_info.lids_per_port), cl_ntoh16(p_sir->switch_info.enforce_cap), p_sir->switch_info.flags); } } void osm_dump_switch_info_record(IN osm_log_t * p_log, IN const ib_switch_info_record_t * p_sir, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_switch_info_record_to_buf(p_sir, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_switch_info_record_v2(IN osm_log_t * p_log, IN const ib_switch_info_record_t * p_sir, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_switch_info_record_to_buf(p_sir, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_pkey_block_to_buf(IN uint64_t port_guid, IN uint16_t block_num, IN uint8_t port_num, IN const ib_pkey_table_t * p_pkey_tbl, OUT char * buf) { if (!buf || !p_pkey_tbl) return; else { char buf_line[1024]; int i, n; for (i = 0, n = 0; i < 32; i++) n += sprintf(buf_line + n, " 0x%04x |", cl_ntoh16(p_pkey_tbl->pkey_entry[i])); sprintf(buf, "P_Key table dump:\n" "\t\t\tport_guid...........0x%016" PRIx64 "\n" "\t\t\tblock_num...........0x%X\n" "\t\t\tport_num............%u\n\tP_Key Table: %s\n", cl_ntoh64(port_guid), block_num, port_num, buf_line); } } void osm_dump_pkey_block(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint16_t block_num, IN uint8_t port_num, IN const ib_pkey_table_t * p_pkey_tbl, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_pkey_block_to_buf(port_guid, block_num, port_num, p_pkey_tbl, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_pkey_block_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint16_t block_num, IN uint8_t port_num, IN const ib_pkey_table_t * p_pkey_tbl, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_pkey_block_to_buf(port_guid, block_num, port_num, p_pkey_tbl, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_slvl_map_table_to_buf(IN uint64_t port_guid, IN uint8_t in_port_num, IN uint8_t out_port_num, IN const ib_slvl_table_t * p_slvl_tbl, OUT char * buf) { if (!buf || !p_slvl_tbl) return; else { char buf_line1[1024], buf_line2[1024]; int n; uint8_t i; for (i = 0, n = 0; i < 16; i++) n += sprintf(buf_line1 + n, " %-2u |", i); for (i = 0, n = 0; i < 16; i++) n += sprintf(buf_line2 + n, "0x%01X |", ib_slvl_table_get(p_slvl_tbl, i)); sprintf(buf, "SLtoVL dump:\n" "\t\t\tport_guid............0x%016" PRIx64 "\n" "\t\t\tin_port_num..........%u\n" "\t\t\tout_port_num.........%u\n\tSL: | %s\n\tVL: | %s\n", cl_ntoh64(port_guid), in_port_num, out_port_num, buf_line1, buf_line2); } } void osm_dump_slvl_map_table(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t in_port_num, IN uint8_t out_port_num, IN const ib_slvl_table_t * p_slvl_tbl, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_slvl_map_table_to_buf(port_guid, in_port_num, out_port_num, p_slvl_tbl, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_slvl_map_table_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t in_port_num, IN uint8_t out_port_num, IN const ib_slvl_table_t * p_slvl_tbl, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_slvl_map_table_to_buf(port_guid, in_port_num, out_port_num, p_slvl_tbl, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_vl_arb_table_to_buf(IN uint64_t port_guid, IN uint8_t block_num, IN uint8_t port_num, IN const ib_vl_arb_table_t * p_vla_tbl, OUT char * buf) { if (!buf || !p_vla_tbl) return; else { char buf_line1[1024], buf_line2[1024]; int i, n; for (i = 0, n = 0; i < 32; i++) n += sprintf(buf_line1 + n, " 0x%01X |", p_vla_tbl->vl_entry[i].vl); for (i = 0, n = 0; i < 32; i++) n += sprintf(buf_line2 + n, " 0x%01X |", p_vla_tbl->vl_entry[i].weight); sprintf(buf, "VLArb dump:\n" "\t\t\tport_guid...........0x%016" PRIx64 "\n" "\t\t\tblock_num...........0x%X\n" "\t\t\tport_num............%u\n\tVL : | %s\n\tWEIGHT:| %s\n", cl_ntoh64(port_guid), block_num, port_num, buf_line1, buf_line2); } } void osm_dump_vl_arb_table(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t block_num, IN uint8_t port_num, IN const ib_vl_arb_table_t * p_vla_tbl, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_vl_arb_table_to_buf(port_guid, block_num, port_num, p_vla_tbl, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_vl_arb_table_v2(IN osm_log_t * p_log, IN uint64_t port_guid, IN uint8_t block_num, IN uint8_t port_num, IN const ib_vl_arb_table_t * p_vla_tbl, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_vl_arb_table_to_buf(port_guid, block_num, port_num, p_vla_tbl, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_sm_info_to_buf(IN const ib_sm_info_t * p_smi, OUT char * buf) { if (!buf || !p_smi) return; else { sprintf(buf, "SMInfo dump:\n" "\t\t\t\tguid....................0x%016" PRIx64 "\n" "\t\t\t\tsm_key..................0x%016" PRIx64 "\n" "\t\t\t\tact_count...............%u\n" "\t\t\t\tpriority................%u\n" "\t\t\t\tsm_state................%u\n", cl_ntoh64(p_smi->guid), cl_ntoh64(p_smi->sm_key), cl_ntoh32(p_smi->act_count), ib_sminfo_get_priority(p_smi), ib_sminfo_get_state(p_smi)); } } void osm_dump_sm_info(IN osm_log_t * p_log, IN const ib_sm_info_t * p_smi, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_sm_info_to_buf(p_smi, buf); osm_log(p_log, OSM_LOG_DEBUG, "%s", buf); } } void osm_dump_sm_info_v2(IN osm_log_t * p_log, IN const ib_sm_info_t * p_smi, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_sm_info_to_buf(p_smi, buf); osm_log_v2(p_log, OSM_LOG_DEBUG, file_id, "%s", buf); } } static void osm_dump_sm_info_record_to_buf(IN const ib_sminfo_record_t * p_smir, OUT char * buf) { if (!buf || !p_smir) return; else { sprintf(buf, "SMInfo Record dump:\n" "\t\t\t\tRID\n" "\t\t\t\tLid.....................%u\n" "\t\t\t\tReserved................0x%X\n" "\t\t\t\tSMInfo dump:\n" "\t\t\t\tguid....................0x%016" PRIx64 "\n" "\t\t\t\tsm_key..................0x%016" PRIx64 "\n" "\t\t\t\tact_count...............%u\n" "\t\t\t\tpriority................%u\n" "\t\t\t\tsm_state................%u\n", cl_ntoh16(p_smir->lid), cl_ntoh16(p_smir->resv0), cl_ntoh64(p_smir->sm_info.guid), cl_ntoh64(p_smir->sm_info.sm_key), cl_ntoh32(p_smir->sm_info.act_count), ib_sminfo_get_priority(&p_smir->sm_info), ib_sminfo_get_state(&p_smir->sm_info)); } } void osm_dump_sm_info_record(IN osm_log_t * p_log, IN const ib_sminfo_record_t * p_smir, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_sm_info_record_to_buf(p_smir, buf); osm_log(p_log, OSM_LOG_DEBUG, "%s", buf); } } void osm_dump_sm_info_record_v2(IN osm_log_t * p_log, IN const ib_sminfo_record_t * p_smir, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_sm_info_record_to_buf(p_smir, buf); osm_log_v2(p_log, OSM_LOG_DEBUG, file_id, "%s", buf); } } static void osm_dump_notice_to_buf_generic(IN const ib_mad_notice_attr_t * p_ntci, OUT char * log_buf) { if (!log_buf || !p_ntci) return; else { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; char buff[1024]; int n; buff[0] = '\0'; /* immediate data based on the trap */ switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) { case SM_GID_IN_SERVICE_TRAP: /* 64 */ case SM_GID_OUT_OF_SERVICE_TRAP: /* 65 */ case SM_MGID_CREATED_TRAP: /* 66 */ case SM_MGID_DESTROYED_TRAP: /* 67 */ sprintf(buff, "\t\t\t\tsrc_gid..................%s\n", inet_ntop(AF_INET6, p_ntci->data_details. ntc_64_67.gid.raw, gid_str, sizeof gid_str)); break; case SM_LINK_STATE_CHANGED_TRAP: /* 128 */ sprintf(buff, "\t\t\t\tsw_lid...................%u\n", cl_ntoh16(p_ntci->data_details.ntc_128.sw_lid)); break; case SM_LINK_INTEGRITY_THRESHOLD_TRAP: /* 129 */ case SM_BUFFER_OVERRUN_THRESHOLD_TRAP: /* 130 */ case SM_WATCHDOG_TIMER_EXPIRED_TRAP: /* 131 */ sprintf(buff, "\t\t\t\tlid......................%u\n" "\t\t\t\tport_num.................%u\n", cl_ntoh16(p_ntci->data_details. ntc_129_131.lid), p_ntci->data_details.ntc_129_131.port_num); break; case SM_LOCAL_CHANGES_TRAP: /* 144 */ sprintf(buff, "\t\t\t\tlid......................%u\n" "\t\t\t\tlocal_changes............%u\n" "\t\t\t\tnew_cap_mask.............0x%08x\n" "\t\t\t\tchange_flags.............0x%x\n" "\t\t\t\tcap_mask2................0x%x\n", cl_ntoh16(p_ntci->data_details.ntc_144.lid), p_ntci->data_details.ntc_144.local_changes, cl_ntoh32(p_ntci->data_details.ntc_144. new_cap_mask), cl_ntoh16(p_ntci->data_details.ntc_144. change_flgs), cl_ntoh16(p_ntci->data_details.ntc_144. cap_mask2)); break; case SM_SYS_IMG_GUID_CHANGED_TRAP: /* 145 */ sprintf(buff, "\t\t\t\tlid......................%u\n" "\t\t\t\tnew_sys_guid.............0x%016" PRIx64 "\n", cl_ntoh16(p_ntci->data_details.ntc_145. lid), cl_ntoh64(p_ntci->data_details.ntc_145. new_sys_guid)); break; case SM_BAD_MKEY_TRAP: /* 256 */ n = sprintf(buff, "\t\t\t\tlid......................%u\n" "\t\t\t\tdrslid...................%u\n" "\t\t\t\tmethod...................0x%x\n" "\t\t\t\tattr_id..................0x%x\n" "\t\t\t\tattr_mod.................0x%x\n" "\t\t\t\tm_key....................0x%016" PRIx64 "\n" "\t\t\t\tdr_notice................%d\n" "\t\t\t\tdr_path_truncated........%d\n" "\t\t\t\tdr_hop_count.............%u\n", cl_ntoh16(p_ntci->data_details.ntc_256.lid), cl_ntoh16(p_ntci->data_details.ntc_256. dr_slid), p_ntci->data_details.ntc_256.method, cl_ntoh16(p_ntci->data_details.ntc_256. attr_id), cl_ntoh32(p_ntci->data_details.ntc_256. attr_mod), cl_ntoh64(p_ntci->data_details.ntc_256. mkey), p_ntci->data_details.ntc_256. dr_trunc_hop >> 7, p_ntci->data_details.ntc_256. dr_trunc_hop >> 6, p_ntci->data_details.ntc_256. dr_trunc_hop & 0x3f); n += snprintf(buff + n, sizeof(buff) - n, "Directed Path Dump of %u hop path:" "\n\t\t\t\tPath = ", p_ntci->data_details.ntc_256. dr_trunc_hop & 0x3f); n += sprint_uint8_arr(buff + n, sizeof(buff) - n, p_ntci->data_details.ntc_256. dr_rtn_path, (p_ntci->data_details.ntc_256. dr_trunc_hop & 0x3f) + 1); if (n >= sizeof(buff)) { n = sizeof(buff) - 2; break; } snprintf(buff + n, sizeof(buff) - n, "\n"); break; case SM_BAD_PKEY_TRAP: /* 257 */ case SM_BAD_QKEY_TRAP: /* 258 */ sprintf(buff, "\t\t\t\tlid1.....................%u\n" "\t\t\t\tlid2.....................%u\n" "\t\t\t\tkey......................0x%x\n" "\t\t\t\tsl.......................%d\n" "\t\t\t\tqp1......................0x%x\n" "\t\t\t\tqp2......................0x%x\n" "\t\t\t\tgid1.....................%s\n" "\t\t\t\tgid2.....................%s\n", cl_ntoh16(p_ntci->data_details.ntc_257_258. lid1), cl_ntoh16(p_ntci->data_details.ntc_257_258. lid2), cl_ntoh32(p_ntci->data_details.ntc_257_258.key), cl_ntoh32(p_ntci->data_details.ntc_257_258. qp1) >> 28, cl_ntoh32(p_ntci->data_details.ntc_257_258. qp1) & 0xffffff, cl_ntoh32(p_ntci->data_details.ntc_257_258. qp2) & 0xffffff, inet_ntop(AF_INET6, p_ntci->data_details. ntc_257_258.gid1.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_ntci->data_details. ntc_257_258.gid2.raw, gid_str2, sizeof gid_str2)); break; case SM_BAD_SWITCH_PKEY_TRAP: /* 259 */ sprintf(buff, "\t\t\t\tdata_valid...............0x%x\n" "\t\t\t\tlid1.....................%u\n" "\t\t\t\tlid2.....................%u\n" "\t\t\t\tpkey.....................0x%x\n" "\t\t\t\tsl.......................%d\n" "\t\t\t\tqp1......................0x%x\n" "\t\t\t\tqp2......................0x%x\n" "\t\t\t\tgid1.....................%s\n" "\t\t\t\tgid2.....................%s\n" "\t\t\t\tsw_lid...................%u\n" "\t\t\t\tport_no..................%u\n", cl_ntoh16(p_ntci->data_details.ntc_259. data_valid), cl_ntoh16(p_ntci->data_details.ntc_259.lid1), cl_ntoh16(p_ntci->data_details.ntc_259.lid2), cl_ntoh16(p_ntci->data_details.ntc_259.pkey), cl_ntoh32(p_ntci->data_details.ntc_259. sl_qp1) >> 24, cl_ntoh32(p_ntci->data_details.ntc_259. sl_qp1) & 0xffffff, cl_ntoh32(p_ntci->data_details.ntc_259.qp2), inet_ntop(AF_INET6, p_ntci->data_details. ntc_259.gid1.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_ntci->data_details. ntc_259.gid2.raw, gid_str2, sizeof gid_str2), cl_ntoh16(p_ntci->data_details.ntc_259.sw_lid), p_ntci->data_details.ntc_259.port_no); break; } sprintf(log_buf, "Generic Notice dump:\n" "\t\t\t\ttype.....................%u\n" "\t\t\t\tprod_type................%u (%s)\n" "\t\t\t\ttrap_num.................%u\n%s", ib_notice_get_type(p_ntci), cl_ntoh32(ib_notice_get_prod_type(p_ntci)), ib_get_producer_type_str(ib_notice_get_prod_type (p_ntci)), cl_ntoh16(p_ntci->g_or_v.generic.trap_num), buff); } } static void osm_dump_notice_to_buf(IN const ib_mad_notice_attr_t * p_ntci, OUT char * buf) { if (!buf || !p_ntci) return; else { sprintf(buf, "Vendor Notice dump:\n" "\t\t\t\ttype.....................%u\n" "\t\t\t\tvendor...................%u\n" "\t\t\t\tdevice_id................%u\n", cl_ntoh16(ib_notice_get_type(p_ntci)), cl_ntoh32(ib_notice_get_vend_id(p_ntci)), cl_ntoh16(p_ntci->g_or_v.vend.dev_id)); } } void osm_dump_notice(IN osm_log_t * p_log, IN const ib_mad_notice_attr_t * p_ntci, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; if (ib_notice_is_generic(p_ntci)) osm_dump_notice_to_buf_generic(p_ntci, buf); else osm_dump_notice_to_buf(p_ntci, buf); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_notice_v2(IN osm_log_t * p_log, IN const ib_mad_notice_attr_t * p_ntci, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; if (ib_notice_is_generic(p_ntci)) osm_dump_notice_to_buf_generic(p_ntci, buf); else osm_dump_notice_to_buf(p_ntci, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_dr_smp_to_buf(IN const ib_smp_t * p_smp, OUT char * buf, IN size_t buf_size) { if (!buf || !p_smp) return; else { unsigned n; n = sprintf(buf, "SMP dump:\n" "\t\t\t\tbase_ver................0x%X\n" "\t\t\t\tmgmt_class..............0x%X\n" "\t\t\t\tclass_ver...............0x%X\n" "\t\t\t\tmethod..................0x%X (%s)\n", p_smp->base_ver, p_smp->mgmt_class, p_smp->class_ver, p_smp->method, ib_get_sm_method_str(p_smp->method)); if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) { n += snprintf(buf + n, buf_size - n, "\t\t\t\tD bit...................0x%X\n" "\t\t\t\tstatus..................0x%X\n", ib_smp_is_d(p_smp), cl_ntoh16(ib_smp_get_status(p_smp))); } else { n += snprintf(buf + n, buf_size - n, "\t\t\t\tstatus..................0x%X\n", cl_ntoh16(p_smp->status)); } n += snprintf(buf + n, buf_size - n, "\t\t\t\thop_ptr.................0x%X\n" "\t\t\t\thop_count...............0x%X\n" "\t\t\t\ttrans_id................0x%" PRIx64 "\n" "\t\t\t\tattr_id.................0x%X (%s)\n" "\t\t\t\tresv....................0x%X\n" "\t\t\t\tattr_mod................0x%X\n" "\t\t\t\tm_key...................0x%016" PRIx64 "\n", p_smp->hop_ptr, p_smp->hop_count, cl_ntoh64(p_smp->trans_id), cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh16(p_smp->resv), cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->m_key)); if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) { uint32_t i; n += snprintf(buf + n, buf_size - n, "\t\t\t\tdr_slid.................%u\n" "\t\t\t\tdr_dlid.................%u\n", cl_ntoh16(p_smp->dr_slid), cl_ntoh16(p_smp->dr_dlid)); n += snprintf(buf + n, buf_size - n, "\n\t\t\t\tInitial path: "); n += sprint_uint8_arr(buf + n, buf_size - n, p_smp->initial_path, p_smp->hop_count + 1); n += snprintf(buf + n, buf_size - n, "\n\t\t\t\tReturn path: "); n += sprint_uint8_arr(buf + n, buf_size - n, p_smp->return_path, p_smp->hop_count + 1); n += snprintf(buf + n, buf_size - n, "\n\t\t\t\tReserved: "); for (i = 0; i < 7; i++) { n += snprintf(buf + n, buf_size - n, "[%0X]", p_smp->resv1[i]); } n += snprintf(buf + n, buf_size - n, "\n"); for (i = 0; i < 64; i += 16) { n += snprintf(buf + n, buf_size - n, "\n\t\t\t\t%02X %02X %02X %02X " "%02X %02X %02X %02X" " %02X %02X %02X %02X %02X %02X %02X %02X\n", p_smp->data[i], p_smp->data[i + 1], p_smp->data[i + 2], p_smp->data[i + 3], p_smp->data[i + 4], p_smp->data[i + 5], p_smp->data[i + 6], p_smp->data[i + 7], p_smp->data[i + 8], p_smp->data[i + 9], p_smp->data[i + 10], p_smp->data[i + 11], p_smp->data[i + 12], p_smp->data[i + 13], p_smp->data[i + 14], p_smp->data[i + 15]); } } else { /* not a Direct Route so provide source and destination lids */ n += snprintf(buf + n, buf_size - n, "\t\t\t\tMAD IS LID ROUTED\n"); } } } void osm_dump_dr_smp(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_dr_smp_to_buf(p_smp, buf, BUF_SIZE); osm_log(p_log, log_level, "%s", buf); } } void osm_dump_dr_smp_v2(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_dr_smp_to_buf(p_smp, buf, BUF_SIZE); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_sa_mad_to_buf(IN const ib_sa_mad_t * p_mad, OUT char * buf) { if (!buf || !p_mad) return; else { /* make sure the mad is valid */ if (p_mad == NULL) { sprintf(buf, "NULL MAD POINTER\n"); return; } sprintf(buf, "SA MAD dump:\n" "\t\t\t\tbase_ver................0x%X\n" "\t\t\t\tmgmt_class..............0x%X\n" "\t\t\t\tclass_ver...............0x%X\n" "\t\t\t\tmethod..................0x%X (%s)\n" "\t\t\t\tstatus..................0x%X\n" "\t\t\t\tresv....................0x%X\n" "\t\t\t\ttrans_id................0x%" PRIx64 "\n" "\t\t\t\tattr_id.................0x%X (%s)\n" "\t\t\t\tresv1...................0x%X\n" "\t\t\t\tattr_mod................0x%X\n" "\t\t\t\trmpp_version............0x%X\n" "\t\t\t\trmpp_type...............0x%X\n" "\t\t\t\trmpp_flags..............0x%X\n" "\t\t\t\trmpp_status.............0x%X\n" "\t\t\t\tseg_num.................0x%X\n" "\t\t\t\tpayload_len/new_win.....0x%X\n" "\t\t\t\tsm_key..................0x%016" PRIx64 "\n" "\t\t\t\tattr_offset.............0x%X\n" "\t\t\t\tresv2...................0x%X\n" "\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n", p_mad->base_ver, p_mad->mgmt_class, p_mad->class_ver, p_mad->method, ib_get_sa_method_str(p_mad->method), cl_ntoh16(p_mad->status), cl_ntoh16(p_mad->resv), cl_ntoh64(p_mad->trans_id), cl_ntoh16(p_mad->attr_id), ib_get_sa_attr_str(p_mad->attr_id), cl_ntoh16(p_mad->resv1), cl_ntoh32(p_mad->attr_mod), p_mad->rmpp_version, p_mad->rmpp_type, p_mad->rmpp_flags, p_mad->rmpp_status, cl_ntoh32(p_mad->seg_num), cl_ntoh32(p_mad->paylen_newwin), cl_ntoh64(p_mad->sm_key), cl_ntoh16(p_mad->attr_offset), cl_ntoh16(p_mad->resv3), cl_ntoh64(p_mad->comp_mask)); strcat(buf, "\n"); } } void osm_dump_sa_mad(IN osm_log_t * p_log, IN const ib_sa_mad_t * p_mad, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_sa_mad_to_buf(p_mad, buf); osm_log(p_log, log_level, "%s\n", buf); } } void osm_dump_sa_mad_v2(IN osm_log_t * p_log, IN const ib_sa_mad_t * p_mad, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_sa_mad_to_buf(p_mad, buf); osm_log_v2(p_log, log_level, file_id, "%s", buf); } } static void osm_dump_dr_path_to_buf(IN const osm_dr_path_t * p_path, OUT char * buf, IN size_t buf_size) { if (!buf || !p_path) return; else { unsigned n = 0; n = sprintf(buf, "Directed Path Dump of %u hop path: " "Path = ", p_path->hop_count); sprint_uint8_arr(buf + n, buf_size - n, p_path->path, p_path->hop_count + 1); } } void osm_dump_dr_path(IN osm_log_t * p_log, IN const osm_dr_path_t * p_path, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_dr_path_to_buf(p_path, buf, BUF_SIZE); osm_log(p_log, log_level, "%s\n", buf); } } void osm_dump_dr_path_v2(IN osm_log_t * p_log, IN const osm_dr_path_t * p_path, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_dr_path_to_buf(p_path, buf, BUF_SIZE); osm_log_v2(p_log, log_level, file_id, "%s\n", buf); } } static void osm_dump_smp_dr_path_to_buf(IN const ib_smp_t * p_smp, OUT char * buf, IN size_t buf_size) { if (!buf || !p_smp) return; else { unsigned n; n = sprintf(buf, "Received SMP on a %u hop path: " "Initial path = ", p_smp->hop_count); n += sprint_uint8_arr(buf + n, buf_size - n, p_smp->initial_path, p_smp->hop_count + 1); n += snprintf(buf + n, buf_size - n, ", Return path = "); n += sprint_uint8_arr(buf + n, buf_size - n, p_smp->return_path, p_smp->hop_count + 1); } } void osm_dump_smp_dr_path(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN osm_log_level_t log_level) { if (osm_log_is_active(p_log, log_level)) { char buf[BUF_SIZE]; osm_dump_smp_dr_path_to_buf(p_smp, buf, BUF_SIZE); osm_log(p_log, log_level, "%s\n", buf); } } void osm_dump_smp_dr_path_v2(IN osm_log_t * p_log, IN const ib_smp_t * p_smp, IN const int file_id, IN osm_log_level_t log_level) { if (osm_log_is_active_v2(p_log, log_level, file_id)) { char buf[BUF_SIZE]; osm_dump_smp_dr_path_to_buf(p_smp, buf, BUF_SIZE); osm_log_v2(p_log, log_level, file_id, "%s\n", buf); } } void osm_dump_dr_path_as_buf(IN size_t max_len, IN const osm_dr_path_t * p_path, OUT char* buf) { sprint_uint8_arr(buf, max_len, p_path->path, p_path->hop_count + 1); } static const char *sm_signal_str[] = { "OSM_SIGNAL_NONE", /* 0 */ "OSM_SIGNAL_SWEEP", /* 1 */ "OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST", /* 2 */ "OSM_SIGNAL_PERFMGR_SWEEP", /* 3 */ "OSM_SIGNAL_GUID_PROCESS_REQUEST", /* 4 */ "UNKNOWN SIGNAL!!" /* 5 */ }; const char *osm_get_sm_signal_str(IN osm_signal_t signal) { if (signal > OSM_SIGNAL_MAX) signal = OSM_SIGNAL_MAX; return sm_signal_str[signal]; } static const char *disp_msg_str[] = { "OSM_MSG_NONE", "OSM_MSG_MAD_NODE_INFO", "OSM_MSG_MAD_PORT_INFO", "OSM_MSG_MAD_SWITCH_INFO", "OSM_MSG_MAD_GUID_INFO", "OSM_MSG_MAD_NODE_DESC", "OSM_MSG_MAD_NODE_RECORD", "OSM_MSG_MAD_PORTINFO_RECORD", "OSM_MSG_MAD_SERVICE_RECORD", "OSM_MSG_MAD_PATH_RECORD", "OSM_MSG_MAD_MCMEMBER_RECORD", "OSM_MSG_MAD_LINK_RECORD", "OSM_MSG_MAD_SMINFO_RECORD", "OSM_MSG_MAD_CLASS_PORT_INFO", "OSM_MSG_MAD_INFORM_INFO", "OSM_MSG_MAD_LFT_RECORD", "OSM_MSG_MAD_LFT", "OSM_MSG_MAD_SM_INFO", "OSM_MSG_MAD_NOTICE", "OSM_MSG_LIGHT_SWEEP_FAIL", "OSM_MSG_MAD_MFT", "OSM_MSG_MAD_PKEY_TBL_RECORD", "OSM_MSG_MAD_VL_ARB_RECORD", "OSM_MSG_MAD_SLVL_TBL_RECORD", "OSM_MSG_MAD_PKEY", "OSM_MSG_MAD_VL_ARB", "OSM_MSG_MAD_SLVL", "OSM_MSG_MAD_GUIDINFO_RECORD", "OSM_MSG_MAD_INFORM_INFO_RECORD", "OSM_MSG_MAD_SWITCH_INFO_RECORD", "OSM_MSG_MAD_MFT_RECORD", #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) "OSM_MSG_MAD_MULTIPATH_RECORD", #endif "OSM_MSG_MAD_PORT_COUNTERS", "OSM_MSG_MAD_MLNX_EXT_PORT_INFO", "UNKNOWN!!" }; const char *osm_get_disp_msg_str(IN cl_disp_msgid_t msg) { if (msg >= OSM_MSG_MAX) msg = OSM_MSG_MAX-1; return disp_msg_str[msg]; } static const char *port_state_str_fixed_width[] = { "NOC", "DWN", "INI", "ARM", "ACT", "???" }; const char *osm_get_port_state_str_fixed_width(IN uint8_t port_state) { if (port_state > IB_LINK_ACTIVE) port_state = IB_LINK_ACTIVE + 1; return port_state_str_fixed_width[port_state]; } static const char *node_type_str_fixed_width[] = { "??", "CA", "SW", "RT", }; const char *osm_get_node_type_str_fixed_width(IN uint8_t node_type) { if (node_type > IB_NODE_TYPE_ROUTER) node_type = 0; return node_type_str_fixed_width[node_type]; } const char *osm_get_manufacturer_str(IN uint64_t guid_ho) { /* note that the max vendor string length is 11 */ static const char *intel_str = "Intel"; static const char *mellanox_str = "Mellanox"; static const char *redswitch_str = "Redswitch"; static const char *silverstorm_str = "SilverStorm"; static const char *topspin_str = "Topspin"; static const char *fujitsu_str = "Fujitsu"; static const char *voltaire_str = "Voltaire"; static const char *yotta_str = "YottaYotta"; static const char *pathscale_str = "PathScale"; static const char *ibm_str = "IBM"; static const char *divergenet_str = "DivergeNet"; static const char *flextronics_str = "Flextronics"; static const char *agilent_str = "Agilent"; static const char *obsidian_str = "Obsidian"; static const char *baymicro_str = "BayMicro"; static const char *lsilogic_str = "LSILogic"; static const char *ddn_str = "DataDirect"; static const char *panta_str = "Panta"; static const char *hp_str = "HP"; static const char *rioworks_str = "Rioworks"; static const char *sun_str = "Sun"; static const char *leafntwks_str = "3LeafNtwks"; static const char *xsigo_str = "Xsigo"; static const char *dell_str = "Dell"; static const char *supermicro_str = "SuperMicro"; static const char *openib_str = "OpenIB"; static const char *unknown_str = "Unknown"; switch ((uint32_t) (guid_ho >> (5 * 8))) { case OSM_VENDOR_ID_INTEL: return intel_str; case OSM_VENDOR_ID_MELLANOX: case OSM_VENDOR_ID_MELLANOX2: case OSM_VENDOR_ID_MELLANOX3: case OSM_VENDOR_ID_MELLANOX4: case OSM_VENDOR_ID_MELLANOX5: return mellanox_str; case OSM_VENDOR_ID_REDSWITCH: return redswitch_str; case OSM_VENDOR_ID_SILVERSTORM: return silverstorm_str; case OSM_VENDOR_ID_TOPSPIN: return topspin_str; case OSM_VENDOR_ID_FUJITSU: case OSM_VENDOR_ID_FUJITSU2: return fujitsu_str; case OSM_VENDOR_ID_VOLTAIRE: return voltaire_str; case OSM_VENDOR_ID_YOTTAYOTTA: return yotta_str; case OSM_VENDOR_ID_PATHSCALE: return pathscale_str; case OSM_VENDOR_ID_IBM: case OSM_VENDOR_ID_IBM2: return ibm_str; case OSM_VENDOR_ID_DIVERGENET: return divergenet_str; case OSM_VENDOR_ID_FLEXTRONICS: return flextronics_str; case OSM_VENDOR_ID_AGILENT: return agilent_str; case OSM_VENDOR_ID_OBSIDIAN: return obsidian_str; case OSM_VENDOR_ID_BAYMICRO: return baymicro_str; case OSM_VENDOR_ID_LSILOGIC: return lsilogic_str; case OSM_VENDOR_ID_DDN: return ddn_str; case OSM_VENDOR_ID_PANTA: return panta_str; case OSM_VENDOR_ID_HP: case OSM_VENDOR_ID_HP2: case OSM_VENDOR_ID_HP3: case OSM_VENDOR_ID_HP4: return hp_str; case OSM_VENDOR_ID_RIOWORKS: return rioworks_str; case OSM_VENDOR_ID_SUN: case OSM_VENDOR_ID_SUN2: return sun_str; case OSM_VENDOR_ID_3LEAFNTWKS: return leafntwks_str; case OSM_VENDOR_ID_XSIGO: return xsigo_str; case OSM_VENDOR_ID_DELL: return dell_str; case OSM_VENDOR_ID_SUPERMICRO: return supermicro_str; case OSM_VENDOR_ID_OPENIB: return openib_str; default: return unknown_str; } } static const char *mtu_str_fixed_width[] = { "??? ", "256 ", "512 ", "1024", "2048", "4096" }; const char *osm_get_mtu_str(IN uint8_t mtu) { if (mtu > IB_MTU_LEN_4096) return mtu_str_fixed_width[0]; else return mtu_str_fixed_width[mtu]; } static const char *lwa_str_fixed_width[] = { "???", "1x ", "4x ", "???", "8x ", "???", "???", "???", "12x" }; const char *osm_get_lwa_str(IN uint8_t lwa) { if (lwa > 8) return lwa_str_fixed_width[0]; else return lwa_str_fixed_width[lwa]; } static const char *lsa_str_fixed_width[] = { "Ext ", "2.5 ", "5 ", "????", "10 " }; static const char *lsea_str_fixed_width[] = { "Std ", "14 ", "25 " }; const char *osm_get_lsa_str(IN uint8_t lsa, IN uint8_t lsea, IN uint8_t state, IN uint8_t fdr10) { if (lsa > IB_LINK_SPEED_ACTIVE_10 || state == IB_LINK_DOWN) return lsa_str_fixed_width[3]; if (lsea == IB_LINK_SPEED_EXT_ACTIVE_NONE) { if (fdr10) return "FDR10"; else return lsa_str_fixed_width[lsa]; } if (lsea > IB_LINK_SPEED_EXT_ACTIVE_25) return lsa_str_fixed_width[3]; return lsea_str_fixed_width[lsea]; } static const char *sm_mgr_signal_str[] = { "OSM_SM_SIGNAL_NONE", /* 0 */ "OSM_SM_SIGNAL_DISCOVERY_COMPLETED", /* 1 */ "OSM_SM_SIGNAL_POLLING_TIMEOUT", /* 2 */ "OSM_SM_SIGNAL_DISCOVER", /* 3 */ "OSM_SM_SIGNAL_DISABLE", /* 4 */ "OSM_SM_SIGNAL_HANDOVER", /* 5 */ "OSM_SM_SIGNAL_HANDOVER_SENT", /* 6 */ "OSM_SM_SIGNAL_ACKNOWLEDGE", /* 7 */ "OSM_SM_SIGNAL_STANDBY", /* 8 */ "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED", /* 9 */ "OSM_SM_SIGNAL_WAIT_FOR_HANDOVER", /* 10 */ "UNKNOWN STATE!!" /* 11 */ }; const char *osm_get_sm_mgr_signal_str(IN osm_sm_signal_t signal) { if (signal > OSM_SM_SIGNAL_MAX) signal = OSM_SM_SIGNAL_MAX; return sm_mgr_signal_str[signal]; } static const char *sm_mgr_state_str[] = { "NOTACTIVE", /* 0 */ "DISCOVERING", /* 1 */ "STANDBY", /* 2 */ "MASTER", /* 3 */ "UNKNOWN STATE!!" /* 4 */ }; const char *osm_get_sm_mgr_state_str(IN uint16_t state) { return state < ARR_SIZE(sm_mgr_state_str) ? sm_mgr_state_str[state] : sm_mgr_state_str[ARR_SIZE(sm_mgr_state_str) - 1]; } int ib_mtu_is_valid(IN const int mtu) { if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU) return 0; return 1; } int ib_rate_is_valid(IN const int rate) { if (rate < IB_MIN_RATE || rate > IB_MAX_RATE) return 0; return 1; } int ib_path_compare_rates(IN const int rate1, IN const int rate2) { int orate1 = 0, orate2 = 0; CL_ASSERT(rate1 >= IB_MIN_RATE && rate1 <= IB_MAX_RATE); CL_ASSERT(rate2 >= IB_MIN_RATE && rate2 <= IB_MAX_RATE); if (rate1 <= IB_MAX_RATE) orate1 = ordered_rates[rate1]; if (rate2 <= IB_MAX_RATE) orate2 = ordered_rates[rate2]; if (orate1 < orate2) return -1; if (orate1 == orate2) return 0; return 1; } static int find_ordered_rate(IN const int rate) { int i; for (i = IB_MIN_RATE; i <= IB_MAX_RATE; i++) { if (ordered_rates[i] == rate) return i; } return 0; } int ib_path_rate_get_prev(IN const int rate) { int orate; CL_ASSERT(rate >= IB_MIN_RATE && rate <= IB_MAX_RATE); if (rate <= IB_MIN_RATE) return 0; if (rate > IB_MAX_RATE) return 0; orate = ordered_rates[rate]; orate--; return find_ordered_rate(orate); } int ib_path_rate_get_next(IN const int rate) { int orate; CL_ASSERT(rate >= IB_MIN_RATE && rate <= IB_MAX_RATE); if (rate < IB_MIN_RATE) return 0; if (rate >= IB_MAX_RATE) return 0; orate = ordered_rates[rate]; orate++; return find_ordered_rate(orate); } opensm-3.3.20/opensm/main.c0000644000205000001450000012173412505250311012403 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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: * Command line interface for opensm. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_MAIN_C #include #include #include #include #include #include volatile unsigned int osm_exit_flag = 0; static volatile unsigned int osm_hup_flag = 0; static volatile unsigned int osm_usr1_flag = 0; static char *pidfile; #define MAX_LOCAL_IBPORTS 64 #define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL) static void mark_exit_flag(int signum) { if (!osm_exit_flag) printf("OpenSM: Got signal %d - exiting...\n", signum); osm_exit_flag = 1; } static void mark_hup_flag(int signum) { osm_hup_flag = 1; } static void mark_usr1_flag(int signum) { osm_usr1_flag = 1; } static sigset_t saved_sigset; static void block_signals() { sigset_t set; sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); sigaddset(&set, SIGHUP); #ifndef HAVE_OLD_LINUX_THREADS sigaddset(&set, SIGUSR1); #endif pthread_sigmask(SIG_SETMASK, &set, &saved_sigset); } static void setup_signals() { struct sigaction act; sigemptyset(&act.sa_mask); act.sa_handler = mark_exit_flag; act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); act.sa_handler = mark_hup_flag; sigaction(SIGHUP, &act, NULL); sigaction(SIGCONT, &act, NULL); #ifndef HAVE_OLD_LINUX_THREADS act.sa_handler = mark_usr1_flag; sigaction(SIGUSR1, &act, NULL); #endif pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL); } static void show_usage(void) { printf("\n------- OpenSM - Usage and options ----------------------\n"); printf("Usage: opensm [options]\n"); printf("Options:\n"); printf("--version\n Prints OpenSM version and exits.\n\n"); printf("--config, -F \n" " The name of the OpenSM config file. When not specified\n" " " OSM_DEFAULT_CONFIG_FILE " will be used (if exists).\n\n"); printf("--create-config, -c \n" " OpenSM will dump its configuration to the specified file and exit.\n" " This is a way to generate OpenSM configuration file template.\n\n"); printf("--guid, -g \n" " This option specifies the local port GUID value\n" " with which OpenSM should bind. OpenSM may be\n" " bound to 1 port at a time.\n" " If GUID given is 0, OpenSM displays a list\n" " of possible port GUIDs and waits for user input.\n" " Without -g, OpenSM tries to use the default port.\n\n"); printf("--lmc, -l \n" " This option specifies the subnet's LMC value.\n" " The number of LIDs assigned to each port is 2^LMC.\n" " The LMC value must be in the range 0-7.\n" " LMC values > 0 allow multiple paths between ports.\n" " LMC values > 0 should only be used if the subnet\n" " topology actually provides multiple paths between\n" " ports, i.e. multiple interconnects between switches.\n" " Without -l, OpenSM defaults to LMC = 0, which allows\n" " one path between any two ports.\n\n"); printf("--priority, -p \n" " This option specifies the SM's PRIORITY.\n" " This will effect the handover cases, where master\n" " is chosen by priority and GUID. Range goes\n" " from 0 (lowest priority) to 15 (highest).\n\n"); printf("--smkey, -k \n" " This option specifies the SM's SM_Key (64 bits).\n" " This will effect SM authentication.\n" " Note that OpenSM version 3.2.1 and below used the\n" " default value '1' in a host byte order, it is fixed\n" " now but you may need this option to interoperate\n" " with old OpenSM running on a little endian machine.\n\n"); printf("--reassign_lids, -r\n" " This option causes OpenSM to reassign LIDs to all\n" " end nodes. Specifying -r on a running subnet\n" " may disrupt subnet traffic.\n" " Without -r, OpenSM attempts to preserve existing\n" " LID assignments resolving multiple use of same LID.\n\n"); printf("--routing_engine, -R \n" " This option chooses routing engine(s) to use instead of default\n" " Min Hop algorithm. Multiple routing engines can be specified\n" " separated by commas so that specific ordering of routing\n" " algorithms will be tried if earlier routing engines fail.\n" " If all configured routing engines fail, OpenSM will always\n" " attempt to route with Min Hop unless 'no_fallback' is\n" " included in the list of routing engines.\n" " Supported engines: updn, dnup, file, ftree, lash, dor, torus-2QoS, dfsssp, sssp\n\n"); printf("--do_mesh_analysis\n" " This option enables additional analysis for the lash\n" " routing engine to precondition switch port assignments\n" " in regular cartesian meshes which may reduce the number\n" " of SLs required to give a deadlock free routing\n\n"); printf("--lash_start_vl \n" " Sets the starting VL to use for the lash routing algorithm.\n" " Defaults to 0.\n"); printf("--sm_sl \n" " Sets the SL to use to communicate with the SM/SA. Defaults to 0.\n\n"); printf("--connect_roots, -z\n" " This option enforces routing engines (up/down and \n" " fat-tree) to make connectivity between root switches\n" " and in this way be IBA compliant. In many cases,\n" " this can violate \"pure\" deadlock free algorithm, so\n" " use it carefully.\n\n"); printf("--ucast_cache, -A\n" " This option enables unicast routing cache to prevent\n" " routing recalculation (which is a heavy task in a\n" " large cluster) when there was no topology change\n" " detected during the heavy sweep, or when the topology\n" " change does not require new routing calculation,\n" " e.g. in case of host reboot.\n" " This option becomes very handy when the cluster size\n" " is thousands of nodes.\n\n"); printf("--lid_matrix_file, -M \n" " This option specifies the name of the lid matrix dump file\n" " from where switch lid matrices (min hops tables will be\n" " loaded.\n\n"); printf("--lfts_file, -U \n" " This option specifies the name of the LFTs file\n" " from where switch forwarding tables will be loaded when using \"file\"\n" " routing engine.\n\n"); printf("--sadb_file, -S \n" " This option specifies the name of the SA DB dump file\n" " from where SA database will be loaded.\n\n"); printf("--root_guid_file, -a \n" " Set the root nodes for the Up/Down or Fat-Tree routing\n" " algorithm to the guids provided in the given file (one\n" " to a line)\n" "\n"); printf("--cn_guid_file, -u \n" " Set the compute nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n" " to the port GUIDs provided in the given file (one to a line)\n\n"); printf("--io_guid_file, -G \n" " Set the I/O nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n" " to the port GUIDs provided in the given file (one to a line)\n\n"); printf("--port-shifting\n" " Attempt to shift port routes around to remove alignment problems\n" " in routing tables\n\n"); printf("--scatter-ports \n" " Randomize best port chosen for a route\n" " Assign ports in a random order instead of round-robin\n" " If zero disable (default), otherwise use the value as a random seed\n\n"); printf("--max_reverse_hops, -H \n" " Set the max number of hops the wrong way around\n" " an I/O node is allowed to do (connectivity for I/O nodes on top swithces)\n\n"); printf("--ids_guid_file, -m \n" " Name of the map file with set of the IDs which will be used\n" " by Up/Down routing algorithm instead of node GUIDs\n" " (format: per line)\n\n"); printf("--guid_routing_order_file, -X \n" " Set the order port guids will be routed for the MinHop\n" " and Up/Down routing algorithms to the guids provided in the\n" " given file (one to a line)\n\n"); printf("--torus_config \n" " This option defines the file name for the extra configuration\n" " info needed for the torus-2QoS routing engine. The default\n" " name is \'"OSM_DEFAULT_TORUS_CONF_FILE"\'\n\n"); printf("--once, -o\n" " This option causes OpenSM to configure the subnet\n" " once, then exit. Ports remain in the ACTIVE state.\n\n"); printf("--sweep, -s \n" " This option specifies the number of seconds between\n" " subnet sweeps. Specifying -s 0 disables sweeping.\n" " Without -s, OpenSM defaults to a sweep interval of\n" " 10 seconds.\n\n"); printf("--timeout, -t \n" " This option specifies the time in milliseconds\n" " used for transaction timeouts.\n" " Timeout values should be > 0.\n" " Without -t, OpenSM defaults to a timeout value of\n" " 200 milliseconds.\n\n"); printf("--retries \n" " This option specifies the number of retries used\n" " for transactions.\n" " Without --retries, OpenSM defaults to %u retries\n" " for transactions.\n\n", OSM_DEFAULT_RETRY_COUNT); printf("--maxsmps, -n \n" " This option specifies the number of VL15 SMP MADs\n" " allowed on the wire at any one time.\n" " Specifying --maxsmps 0 allows unlimited outstanding\n" " SMPs.\n" " Without --maxsmps, OpenSM defaults to a maximum of\n" " 4 outstanding SMPs.\n\n"); printf("--console, -q [off|local" #ifdef ENABLE_OSM_CONSOLE_LOOPBACK "|loopback" #endif #ifdef ENABLE_OSM_CONSOLE_SOCKET "|socket" #endif "]\n This option activates the OpenSM console (default off).\n\n"); #ifdef ENABLE_OSM_CONSOLE_LOOPBACK printf("--console-port, -C \n" " Specify an alternate telnet port for the console (default %d).\n\n", OSM_DEFAULT_CONSOLE_PORT); #endif printf("--ignore_guids, -i \n" " This option provides the means to define a set of ports\n" " (by guid) that will be ignored by the link load\n" " equalization algorithm.\n\n"); printf("--hop_weights_file, -w \n" " This option provides the means to define a weighting\n" " factor per port for customizing the least weight\n" " hops for the routing.\n\n"); printf("--port_search_ordering_file, -O \n" " This option provides the means to define a mapping\n" " between ports and dimension (Order) for controlling\n" " Dimension Order Routing (DOR).\n" " Moreover this option provides the means to define non\n" " default routing port order.\n\n"); printf("--dimn_ports_file, -O (DEPRECATED)\n" " Use --port_search_ordering_file instead.\n" " This option provides the means to define a mapping\n" " between ports and dimension (Order) for controlling\n" " Dimension Order Routing (DOR).\n\n"); printf("--honor_guid2lid, -x\n" " This option forces OpenSM to honor the guid2lid file,\n" " when it comes out of Standby state, if such file exists\n" " under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n"); printf("--log_file, -f \n" " This option defines the log to be the given file.\n" " By default, the log goes to /var/log/opensm.log.\n" " For the log to go to standard output use -f stdout.\n\n"); printf("--log_limit, -L \n" " This option defines maximal log file size in MB. When\n" " specified the log file will be truncated upon reaching\n" " this limit.\n\n"); printf("--erase_log_file, -e\n" " This option will cause deletion of the log file\n" " (if it previously exists). By default, the log file\n" " is accumulative.\n\n"); printf("--Pconfig, -P \n" " This option defines the optional partition configuration file.\n" " The default name is \'" OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n"); printf("--no_part_enforce, -N (DEPRECATED)\n" " Use --part_enforce instead.\n" " This option disables partition enforcement on switch external ports.\n\n"); printf("--part_enforce, -Z [both, in, out, off]\n" " This option indicates the partition enforcement type (for switches)\n" " Enforcement type can be outbound only (out), inbound only (in), both or\n" " disabled (off). Default is both.\n\n"); printf("--allow_both_pkeys, -W\n" " This option indicates whether both full and limited membership\n" " on the same partition can be configured in the PKeyTable.\n" " Default is not to allow both pkeys.\n\n"); printf("--qos, -Q\n" " This option enables QoS setup.\n\n"); printf("--qos_policy_file, -Y \n" " This option defines the optional QoS policy file.\n" " The default name is \'" OSM_DEFAULT_QOS_POLICY_FILE "\'.\n\n"); printf("--congestion_control\n" " (EXPERIMENTAL) This option enables congestion control configuration.\n\n"); printf("--cc_key \n" " (EXPERIMENTAL) This option configures the CCkey to use when configuring\n" " congestion control.\n\n"); printf("--stay_on_fatal, -y\n" " This option will cause SM not to exit on fatal initialization\n" " issues: if SM discovers duplicated guids or 12x link with\n" " lane reversal badly configured.\n" " By default, the SM will exit on these errors.\n\n"); printf("--daemon, -B\n" " Run in daemon mode - OpenSM will run in the background.\n\n"); printf("--inactive, -I\n" " Start SM in inactive rather than normal init SM state.\n\n"); #ifdef ENABLE_OSM_PERF_MGR printf("--perfmgr\n" " Start with PerfMgr enabled.\n\n"); printf("--perfmgr_sweep_time_s \n" " PerfMgr sweep interval in seconds.\n\n"); #endif printf("--prefix_routes_file \n" " This option specifies the prefix routes file.\n" " Prefix routes control how the SA responds to path record\n" " queries for off-subnet DGIDs. Default file is:\n" " " OSM_DEFAULT_PREFIX_ROUTES_FILE "\n\n"); printf("--consolidate_ipv6_snm_req\n" " Use shared MLID for IPv6 Solicited Node Multicast groups\n" " per MGID scope and P_Key.\n\n"); printf("--guid_routing_order_no_scatter\n" " Don't use scatter for ports defined in guid_routing_order file\n\n"); printf("--log_prefix \n" " Prefix to syslog messages from OpenSM.\n\n"); printf("--verbose, -v\n" " This option increases the log verbosity level.\n" " The -v option may be specified multiple times\n" " to further increase the verbosity level.\n" " See the -D option for more information about\n" " log verbosity.\n\n"); printf("--V, -V\n" " This option sets the maximum verbosity level and\n" " forces log flushing.\n" " The -V is equivalent to '-D 0xFF -d 2'.\n" " See the -D option for more information about\n" " log verbosity.\n\n"); printf("--D, -D \n" " This option sets the log verbosity level.\n" " A flags field must follow the -D option.\n" " A bit set/clear in the flags enables/disables a\n" " specific log level as follows:\n" " BIT LOG LEVEL ENABLED\n" " ---- -----------------\n" " 0x01 - ERROR (error messages)\n" " 0x02 - INFO (basic messages, low volume)\n" " 0x04 - VERBOSE (interesting stuff, moderate volume)\n" " 0x08 - DEBUG (diagnostic, high volume)\n" " 0x10 - FUNCS (function entry/exit, very high volume)\n" " 0x20 - FRAMES (dumps all SMP and GMP frames)\n" " 0x40 - ROUTING (dump FDB routing information)\n" " 0x80 - currently unused.\n" " Without -D, OpenSM defaults to ERROR + INFO (0x3).\n" " Specifying -D 0 disables all messages.\n" " Specifying -D 0xFF enables all messages (see -V).\n" " High verbosity levels may require increasing\n" " the transaction timeout with the -t option.\n\n"); printf("--debug, -d \n" " This option specifies a debug option.\n" " These options are not normally needed.\n" " The number following -d selects the debug\n" " option to enable as follows:\n" " OPT Description\n" " --- -----------------\n" " -d0 - Ignore other SM nodes\n" " -d1 - Force single threaded dispatching\n" " -d2 - Force log flushing after each log message\n" " -d3 - Disable multicast support\n" " -d10 - Put OpenSM in testability mode\n" " Without -d, no debug options are enabled\n\n"); printf("--help, -h, -?\n" " Display this usage info then exit.\n\n"); fflush(stdout); exit(2); } static ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid) { ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS]; uint32_t num_ports = MAX_LOCAL_IBPORTS; uint32_t i, choice = 0; ib_api_status_t status; for (i = 0; i < num_ports; i++) { attr_array[i].num_pkeys = 0; attr_array[i].p_pkey_table = NULL; attr_array[i].num_gids = 0; attr_array[i].p_gid_table = NULL; } /* Call the transport layer for a list of local port GUID values */ status = osm_vendor_get_all_port_attr(p_osm->p_vendor, attr_array, &num_ports); if (status != IB_SUCCESS) { printf("\nError from osm_vendor_get_all_port_attr (%x)\n", status); return 0; } /* if num_ports is 0 - return 0 */ if (num_ports == 0) { printf("\nNo local ports detected!\n"); return 0; } /* If num_ports is 1, then there is only one possible port to use. * Use it. */ if (num_ports == 1) { printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); return attr_array[0].port_guid; } /* If port_guid is 0 - use the first connected port */ if (port_guid == 0) { for (i = 0; i < num_ports; i++) if (attr_array[i].link_state > IB_LINK_DOWN) break; if (i == num_ports) i = 0; printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid)); return attr_array[i].port_guid; } if (p_osm->subn.opt.daemon) return 0; /* More than one possible port - list all ports and let the user * to choose. */ while (1) { printf("\nChoose a local port number with which to bind:\n\n"); for (i = 0; i < num_ports; i++) /* Print the index + 1 since by convention, port * numbers start with 1 on host channel adapters. */ printf("\t%u: GUID 0x%" PRIx64 ", lid %u, state %s\n", i + 1, cl_ntoh64(attr_array[i].port_guid), attr_array[i].lid, ib_get_port_state_str(attr_array[i].link_state)); printf("\n\t0: Exit\n"); printf("\nEnter choice (0-%u): ", i); fflush(stdout); if (scanf("%u", &choice) <= 0) { char junk[128]; if (scanf("%s", junk) <= 0) printf("\nError: Cannot scan!\n"); } else if (choice == 0) return 0; else if (choice <= num_ports) break; printf("\nError: Lame choice! Please try again.\n"); } choice--; printf("Choice guid=0x%" PRIx64 "\n", cl_ntoh64(attr_array[choice].port_guid)); return attr_array[choice].port_guid; } static void remove_pidfile(void) { if (pidfile) unlink(pidfile); } static int daemonize(osm_opensm_t * osm) { pid_t pid; int fd; FILE *f; fd = open("/dev/null", O_WRONLY); if (fd < 0) { perror("open"); return -1; } if ((pid = fork()) < 0) { perror("fork"); exit(-1); } else if (pid > 0) exit(0); setsid(); if ((pid = fork()) < 0) { perror("fork"); exit(-1); } else if (pid > 0) exit(0); if (pidfile) { remove_pidfile(); f = fopen(pidfile, "w"); if (f) { fprintf(f, "%d\n", getpid()); fclose(f); } else { perror("fopen"); exit(1); } } close(0); close(1); close(2); dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); return 0; } int osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm) { int console_init_flag = 0; if (is_console_enabled(p_opt)) { if (!osm_console_init(p_opt, &p_osm->console, &p_osm->log)) console_init_flag = 1; } /* Sit here forever - dwell or do console i/o & cmds */ while (!osm_exit_flag) { if (console_init_flag) { if (osm_console(p_osm)) console_init_flag = 0; } else cl_thread_suspend(10000); if (osm_usr1_flag) { osm_usr1_flag = 0; osm_log_reopen_file(&(p_osm->log)); } if (osm_hup_flag) { osm_hup_flag = 0; /* a HUP signal should only start a new heavy sweep */ p_osm->subn.force_heavy_sweep = TRUE; osm_opensm_sweep(p_osm); } } if (is_console_enabled(p_opt)) osm_console_exit(&p_osm->console, &p_osm->log); return 0; } #define SET_STR_OPT(opt, val) do { \ opt = val ? strdup(val) : NULL ; \ } while (0) int main(int argc, char *argv[]) { osm_opensm_t osm; osm_subn_opt_t opt; ib_net64_t sm_key = 0; ib_api_status_t status; uint32_t temp, dbg_lvl; boolean_t run_once_flag = FALSE; int32_t vendor_debug = 0; int next_option; char *conf_template = NULL; const char *config_file = NULL; uint32_t val; const char *const short_option = "F:c:i:w:O:f:ed:D:g:l:L:s:t:a:u:m:X:R:zM:U:S:P:Y:ANZ:WBIQvVhoryxp:n:q:k:C:G:H:"; /* In the array below, the 2nd parameter specifies the number of arguments as follows: 0: no arguments 1: argument 2: optional */ const struct option long_option[] = { {"version", 0, NULL, 12}, {"config", 1, NULL, 'F'}, {"create-config", 1, NULL, 'c'}, {"debug", 1, NULL, 'd'}, {"guid", 1, NULL, 'g'}, {"ignore_guids", 1, NULL, 'i'}, {"hop_weights_file", 1, NULL, 'w'}, {"dimn_ports_file", 1, NULL, 'O'}, {"port_search_ordering_file", 1, NULL, 'O'}, {"lmc", 1, NULL, 'l'}, {"sweep", 1, NULL, 's'}, {"timeout", 1, NULL, 't'}, {"verbose", 0, NULL, 'v'}, {"D", 1, NULL, 'D'}, {"log_file", 1, NULL, 'f'}, {"log_limit", 1, NULL, 'L'}, {"erase_log_file", 0, NULL, 'e'}, {"Pconfig", 1, NULL, 'P'}, {"no_part_enforce", 0, NULL, 'N'}, {"part_enforce", 1, NULL, 'Z'}, {"allow_both_pkeys", 0, NULL, 'W'}, {"qos", 0, NULL, 'Q'}, {"qos_policy_file", 1, NULL, 'Y'}, {"congestion_control", 0, NULL, 128}, {"cc_key", 1, NULL, 129}, {"maxsmps", 1, NULL, 'n'}, {"console", 1, NULL, 'q'}, {"V", 0, NULL, 'V'}, {"help", 0, NULL, 'h'}, {"once", 0, NULL, 'o'}, {"reassign_lids", 0, NULL, 'r'}, {"priority", 1, NULL, 'p'}, {"smkey", 1, NULL, 'k'}, {"routing_engine", 1, NULL, 'R'}, {"ucast_cache", 0, NULL, 'A'}, {"connect_roots", 0, NULL, 'z'}, {"lid_matrix_file", 1, NULL, 'M'}, {"lfts_file", 1, NULL, 'U'}, {"sadb_file", 1, NULL, 'S'}, {"root_guid_file", 1, NULL, 'a'}, {"cn_guid_file", 1, NULL, 'u'}, {"io_guid_file", 1, NULL, 'G'}, {"port-shifting", 0, NULL, 11}, {"scatter-ports", 1, NULL, 14}, {"max_reverse_hops", 1, NULL, 'H'}, {"ids_guid_file", 1, NULL, 'm'}, {"guid_routing_order_file", 1, NULL, 'X'}, {"stay_on_fatal", 0, NULL, 'y'}, {"honor_guid2lid", 0, NULL, 'x'}, #ifdef ENABLE_OSM_CONSOLE_LOOPBACK {"console-port", 1, NULL, 'C'}, #endif {"daemon", 0, NULL, 'B'}, {"pidfile", 1, NULL, 'J'}, {"inactive", 0, NULL, 'I'}, #ifdef ENABLE_OSM_PERF_MGR {"perfmgr", 0, NULL, 1}, {"perfmgr_sweep_time_s", 1, NULL, 2}, #endif {"prefix_routes_file", 1, NULL, 3}, {"consolidate_ipv6_snm_req", 0, NULL, 4}, {"do_mesh_analysis", 0, NULL, 5}, {"lash_start_vl", 1, NULL, 6}, {"sm_sl", 1, NULL, 7}, {"retries", 1, NULL, 8}, {"log_prefix", 1, NULL, 9}, {"torus_config", 1, NULL, 10}, {"guid_routing_order_no_scatter", 0, NULL, 13}, {NULL, 0, NULL, 0} /* Required at the end of the array */ }; /* force stdout to be line-buffered */ setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Make sure that the opensm and complib were compiled using same modes (debug/free) */ if (osm_is_debug() != cl_is_debug()) { fprintf(stderr, "ERROR: OpenSM and Complib were compiled using different modes\n"); fprintf(stderr, "ERROR: OpenSM debug:%d Complib debug:%d \n", osm_is_debug(), cl_is_debug()); exit(1); } printf("-------------------------------------------------\n"); printf("%s\n", OSM_VERSION); do { next_option = getopt_long_only(argc, argv, short_option, long_option, NULL); switch (next_option) { case 'F': config_file = optarg; printf("Config file is `%s`:\n", config_file); break; default: break; } } while (next_option != -1); optind = 0; /* reset command line */ if (!config_file) config_file = OSM_DEFAULT_CONFIG_FILE; osm_subn_set_default_opt(&opt); if (osm_subn_parse_conf_file(config_file, &opt) < 0) printf("\nFail to parse config file \'%s\'\n", config_file); printf("Command Line Arguments:\n"); do { next_option = getopt_long_only(argc, argv, short_option, long_option, NULL); switch (next_option) { case 12: /* --version - already printed above */ exit(0); break; case 'F': break; case 'c': conf_template = optarg; printf(" Creating config file template \'%s\'.\n", conf_template); break; case 'o': /* Run once option. */ run_once_flag = TRUE; printf(" Run Once\n"); break; case 'r': /* Reassign LIDs subnet option. */ opt.reassign_lids = TRUE; printf(" Reassign LIDs\n"); break; case 'i': /* Specifies ignore guids file. */ SET_STR_OPT(opt.port_prof_ignore_file, optarg); printf(" Ignore Guids File = %s\n", opt.port_prof_ignore_file); break; case 'w': SET_STR_OPT(opt.hop_weights_file, optarg); printf(" Hop Weights File = %s\n", opt.hop_weights_file); break; case 'O': SET_STR_OPT(opt.port_search_ordering_file, optarg); printf(" Port Search Ordering/Dimension Ports File = %s\n", opt.port_search_ordering_file); break; case 'g': /* Specifies port guid with which to bind. */ opt.guid = cl_hton64(strtoull(optarg, NULL, 16)); if (!opt.guid) /* If guid is 0 - need to display the * guid list */ opt.guid = INVALID_GUID; else printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(opt.guid)); break; case 's': val = strtol(optarg, NULL, 0); /* Check that the number is not too large */ if (((uint32_t) (val * 1000000)) / 1000000 != val) fprintf(stderr, "ERROR: sweep interval given is too large. Ignoring it.\n"); else { opt.sweep_interval = val; printf(" sweep interval = %d\n", opt.sweep_interval); } break; case 't': val = strtoul(optarg, NULL, 0); opt.transaction_timeout = strtoul(optarg, NULL, 0); if (val == 0) fprintf(stderr, "ERROR: timeout value 0 is invalid. Ignoring it.\n"); else { opt.transaction_timeout = val; printf(" Transaction timeout = %u\n", opt.transaction_timeout); } break; case 'n': opt.max_wire_smps = strtoul(optarg, NULL, 0); if (opt.max_wire_smps == 0 || opt.max_wire_smps > 0x7FFFFFFF) opt.max_wire_smps = 0x7FFFFFFF; printf(" Max wire smp's = %d\n", opt.max_wire_smps); break; case 'q': /* * OpenSM interactive console */ if (strcmp(optarg, OSM_DISABLE_CONSOLE) == 0 || strcmp(optarg, OSM_LOCAL_CONSOLE) == 0 #ifdef ENABLE_OSM_CONSOLE_SOCKET || strcmp(optarg, OSM_REMOTE_CONSOLE) == 0 #endif #ifdef ENABLE_OSM_CONSOLE_LOOPBACK || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0 #endif ) SET_STR_OPT(opt.console, optarg); else printf("-console %s option not understood\n", optarg); break; #ifdef ENABLE_OSM_CONSOLE_LOOPBACK case 'C': opt.console_port = strtol(optarg, NULL, 0); break; #endif case 'd': dbg_lvl = strtol(optarg, NULL, 0); printf(" d level = 0x%x\n", dbg_lvl); if (dbg_lvl == 0) { printf(" Debug mode: Ignore Other SMs\n"); opt.ignore_other_sm = TRUE; } else if (dbg_lvl == 1) { printf(" Debug mode: Forcing Single Thread\n"); opt.single_thread = TRUE; } else if (dbg_lvl == 2) { printf(" Debug mode: Force Log Flush\n"); opt.force_log_flush = TRUE; } else if (dbg_lvl == 3) { printf (" Debug mode: Disable multicast support\n"); opt.disable_multicast = TRUE; } /* * NOTE: Debug level 4 used to be used for memory * tracking but this is now deprecated */ else if (dbg_lvl == 5) vendor_debug++; else printf(" OpenSM: Unknown debug option %d" " ignored\n", dbg_lvl); break; case 'l': temp = strtoul(optarg, NULL, 0); if (temp > 7) { fprintf(stderr, "ERROR: LMC must be 7 or less.\n"); return -1; } opt.lmc = (uint8_t) temp; printf(" LMC = %d\n", temp); break; case 'D': opt.log_flags = strtol(optarg, NULL, 0); printf(" verbose option -D = 0x%x\n", opt.log_flags); break; case 'f': SET_STR_OPT(opt.log_file, optarg); break; case 'L': opt.log_max_size = strtoul(optarg, NULL, 0); printf(" Log file max size is %u MBytes\n", opt.log_max_size); break; case 'e': opt.accum_log_file = FALSE; printf(" Creating new log file\n"); break; case 'J': pidfile = optarg; break; case 'P': SET_STR_OPT(opt.partition_config_file, optarg); break; case 'N': opt.no_partition_enforcement = TRUE; break; case 'Z': if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0 || strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0 || strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0 || strcmp(optarg, OSM_PARTITION_ENFORCE_OFF) == 0) { SET_STR_OPT(opt.part_enforce, optarg); if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0) opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH; else if (strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0) opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_IN; else if (strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0) opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OUT; else opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF; } else printf("-part_enforce %s option not understood\n", optarg); break; case 'W': opt.allow_both_pkeys = TRUE; break; case 'Q': opt.qos = TRUE; break; case 'Y': SET_STR_OPT(opt.qos_policy_file, optarg); printf(" QoS policy file \'%s\'\n", optarg); break; case 128: opt.congestion_control = TRUE; break; case 129: opt.cc_key = strtoull(optarg, NULL, 0); printf(" CC Key 0x%" PRIx64 "\n", opt.cc_key); break; case 'y': opt.exit_on_fatal = FALSE; printf(" Staying on fatal initialization errors\n"); break; case 'v': opt.log_flags = (opt.log_flags << 1) | 1; printf(" Verbose option -v (log flags = 0x%X)\n", opt.log_flags); break; case 'V': opt.log_flags = 0xFF; opt.force_log_flush = TRUE; printf(" Big V selected\n"); break; case 'p': temp = strtoul(optarg, NULL, 0); if (temp > 15) { fprintf(stderr, "ERROR: priority must be between 0 and 15\n"); return -1; } opt.sm_priority = (uint8_t) temp; printf(" Priority = %d\n", temp); break; case 'k': sm_key = cl_hton64(strtoull(optarg, NULL, 16)); printf(" SM Key <0x%" PRIx64 ">\n", cl_hton64(sm_key)); opt.sm_key = sm_key; break; case 'R': SET_STR_OPT(opt.routing_engine_names, optarg); printf(" Activate \'%s\' routing engine(s)\n", optarg); break; case 'z': opt.connect_roots = TRUE; printf(" Connect roots option is on\n"); break; case 'A': opt.use_ucast_cache = TRUE; printf(" Unicast routing cache option is on\n"); break; case 'M': SET_STR_OPT(opt.lid_matrix_dump_file, optarg); printf(" Lid matrix dump file is \'%s\'\n", optarg); break; case 'U': SET_STR_OPT(opt.lfts_file, optarg); printf(" LFTs file is \'%s\'\n", optarg); break; case 'S': SET_STR_OPT(opt.sa_db_file, optarg); printf(" SA DB file is \'%s\'\n", optarg); break; case 'a': SET_STR_OPT(opt.root_guid_file, optarg); printf(" Root Guid File: %s\n", opt.root_guid_file); break; case 'u': SET_STR_OPT(opt.cn_guid_file, optarg); printf(" Compute Node Guid File: %s\n", opt.cn_guid_file); break; case 'G': SET_STR_OPT(opt.io_guid_file, optarg); printf(" I/O Node Guid File: %s\n", opt.io_guid_file); break; case 11: opt.port_shifting = TRUE; printf(" Port Shifting is on\n"); break; case 14: opt.scatter_ports = strtol(optarg, NULL, 0); printf(" Scatter Ports is on\n"); break; case 'H': opt.max_reverse_hops = atoi(optarg); printf(" Max Reverse Hops: %d\n", opt.max_reverse_hops); break; case 'm': SET_STR_OPT(opt.ids_guid_file, optarg); printf(" IDs Guid File: %s\n", opt.ids_guid_file); break; case 'X': SET_STR_OPT(opt.guid_routing_order_file, optarg); printf(" GUID Routing Order File: %s\n", opt.guid_routing_order_file); break; case 'x': opt.honor_guid2lid_file = TRUE; printf(" Honor guid2lid file, if possible\n"); break; case 'B': opt.daemon = TRUE; printf(" Daemon mode\n"); break; case 'I': opt.sm_inactive = TRUE; printf(" SM started in inactive state\n"); break; #ifdef ENABLE_OSM_PERF_MGR case 1: opt.perfmgr = TRUE; break; case 2: opt.perfmgr_sweep_time_s = atoi(optarg); break; #endif /* ENABLE_OSM_PERF_MGR */ case 3: SET_STR_OPT(opt.prefix_routes_file, optarg); break; case 4: opt.consolidate_ipv6_snm_req = TRUE; break; case 5: opt.do_mesh_analysis = TRUE; break; case 6: temp = strtoul(optarg, NULL, 0); if (temp >= IB_MAX_NUM_VLS) { fprintf(stderr, "ERROR: starting lash vl must be between 0 and 15\n"); return -1; } opt.lash_start_vl = (uint8_t) temp; printf(" LASH starting VL = %d\n", opt.lash_start_vl); break; case 7: temp = strtoul(optarg, NULL, 0); if (temp > 15) { fprintf(stderr, "ERROR: SM's SL must be between 0 and 15\n"); return -1; } opt.sm_sl = (uint8_t) temp; printf(" SMSL = %d\n", opt.sm_sl); break; case 8: opt.transaction_retries = strtoul(optarg, NULL, 0); printf(" Transaction retries = %u\n", opt.transaction_retries); break; case 9: SET_STR_OPT(opt.log_prefix, optarg); printf("Log prefix = %s\n", opt.log_prefix); break; case 10: SET_STR_OPT(opt.torus_conf_file, optarg); printf("Torus-2QoS config file = %s\n", opt.torus_conf_file); break; case 13: opt.guid_routing_order_no_scatter = TRUE; break; case 'h': case '?': case ':': show_usage(); break; case -1: break; /* done with option */ default: /* something wrong */ abort(); } } while (next_option != -1); if (opt.log_file != NULL) printf(" Log File: %s\n", opt.log_file); /* Done with options description */ printf("-------------------------------------------------\n"); if (conf_template) { status = osm_subn_write_conf_file(conf_template, &opt); if (status) printf("\nosm_subn_write_conf_file failed!\n"); exit(status); } osm_subn_verify_config(&opt); if (vendor_debug) osm_vendor_set_debug(osm.p_vendor, vendor_debug); block_signals(); if (opt.daemon) { if (INVALID_GUID == opt.guid) { fprintf(stderr, "ERROR: Invalid GUID specified; exiting because of daemon mode\n"); return -1; } daemonize(&osm); } complib_init(); status = osm_opensm_init(&osm, &opt); if (status != IB_SUCCESS) { const char *err_str = ib_get_err_str(status); if (err_str == NULL) err_str = "Unknown Error Type"; printf("\nError from osm_opensm_init: %s.\n", err_str); /* We will just exit, and not go to Exit, since we don't want the destroy to be called. */ complib_exit(); return status; } /* If the user didn't specify a GUID on the command line, then get a port GUID value with which to bind. */ if (opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID)) opt.guid = get_port_guid(&osm, opt.guid); if (opt.guid == 0) goto Exit2; status = osm_opensm_init_finish(&osm, &opt); if (status != IB_SUCCESS) { const char *err_str = ib_get_err_str(status); if (err_str == NULL) err_str = "Unknown Error Type"; printf("\nError from osm_opensm_init_finish: %s.\n", err_str); goto Exit2; } status = osm_opensm_bind(&osm, opt.guid); if (status != IB_SUCCESS) { printf("\nError from osm_opensm_bind (0x%X)\n", status); printf ("Perhaps another instance of OpenSM is already running\n"); goto Exit; } setup_signals(); osm_opensm_sweep(&osm); if (run_once_flag == TRUE) { while (!osm_exit_flag) { status = osm_opensm_wait_for_subnet_up(&osm, osm.subn.opt. sweep_interval * 1000000, TRUE); if (!status) osm_exit_flag = 1; } } else { /* * Sit here until signaled to exit */ osm_manager_loop(&opt, &osm); } if (osm.mad_pool.mads_out) { fprintf(stdout, "There are still %u MADs out. Forcing the exit of the OpenSM application...\n", osm.mad_pool.mads_out); #ifdef HAVE_LIBPTHREAD pthread_cond_signal(&osm.stats.cond); #else cl_event_signal(&osm.stats.event); #endif } Exit: osm_opensm_destroy(&osm); Exit2: osm_opensm_destroy_finish(&osm); complib_exit(); remove_pidfile(); exit(0); } opensm-3.3.20/opensm/osm_console_io.c0000644000205000001450000001641312407112060014462 00000000000000/* * Copyright (c) 2005-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2008 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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: * Provide a framework for the Console which decouples the connection * or I/O from the functionality, or commands. * * Extensible - allows a variety of connection methods independent of * the console commands. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #define _GNU_SOURCE /* for getline */ #ifdef ENABLE_OSM_CONSOLE_LOOPBACK #include #include #include #include #endif #include #include #include #include #define FILE_ID OSM_FILE_CONSOLE_IO_C #include #include static int is_local(char *str) { /* convenience - checks if just stdin/stdout */ if (str) return (strcmp(str, OSM_LOCAL_CONSOLE) == 0); return 0; } #ifdef ENABLE_OSM_CONSOLE_LOOPBACK static int is_loopback(char *str) { /* convenience - checks if socket based connection */ if (str) return (strcmp(str, OSM_LOOPBACK_CONSOLE) == 0); return 0; } #else #define is_loopback is_local #endif #ifdef ENABLE_OSM_CONSOLE_SOCKET static int is_remote(char *str) { /* convenience - checks if socket based connection */ if (str) return strcmp(str, OSM_REMOTE_CONSOLE) == 0 || is_loopback(str); return 0; } #else #define is_remote is_loopback #endif int is_console_enabled(osm_subn_opt_t * p_opt) { /* checks for a variety of types of consoles - default is off or 0 */ if (p_opt) return is_local(p_opt->console) || is_loopback(p_opt->console) || is_remote(p_opt->console); return 0; } #ifdef ENABLE_OSM_CONSOLE_LOOPBACK int cio_close(osm_console_t * p_oct, osm_log_t * p_log) { int rtnval = -1; if (p_oct && p_oct->in_fd > 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Console connection closed: %s (%s)\n", p_oct->client_hn, p_oct->client_ip); rtnval = fclose(p_oct->in); p_oct->in_fd = -1; p_oct->out_fd = -1; p_oct->in = NULL; p_oct->out = NULL; } return rtnval; } int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log) { /* returns zero if opened fine, -1 otherwise */ char *p_line; size_t len; ssize_t n; if (p_oct->in_fd >= 0) { FILE *file = fdopen(new_fd, "w+"); fprintf(file, "OpenSM Console connection already in use\n" " kill other session (y/n)? "); fflush(file); p_line = NULL; n = getline(&p_line, &len, file); if (n > 0 && (p_line[0] == 'y' || p_line[0] == 'Y')) cio_close(p_oct, p_log); else { OSM_LOG(p_log, OSM_LOG_INFO, "Console connection aborted: %s (%s) - " "already in use\n", p_oct->client_hn, p_oct->client_ip); fclose(file); free(p_line); return -1; } free(p_line); } p_oct->in_fd = new_fd; p_oct->out_fd = p_oct->in_fd; p_oct->in = fdopen(p_oct->in_fd, "w+"); p_oct->out = p_oct->in; osm_console_prompt(p_oct->out); OSM_LOG(p_log, OSM_LOG_VERBOSE, "Console connection accepted: %s (%s)\n", p_oct->client_hn, p_oct->client_ip); return (p_oct->in == NULL) ? -1 : 0; } /********************************************************************** * Do authentication & authorization check **********************************************************************/ int is_authorized(osm_console_t * p_oct) { /* allowed to use the console? */ p_oct->authorized = !is_remote(p_oct->client_type) || hosts_ctl((char *)OSM_DAEMON_NAME, p_oct->client_hn, p_oct->client_ip, (char *)STRING_UNKNOWN); return p_oct->authorized; } #endif void osm_console_prompt(FILE * out) { if (out) { fprintf(out, "OpenSM %s", OSM_COMMAND_PROMPT); fflush(out); } } int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log) { p_oct->socket = -1; strncpy(p_oct->client_type, opt->console, sizeof(p_oct->client_type)); /* set up the file descriptors for the console */ if (strcmp(opt->console, OSM_LOCAL_CONSOLE) == 0) { p_oct->in = stdin; p_oct->out = stdout; p_oct->in_fd = fileno(stdin); p_oct->out_fd = fileno(stdout); osm_console_prompt(p_oct->out); #ifdef ENABLE_OSM_CONSOLE_LOOPBACK } else if (strcmp(opt->console, OSM_LOOPBACK_CONSOLE) == 0 #ifdef ENABLE_OSM_CONSOLE_SOCKET || strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0 #endif ) { struct sockaddr_in sin; int optval = 1; if ((p_oct->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4B01: Failed to open console socket: %s\n", strerror(errno)); return -1; } if (setsockopt(p_oct->socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4B06: Failed to set socket option: %s\n", strerror(errno)); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons(opt->console_port); #ifdef ENABLE_OSM_CONSOLE_SOCKET if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0) sin.sin_addr.s_addr = htonl(INADDR_ANY); else #endif sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(p_oct->socket, &sin, sizeof(sin)) < 0) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4B02: Failed to bind console socket: %s\n", strerror(errno)); return -1; } if (listen(p_oct->socket, 1) < 0) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4B03: Failed to listen on console socket: %s\n", strerror(errno)); return -1; } signal(SIGPIPE, SIG_IGN); /* protect ourselves from closed pipes */ p_oct->in = NULL; p_oct->out = NULL; p_oct->in_fd = -1; p_oct->out_fd = -1; OSM_LOG(p_log, OSM_LOG_INFO, "Console listening on port %d\n", opt->console_port); #endif } return 0; } /* clean up and release resources */ void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log) { #ifdef ENABLE_OSM_CONSOLE_LOOPBACK cio_close(p_oct, p_log); if (p_oct->socket > 0) { OSM_LOG(p_log, OSM_LOG_INFO, "Closing console socket\n"); close(p_oct->socket); p_oct->socket = -1; } #endif } opensm-3.3.20/opensm/osm_console.c0000644000205000001450000015225112533612011013775 00000000000000/* * Copyright (c) 2005-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. All rights reserved. * Copyright (c) 2010,2011 Mellanox Technologies LTD. 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #define _GNU_SOURCE /* for getline */ #include #include #include #include #include #include #include #ifdef ENABLE_OSM_CONSOLE_LOOPBACK #include #endif #include #include #include #include #include #define FILE_ID OSM_FILE_CONSOLE_C #include #include #include #include extern void osm_update_node_desc(IN osm_opensm_t *osm); struct command { const char *name; void (*help_function) (FILE * out, int detail); void (*parse_function) (char **p_last, osm_opensm_t * p_osm, FILE * out); }; static struct { int on; int delay_s; time_t previous; void (*loop_function) (osm_opensm_t * p_osm, FILE * out); } loop_command = { .on = 0, .delay_s = 2, .loop_function = NULL}; static const struct command console_cmds[]; static char *next_token(char **p_last) { return strtok_r(NULL, " \t\n\r", p_last); } #ifdef ENABLE_OSM_PERF_MGR static char *name_token(char **p_last) { return strtok_r(NULL, "\t\n\r", p_last); } #endif static void help_command(FILE * out, int detail) { int i; fprintf(out, "Supported commands and syntax:\n"); fprintf(out, "help []\n"); /* skip help command */ for (i = 1; console_cmds[i].name; i++) console_cmds[i].help_function(out, 0); } static void help_quit(FILE * out, int detail) { fprintf(out, "quit (not valid in local mode; use ctl-c)\n"); } static void help_loglevel(FILE * out, int detail) { fprintf(out, "loglevel []\n"); if (detail) { fprintf(out, " log-level is OR'ed from the following\n"); fprintf(out, " OSM_LOG_NONE 0x%02X\n", OSM_LOG_NONE); fprintf(out, " OSM_LOG_ERROR 0x%02X\n", OSM_LOG_ERROR); fprintf(out, " OSM_LOG_INFO 0x%02X\n", OSM_LOG_INFO); fprintf(out, " OSM_LOG_VERBOSE 0x%02X\n", OSM_LOG_VERBOSE); fprintf(out, " OSM_LOG_DEBUG 0x%02X\n", OSM_LOG_DEBUG); fprintf(out, " OSM_LOG_FUNCS 0x%02X\n", OSM_LOG_FUNCS); fprintf(out, " OSM_LOG_FRAMES 0x%02X\n", OSM_LOG_FRAMES); fprintf(out, " OSM_LOG_ROUTING 0x%02X\n", OSM_LOG_ROUTING); fprintf(out, " OSM_LOG_SYS 0x%02X\n", OSM_LOG_SYS); fprintf(out, "\n"); fprintf(out, " OSM_LOG_DEFAULT_LEVEL 0x%02X\n", OSM_LOG_DEFAULT_LEVEL); } } static void help_permodlog(FILE * out, int detail) { fprintf(out, "permodlog\n"); } static void help_priority(FILE * out, int detail) { fprintf(out, "priority []\n"); } static void help_resweep(FILE * out, int detail) { fprintf(out, "resweep [heavy|light]\n"); } static void help_reroute(FILE * out, int detail) { fprintf(out, "reroute\n"); if (detail) { fprintf(out, "reroute the fabric\n"); } } static void help_sweep(FILE * out, int detail) { fprintf(out, "sweep [on|off]\n"); if (detail) { fprintf(out, "enable or disable sweeping\n"); fprintf(out, " [on] sweep normally\n"); fprintf(out, " [off] inhibit all sweeping\n"); } } static void help_status(FILE * out, int detail) { fprintf(out, "status [loop]\n"); if (detail) { fprintf(out, " loop -- type \"q\" to quit\n"); } } static void help_logflush(FILE * out, int detail) { fprintf(out, "logflush [on|off] -- toggle opensm.log file flushing\n"); } static void help_querylid(FILE * out, int detail) { fprintf(out, "querylid lid -- print internal information about the lid specified\n"); } static void help_portstatus(FILE * out, int detail) { fprintf(out, "portstatus [ca|switch|router]\n"); if (detail) { fprintf(out, "summarize port status\n"); fprintf(out, " [ca|switch|router] -- limit the results to the node type specified\n"); } } static void help_switchbalance(FILE * out, int detail) { fprintf(out, "switchbalance [verbose] [guid]\n"); if (detail) { fprintf(out, "output switch balancing information\n"); fprintf(out, " [verbose] -- verbose output\n" " [guid] -- limit results to specified guid\n"); } } static void help_lidbalance(FILE * out, int detail) { fprintf(out, "lidbalance [switchguid]\n"); if (detail) { fprintf(out, "output lid balanced forwarding information\n"); fprintf(out, " [switchguid] -- limit results to specified switch guid\n"); } } static void help_dump_conf(FILE *out, int detail) { fprintf(out, "dump_conf\n"); if (detail) { fprintf(out, "dump current opensm configuration\n"); } } static void help_update_desc(FILE *out, int detail) { fprintf(out, "update_desc\n"); if (detail) { fprintf(out, "update node description for all nodes\n"); } } #ifdef ENABLE_OSM_PERF_MGR static void help_perfmgr(FILE * out, int detail) { fprintf(out, "perfmgr(pm) [enable|disable\n" " |clear_counters|dump_counters|print_counters(pc)|print_errors(pe)\n" " |set_rm_nodes|clear_rm_nodes|clear_inactive\n" " |set_query_cpi|clear_query_cpi\n" " |dump_redir|clear_redir\n" " |sweep|sweep_time[seconds]]\n"); if (detail) { fprintf(out, "perfmgr -- print the performance manager state\n"); fprintf(out, " [enable|disable] -- change the perfmgr state\n"); fprintf(out, " [sweep] -- Initiate a sweep of the fabric\n"); fprintf(out, " [sweep_time] -- change the perfmgr sweep time (requires [seconds] option)\n"); fprintf(out, " [clear_counters] -- clear the counters stored\n"); fprintf(out, " [dump_counters [mach]] -- dump the counters (optionally in [mach]ine readable format)\n"); fprintf(out, " [print_counters [][:]] -- print the internal counters\n" " Optionaly limit output by name, guid, or port\n"); fprintf(out, " [pc [][:]] -- same as print_counters\n"); fprintf(out, " [print_errors []] -- print only ports with errors\n" " Optionaly limit output by name or guid\n"); fprintf(out, " [pe []] -- same as print_errors\n"); fprintf(out, " [dump_redir []] -- dump the redirection table\n"); fprintf(out, " [clear_redir []] -- clear the redirection table\n"); fprintf(out, " [[set|clear]_rm_nodes] -- enable/disable the removal of \"inactive\" nodes from the DB\n" " Inactive nodes are those which no longer appear on the fabric\n"); fprintf(out, " [[set|clear]_query_cpi] -- enable/disable PerfMgrGet(ClassPortInfo)\n" " ClassPortInfo indicates hardware support for extended attributes such as PortCountersExtended\n"); fprintf(out, " [clear_inactive] -- Delete inactive nodes from the DB\n"); } } static void help_pm(FILE *out, int detail) { if (detail) help_perfmgr(out, detail); } #endif /* ENABLE_OSM_PERF_MGR */ /* more help routines go here */ static void help_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; int i, found = 0; p_cmd = next_token(p_last); if (!p_cmd) help_command(out, 0); else { for (i = 1; console_cmds[i].name; i++) { if (!strcmp(p_cmd, console_cmds[i].name)) { found = 1; console_cmds[i].help_function(out, 1); break; } } if (!found) { fprintf(out, "%s : Command not found\n\n", p_cmd); help_command(out, 0); } } } static void loglevel_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; int level; p_cmd = next_token(p_last); if (!p_cmd) fprintf(out, "Current log level is 0x%x\n", osm_log_get_level(&p_osm->log)); else { /* Handle x, 0x, and decimal specification of log level */ if (!strncmp(p_cmd, "x", 1)) { p_cmd++; level = strtoul(p_cmd, NULL, 16); } else { if (!strncmp(p_cmd, "0x", 2)) { p_cmd += 2; level = strtoul(p_cmd, NULL, 16); } else level = strtol(p_cmd, NULL, 10); } if ((level >= 0) && (level < 256)) { fprintf(out, "Setting log level to 0x%x\n", level); osm_log_set_level(&p_osm->log, level); } else fprintf(out, "Invalid log level 0x%x\n", level); } } static void permodlog_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { FILE *fp; char buf[1024]; if (p_osm->subn.opt.per_module_logging_file != NULL) { fp = fopen(p_osm->subn.opt.per_module_logging_file, "r"); if (!fp) { if (errno == ENOENT) return; fprintf(out, "fopen(%s) failed: %s\n", p_osm->subn.opt.per_module_logging_file, strerror(errno)); return; } fprintf(out, "Per module logging file: %s\n", p_osm->subn.opt.per_module_logging_file); while (fgets(buf, sizeof buf, fp) != NULL) fprintf(out, "%s", buf); fclose(fp); fprintf(out, "\n"); } } static void priority_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; int priority; p_cmd = next_token(p_last); if (!p_cmd) fprintf(out, "Current sm-priority is %d\n", p_osm->subn.opt.sm_priority); else { priority = strtol(p_cmd, NULL, 0); if (0 > priority || 15 < priority) fprintf(out, "Invalid sm-priority %d; must be between 0 and 15\n", priority); else { fprintf(out, "Setting sm-priority to %d\n", priority); osm_set_sm_priority(&p_osm->sm, (uint8_t)priority); } } } static const char *sm_state_str(int state) { switch (state) { case IB_SMINFO_STATE_DISCOVERING: return "Discovering"; case IB_SMINFO_STATE_STANDBY: return "Standby "; case IB_SMINFO_STATE_NOTACTIVE: return "Not Active "; case IB_SMINFO_STATE_MASTER: return "Master "; } return "UNKNOWN "; } static const char *sa_state_str(osm_sa_state_t state) { switch (state) { case OSM_SA_STATE_INIT: return "Init"; case OSM_SA_STATE_READY: return "Ready"; } return "UNKNOWN"; } static void dump_sms(osm_opensm_t * p_osm, FILE * out) { osm_subn_t *p_subn = &p_osm->subn; osm_remote_sm_t *p_rsm; fprintf(out, "\n Known SMs\n" " ---------\n"); fprintf(out, " Port GUID SM State Priority\n"); fprintf(out, " --------- -------- --------\n"); fprintf(out, " 0x%" PRIx64 " %s %d SELF\n", cl_ntoh64(p_subn->sm_port_guid), sm_state_str(p_subn->sm_state), p_subn->opt.sm_priority); CL_PLOCK_ACQUIRE(p_osm->sm.p_lock); p_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl); while (p_rsm != (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) { fprintf(out, " 0x%" PRIx64 " %s %d\n", cl_ntoh64(p_rsm->smi.guid), sm_state_str(ib_sminfo_get_state(&p_rsm->smi)), ib_sminfo_get_priority(&p_rsm->smi)); p_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item); } CL_PLOCK_RELEASE(p_osm->sm.p_lock); } static void print_status(osm_opensm_t * p_osm, FILE * out) { cl_list_item_t *item; if (out) { const char *re_str; cl_plock_acquire(&p_osm->lock); fprintf(out, " OpenSM Version : %s\n", p_osm->osm_version); fprintf(out, " SM State : %s\n", sm_state_str(p_osm->subn.sm_state)); fprintf(out, " SM Priority : %d\n", p_osm->subn.opt.sm_priority); fprintf(out, " SA State : %s\n", sa_state_str(p_osm->sa.state)); re_str = p_osm->routing_engine_used ? osm_routing_engine_type_str(p_osm->routing_engine_used->type) : osm_routing_engine_type_str(OSM_ROUTING_ENGINE_TYPE_NONE); fprintf(out, " Routing Engine : %s\n", re_str); fprintf(out, " Loaded event plugins :"); if (cl_qlist_head(&p_osm->plugin_list) == cl_qlist_end(&p_osm->plugin_list)) { fprintf(out, " "); } for (item = cl_qlist_head(&p_osm->plugin_list); item != cl_qlist_end(&p_osm->plugin_list); item = cl_qlist_next(item)) fprintf(out, " %s", ((osm_epi_plugin_t *)item)->plugin_name); fprintf(out, "\n"); #ifdef ENABLE_OSM_PERF_MGR fprintf(out, "\n PerfMgr state/sweep state : %s/%s\n", osm_perfmgr_get_state_str(&p_osm->perfmgr), osm_perfmgr_get_sweep_state_str(&p_osm->perfmgr)); #endif fprintf(out, "\n MAD stats\n" " ---------\n" " QP0 MADs outstanding : %u\n" " QP0 MADs outstanding (on wire) : %u\n" " QP0 MADs rcvd : %u\n" " QP0 MADs sent : %u\n" " QP0 unicasts sent : %u\n" " QP0 unknown MADs rcvd : %u\n" " SA MADs outstanding : %u\n" " SA MADs rcvd : %u\n" " SA MADs sent : %u\n" " SA unknown MADs rcvd : %u\n" " SA MADs ignored : %u\n", (uint32_t)p_osm->stats.qp0_mads_outstanding, (uint32_t)p_osm->stats.qp0_mads_outstanding_on_wire, (uint32_t)p_osm->stats.qp0_mads_rcvd, (uint32_t)p_osm->stats.qp0_mads_sent, (uint32_t)p_osm->stats.qp0_unicasts_sent, (uint32_t)p_osm->stats.qp0_mads_rcvd_unknown, (uint32_t)p_osm->stats.sa_mads_outstanding, (uint32_t)p_osm->stats.sa_mads_rcvd, (uint32_t)p_osm->stats.sa_mads_sent, (uint32_t)p_osm->stats.sa_mads_rcvd_unknown, (uint32_t)p_osm->stats.sa_mads_ignored); fprintf(out, "\n Subnet flags\n" " ------------\n" " Sweeping enabled : %d\n" " Sweep interval (seconds) : %u\n" " Ignore existing lfts : %d\n" " Subnet Init errors : %d\n" " In sweep hop 0 : %d\n" " First time master sweep : %d\n" " Coming out of standby : %d\n", p_osm->subn.sweeping_enabled, p_osm->subn.opt.sweep_interval, p_osm->subn.ignore_existing_lfts, p_osm->subn.subnet_initialization_error, p_osm->subn.in_sweep_hop_0, p_osm->subn.first_time_master_sweep, p_osm->subn.coming_out_of_standby); dump_sms(p_osm, out); fprintf(out, "\n"); cl_plock_release(&p_osm->lock); } } static int loop_command_check_time(void) { time_t cur = time(NULL); if ((loop_command.previous + loop_command.delay_s) < cur) { loop_command.previous = cur; return 1; } return 0; } static void status_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; p_cmd = next_token(p_last); if (p_cmd) { if (strcmp(p_cmd, "loop") == 0) { fprintf(out, "Looping on status command...\n"); fflush(out); loop_command.on = 1; loop_command.previous = time(NULL); loop_command.loop_function = print_status; } else { help_status(out, 1); return; } } print_status(p_osm, out); } static void resweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; p_cmd = next_token(p_last); if (!p_cmd || (strcmp(p_cmd, "heavy") != 0 && strcmp(p_cmd, "light") != 0)) { fprintf(out, "Invalid resweep command\n"); help_resweep(out, 1); } else { if (strcmp(p_cmd, "heavy") == 0) p_osm->subn.force_heavy_sweep = TRUE; osm_opensm_sweep(p_osm); } } static void reroute_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { p_osm->subn.force_reroute = TRUE; osm_opensm_sweep(p_osm); } static void sweep_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; p_cmd = next_token(p_last); if (!p_cmd || (strcmp(p_cmd, "on") != 0 && strcmp(p_cmd, "off") != 0)) { fprintf(out, "Invalid sweep command\n"); help_sweep(out, 1); } else { if (strcmp(p_cmd, "on") == 0) p_osm->subn.sweeping_enabled = TRUE; else p_osm->subn.sweeping_enabled = FALSE; } } static void logflush_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; p_cmd = next_token(p_last); if (!p_cmd || (strcmp(p_cmd, "on") != 0 && strcmp(p_cmd, "off") != 0)) { fprintf(out, "Invalid logflush command\n"); help_sweep(out, 1); } else { if (strcmp(p_cmd, "on") == 0) { p_osm->log.flush = TRUE; fflush(p_osm->log.out_port); } else p_osm->log.flush = FALSE; } } static void querylid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { unsigned int p = 0; uint16_t lid = 0; osm_port_t *p_port = NULL; char *p_cmd = next_token(p_last); if (!p_cmd) { fprintf(out, "no LID specified\n"); help_querylid(out, 1); return; } lid = (uint16_t) strtoul(p_cmd, NULL, 0); cl_plock_acquire(&p_osm->lock); p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid); if (!p_port) goto invalid_lid; fprintf(out, "Query results for LID %u\n", lid); fprintf(out, " GUID : 0x%016" PRIx64 "\n" " Node Desc : %s\n" " Node Type : %s\n" " Num Ports : %d\n", cl_ntoh64(p_port->guid), p_port->p_node->print_desc, ib_get_node_type_str(osm_node_get_type(p_port->p_node)), p_port->p_node->node_info.num_ports); if (p_port->p_node->sw) p = 0; else p = 1; for ( /* see above */ ; p < p_port->p_node->physp_tbl_size; p++) { fprintf(out, " Port %u health : %s\n", p, p_port->p_node->physp_table[p]. healthy ? "OK" : "ERROR"); } cl_plock_release(&p_osm->lock); return; invalid_lid: cl_plock_release(&p_osm->lock); fprintf(out, "Invalid lid %d\n", lid); return; } /** * Data structures for the portstatus command */ typedef struct _port_report { struct _port_report *next; uint64_t node_guid; uint8_t port_num; char print_desc[IB_NODE_DESCRIPTION_SIZE + 1]; } port_report_t; static void __tag_port_report(port_report_t ** head, uint64_t node_guid, uint8_t port_num, char *print_desc) { port_report_t *rep = malloc(sizeof(*rep)); if (!rep) return; rep->node_guid = node_guid; rep->port_num = port_num; memcpy(rep->print_desc, print_desc, IB_NODE_DESCRIPTION_SIZE + 1); rep->next = NULL; if (*head) { rep->next = *head; *head = rep; } else *head = rep; } static void __print_port_report(FILE * out, port_report_t * head) { port_report_t *item = head; while (item != NULL) { fprintf(out, " 0x%016" PRIx64 " %d (%s)\n", item->node_guid, item->port_num, item->print_desc); port_report_t *next = item->next; free(item); item = next; } } typedef struct { uint8_t node_type_lim; /* limit the results; 0 == ALL */ uint64_t total_nodes; uint64_t total_ports; uint64_t ports_down; uint64_t ports_active; uint64_t ports_disabled; port_report_t *disabled_ports; uint64_t ports_1X; uint64_t ports_4X; uint64_t ports_8X; uint64_t ports_12X; uint64_t ports_unknown_width; port_report_t *unknown_width_ports; uint64_t ports_unenabled_width; port_report_t *unenabled_width_ports; uint64_t ports_reduced_width; port_report_t *reduced_width_ports; uint64_t ports_sdr; uint64_t ports_ddr; uint64_t ports_qdr; uint64_t ports_fdr10; uint64_t ports_fdr; uint64_t ports_edr; uint64_t ports_unknown_speed; port_report_t *unknown_speed_ports; uint64_t ports_unenabled_speed; port_report_t *unenabled_speed_ports; uint64_t ports_reduced_speed; port_report_t *reduced_speed_ports; } fabric_stats_t; /** * iterator function to get portstatus on each node */ static void __get_stats(cl_map_item_t * const p_map_item, void *context) { fabric_stats_t *fs = (fabric_stats_t *) context; osm_node_t *node = (osm_node_t *) p_map_item; osm_physp_t *physp0; ib_port_info_t *pi0; uint8_t num_ports = osm_node_get_num_physp(node); uint8_t port = 0; /* Skip nodes we are not interested in */ if (fs->node_type_lim != 0 && fs->node_type_lim != node->node_info.node_type) return; fs->total_nodes++; if (osm_node_get_type(node) == IB_NODE_TYPE_SWITCH) { physp0 = osm_node_get_physp_ptr(node, 0); pi0 = &physp0->port_info; } else pi0 = NULL; for (port = 1; port < num_ports; port++) { osm_physp_t *phys = osm_node_get_physp_ptr(node, port); ib_port_info_t *pi = NULL; ib_mlnx_ext_port_info_t *epi = NULL; uint8_t active_speed = 0; uint8_t enabled_speed = 0; uint8_t active_width = 0; uint8_t enabled_width = 0; uint8_t port_state = 0; uint8_t port_phys_state = 0; if (!phys) continue; pi = &phys->port_info; epi = &phys->ext_port_info; if (!pi0) pi0 = pi; active_speed = ib_port_info_get_link_speed_active(pi); enabled_speed = ib_port_info_get_link_speed_enabled(pi); active_width = pi->link_width_active; enabled_width = pi->link_width_enabled; port_state = ib_port_info_get_port_state(pi); port_phys_state = ib_port_info_get_port_phys_state(pi); if (port_state == IB_LINK_DOWN) fs->ports_down++; else if (port_state == IB_LINK_ACTIVE) fs->ports_active++; if (port_phys_state == IB_PORT_PHYS_STATE_DISABLED) { __tag_port_report(&(fs->disabled_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_disabled++; } fs->total_ports++; if (port_state == IB_LINK_DOWN) continue; if (!(active_width & enabled_width)) { __tag_port_report(&(fs->unenabled_width_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unenabled_width++; } else if ((enabled_width ^ active_width) > active_width) { __tag_port_report(&(fs->reduced_width_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_reduced_width++; } /* unenabled speed usually due to problems with force_link_speed */ if (!(active_speed & enabled_speed)) { __tag_port_report(&(fs->unenabled_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unenabled_speed++; } else if ((enabled_speed ^ active_speed) > active_speed) { __tag_port_report(&(fs->reduced_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_reduced_speed++; } switch (active_speed) { case IB_LINK_SPEED_ACTIVE_2_5: fs->ports_sdr++; break; case IB_LINK_SPEED_ACTIVE_5: fs->ports_ddr++; break; case IB_LINK_SPEED_ACTIVE_10: if (!(pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) || ((pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) && !ib_port_info_get_link_speed_ext_active(pi))) { if (epi->link_speed_active & FDR10) fs->ports_fdr10++; else { fs->ports_qdr++; /* check for speed reduced from FDR10 */ if (epi->link_speed_enabled & FDR10) { __tag_port_report(&(fs->reduced_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_reduced_speed++; } } } break; case IB_LINK_SPEED_ACTIVE_EXTENDED: break; default: __tag_port_report(&(fs->unknown_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unknown_speed++; break; } if (pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS && ib_port_info_get_link_speed_ext_sup(pi) && (enabled_speed = ib_port_info_get_link_speed_ext_enabled(pi)) != IB_LINK_SPEED_EXT_DISABLE && active_speed == IB_LINK_SPEED_ACTIVE_10) { active_speed = ib_port_info_get_link_speed_ext_active(pi); if (!(active_speed & enabled_speed)) { __tag_port_report(&(fs->unenabled_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unenabled_speed++; } else if ((enabled_speed ^ active_speed) > active_speed) { __tag_port_report(&(fs->reduced_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_reduced_speed++; } switch (active_speed) { case IB_LINK_SPEED_EXT_ACTIVE_14: fs->ports_fdr++; break; case IB_LINK_SPEED_EXT_ACTIVE_25: fs->ports_edr++; break; case IB_LINK_SPEED_EXT_ACTIVE_NONE: break; default: __tag_port_report(&(fs->unknown_speed_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unknown_speed++; break; } } switch (active_width) { case IB_LINK_WIDTH_ACTIVE_1X: fs->ports_1X++; break; case IB_LINK_WIDTH_ACTIVE_4X: fs->ports_4X++; break; case IB_LINK_WIDTH_ACTIVE_8X: fs->ports_8X++; break; case IB_LINK_WIDTH_ACTIVE_12X: fs->ports_12X++; break; default: __tag_port_report(&(fs->unknown_width_ports), cl_ntoh64(node->node_info.node_guid), port, node->print_desc); fs->ports_unknown_width++; break; } } } static void portstatus_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { fabric_stats_t fs; struct timeval before, after; char *p_cmd; memset(&fs, 0, sizeof(fs)); p_cmd = next_token(p_last); if (p_cmd) { if (strcmp(p_cmd, "ca") == 0) { fs.node_type_lim = IB_NODE_TYPE_CA; } else if (strcmp(p_cmd, "switch") == 0) { fs.node_type_lim = IB_NODE_TYPE_SWITCH; } else if (strcmp(p_cmd, "router") == 0) { fs.node_type_lim = IB_NODE_TYPE_ROUTER; } else { fprintf(out, "Node type not understood\n"); help_portstatus(out, 1); return; } } gettimeofday(&before, NULL); /* for each node in the system gather the stats */ cl_plock_acquire(&p_osm->lock); cl_qmap_apply_func(&(p_osm->subn.node_guid_tbl), __get_stats, (void *)&fs); cl_plock_release(&p_osm->lock); gettimeofday(&after, NULL); /* report the stats */ fprintf(out, "\"%s\" port status:\n", fs.node_type_lim ? ib_get_node_type_str(fs. node_type_lim) : "ALL"); fprintf(out, " %" PRIu64 " port(s) scanned on %" PRIu64 " nodes in %lu us\n", fs.total_ports, fs.total_nodes, after.tv_usec - before.tv_usec); if (fs.ports_down) fprintf(out, " %" PRIu64 " down\n", fs.ports_down); if (fs.ports_active) fprintf(out, " %" PRIu64 " active\n", fs.ports_active); if (fs.ports_1X) fprintf(out, " %" PRIu64 " at 1X\n", fs.ports_1X); if (fs.ports_4X) fprintf(out, " %" PRIu64 " at 4X\n", fs.ports_4X); if (fs.ports_8X) fprintf(out, " %" PRIu64 " at 8X\n", fs.ports_8X); if (fs.ports_12X) fprintf(out, " %" PRIu64 " at 12X\n", fs.ports_12X); if (fs.ports_sdr) fprintf(out, " %" PRIu64 " at 2.5 Gbps\n", fs.ports_sdr); if (fs.ports_ddr) fprintf(out, " %" PRIu64 " at 5.0 Gbps\n", fs.ports_ddr); if (fs.ports_qdr) fprintf(out, " %" PRIu64 " at 10.0 Gbps\n", fs.ports_qdr); if (fs.ports_fdr10) fprintf(out, " %" PRIu64 " at 10.0 Gbps (FDR10)\n", fs.ports_fdr10); if (fs.ports_fdr) fprintf(out, " %" PRIu64 " at 14.0625 Gbps\n", fs.ports_fdr); if (fs.ports_edr) fprintf(out, " %" PRIu64 " at 25.78125 Gbps\n", fs.ports_edr); if (fs.ports_disabled + fs.ports_reduced_speed + fs.ports_reduced_width + fs.ports_unenabled_width + fs.ports_unenabled_speed + fs.ports_unknown_width + fs.ports_unknown_speed > 0) { fprintf(out, "\nPossible issues:\n"); } if (fs.ports_disabled) { fprintf(out, " %" PRIu64 " disabled\n", fs.ports_disabled); __print_port_report(out, fs.disabled_ports); } if (fs.ports_unenabled_speed) { fprintf(out, " %" PRIu64 " with unenabled speed\n", fs.ports_unenabled_speed); __print_port_report(out, fs.unenabled_speed_ports); } if (fs.ports_reduced_speed) { fprintf(out, " %" PRIu64 " with reduced speed\n", fs.ports_reduced_speed); __print_port_report(out, fs.reduced_speed_ports); } if (fs.ports_unknown_speed) { fprintf(out, " %" PRIu64 " with unknown speed\n", fs.ports_unknown_speed); __print_port_report(out, fs.unknown_speed_ports); } if (fs.ports_unenabled_width) { fprintf(out, " %" PRIu64 " with unenabled width\n", fs.ports_unenabled_width); __print_port_report(out, fs.unenabled_width_ports); } if (fs.ports_reduced_width) { fprintf(out, " %" PRIu64 " with reduced width\n", fs.ports_reduced_width); __print_port_report(out, fs.reduced_width_ports); } if (fs.ports_unknown_width) { fprintf(out, " %" PRIu64 " with unknown width\n", fs.ports_unknown_width); __print_port_report(out, fs.unknown_width_ports); } fprintf(out, "\n"); } static void switchbalance_check(osm_opensm_t * p_osm, osm_switch_t * p_sw, FILE * out, int verbose) { uint8_t port_num; uint8_t num_ports; const cl_qmap_t *p_port_tbl; osm_port_t *p_port; osm_physp_t *p_physp; osm_physp_t *p_rem_physp; osm_node_t *p_rem_node; uint32_t count[255]; /* max ports is a uint8_t */ uint8_t output_ports[255]; uint8_t output_ports_count = 0; uint32_t min_count = 0xFFFFFFFF; uint32_t max_count = 0; unsigned int i; memset(count, '\0', sizeof(uint32_t) * 255); /* Count port usage */ p_port_tbl = &p_osm->subn.port_guid_tbl; for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl); p_port != (osm_port_t *) cl_qmap_end(p_port_tbl); p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; /* Don't count switches in port usage */ if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH) continue; osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); if (min_lid_ho == 0 || max_lid_ho == 0) continue; for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) { port_num = osm_switch_get_port_by_lid(p_sw, lid_ho, OSM_NEW_LFT); if (port_num == OSM_NO_PATH) continue; count[port_num]++; } } num_ports = p_sw->num_ports; for (port_num = 1; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); /* if port is down/unhealthy, don't consider it in * min/max calculations */ if (!p_physp || !osm_physp_is_healthy(p_physp) || !osm_physp_get_remote(p_physp)) continue; p_rem_physp = osm_physp_get_remote(p_physp); p_rem_node = osm_physp_get_node_ptr(p_rem_physp); /* If we are directly connected to a CA/router, its not really * up for balancing consideration. */ if (osm_node_get_type(p_rem_node) != IB_NODE_TYPE_SWITCH) continue; output_ports[output_ports_count] = port_num; output_ports_count++; if (count[port_num] < min_count) min_count = count[port_num]; if (count[port_num] > max_count) max_count = count[port_num]; } if (verbose || ((max_count - min_count) > 1)) { if ((max_count - min_count) > 1) fprintf(out, "Unbalanced Switch: 0x%016" PRIx64 " (%s)\n", cl_ntoh64(p_sw->p_node->node_info.node_guid), p_sw->p_node->print_desc); else fprintf(out, "Switch: 0x%016" PRIx64 " (%s)\n", cl_ntoh64(p_sw->p_node->node_info.node_guid), p_sw->p_node->print_desc); for (i = 0; i < output_ports_count; i++) { fprintf(out, "Port %d: %d\n", output_ports[i], count[output_ports[i]]); } } } static void switchbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; uint64_t guid = 0; osm_switch_t *p_sw; int verbose = 0; p_cmd = next_token(p_last); if (p_cmd) { char *p_end; if (strcmp(p_cmd, "verbose") == 0) { verbose++; p_cmd = next_token(p_last); } if (p_cmd) { guid = strtoull(p_cmd, &p_end, 0); if (!guid || *p_end != '\0') { fprintf(out, "Invalid guid specified\n"); help_switchbalance(out, 1); return; } } } cl_plock_acquire(&p_osm->lock); if (guid) { p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid)); if (!p_sw) { fprintf(out, "guid not found\n"); goto lock_exit; } switchbalance_check(p_osm, p_sw, out, verbose); } else { cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl; for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl); p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) switchbalance_check(p_osm, p_sw, out, verbose); } lock_exit: cl_plock_release(&p_osm->lock); return; } static void lidbalance_check(osm_opensm_t * p_osm, osm_switch_t * p_sw, FILE * out) { uint8_t port_num; const cl_qmap_t *p_port_tbl; osm_port_t *p_port; p_port_tbl = &p_osm->subn.port_guid_tbl; for (p_port = (osm_port_t *) cl_qmap_head(p_port_tbl); p_port != (osm_port_t *) cl_qmap_end(p_port_tbl); p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { uint32_t port_count[255]; /* max ports is a uint8_t */ osm_node_t *rem_node[255]; uint32_t rem_node_count; uint32_t rem_count[255]; osm_physp_t *p_physp; osm_physp_t *p_rem_physp; osm_node_t *p_rem_node; uint32_t port_min_count = 0xFFFFFFFF; uint32_t port_max_count = 0; uint32_t rem_min_count = 0xFFFFFFFF; uint32_t rem_max_count = 0; uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; uint8_t num_ports; unsigned int i; /* we only care about non-switches */ if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH) continue; osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); if (min_lid_ho == 0 || max_lid_ho == 0) continue; memset(port_count, '\0', sizeof(uint32_t) * 255); memset(rem_node, '\0', sizeof(osm_node_t *) * 255); rem_node_count = 0; memset(rem_count, '\0', sizeof(uint32_t) * 255); for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) { boolean_t rem_node_found = FALSE; unsigned int indx = 0; port_num = osm_switch_get_port_by_lid(p_sw, lid_ho, OSM_NEW_LFT); if (port_num == OSM_NO_PATH) continue; p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); /* if port is down/unhealthy, can't calculate */ if (!p_physp || !osm_physp_is_healthy(p_physp) || !osm_physp_get_remote(p_physp)) continue; p_rem_physp = osm_physp_get_remote(p_physp); p_rem_node = osm_physp_get_node_ptr(p_rem_physp); /* determine if we've seen this remote node before. * If not, store it. If yes, update the counter */ for (i = 0; i < rem_node_count; i++) { if (rem_node[i] == p_rem_node) { rem_node_found = TRUE; indx = i; break; } } if (!rem_node_found) { rem_node[rem_node_count] = p_rem_node; rem_count[rem_node_count]++; indx = rem_node_count; rem_node_count++; } else rem_count[indx]++; port_count[port_num]++; } if (!rem_node_count) continue; for (i = 0; i < rem_node_count; i++) { if (rem_count[i] < rem_min_count) rem_min_count = rem_count[i]; if (rem_count[i] > rem_max_count) rem_max_count = rem_count[i]; } num_ports = p_sw->num_ports; for (i = 0; i < num_ports; i++) { if (!port_count[i]) continue; if (port_count[i] < port_min_count) port_min_count = port_count[i]; if (port_count[i] > port_max_count) port_max_count = port_count[i]; } /* Output if this CA/router is being forwarded an unbalanced number of * times to a destination. */ if ((rem_max_count - rem_min_count) > 1) { fprintf(out, "Unbalanced Remote Forwarding: Switch 0x%016" PRIx64 " (%s): ", cl_ntoh64(p_sw->p_node->node_info.node_guid), p_sw->p_node->print_desc); if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_CA) fprintf(out, "CA"); else if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_ROUTER) fprintf(out, "Router"); fprintf(out, " 0x%016" PRIx64 " (%s): ", cl_ntoh64(p_port->p_node->node_info.node_guid), p_port->p_node->print_desc); for (i = 0; i < rem_node_count; i++) { fprintf(out, "Dest 0x%016" PRIx64 "(%s) - %u ", cl_ntoh64(rem_node[i]->node_info. node_guid), rem_node[i]->print_desc, rem_count[i]); } fprintf(out, "\n"); } /* Output if this CA/router is being forwarded through a port * an unbalanced number of times. */ if ((port_max_count - port_min_count) > 1) { fprintf(out, "Unbalanced Port Forwarding: Switch 0x%016" PRIx64 " (%s): ", cl_ntoh64(p_sw->p_node->node_info.node_guid), p_sw->p_node->print_desc); if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_CA) fprintf(out, "CA"); else if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_ROUTER) fprintf(out, "Router"); fprintf(out, " 0x%016" PRIx64 " (%s): ", cl_ntoh64(p_port->p_node->node_info.node_guid), p_port->p_node->print_desc); for (i = 0; i < num_ports; i++) { if (!port_count[i]) continue; fprintf(out, "Port %u - %u: ", i, port_count[i]); } fprintf(out, "\n"); } } } static void lidbalance_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; uint64_t guid = 0; osm_switch_t *p_sw; p_cmd = next_token(p_last); if (p_cmd) { char *p_end; guid = strtoull(p_cmd, &p_end, 0); if (!guid || *p_end != '\0') { fprintf(out, "Invalid switchguid specified\n"); help_lidbalance(out, 1); return; } } cl_plock_acquire(&p_osm->lock); if (guid) { p_sw = osm_get_switch_by_guid(&p_osm->subn, cl_hton64(guid)); if (!p_sw) { fprintf(out, "switchguid not found\n"); goto lock_exit; } lidbalance_check(p_osm, p_sw, out); } else { cl_qmap_t *p_sw_guid_tbl = &p_osm->subn.sw_guid_tbl; for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_guid_tbl); p_sw != (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) lidbalance_check(p_osm, p_sw, out); } lock_exit: cl_plock_release(&p_osm->lock); return; } static void dump_conf_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { osm_subn_output_conf(out, &p_osm->subn.opt); } static void update_desc_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { osm_update_node_desc(p_osm); } #ifdef ENABLE_OSM_PERF_MGR static monitored_node_t *find_node_by_name(osm_opensm_t * p_osm, char *nodename) { cl_map_item_t *item; monitored_node_t *node; item = cl_qmap_head(&p_osm->perfmgr.monitored_map); while (item != cl_qmap_end(&p_osm->perfmgr.monitored_map)) { node = (monitored_node_t *)item; if (strcmp(node->name, nodename) == 0) return node; item = cl_qmap_next(item); } return NULL; } static monitored_node_t *find_node_by_guid(osm_opensm_t * p_osm, uint64_t guid) { cl_map_item_t *node; node = cl_qmap_get(&p_osm->perfmgr.monitored_map, guid); if (node != cl_qmap_end(&p_osm->perfmgr.monitored_map)) return (monitored_node_t *)node; return NULL; } static void dump_redir_entry(monitored_node_t *p_mon_node, FILE * out) { int port, redir; /* only display monitored nodes with redirection info */ redir = 0; for (port = (p_mon_node->esp0) ? 0 : 1; port < p_mon_node->num_ports; port++) { if (p_mon_node->port[port].redirection) { if (!redir) { fprintf(out, " Node GUID ESP0 Name\n"); fprintf(out, " --------- ---- ----\n"); fprintf(out, " 0x%" PRIx64 " %d %s\n", p_mon_node->guid, p_mon_node->esp0, p_mon_node->name); fprintf(out, "\n Port Valid LIDs PKey QP PKey Index\n"); fprintf(out, " ---- ----- ---- ---- -- ----------\n"); redir = 1; } fprintf(out, " %d %d %u->%u 0x%x 0x%x %d\n", port, p_mon_node->port[port].valid, cl_ntoh16(p_mon_node->port[port].orig_lid), cl_ntoh16(p_mon_node->port[port].lid), cl_ntoh16(p_mon_node->port[port].pkey), cl_ntoh32(p_mon_node->port[port].qp), p_mon_node->port[port].pkey_ix); } } if (redir) fprintf(out, "\n"); } static void dump_redir(osm_opensm_t * p_osm, char *nodename, FILE * out) { monitored_node_t *p_mon_node; uint64_t guid; if (!p_osm->subn.opt.perfmgr_redir) fprintf(out, "Perfmgr redirection not enabled\n"); fprintf(out, "\nRedirection Table\n"); fprintf(out, "-----------------\n"); cl_plock_acquire(&p_osm->lock); if (nodename) { guid = strtoull(nodename, NULL, 0); if (guid == 0 && errno) p_mon_node = find_node_by_name(p_osm, nodename); else p_mon_node = find_node_by_guid(p_osm, guid); if (p_mon_node) dump_redir_entry(p_mon_node, out); else { if (guid == 0 && errno) fprintf(out, "Node %s not found...\n", nodename); else fprintf(out, "Node 0x%" PRIx64 " not found...\n", guid); } } else { p_mon_node = (monitored_node_t *) cl_qmap_head(&p_osm->perfmgr.monitored_map); while (p_mon_node != (monitored_node_t *) cl_qmap_end(&p_osm->perfmgr.monitored_map)) { dump_redir_entry(p_mon_node, out); p_mon_node = (monitored_node_t *) cl_qmap_next((const cl_map_item_t *)p_mon_node); } } cl_plock_release(&p_osm->lock); } static void clear_redir_entry(monitored_node_t *p_mon_node) { int port; ib_net16_t orig_lid; for (port = (p_mon_node->esp0) ? 0 : 1; port < p_mon_node->num_ports; port++) { if (p_mon_node->port[port].redirection) { orig_lid = p_mon_node->port[port].orig_lid; memset(&p_mon_node->port[port], 0, sizeof(monitored_port_t)); p_mon_node->port[port].valid = TRUE; p_mon_node->port[port].orig_lid = orig_lid; } } } static void clear_redir(osm_opensm_t * p_osm, char *nodename, FILE * out) { monitored_node_t *p_mon_node; uint64_t guid; if (!p_osm->subn.opt.perfmgr_redir) fprintf(out, "Perfmgr redirection not enabled\n"); cl_plock_acquire(&p_osm->lock); if (nodename) { guid = strtoull(nodename, NULL, 0); if (guid == 0 && errno) p_mon_node = find_node_by_name(p_osm, nodename); else p_mon_node = find_node_by_guid(p_osm, guid); if (p_mon_node) clear_redir_entry(p_mon_node); else { if (guid == 0 && errno) fprintf(out, "Node %s not found...\n", nodename); else fprintf(out, "Node 0x%" PRIx64 " not found...\n", guid); } } else { p_mon_node = (monitored_node_t *) cl_qmap_head(&p_osm->perfmgr.monitored_map); while (p_mon_node != (monitored_node_t *) cl_qmap_end(&p_osm->perfmgr.monitored_map)) { clear_redir_entry(p_mon_node); p_mon_node = (monitored_node_t *) cl_qmap_next((const cl_map_item_t *)p_mon_node); } } cl_plock_release(&p_osm->lock); } static void perfmgr_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { char *p_cmd; p_cmd = next_token(p_last); if (p_cmd) { if (strcmp(p_cmd, "enable") == 0) { osm_perfmgr_set_state(&p_osm->perfmgr, PERFMGR_STATE_ENABLED); } else if (strcmp(p_cmd, "disable") == 0) { osm_perfmgr_set_state(&p_osm->perfmgr, PERFMGR_STATE_DISABLE); } else if (strcmp(p_cmd, "clear_counters") == 0) { osm_perfmgr_clear_counters(&p_osm->perfmgr); } else if (strcmp(p_cmd, "set_rm_nodes") == 0) { osm_perfmgr_set_rm_nodes(&p_osm->perfmgr, 1); } else if (strcmp(p_cmd, "clear_rm_nodes") == 0) { osm_perfmgr_set_rm_nodes(&p_osm->perfmgr, 0); } else if (strcmp(p_cmd, "set_query_cpi") == 0) { osm_perfmgr_set_query_cpi(&p_osm->perfmgr, 1); } else if (strcmp(p_cmd, "clear_query_cpi") == 0) { osm_perfmgr_set_query_cpi(&p_osm->perfmgr, 0); } else if (strcmp(p_cmd, "dump_counters") == 0) { p_cmd = next_token(p_last); if (p_cmd && (strcmp(p_cmd, "mach") == 0)) { osm_perfmgr_dump_counters(&p_osm->perfmgr, PERFMGR_EVENT_DB_DUMP_MR); } else { osm_perfmgr_dump_counters(&p_osm->perfmgr, PERFMGR_EVENT_DB_DUMP_HR); } } else if (strcmp(p_cmd, "clear_inactive") == 0) { unsigned cnt = osm_perfmgr_delete_inactive(&p_osm->perfmgr); fprintf(out, "Removed %u nodes from Database\n", cnt); } else if (strcmp(p_cmd, "print_counters") == 0 || strcmp(p_cmd, "pc") == 0) { char *port = NULL; p_cmd = name_token(p_last); if (p_cmd) { port = strchr(p_cmd, ':'); if (port) { *port = '\0'; port++; } } osm_perfmgr_print_counters(&p_osm->perfmgr, p_cmd, out, port, 0); } else if (strcmp(p_cmd, "print_errors") == 0 || strcmp(p_cmd, "pe") == 0) { p_cmd = name_token(p_last); osm_perfmgr_print_counters(&p_osm->perfmgr, p_cmd, out, NULL, 1); } else if (strcmp(p_cmd, "dump_redir") == 0) { p_cmd = name_token(p_last); dump_redir(p_osm, p_cmd, out); } else if (strcmp(p_cmd, "clear_redir") == 0) { p_cmd = name_token(p_last); clear_redir(p_osm, p_cmd, out); } else if (strcmp(p_cmd, "sweep_time") == 0) { p_cmd = next_token(p_last); if (p_cmd) { uint16_t time_s = atoi(p_cmd); if (time_s < 1) fprintf(out, "sweep_time requires a " "positive time period " "(in seconds) to be " "specified\n"); else osm_perfmgr_set_sweep_time_s( &p_osm->perfmgr, time_s); } else { fprintf(out, "sweep_time requires a time period " "(in seconds) to be specified\n"); } } else if (strcmp(p_cmd, "sweep") == 0) { osm_sm_signal(&p_osm->sm, OSM_SIGNAL_PERFMGR_SWEEP); fprintf(out, "sweep initiated...\n"); } else { fprintf(out, "\"%s\" option not found\n", p_cmd); } } else { fprintf(out, "Performance Manager status:\n" "state : %s\n" "sweep state : %s\n" "sweep time : %us\n" "outstanding queries/max : %d/%u\n" "remove missing nodes from DB : %s\n" "query ClassPortInfo : %s\n", osm_perfmgr_get_state_str(&p_osm->perfmgr), osm_perfmgr_get_sweep_state_str(&p_osm->perfmgr), osm_perfmgr_get_sweep_time_s(&p_osm->perfmgr), p_osm->perfmgr.outstanding_queries, p_osm->perfmgr.max_outstanding_queries, osm_perfmgr_get_rm_nodes(&p_osm->perfmgr) ? "TRUE" : "FALSE", osm_perfmgr_get_query_cpi(&p_osm->perfmgr) ? "TRUE" : "FALSE"); } } #endif /* ENABLE_OSM_PERF_MGR */ static void quit_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { cio_close(&p_osm->console, &p_osm->log); } static void help_version(FILE * out, int detail) { fprintf(out, "version -- print the OSM version\n"); } static void version_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { fprintf(out, "%s build %s %s\n", p_osm->osm_version, __DATE__, __TIME__); } /* more parse routines go here */ typedef struct _regexp_list { regex_t exp; struct _regexp_list *next; } regexp_list_t; static void dump_portguid_parse(char **p_last, osm_opensm_t * p_osm, FILE * out) { cl_qmap_t *p_alias_port_guid_tbl; osm_alias_guid_t *p_alias_guid, *p_next_alias_guid; regexp_list_t *p_regexp, *p_head_regexp = NULL; FILE *output = out; while (1) { char *p_cmd = next_token(p_last); if (!p_cmd) break; if (strcmp(p_cmd, "file") == 0) { p_cmd = next_token(p_last); if (p_cmd) { output = fopen(p_cmd, "w+"); if (output == NULL) { fprintf(out, "Could not open file %s: %s\n", p_cmd, strerror(errno)); output = out; } } else fprintf(out, "No file name passed\n"); } else if (!(p_regexp = malloc(sizeof(*p_regexp)))) { fprintf(out, "No memory\n"); break; } else if (regcomp(&p_regexp->exp, p_cmd, REG_NOSUB | REG_EXTENDED) != 0) { fprintf(out, "Cannot parse regular expression \'%s\'." " Skipping\n", p_cmd); free(p_regexp); continue; } else { p_regexp->next = p_head_regexp; p_head_regexp = p_regexp; } } /* Check we have at least one expression to match */ if (p_head_regexp == NULL) { fprintf(out, "No valid expression provided. Aborting\n"); goto Exit; } if (p_osm->sm.p_subn->need_update != 0) { fprintf(out, "Subnet is not ready yet. Try again later\n"); goto Free_and_exit; } /* Subnet doesn't need to be updated so we can carry on */ p_alias_port_guid_tbl = &(p_osm->sm.p_subn->alias_port_guid_tbl); CL_PLOCK_ACQUIRE(p_osm->sm.p_lock); p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_alias_port_guid_tbl); while (p_next_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_alias_port_guid_tbl)) { p_alias_guid = p_next_alias_guid; p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_next_alias_guid->map_item); for (p_regexp = p_head_regexp; p_regexp != NULL; p_regexp = p_regexp->next) if (regexec(&p_regexp->exp, p_alias_guid->p_base_port->p_node->print_desc, 0, NULL, 0) == 0) { fprintf(output, "0x%" PRIxLEAST64 "\n", cl_ntoh64(p_alias_guid->alias_guid)); break; } } CL_PLOCK_RELEASE(p_osm->sm.p_lock); Free_and_exit: for (; p_head_regexp; p_head_regexp = p_regexp) { p_regexp = p_head_regexp->next; regfree(&p_head_regexp->exp); free(p_head_regexp); } Exit: if (output != out) fclose(output); } static void help_dump_portguid(FILE * out, int detail) { fprintf(out, "dump_portguid [file filename] regexp1 [regexp2 [regexp3 ...]] -- Dump port GUID matching a regexp \n"); if (detail) { fprintf(out, "getguidgetguid -- Dump all the port GUID whom node_desc matches one of the provided regexp\n"); fprintf(out, " [file filename] -- Send the port GUID list to the specified file instead of regular output\n"); } } static const struct command console_cmds[] = { {"help", &help_command, &help_parse}, {"quit", &help_quit, &quit_parse}, {"loglevel", &help_loglevel, &loglevel_parse}, {"permodlog", &help_permodlog, &permodlog_parse}, {"priority", &help_priority, &priority_parse}, {"resweep", &help_resweep, &resweep_parse}, {"reroute", &help_reroute, &reroute_parse}, {"sweep", &help_sweep, &sweep_parse}, {"status", &help_status, &status_parse}, {"logflush", &help_logflush, &logflush_parse}, {"querylid", &help_querylid, &querylid_parse}, {"portstatus", &help_portstatus, &portstatus_parse}, {"switchbalance", &help_switchbalance, &switchbalance_parse}, {"lidbalance", &help_lidbalance, &lidbalance_parse}, {"dump_conf", &help_dump_conf, &dump_conf_parse}, {"update_desc", &help_update_desc, &update_desc_parse}, {"version", &help_version, &version_parse}, #ifdef ENABLE_OSM_PERF_MGR {"perfmgr", &help_perfmgr, &perfmgr_parse}, {"pm", &help_pm, &perfmgr_parse}, #endif /* ENABLE_OSM_PERF_MGR */ {"dump_portguid", &help_dump_portguid, &dump_portguid_parse}, {NULL, NULL, NULL} /* end of array */ }; static void parse_cmd_line(char *line, osm_opensm_t * p_osm) { char *p_cmd, *p_last; int i, found = 0; FILE *out = p_osm->console.out; while (isspace(*line)) line++; if (!*line) return; /* find first token which is the command */ p_cmd = strtok_r(line, " \t\n\r", &p_last); if (p_cmd) { for (i = 0; console_cmds[i].name; i++) { if (loop_command.on) { if (!strcmp(p_cmd, "q")) { loop_command.on = 0; } found = 1; break; } if (!strcmp(p_cmd, console_cmds[i].name)) { found = 1; console_cmds[i].parse_function(&p_last, p_osm, out); break; } } if (!found) { fprintf(out, "%s : Command not found\n\n", p_cmd); help_command(out, 0); } } else { fprintf(out, "Error parsing command line: `%s'\n", line); } if (loop_command.on) { fprintf(out, "use \"q\" to quit loop\n"); fflush(out); } } int osm_console(osm_opensm_t * p_osm) { struct pollfd pollfd[2]; char *p_line; size_t len; ssize_t n; struct pollfd *fds; nfds_t nfds; osm_console_t *p_oct = &p_osm->console; pollfd[0].fd = p_oct->socket; pollfd[0].events = POLLIN; pollfd[0].revents = 0; pollfd[1].fd = p_oct->in_fd; pollfd[1].events = POLLIN; pollfd[1].revents = 0; fds = p_oct->socket < 0 ? &pollfd[1] : pollfd; nfds = p_oct->socket < 0 || pollfd[1].fd < 0 ? 1 : 2; if (loop_command.on && loop_command_check_time() && loop_command.loop_function) { if (p_oct->out) { loop_command.loop_function(p_osm, p_oct->out); fflush(p_oct->out); } else { loop_command.on = 0; } } if (poll(fds, nfds, 1000) <= 0) return 0; #ifdef ENABLE_OSM_CONSOLE_LOOPBACK if (pollfd[0].revents & POLLIN) { int new_fd = 0; struct sockaddr_in sin; socklen_t len = sizeof(sin); struct hostent *hent; if ((new_fd = accept(p_oct->socket, &sin, &len)) < 0) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4B04: Failed to accept console socket: %s\n", strerror(errno)); p_oct->in_fd = -1; return 0; } if (inet_ntop (AF_INET, &sin.sin_addr, p_oct->client_ip, sizeof(p_oct->client_ip)) == NULL) { snprintf(p_oct->client_ip, sizeof(p_oct->client_ip), "STRING_UNKNOWN"); } if ((hent = gethostbyaddr((const char *)&sin.sin_addr, sizeof(struct in_addr), AF_INET)) == NULL) { snprintf(p_oct->client_hn, sizeof(p_oct->client_hn), "STRING_UNKNOWN"); } else { snprintf(p_oct->client_hn, sizeof(p_oct->client_hn), "%s", hent->h_name); } if (is_authorized(p_oct)) { cio_open(p_oct, new_fd, &p_osm->log); } else { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4B05: Console connection denied: %s (%s)\n", p_oct->client_hn, p_oct->client_ip); close(new_fd); } return 0; } #endif if (pollfd[1].revents & POLLIN) { p_line = NULL; /* Get input line */ n = getline(&p_line, &len, p_oct->in); if (n > 0) { /* Parse and act on input */ parse_cmd_line(p_line, p_osm); if (!loop_command.on) { osm_console_prompt(p_oct->out); } } else cio_close(p_oct, &p_osm->log); if (p_line) free(p_line); return 0; } /* input fd is closed (hanged up) */ if (pollfd[1].revents & POLLHUP) { #ifdef ENABLE_OSM_CONSOLE_LOOPBACK /* If we are using a socket, we close the current connection */ if (p_oct->socket >= 0) { cio_close(p_oct, &p_osm->log); return 0; } #endif /* If we use a local console, stdin is closed (most probable is pipe ended) * so we close the local console */ return -1; } return 0; } opensm-3.3.20/opensm/osm_db_files.c0000644000205000001450000004515212421444136014112 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 the osm_db interface using simple text files */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_DB_FILES_C #include #include #include /****d* Database/OSM_DB_MAX_LINE_LEN * NAME * OSM_DB_MAX_LINE_LEN * * DESCRIPTION * The Maximal line length allowed for the file * * SYNOPSIS */ #define OSM_DB_MAX_LINE_LEN 1024 /**********/ /****d* Database/OSM_DB_MAX_GUID_LEN * NAME * OSM_DB_MAX_GUID_LEN * * DESCRIPTION * The Maximal word length allowed for the file (guid or lid) * * SYNOPSIS */ #define OSM_DB_MAX_GUID_LEN 32 /**********/ /****s* OpenSM: Database/osm_db_domain_imp * NAME * osm_db_domain_imp * * DESCRIPTION * An implementation for domain of the database based on text files and * hash tables. * * SYNOPSIS */ typedef struct osm_db_domain_imp { char *file_name; st_table *p_hash; cl_spinlock_t lock; boolean_t dirty; } osm_db_domain_imp_t; /* * FIELDS * * SEE ALSO * osm_db_domain_t *********/ /****s* OpenSM: Database/osm_db_imp_t * NAME * osm_db_imp_t * * DESCRIPTION * An implementation for file based database * * SYNOPSIS */ typedef struct osm_db_imp { const char *db_dir_name; } osm_db_imp_t; /* * FIELDS * * db_dir_name * The directory holding the database * * SEE ALSO * osm_db_t *********/ void osm_db_construct(IN osm_db_t * p_db) { memset(p_db, 0, sizeof(osm_db_t)); cl_list_construct(&p_db->domains); } void osm_db_domain_destroy(IN osm_db_domain_t * p_db_domain) { osm_db_domain_imp_t *p_domain_imp; p_domain_imp = (osm_db_domain_imp_t *) p_db_domain->p_domain_imp; osm_db_clear(p_db_domain); cl_spinlock_destroy(&p_domain_imp->lock); st_free_table(p_domain_imp->p_hash); free(p_domain_imp->file_name); free(p_domain_imp); } void osm_db_destroy(IN osm_db_t * p_db) { osm_db_domain_t *p_domain; while ((p_domain = cl_list_remove_head(&p_db->domains)) != NULL) { osm_db_domain_destroy(p_domain); free(p_domain); } cl_list_destroy(&p_db->domains); free(p_db->p_db_imp); } int osm_db_init(IN osm_db_t * p_db, IN osm_log_t * p_log) { osm_db_imp_t *p_db_imp; struct stat dstat; OSM_LOG_ENTER(p_log); p_db_imp = malloc(sizeof(osm_db_imp_t)); if (!p_db_imp) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6100: " "Failed to allocate db memory\n"); return -1; } p_db_imp->db_dir_name = getenv("OSM_CACHE_DIR"); if (!p_db_imp->db_dir_name || !(*p_db_imp->db_dir_name)) p_db_imp->db_dir_name = OSM_DEFAULT_CACHE_DIR; /* Create the directory if it doesn't exist */ /* There is a difference in creating directory between windows and linux */ #ifdef __WIN__ { int ret; ret = SHCreateDirectoryEx(NULL, p_db_imp->db_dir_name, NULL); if (ret != ERROR_SUCCESS && ret != ERROR_ALREADY_EXISTS && ret != ERROR_FILE_EXISTS) goto err; } #else /* __WIN__ */ /* make sure the directory exists */ if (lstat(p_db_imp->db_dir_name, &dstat)) { if (mkdir(p_db_imp->db_dir_name, 0755)) goto err; } #endif p_db->p_log = p_log; p_db->p_db_imp = (void *)p_db_imp; cl_list_init(&p_db->domains, 5); OSM_LOG_EXIT(p_log); return 0; err: OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6101: " "Failed to create the db directory:%s\n", p_db_imp->db_dir_name); free(p_db_imp); OSM_LOG_EXIT(p_log); return 1; } osm_db_domain_t *osm_db_domain_init(IN osm_db_t * p_db, IN const char *domain_name) { osm_db_domain_t *p_domain; osm_db_domain_imp_t *p_domain_imp; size_t path_len; osm_log_t *p_log = p_db->p_log; FILE *p_file; OSM_LOG_ENTER(p_log); /* allocate a new domain object */ p_domain = malloc(sizeof(osm_db_domain_t)); if (p_domain == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610C: " "Failed to allocate domain memory\n"); goto Exit; } p_domain_imp = malloc(sizeof(osm_db_domain_imp_t)); if (p_domain_imp == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610D: " "Failed to allocate domain_imp memory\n"); free(p_domain); p_domain = NULL; goto Exit; } path_len = strlen(((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name) + strlen(domain_name) + 2; /* set the domain file name */ p_domain_imp->file_name = malloc(path_len); if (p_domain_imp->file_name == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610E: " "Failed to allocate file_name memory\n"); free(p_domain_imp); free(p_domain); p_domain = NULL; goto Exit; } snprintf(p_domain_imp->file_name, path_len, "%s/%s", ((osm_db_imp_t *) p_db->p_db_imp)->db_dir_name, domain_name); /* make sure the file exists - or exit if not writable */ p_file = fopen(p_domain_imp->file_name, "a+"); if (!p_file) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6102: " "Failed to open the db file:%s\n", p_domain_imp->file_name); free(p_domain_imp); free(p_domain); p_domain = NULL; goto Exit; } fclose(p_file); /* initialize the hash table object */ p_domain_imp->p_hash = st_init_strtable(); CL_ASSERT(p_domain_imp->p_hash != NULL); p_domain_imp->dirty = FALSE; p_domain->p_db = p_db; cl_list_insert_tail(&p_db->domains, p_domain); p_domain->p_domain_imp = p_domain_imp; cl_spinlock_construct(&p_domain_imp->lock); cl_spinlock_init(&p_domain_imp->lock); Exit: OSM_LOG_EXIT(p_log); return p_domain; } int osm_db_restore(IN osm_db_domain_t * p_domain) { osm_log_t *p_log = p_domain->p_db->p_log; osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; FILE *p_file; int status; char sLine[OSM_DB_MAX_LINE_LEN]; boolean_t before_key; char *p_first_word, *p_rest_of_line, *p_last; char *p_key = NULL; char *p_prev_val = NULL, *p_accum_val = NULL; char *endptr = NULL; unsigned int line_num; OSM_LOG_ENTER(p_log); /* take the lock on the domain */ cl_spinlock_acquire(&p_domain_imp->lock); /* open the file - read mode */ p_file = fopen(p_domain_imp->file_name, "r"); if (!p_file) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6103: " "Failed to open the db file:%s\n", p_domain_imp->file_name); status = 1; goto Exit; } /* parse the file allocating new hash tables as required */ /* states: before_key (0) -> in_key (1) before_key: if a word on the first byte - it is the key. state=in_key the rest of the line is start of the value. in_key: unless the line is empty - add it (with newlines) to the value. if empty: state=before_key */ status = 0; before_key = TRUE; line_num = 0; /* if we got to EOF in the middle of a key we add a last newline */ while ((fgets(sLine, OSM_DB_MAX_LINE_LEN, p_file) != NULL) || ((before_key == FALSE) && strcpy(sLine, "\n")) ) { line_num++; if (before_key) { if ((sLine[0] != ' ') && (sLine[0] != '\t') && (sLine[0] != '\n')) { /* we got a new key */ before_key = FALSE; /* handle the key */ p_first_word = strtok_r(sLine, " \t\n", &p_last); if (!p_first_word) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6104: " "Failed to get key from line:%u : %s (file:%s)\n", line_num, sLine, p_domain_imp->file_name); status = 1; goto EndParsing; } if (strlen(p_first_word) > OSM_DB_MAX_GUID_LEN) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610A: " "Illegal key from line:%u : %s (file:%s)\n", line_num, sLine, p_domain_imp->file_name); status = 1; goto EndParsing; } p_key = malloc(sizeof(char) * (strlen(p_first_word) + 1)); strcpy(p_key, p_first_word); p_rest_of_line = strtok_r(NULL, "\n", &p_last); if (p_rest_of_line != NULL) { p_accum_val = malloc(sizeof(char) * (strlen(p_rest_of_line) + 1)); strcpy(p_accum_val, p_rest_of_line); } else { p_accum_val = malloc(2); strcpy(p_accum_val, "\0"); } } else if (sLine[0] != '\n') { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6105: " "How did we get here? line:%u : %s (file:%s)\n", line_num, sLine, p_domain_imp->file_name); status = 1; goto EndParsing; } } /* before key */ else { /* we already have a key */ if (sLine[0] == '\n') { /* got an end of key */ before_key = TRUE; /* make sure the key was not previously used */ if (st_lookup(p_domain_imp->p_hash, (st_data_t) p_key, (void *)&p_prev_val)) { /* if previously used we ignore this guid */ OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6106: " "Key:%s already exists in:%s with value:%s." " Removing it\n", p_key, p_domain_imp->file_name, p_prev_val); free(p_key); p_key = NULL; free(p_accum_val); p_accum_val = NULL; continue; } else { p_prev_val = NULL; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Got key:%s value:%s\n", p_key, p_accum_val); /* check that the key is a number */ if (!strtouq(p_key, &endptr, 0) && *endptr != '\0') { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 610B: " "Key:%s is invalid\n", p_key); free(p_key); p_key = NULL; free(p_accum_val); p_accum_val = NULL; } else { /* store our key and value */ st_insert(p_domain_imp->p_hash, (st_data_t) p_key, (st_data_t) p_accum_val); } } else { /* accumulate into the value */ p_prev_val = p_accum_val; p_accum_val = malloc(strlen(p_prev_val) + strlen(sLine) + 1); strcpy(p_accum_val, p_prev_val); free(p_prev_val); p_prev_val = NULL; strcat(p_accum_val, sLine); } } /* in key */ } /* while lines or last line */ EndParsing: fclose(p_file); Exit: cl_spinlock_release(&p_domain_imp->lock); OSM_LOG_EXIT(p_log); return status; } static int dump_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) { FILE *p_file = (FILE *) arg; char *p_key = (char *)key; char *p_val = (char *)val; fprintf(p_file, "%s %s\n\n", p_key, p_val); return ST_CONTINUE; } int osm_db_store(IN osm_db_domain_t * p_domain, IN boolean_t fsync_high_avail_files) { osm_log_t *p_log = p_domain->p_db->p_log; osm_db_domain_imp_t *p_domain_imp; FILE *p_file = NULL; int fd, status = 0; char *p_tmp_file_name = NULL; OSM_LOG_ENTER(p_log); p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; p_tmp_file_name = malloc(sizeof(char) * (strlen(p_domain_imp->file_name) + 8)); if (!p_tmp_file_name) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6113: " "Failed to allocate memory for temporary file name\n"); goto Exit2; } strcpy(p_tmp_file_name, p_domain_imp->file_name); strcat(p_tmp_file_name, ".tmp"); cl_spinlock_acquire(&p_domain_imp->lock); if (p_domain_imp->dirty == FALSE) goto Exit; /* open up the output file */ p_file = fopen(p_tmp_file_name, "w"); if (!p_file) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6107: " "Failed to open the db file:%s for writing: err:%s\n", p_domain_imp->file_name, strerror(errno)); status = 1; goto Exit; } st_foreach(p_domain_imp->p_hash, dump_tbl_entry, (st_data_t) p_file); if (fsync_high_avail_files) { if (fflush(p_file) == 0) { fd = fileno(p_file); if (fd != -1) { if (fsync(fd) == -1) OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6110: fsync() failed (%s) for %s\n", strerror(errno), p_domain_imp->file_name); } else OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6111: " "fileno() failed for %s\n", p_domain_imp->file_name); } else OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6112: " "fflush() failed (%s) for %s\n", strerror(errno), p_domain_imp->file_name); } fclose(p_file); status = rename(p_tmp_file_name, p_domain_imp->file_name); if (status) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 6108: " "Failed to rename the db file to:%s (err:%s)\n", p_domain_imp->file_name, strerror(errno)); goto Exit; } p_domain_imp->dirty = FALSE; Exit: cl_spinlock_release(&p_domain_imp->lock); free(p_tmp_file_name); Exit2: OSM_LOG_EXIT(p_log); return status; } /* simply de-allocate the key and the value and return the code that makes the st_foreach delete the entry */ static int clear_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) { free((char *)key); free((char *)val); return ST_DELETE; } int osm_db_clear(IN osm_db_domain_t * p_domain) { osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; cl_spinlock_acquire(&p_domain_imp->lock); st_foreach(p_domain_imp->p_hash, clear_tbl_entry, (st_data_t) NULL); cl_spinlock_release(&p_domain_imp->lock); return 0; } static int get_key_of_tbl_entry(st_data_t key, st_data_t val, st_data_t arg) { cl_list_t *p_list = (cl_list_t *) arg; cl_list_insert_tail(p_list, (void *)key); return ST_CONTINUE; } int osm_db_keys(IN osm_db_domain_t * p_domain, OUT cl_list_t * p_key_list) { osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; cl_spinlock_acquire(&p_domain_imp->lock); st_foreach(p_domain_imp->p_hash, get_key_of_tbl_entry, (st_data_t) p_key_list); cl_spinlock_release(&p_domain_imp->lock); return 0; } char *osm_db_lookup(IN osm_db_domain_t * p_domain, IN char *p_key) { osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; char *p_val = NULL; cl_spinlock_acquire(&p_domain_imp->lock); if (!st_lookup(p_domain_imp->p_hash, (st_data_t) p_key, (void *)&p_val)) p_val = NULL; cl_spinlock_release(&p_domain_imp->lock); return p_val; } int osm_db_update(IN osm_db_domain_t * p_domain, IN char *p_key, IN char *p_val) { osm_log_t *p_log = p_domain->p_db->p_log; osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; char *p_prev_val = NULL; char *p_new_key; char *p_new_val; cl_spinlock_acquire(&p_domain_imp->lock); if (st_lookup(p_domain_imp->p_hash, (st_data_t) p_key, (void *)&p_prev_val)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Key:%s previously exists in:%s with value:%s\n", p_key, p_domain_imp->file_name, p_prev_val); p_new_key = p_key; /* same key, same value - nothing to update */ if (p_prev_val && !strcmp(p_val, p_prev_val)) goto Exit; } else { /* need to allocate the key */ p_new_key = malloc(sizeof(char) * (strlen(p_key) + 1)); strcpy(p_new_key, p_key); } /* need to arange a new copy of the value */ p_new_val = malloc(sizeof(char) * (strlen(p_val) + 1)); strcpy(p_new_val, p_val); st_insert(p_domain_imp->p_hash, (st_data_t) p_new_key, (st_data_t) p_new_val); if (p_prev_val) free(p_prev_val); p_domain_imp->dirty = TRUE; Exit: cl_spinlock_release(&p_domain_imp->lock); return 0; } int osm_db_delete(IN osm_db_domain_t * p_domain, IN char *p_key) { osm_log_t *p_log = p_domain->p_db->p_log; osm_db_domain_imp_t *p_domain_imp = (osm_db_domain_imp_t *) p_domain->p_domain_imp; char *p_prev_val = NULL; int res; OSM_LOG_ENTER(p_log); cl_spinlock_acquire(&p_domain_imp->lock); if (st_delete(p_domain_imp->p_hash, (void *)&p_key, (void *)&p_prev_val)) { if (st_lookup(p_domain_imp->p_hash, (st_data_t) p_key, (void *)&p_prev_val)) { OSM_LOG(p_log, OSM_LOG_ERROR, "key:%s still exists in:%s with value:%s\n", p_key, p_domain_imp->file_name, p_prev_val); res = 1; } else { free(p_key); free(p_prev_val); p_domain_imp->dirty = TRUE; res = 0; } } else { OSM_LOG(p_log, OSM_LOG_DEBUG, "fail to find key:%s. delete failed\n", p_key); res = 1; } cl_spinlock_release(&p_domain_imp->lock); OSM_LOG_EXIT(p_log); return res; } #ifdef TEST_OSMDB #include #include int main(int argc, char **argv) { osm_db_t db; osm_log_t log; osm_db_domain_t *p_dbd; cl_list_t keys; cl_list_iterator_t kI; char *p_key; char *p_val; int i; cl_list_construct(&keys); cl_list_init(&keys, 10); osm_log_init_v2(&log, TRUE, 0xff, "/var/log/osm_db_test.log", 0, FALSE); osm_db_construct(&db); if (osm_db_init(&db, &log)) { printf("db init failed\n"); exit(1); } p_dbd = osm_db_domain_init(&db, "lid_by_guid"); if (!p_dbd) { printf("db domain init failed\n"); exit(1); } if (osm_db_restore(p_dbd)) { printf("failed to restore\n"); } if (osm_db_keys(p_dbd, &keys)) { printf("failed to get keys\n"); } else { kI = cl_list_head(&keys); while (kI != cl_list_end(&keys)) { p_key = cl_list_obj(kI); kI = cl_list_next(kI); p_val = osm_db_lookup(p_dbd, p_key); printf("key = %s val = %s\n", p_key, p_val); } } cl_list_remove_all(&keys); /* randomly add and remove numbers */ for (i = 0; i < 10; i++) { int k; float v; int is_add; char val_buf[16]; char key_buf[16]; k = floor(1.0 * rand() / RAND_MAX * 100); v = rand(); sprintf(key_buf, "%u", k); sprintf(val_buf, "%u", v); is_add = (rand() < RAND_MAX / 2); if (is_add) { osm_db_update(p_dbd, key_buf, val_buf); } else { osm_db_delete(p_dbd, key_buf); } } if (osm_db_keys(p_dbd, &keys)) { printf("failed to get keys\n"); } else { kI = cl_list_head(&keys); while (kI != cl_list_end(&keys)) { p_key = cl_list_obj(kI); kI = cl_list_next(kI); p_val = osm_db_lookup(p_dbd, p_key); printf("key = %s val = %s\n", p_key, p_val); } } if (osm_db_store(p_dbd, FALSE)) printf("failed to store\n"); osm_db_destroy(&db); cl_list_destroy(&keys); } #endif opensm-3.3.20/opensm/osm_db_pack.c0000644000205000001450000001762612272264653013743 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_DB_PACK_C #include static inline void pack_guid(uint64_t guid, char *p_guid_str) { sprintf(p_guid_str, "0x%016" PRIx64, guid); } static inline uint64_t unpack_guid(char *p_guid_str) { return strtoull(p_guid_str, NULL, 0); } static inline void pack_lids(uint16_t min_lid, uint16_t max_lid, char *lid_str) { sprintf(lid_str, "0x%04x 0x%04x", min_lid, max_lid); } static inline int unpack_lids(IN char *p_lid_str, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid) { unsigned long tmp; char *p_next; char *p_num; char lids_str[24]; strncpy(lids_str, p_lid_str, 23); lids_str[23] = '\0'; p_num = strtok_r(lids_str, " \t", &p_next); if (!p_num) return 1; tmp = strtoul(p_num, NULL, 0); if (tmp >= 0xC000) return 1; *p_min_lid = (uint16_t) tmp; p_num = strtok_r(NULL, " \t", &p_next); if (!p_num) return 1; tmp = strtoul(p_num, NULL, 0); if (tmp >= 0xC000) return 1; *p_max_lid = (uint16_t) tmp; return 0; } static inline void pack_mkey(uint64_t mkey, char *p_mkey_str) { sprintf(p_mkey_str, "0x%016" PRIx64, mkey); } static inline uint64_t unpack_mkey(char *p_mkey_str) { return strtoull(p_mkey_str, NULL, 0); } static inline void pack_neighbor(uint64_t guid, uint8_t portnum, char *p_str) { sprintf(p_str, "0x%016" PRIx64 ":%u", guid, portnum); } static inline int unpack_neighbor(char *p_str, uint64_t *guid, uint8_t *portnum) { char tmp_str[24]; char *p_num, *p_next; unsigned long tmp_port; strncpy(tmp_str, p_str, 23); tmp_str[23] = '\0'; p_num = strtok_r(tmp_str, ":", &p_next); if (!p_num) return 1; if (guid) *guid = strtoull(p_num, NULL, 0); p_num = strtok_r(NULL, ":", &p_next); if (!p_num) return 1; if (portnum) { tmp_port = strtoul(p_num, NULL, 0); CL_ASSERT(tmp_port < 0x100); *portnum = (uint8_t) tmp_port; } return 0; } int osm_db_guid2lid_guids(IN osm_db_domain_t * p_g2l, OUT cl_qlist_t * p_guid_list) { char *p_key; cl_list_t keys; osm_db_guid_elem_t *p_guid_elem; cl_list_construct(&keys); cl_list_init(&keys, 10); if (osm_db_keys(p_g2l, &keys)) return 1; while ((p_key = cl_list_remove_head(&keys)) != NULL) { p_guid_elem = (osm_db_guid_elem_t *) malloc(sizeof(osm_db_guid_elem_t)); CL_ASSERT(p_guid_elem != NULL); p_guid_elem->guid = unpack_guid(p_key); cl_qlist_insert_head(p_guid_list, &p_guid_elem->item); } cl_list_destroy(&keys); return 0; } int osm_db_guid2lid_get(IN osm_db_domain_t * p_g2l, IN uint64_t guid, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid) { char guid_str[20]; char *p_lid_str; uint16_t min_lid, max_lid; pack_guid(guid, guid_str); p_lid_str = osm_db_lookup(p_g2l, guid_str); if (!p_lid_str) return 1; if (unpack_lids(p_lid_str, &min_lid, &max_lid)) return 1; if (p_min_lid) *p_min_lid = min_lid; if (p_max_lid) *p_max_lid = max_lid; return 0; } int osm_db_guid2lid_set(IN osm_db_domain_t * p_g2l, IN uint64_t guid, IN uint16_t min_lid, IN uint16_t max_lid) { char guid_str[20]; char lid_str[16]; pack_guid(guid, guid_str); pack_lids(min_lid, max_lid, lid_str); return osm_db_update(p_g2l, guid_str, lid_str); } int osm_db_guid2lid_delete(IN osm_db_domain_t * p_g2l, IN uint64_t guid) { char guid_str[20]; pack_guid(guid, guid_str); return osm_db_delete(p_g2l, guid_str); } int osm_db_guid2mkey_guids(IN osm_db_domain_t * p_g2m, OUT cl_qlist_t * p_guid_list) { char *p_key; cl_list_t keys; osm_db_guid_elem_t *p_guid_elem; cl_list_construct(&keys); cl_list_init(&keys, 10); if (osm_db_keys(p_g2m, &keys)) return 1; while ((p_key = cl_list_remove_head(&keys)) != NULL) { p_guid_elem = (osm_db_guid_elem_t *) malloc(sizeof(osm_db_guid_elem_t)); CL_ASSERT(p_guid_elem != NULL); p_guid_elem->guid = unpack_guid(p_key); cl_qlist_insert_head(p_guid_list, &p_guid_elem->item); } cl_list_destroy(&keys); return 0; } int osm_db_guid2mkey_get(IN osm_db_domain_t * p_g2m, IN uint64_t guid, OUT uint64_t * p_mkey) { char guid_str[20]; char *p_mkey_str; pack_guid(guid, guid_str); p_mkey_str = osm_db_lookup(p_g2m, guid_str); if (!p_mkey_str) return 1; if (p_mkey) *p_mkey = unpack_mkey(p_mkey_str); return 0; } int osm_db_guid2mkey_set(IN osm_db_domain_t * p_g2m, IN uint64_t guid, IN uint64_t mkey) { char guid_str[20]; char mkey_str[20]; pack_guid(guid, guid_str); pack_mkey(mkey, mkey_str); return osm_db_update(p_g2m, guid_str, mkey_str); } int osm_db_guid2mkey_delete(IN osm_db_domain_t * p_g2m, IN uint64_t guid) { char guid_str[20]; pack_guid(guid, guid_str); return osm_db_delete(p_g2m, guid_str); } int osm_db_neighbor_guids(IN osm_db_domain_t * p_neighbor, OUT cl_qlist_t * p_neighbor_list) { char *p_key; cl_list_t keys; osm_db_neighbor_elem_t *p_neighbor_elem; cl_list_construct(&keys); cl_list_init(&keys, 10); if (osm_db_keys(p_neighbor, &keys)) return 1; while ((p_key = cl_list_remove_head(&keys)) != NULL) { p_neighbor_elem = (osm_db_neighbor_elem_t *) malloc(sizeof(osm_db_neighbor_elem_t)); CL_ASSERT(p_neighbor_elem != NULL); unpack_neighbor(p_key, &p_neighbor_elem->guid, &p_neighbor_elem->portnum); cl_qlist_insert_head(p_neighbor_list, &p_neighbor_elem->item); } cl_list_destroy(&keys); return 0; } int osm_db_neighbor_get(IN osm_db_domain_t * p_neighbor, IN uint64_t guid1, IN uint8_t portnum1, OUT uint64_t * p_guid2, OUT uint8_t * p_portnum2) { char neighbor_str[24]; char *p_other_str; uint64_t temp_guid; uint8_t temp_portnum; pack_neighbor(guid1, portnum1, neighbor_str); p_other_str = osm_db_lookup(p_neighbor, neighbor_str); if (!p_other_str) return 1; if (unpack_neighbor(p_other_str, &temp_guid, &temp_portnum)) return 1; if (p_guid2) *p_guid2 = temp_guid; if (p_portnum2) *p_portnum2 = temp_portnum; return 0; } int osm_db_neighbor_set(IN osm_db_domain_t * p_neighbor, IN uint64_t guid1, IN uint8_t portnum1, IN uint64_t guid2, IN uint8_t portnum2) { char n1_str[24], n2_str[24]; pack_neighbor(guid1, portnum1, n1_str); pack_neighbor(guid2, portnum2, n2_str); return osm_db_update(p_neighbor, n1_str, n2_str); } int osm_db_neighbor_delete(IN osm_db_domain_t * p_neighbor, IN uint64_t guid, IN uint8_t portnum) { char n_str[24]; pack_neighbor(guid, portnum, n_str); return osm_db_delete(p_neighbor, n_str); } opensm-3.3.20/opensm/osm_drop_mgr.c0000644000205000001450000004465312604753736014175 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_drop_mgr_t. * This object represents the Drop Manager object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_DROP_MGR_C #include #include #include #include #include #include #include #include #include #include static void drop_mgr_remove_router(osm_sm_t * sm, IN const ib_net64_t portguid) { osm_router_t *p_rtr; cl_qmap_t *p_rtr_guid_tbl; p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl; p_rtr = (osm_router_t *) cl_qmap_remove(p_rtr_guid_tbl, portguid); if (p_rtr != (osm_router_t *) cl_qmap_end(p_rtr_guid_tbl)) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Cleaned router for port guid 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); osm_router_delete(&p_rtr); } } static void drop_mgr_clean_physp(osm_sm_t * sm, IN osm_physp_t * p_physp) { osm_physp_t *p_remote_physp; osm_port_t *p_remote_port; p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) { p_remote_port = osm_get_port_by_guid(sm->p_subn, p_remote_physp->port_guid); if (p_remote_port) { /* Let's check if this is a case of link that is lost (both ports weren't recognized), or a "hiccup" in the subnet - in which case the remote port was recognized, and its state is ACTIVE. If this is just a "hiccup" - force a heavy sweep in the next sweep. We don't want to lose that part of the subnet. */ if (p_remote_port->discovery_count && osm_physp_get_port_state(p_remote_physp) == IB_LINK_ACTIVE) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Forcing new heavy sweep. Remote " "port 0x%016" PRIx64 " port num: %u " "was recognized in ACTIVE state\n", cl_ntoh64(p_remote_physp->port_guid), p_remote_physp->port_num); sm->p_subn->force_heavy_sweep = TRUE; } /* If the remote node is ca or router - need to remove the remote port, since it is no longer reachable. This can be done if we reset the discovery count of the remote port. */ if (!p_remote_physp->p_node->sw && p_remote_physp->port_guid != sm->p_subn->sm_port_guid) { p_remote_port->discovery_count = 0; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Resetting discovery count of node: " "0x%016" PRIx64 " port num:%u\n", cl_ntoh64(osm_node_get_node_guid (p_remote_physp->p_node)), p_remote_physp->port_num); } } OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Unlinking local node 0x%016" PRIx64 ", port %u" "\n\t\t\t\tand remote node 0x%016" PRIx64 ", port %u\n", cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)), p_physp->port_num, cl_ntoh64(osm_node_get_node_guid (p_remote_physp->p_node)), p_remote_physp->port_num); if (sm->ucast_mgr.cache_valid) osm_ucast_cache_add_link(&sm->ucast_mgr, p_physp, p_remote_physp); osm_physp_unlink(p_physp, p_remote_physp); } /* Make port as undiscovered */ p_physp->p_node->physp_discovered[p_physp->port_num] = 0; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Clearing node 0x%016" PRIx64 " physical port number %u\n", cl_ntoh64(osm_node_get_node_guid(p_physp->p_node)), p_physp->port_num); osm_physp_destroy(p_physp); } static void drop_mgr_remove_port(osm_sm_t * sm, IN osm_port_t * p_port) { ib_net64_t port_guid; osm_port_t *p_port_check; cl_qmap_t *p_alias_guid_tbl; cl_qmap_t *p_sm_guid_tbl; osm_mcm_port_t *mcm_port; cl_ptr_vector_t *p_port_lid_tbl; uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; osm_node_t *p_node; osm_remote_sm_t *p_sm; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; osm_guidinfo_work_obj_t *wobj; cl_list_item_t *item, *next_item; ib_gid_t port_gid; ib_mad_notice_attr_t notice; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); port_guid = osm_port_get_guid(p_port); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Unreachable port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); p_port_check = (osm_port_t *) cl_qmap_get(&sm->p_subn->port_guid_tbl, port_guid); if (p_port_check != p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0101: " "Port 0x%016" PRIx64 " not in guid table\n", cl_ntoh64(port_guid)); goto Exit; } /* issue a notice - trap 65 (SM_GID_OUT_OF_SERVICE_TRAP) */ /* details of the notice */ notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT; /* is generic subn mgt type */ ib_notice_set_prod_type_ho(¬ice, 4); /* A class manager generator */ /* endport ceases to be reachable */ notice.g_or_v.generic.trap_num = CL_HTON16(SM_GID_OUT_OF_SERVICE_TRAP); /* 65 */ /* The sm_base_lid is saved in network order already. */ notice.issuer_lid = sm->p_subn->sm_base_lid; /* following C14-72.1.2 and table 119 p725 */ /* we need to provide the GID */ port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; port_gid.unicast.interface_id = port_guid; memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid), sizeof(ib_gid_t)); /* According to page 653 - the issuer gid in this case of trap is the SM gid, since the SM is the initiator of this trap. */ notice.issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; notice.issuer_gid.unicast.interface_id = sm->p_subn->sm_port_guid; status = osm_report_notice(sm->p_log, sm->p_subn, ¬ice); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0103: " "Error sending trap reports (%s)\n", ib_get_err_str(status)); } next_item = cl_qlist_head(&sm->p_subn->alias_guid_list); while (next_item != cl_qlist_end(&sm->p_subn->alias_guid_list)) { item = next_item; next_item = cl_qlist_next(item); wobj = cl_item_obj(item, wobj, list_item); if (wobj->p_port == p_port) { cl_qlist_remove_item(&sm->p_subn->alias_guid_list, &wobj->list_item); osm_guid_work_obj_delete(wobj); } } while (!cl_is_qlist_empty(&p_port->mcm_list)) { mcm_port = cl_item_obj(cl_qlist_head(&p_port->mcm_list), mcm_port, list_item); osm_mgrp_delete_port(sm->p_subn, sm->p_log, mcm_port->mgrp, p_port); } p_alias_guid_tbl = &sm->p_subn->alias_port_guid_tbl; p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_head(p_alias_guid_tbl); while (p_alias_guid_check != (osm_alias_guid_t *) cl_qmap_end(p_alias_guid_tbl)) { if (p_alias_guid_check->p_base_port == p_port) p_alias_guid = p_alias_guid_check; else p_alias_guid = NULL; p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid_check->map_item); if (p_alias_guid) { cl_qmap_remove_item(p_alias_guid_tbl, &p_alias_guid->map_item); osm_alias_guid_delete(&p_alias_guid); } } cl_qmap_remove(&sm->p_subn->port_guid_tbl, port_guid); p_sm_guid_tbl = &sm->p_subn->sm_guid_tbl; p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_guid_tbl, port_guid); if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl)) { /* need to remove this item */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Cleaned SM for port guid 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); free(p_sm); } drop_mgr_remove_router(sm, port_guid); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Clearing abandoned LID range [%u,%u]\n", min_lid_ho, max_lid_ho); p_port_lid_tbl = &sm->p_subn->port_lid_tbl; for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) cl_ptr_vector_set(p_port_lid_tbl, lid_ho, NULL); drop_mgr_clean_physp(sm, p_port->p_physp); /* Delete event forwarding subscriptions */ if (sm->p_subn->opt.drop_event_subscriptions) { if (osm_infr_remove_subscriptions(sm->p_subn, sm->p_log, port_guid) == CL_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Removed event subscriptions for port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); } /* initialize the p_node - may need to get node_desc later */ p_node = p_port->p_node; osm_port_delete(&p_port); OSM_LOG(sm->p_log, OSM_LOG_INFO, "Removed port with GUID:0x%016" PRIx64 " LID range [%u, %u] of node:%s\n", cl_ntoh64(port_gid.unicast.interface_id), min_lid_ho, max_lid_ho, p_node ? p_node->print_desc : "UNKNOWN"); Exit: OSM_LOG_EXIT(sm->p_log); } static void drop_mgr_remove_switch(osm_sm_t * sm, IN osm_node_t * p_node) { osm_switch_t *p_sw; cl_qmap_t *p_sw_guid_tbl; ib_net64_t node_guid; OSM_LOG_ENTER(sm->p_log); node_guid = osm_node_get_node_guid(p_node); p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl; p_sw = (osm_switch_t *) cl_qmap_remove(p_sw_guid_tbl, node_guid); if (p_sw == (osm_switch_t *) cl_qmap_end(p_sw_guid_tbl)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0102: " "Node 0x%016" PRIx64 " not in switch table\n", cl_ntoh64(osm_node_get_node_guid(p_node))); } else { p_node->sw = NULL; osm_switch_delete(&p_sw); } OSM_LOG_EXIT(sm->p_log); } static boolean_t drop_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node) { osm_physp_t *p_physp; osm_port_t *p_port; osm_node_t *p_node_check; uint32_t port_num; uint32_t max_ports; ib_net64_t port_guid; boolean_t return_val = FALSE; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Unreachable node 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); if (sm->ucast_mgr.cache_valid) osm_ucast_cache_add_node(&sm->ucast_mgr, p_node); /* Delete all the logical and physical port objects associated with this node. */ max_ports = osm_node_get_num_physp(p_node); for (port_num = 0; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_physp) { port_guid = osm_physp_get_port_guid(p_physp); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (p_port) drop_mgr_remove_port(sm, p_port); else drop_mgr_clean_physp(sm, p_physp); } } return_val = TRUE; if (p_node->sw) drop_mgr_remove_switch(sm, p_node); p_node_check = (osm_node_t *) cl_qmap_remove(&sm->p_subn->node_guid_tbl, osm_node_get_node_guid(p_node)); if (p_node_check != p_node) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0105: " "Node 0x%016" PRIx64 " not in guid table\n", cl_ntoh64(osm_node_get_node_guid(p_node))); } /* free memory allocated to node */ osm_node_delete(&p_node); OSM_LOG_EXIT(sm->p_log); return return_val; } static void drop_mgr_check_switch_node(osm_sm_t * sm, IN osm_node_t * p_node) { ib_net64_t node_guid; osm_physp_t *p_physp, *p_remote_physp; osm_node_t *p_remote_node; osm_port_t *p_port; ib_net64_t port_guid; uint8_t port_num, remote_port_num; OSM_LOG_ENTER(sm->p_log); node_guid = osm_node_get_node_guid(p_node); /* Make sure we have a switch object for this node */ if (!p_node->sw) { /* We do not have switch info for this node */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Node 0x%016" PRIx64 " no switch in table\n", cl_ntoh64(node_guid)); drop_mgr_process_node(sm, p_node); goto Exit; } /* Make sure we have a port object for port zero */ p_physp = osm_node_get_physp_ptr(p_node, 0); if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Node 0x%016" PRIx64 " no valid physical port 0\n", cl_ntoh64(node_guid)); drop_mgr_process_node(sm, p_node); goto Exit; } port_guid = osm_physp_get_port_guid(p_physp); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Node 0x%016" PRIx64 " has no port object\n", cl_ntoh64(node_guid)); drop_mgr_process_node(sm, p_node); goto Exit; } if (!p_node->physp_discovered[0]) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Node 0x%016" PRIx64 " port has discovery count zero\n", cl_ntoh64(node_guid)); drop_mgr_process_node(sm, p_node); goto Exit; } /* * Unlink all ports that havn't been discovered during the last sweep. * Optimization: Skip the check if discovered all the ports of the switch. */ if (p_port->discovery_count < p_node->physp_tbl_size) { for (port_num = 1; port_num < p_node->physp_tbl_size; port_num++) { if (!p_node->physp_discovered[port_num]) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; p_remote_physp = osm_physp_get_remote(p_physp); if (!p_remote_physp) continue; p_remote_node = osm_physp_get_node_ptr(p_remote_physp); remote_port_num = osm_physp_get_port_num(p_remote_physp); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Unlinking local node 0x%" PRIx64 ", port %u" "\n\t\t\t\tand remote node 0x%" PRIx64 ", port %u due to missing PortInfo\n", cl_ntoh64(osm_node_get_node_guid (p_node)), port_num, cl_ntoh64(osm_node_get_node_guid (p_remote_node)), remote_port_num); if (sm->ucast_mgr.cache_valid) osm_ucast_cache_add_link(&sm->ucast_mgr, p_physp, p_remote_physp); osm_node_unlink(p_node, (uint8_t) port_num, p_remote_node, (uint8_t) remote_port_num); } } } Exit: OSM_LOG_EXIT(sm->p_log); return; } void osm_drop_mgr_process(osm_sm_t * sm) { cl_qmap_t *p_node_guid_tbl, *p_port_guid_tbl; osm_port_t *p_port, *p_next_port; osm_node_t *p_node, *p_next_node; int max_ports, port_num; osm_physp_t *p_physp; ib_net64_t port_guid; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); p_node_guid_tbl = &sm->p_subn->node_guid_tbl; p_port_guid_tbl = &sm->p_subn->port_guid_tbl; CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_next_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); while (p_next_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl)) { p_node = p_next_node; p_next_node = (osm_node_t *) cl_qmap_next(&p_next_node->map_item); CL_ASSERT(cl_qmap_key(&p_node->map_item) == osm_node_get_node_guid(p_node)); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Checking node 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); /* Check if this node was discovered during the last sweep. If not, it is unreachable in the current subnet, and should therefore be removed from the subnet object. */ if (p_node->discovery_count == 0) drop_mgr_process_node(sm, p_node); else { /* * We want to preserve the configured pkey indexes, * so if we don't receive GetResp P_KeyTable for some block, * do the following: * 1. Drop node if the node is sw and got timeout for port 0. * 2. Drop node if node is HCA/RTR. * 3. Drop only physp if got timeout for sw when the port isn't 0. * We'll set error during initialization in order to * cause an immediate heavy sweep and try to get the * configured P_KeyTable again. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) port_num = 0; else port_num = 1; max_ports = osm_node_get_num_physp(p_node); for (; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || p_physp->pkeys.rcv_blocks_cnt == 0) continue; p_physp->pkeys.rcv_blocks_cnt = 0; p_physp->need_update = 2; sm->p_subn->subnet_initialization_error = TRUE; port_guid = osm_physp_get_port_guid(p_physp); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); CL_ASSERT(p_port); if (p_node->physp_discovered[port_num]) { p_node->physp_discovered[port_num] = 0; p_port->discovery_count--; } } } } /* Go over all the nodes. If the node is a switch - make sure there is also a switch record for it, and a portInfo record for port zero of of the node. If not - this means that there was some error in getting the data of this node. Drop the node. */ p_next_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); while (p_next_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl)) { p_node = p_next_node; p_next_node = (osm_node_t *) cl_qmap_next(&p_next_node->map_item); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Checking full discovery of node 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH) continue; /* We are handling a switch node */ drop_mgr_check_switch_node(sm, p_node); } p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) { p_port = p_next_port; p_next_port = (osm_port_t *) cl_qmap_next(&p_next_port->map_item); CL_ASSERT(cl_qmap_key(&p_port->map_item) == osm_port_get_guid(p_port)); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Checking port 0x%016" PRIx64 "\n", cl_ntoh64(osm_port_get_guid(p_port))); /* If the port is unreachable, remove it from the guid table. */ if (p_port->discovery_count == 0) drop_mgr_remove_port(sm, p_port); } CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_guid_info_rcv.c0000644000205000001450000000732012327471402015154 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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 osm_gi_rcv_t. * This object represents the GUIDInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_GUID_INFO_RCV_C #include #include #include #include #include #include #include #include #include #include void osm_gi_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_guid_info_t *p_gi; ib_smp_t *p_smp; osm_port_t *p_port; osm_gi_context_t *p_context; ib_net64_t port_guid, node_guid; uint8_t block_num; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_gi_context_ptr(p_madw); p_gi = ib_smp_get_payload_ptr(p_smp); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_GUID_INFO); block_num = (uint8_t) cl_ntoh32(p_smp->attr_mod); port_guid = p_context->port_guid; node_guid = p_context->node_guid; osm_dump_guid_info_v2(sm->p_log, node_guid, port_guid, block_num, p_gi, FILE_ID, OSM_LOG_DEBUG); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4701: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } CL_PLOCK_RELEASE(sm->p_lock); Exit: /* Release the lock before jumping here!! */ OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_guid_mgr.c0000644000205000001450000001101312272264653014135 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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 osm_guid_mgr_t. * This object implements the GUID manager object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_GUID_MGR_C #include #include #include #include static void guidinfo_set(IN osm_sa_t *sa, IN osm_port_t *p_port, IN uint8_t block_num) { uint8_t payload[IB_SMP_DATA_SIZE]; osm_madw_context_t context; ib_api_status_t status; memcpy(payload, &((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES]), sizeof(ib_guid_info_t)); context.gi_context.node_guid = osm_node_get_node_guid(p_port->p_node); context.gi_context.port_guid = osm_physp_get_port_guid(p_port->p_physp); context.gi_context.set_method = TRUE; context.gi_context.port_num = osm_physp_get_port_num(p_port->p_physp); status = osm_req_set(sa->sm, osm_physp_get_dr_path_ptr(p_port->p_physp), payload, sizeof(payload), IB_MAD_ATTR_GUID_INFO, cl_hton32((uint32_t)block_num), FALSE, ib_port_info_get_m_key(&p_port->p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5109: " "Failure initiating GUIDInfo request (%s)\n", ib_get_err_str(status)); } osm_guidinfo_work_obj_t *osm_guid_work_obj_new(IN osm_port_t * p_port, IN uint8_t block_num) { osm_guidinfo_work_obj_t *p_obj; /* clean allocated memory to avoid assertion when trying to insert to qlist. see cl_qlist_insert_tail(): CL_ASSERT(p_list_item->p_list != p_list) */ p_obj = calloc(1, sizeof(*p_obj)); if (p_obj) { p_obj->p_port = p_port; p_obj->block_num = block_num; } return p_obj; } void osm_guid_work_obj_delete(IN osm_guidinfo_work_obj_t * p_wobj) { free(p_wobj); } int osm_queue_guidinfo(IN osm_sa_t *sa, IN osm_port_t *p_port, IN uint8_t block_num) { osm_guidinfo_work_obj_t *p_obj; int status = 1; p_obj = osm_guid_work_obj_new(p_port, block_num); if (p_obj) cl_qlist_insert_tail(&sa->p_subn->alias_guid_list, &p_obj->list_item); else { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510F: " "Memory allocation of guid work object failed\n"); status = 0; } return status; } void osm_guid_mgr_process(IN osm_sm_t * sm) { osm_guidinfo_work_obj_t *p_obj; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Processing alias guid list\n"); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); while (cl_qlist_count(&sm->p_subn->alias_guid_list)) { p_obj = (osm_guidinfo_work_obj_t *) cl_qlist_remove_head(&sm->p_subn->alias_guid_list); guidinfo_set(&sm->p_subn->p_osm->sa, p_obj->p_port, p_obj->block_num); osm_guid_work_obj_delete(p_obj); } CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_inform.c0000644000205000001450000006654512604757300013651 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 inform record functions. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_INFORM_C #include #include #include #include #include #include typedef struct osm_infr_match_ctxt { cl_list_t *p_remove_infr_list; ib_mad_notice_attr_t *p_ntc; } osm_infr_match_ctxt_t; void osm_infr_delete(IN osm_infr_t * p_infr) { free(p_infr); } osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec) { osm_infr_t *p_infr; CL_ASSERT(p_infr_rec); p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t)); if (p_infr) memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t)); return p_infr; } static void dump_all_informs(IN const osm_subn_t * p_subn, IN osm_log_t * p_log) { cl_list_item_t *p_list_item; if (!OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_DEBUG)) return; p_list_item = cl_qlist_head(&p_subn->sa_infr_list); while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { osm_dump_inform_info_v2(p_log, &((osm_infr_t *) p_list_item)-> inform_record.inform_info, FILE_ID, OSM_LOG_DEBUG); p_list_item = cl_qlist_next(p_list_item); } } /********************************************************************** * Match an infr by the InformInfo and Address vector **********************************************************************/ static cl_status_t match_inf_rec(IN const cl_list_item_t * p_list_item, IN void *context) { osm_infr_t *p_infr_rec = (osm_infr_t *) context; osm_infr_t *p_infr = (osm_infr_t *) p_list_item; ib_inform_info_t *p_ii_rec = &p_infr_rec->inform_record.inform_info; ib_inform_info_t *p_ii = &p_infr->inform_record.inform_info; osm_log_t *p_log = p_infr_rec->sa->p_log; cl_status_t status = CL_NOT_FOUND; OSM_LOG_ENTER(p_log); if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr, sizeof(p_infr_rec->report_addr))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n"); goto Exit; } /* if inform_info.gid is not zero, ignore lid range */ if (ib_gid_is_notzero(&p_ii_rec->gid)) { if (memcmp(&p_ii->gid, &p_ii_rec->gid, sizeof(p_ii->gid))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.gid\n"); goto Exit; } } else { if ((p_ii->lid_range_begin != p_ii_rec->lid_range_begin) || (p_ii->lid_range_end != p_ii_rec->lid_range_end)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.LIDRange\n"); goto Exit; } } if (p_ii->trap_type != p_ii_rec->trap_type) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.TrapType\n"); goto Exit; } if (p_ii->is_generic != p_ii_rec->is_generic) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.IsGeneric\n"); goto Exit; } if (p_ii->is_generic) { if (p_ii->g_or_v.generic.trap_num != p_ii_rec->g_or_v.generic.trap_num) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Generic.TrapNumber\n"); else if (p_ii->g_or_v.generic.qpn_resp_time_val != p_ii_rec->g_or_v.generic.qpn_resp_time_val) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Generic.QPNRespTimeVal\n"); else if (p_ii->g_or_v.generic.node_type_msb != p_ii_rec->g_or_v.generic.node_type_msb) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Generic.NodeTypeMSB\n"); else if (p_ii->g_or_v.generic.node_type_lsb != p_ii_rec->g_or_v.generic.node_type_lsb) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Generic.NodeTypeLSB\n"); else status = CL_SUCCESS; } else { if (p_ii->g_or_v.vend.dev_id != p_ii_rec->g_or_v.vend.dev_id) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Vendor.DeviceID\n"); else if (p_ii->g_or_v.vend.qpn_resp_time_val != p_ii_rec->g_or_v.vend.qpn_resp_time_val) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Vendor.QPNRespTimeVal\n"); else if (p_ii->g_or_v.vend.vendor_id_msb != p_ii_rec->g_or_v.vend.vendor_id_msb) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Vendor.VendorIdMSB\n"); else if (p_ii->g_or_v.vend.vendor_id_lsb != p_ii_rec->g_or_v.vend.vendor_id_lsb) OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by InformInfo.Vendor.VendorIdLSB\n"); else status = CL_SUCCESS; } Exit: OSM_LOG_EXIT(p_log); return status; } osm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr_rec) { cl_list_item_t *p_list_item; OSM_LOG_ENTER(p_log); dump_all_informs(p_subn, p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n"); osm_dump_inform_info_v2(p_log, &(p_infr_rec->inform_record.inform_info), FILE_ID, OSM_LOG_DEBUG); OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n", cl_qlist_count(&p_subn->sa_infr_list)); p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list, match_inf_rec, p_infr_rec); if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list)) p_list_item = NULL; OSM_LOG_EXIT(p_log); return (osm_infr_t *) p_list_item; } void osm_infr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr) { OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Inserting new InformInfo Record into Database\n"); OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n", cl_qlist_count(&p_subn->sa_infr_list)); dump_all_informs(p_subn, p_log); #if 0 osm_dump_inform_info_v2(p_log, &(p_infr->inform_record.inform_info), FILE_ID, OSM_LOG_DEBUG); #endif cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item); p_subn->p_osm->sa.dirty = TRUE; OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n", cl_qlist_count(&p_subn->sa_infr_list)); dump_all_informs(p_subn, p_log); OSM_LOG_EXIT(p_log); } void osm_infr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_infr_t * p_infr) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s" " Enum:0x%X from Database\n", inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw, gid_str, sizeof gid_str), p_infr->inform_record.subscriber_enum); osm_dump_inform_info_v2(p_log, &(p_infr->inform_record.inform_info), FILE_ID, OSM_LOG_DEBUG); cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item); p_subn->p_osm->sa.dirty = TRUE; osm_infr_delete(p_infr); OSM_LOG_EXIT(p_log); } ib_api_status_t osm_infr_remove_subscriptions(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN ib_net64_t port_guid) { cl_list_item_t *p_list_item; osm_infr_t *p_infr; ib_api_status_t status = CL_NOT_FOUND; OSM_LOG_ENTER(p_log); /* go over all inform info available at the subnet */ /* match to the given GID and delete subscriptions if match */ p_list_item = cl_qlist_head(&p_subn->sa_infr_list); while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { p_infr = (osm_infr_t *)p_list_item; p_list_item = cl_qlist_next(p_list_item); if (port_guid != p_infr->inform_record.subscriber_gid.unicast.interface_id) continue; /* Remove this event subscription */ osm_infr_remove_from_db(p_subn, p_log, p_infr); status = CL_SUCCESS; } OSM_LOG_EXIT(p_log); return (status); } /********************************************************************** * Send a report: * Given a target address to send to and the notice. * We need to send SubnAdmReport **********************************************************************/ static ib_api_status_t send_report(IN osm_infr_t * p_infr_rec, /* the informinfo */ IN ib_mad_notice_attr_t * p_ntc /* notice to send */ ) { osm_madw_t *p_report_madw; ib_mad_notice_attr_t *p_report_ntc; ib_mad_t *p_mad; ib_sa_mad_t *p_sa_mad; static atomic32_t trap_fwd_trans_id = 0x02DAB000; ib_api_status_t status = IB_SUCCESS; osm_log_t *p_log = p_infr_rec->sa->p_log; ib_net64_t tid; OSM_LOG_ENTER(p_log); /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */ /* it is better to use LIDs since the GIDs might not be there for SMI traps */ OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID %u" " to InformInfo LID %u GUID 0x%" PRIx64 ", TID 0x%X\n", cl_ntoh16(p_ntc->issuer_lid), cl_ntoh16(p_infr_rec->report_addr.dest_lid), cl_ntoh64(p_infr_rec->inform_record.subscriber_gid.unicast.interface_id), trap_fwd_trans_id); /* get the MAD to send */ p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool, p_infr_rec->h_bind, MAD_BLOCK_SIZE, &(p_infr_rec->report_addr)); if (!p_report_madw) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203: " "Cannot send report to LID %u, osm_mad_pool_get failed\n", cl_ntoh16(p_infr_rec->report_addr.dest_lid)); status = IB_ERROR; goto Exit; } p_report_madw->resp_expected = TRUE; /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) & (uint64_t) (0xFFFFFFFF)); if (trap_fwd_trans_id == 0) tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) & (uint64_t) (0xFFFFFFFF)); p_mad = osm_madw_get_mad_ptr(p_report_madw); ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT, tid, IB_MAD_ATTR_NOTICE, 0); p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw); p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data); /* copy the notice */ *p_report_ntc = *p_ntc; /* The TRUE is for: response is expected */ osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE); Exit: OSM_LOG_EXIT(p_log); return status; } static int is_access_permitted(osm_infr_t *p_infr_rec, osm_infr_match_ctxt_t *p_infr_match ) { cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list; ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; uint16_t trap_num = cl_ntoh16(p_ntc->g_or_v.generic.trap_num); osm_subn_t *p_subn = p_infr_rec->sa->p_subn; osm_log_t *p_log = p_infr_rec->sa->p_log; osm_mgrp_t *p_mgrp; ib_gid_t source_gid; osm_port_t *p_src_port; osm_port_t *p_dest_port; /* In case of SM_GID_IN_SERVICE_TRAP(64) or SM_GID_OUT_OF_SERVICE_TRAP(65) traps the source gid comparison should be done on the trap source (saved as the gid in the data details field). For traps SM_MGID_CREATED_TRAP(66) or SM_MGID_DESTROYED_TRAP(67) the data details gid is the MGID. We need to check whether the subscriber has a compatible pkey with MC group. In all other cases the issuer gid is the trap source. */ if (trap_num >= SM_GID_IN_SERVICE_TRAP && trap_num <= SM_MGID_DESTROYED_TRAP) /* The issuer of these traps is the SM so source_gid is the gid saved on the data details */ source_gid = p_ntc->data_details.ntc_64_67.gid; else source_gid = p_ntc->issuer_gid; p_dest_port = osm_get_port_by_lid(p_subn, p_infr_rec->report_addr.dest_lid); if (!p_dest_port) { OSM_LOG(p_log, OSM_LOG_INFO, "Cannot find destination port with LID:%u\n", cl_ntoh16(p_infr_rec->report_addr.dest_lid)); goto Exit; } /* Check if there is a pkey match. o13-17.1.1 */ switch (trap_num) { case SM_MGID_CREATED_TRAP: case SM_MGID_DESTROYED_TRAP: p_mgrp = osm_get_mgrp_by_mgid(p_subn, &source_gid); if (!p_mgrp) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(p_log, OSM_LOG_INFO, "Cannot find MGID %s\n", inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str)); goto Exit; } if (!osm_physp_has_pkey(p_log, p_mgrp->mcmember_rec.pkey, p_dest_port->p_physp)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(p_log, OSM_LOG_INFO, "MGID %s and port GUID:0x%016" PRIx64 " do not share same pkey\n", inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str), cl_ntoh64(p_dest_port->guid)); goto Exit; } break; default: p_src_port = osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id); if (!p_src_port) { OSM_LOG(p_log, OSM_LOG_INFO, "Cannot find source port with GUID:0x%016" PRIx64 "\n", cl_ntoh64(source_gid.unicast.interface_id)); goto Exit; } if (osm_port_share_pkey(p_log, p_src_port, p_dest_port, p_subn->opt.allow_both_pkeys) == FALSE) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n"); /* According to o13-17.1.2 - If this informInfo does not have lid_range_begin of 0xFFFF, then this informInfo request should be removed from database */ if (p_ii->lid_range_begin != 0xFFFF) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Pkey mismatch on lid_range_begin != 0xFFFF. " "Need to remove this informInfo from db\n"); /* add the informInfo record to the remove_infr list */ cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec); } goto Exit; } break; } return 1; Exit: return 0; } /********************************************************************** * This routine compares a given Notice and a ListItem of InformInfo type. * PREREQUISITE: * The Notice.GID should be pre-filled with the trap generator GID **********************************************************************/ static void match_notice_to_inf_rec(IN cl_list_item_t * p_list_item, IN void *context) { osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context; ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item; ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); osm_log_t *p_log = p_infr_rec->sa->p_log; OSM_LOG_ENTER(p_log); /* matching rules * InformInfo Notice * GID IssuerGID if non zero must match the trap * LIDRange IssuerLID apply only if GID=0 * IsGeneric IsGeneric is compulsory and must match the trap * Type Type if not 0xFFFF must match * TrapNumber TrapNumber if not 0xFFFF must match * DeviceId DeviceID if not 0xFFFF must match * QPN dont care * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation * VendorID VendorID match or 0xFFFFFF */ /* GID IssuerGID if non zero must match the trap */ if (p_ii->gid.unicast.prefix != 0 || p_ii->gid.unicast.interface_id != 0) { /* match by GID */ if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), sizeof(ib_gid_t))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n"); goto Exit; } } else { /* LIDRange IssuerLID apply only if GID=0 */ /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */ if (p_ii->lid_range_begin != 0xFFFF) { /* a real lid range is given - check it */ if ((cl_hton16(p_ii->lid_range_begin) > cl_hton16(p_ntc->issuer_lid)) || (cl_hton16(p_ntc->issuer_lid) > cl_hton16(p_ii->lid_range_end))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by LID Range. Needed: %u <= %u <= %u\n", cl_hton16(p_ii->lid_range_begin), cl_hton16(p_ntc->issuer_lid), cl_hton16(p_ii->lid_range_end)); goto Exit; } } } /* IsGeneric IsGeneric is compulsory and must match the trap */ if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) || (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n"); goto Exit; } /* Type Type if not 0xFFFF must match */ if ((p_ii->trap_type != 0xFFFF) && (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n"); goto Exit; } /* based on generic type */ if (p_ii->is_generic) { /* TrapNumber TrapNumber if not 0xFFFF must match */ if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) && (p_ii->g_or_v.generic.trap_num != p_ntc->g_or_v.generic.trap_num)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n"); goto Exit; } /* ProducerType ProducerType match or 0xFFFFFF */ if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF) && (ib_inform_info_get_prod_type(p_ii) != ib_notice_get_prod_type(p_ntc))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n", cl_ntoh32(ib_inform_info_get_prod_type(p_ii)), ib_get_producer_type_str (ib_inform_info_get_prod_type(p_ii)), cl_ntoh32(ib_notice_get_prod_type(p_ntc)), ib_get_producer_type_str(ib_notice_get_prod_type (p_ntc))); goto Exit; } } else { /* DeviceId DeviceID if not 0xFFFF must match */ if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) && (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n"); goto Exit; } /* VendorID VendorID match or 0xFFFFFF */ if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) && (ib_inform_info_get_vend_id(p_ii) != ib_notice_get_vend_id(p_ntc))) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Vendor ID\n"); goto Exit; } } if (!is_access_permitted(p_infr_rec, p_infr_match)) goto Exit; /* send the report to the address provided in the inform record */ OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n"); send_report(p_infr_rec, p_ntc); Exit: OSM_LOG_EXIT(p_log); } /********************************************************************** * Once a Trap was received by osm_trap_rcv, or a Trap sourced by * the SM was sent (Traps 64-67), this routine is called with a copy of * the notice data. * Given a notice attribute - compare and see if it matches the InformInfo * element and if it does - call the Report(Notice) for the * target QP registered by the address stored in the InformInfo element **********************************************************************/ static void log_notice(osm_log_t * log, osm_log_level_t level, ib_mad_notice_attr_t * ntc) { char gid_str[INET6_ADDRSTRLEN], gid_str2[INET6_ADDRSTRLEN]; ib_gid_t *gid; ib_gid_t *gid1, *gid2; /* an official Event information log */ if (ib_notice_is_generic(ntc)) { if ((ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_IN_SERVICE_TRAP)) || (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_OUT_OF_SERVICE_TRAP)) || (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_CREATED_TRAP)) || (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_DESTROYED_TRAP))) gid = &ntc->data_details.ntc_64_67.gid; else gid = &ntc->issuer_gid; switch (cl_ntoh16(ntc->g_or_v.generic.trap_num)) { case SM_GID_IN_SERVICE_TRAP: case SM_GID_OUT_OF_SERVICE_TRAP: OSM_LOG(log, level, "Reporting Informational Notice \"%s\", GID:%s\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); break; case SM_MGID_CREATED_TRAP: case SM_MGID_DESTROYED_TRAP: OSM_LOG(log, level, "Reporting Informational Notice \"%s\", MGID:%s\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); break; case SM_UNPATH_TRAP: case SM_REPATH_TRAP: /* TODO: Fill in details once SM starts to use these traps */ OSM_LOG(log, level, "Reporting Informational Notice \"%s\"n", ib_get_trap_str(ntc->g_or_v.generic.trap_num)); break; case SM_LINK_STATE_CHANGED_TRAP: OSM_LOG(log, level, "Reporting Urgent Notice \"%s\" from switch LID %u, " "GUID 0x%016" PRIx64 "\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id)); break; case SM_LINK_INTEGRITY_THRESHOLD_TRAP: case SM_BUFFER_OVERRUN_THRESHOLD_TRAP: case SM_WATCHDOG_TIMER_EXPIRED_TRAP: OSM_LOG(log, level, "Reporting Urgent Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 ", port %u\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), ntc->data_details.ntc_129_131.port_num); break; case SM_LOCAL_CHANGES_TRAP: if (ntc->data_details.ntc_144.local_changes == 1) OSM_LOG(log, level, "Reporting Informational Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 ", ChangeFlags 0x%04x, " "CapabilityMask2 0x%04x\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), cl_ntoh16(ntc->data_details.ntc_144.change_flgs), cl_ntoh16(ntc->data_details.ntc_144.cap_mask2)); else OSM_LOG(log, level, "Reporting Informational Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 ", new CapabilityMask 0x%08x\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), cl_ntoh32(ntc->data_details.ntc_144.new_cap_mask)); break; case SM_SYS_IMG_GUID_CHANGED_TRAP: OSM_LOG(log, level, "Reporting Informational Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 ", new SysImageGUID 0x%016" PRIx64 "\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), cl_ntoh64(ntc->data_details.ntc_145.new_sys_guid)); break; case SM_BAD_MKEY_TRAP: OSM_LOG(log, level, "Reporting Security Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 ", Method 0x%x, Attribute 0x%x, " "AttrMod 0x%x, M_Key 0x%016" PRIx64 "\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), ntc->data_details.ntc_256.method, cl_ntoh16(ntc->data_details.ntc_256.attr_id), cl_ntoh32(ntc->data_details.ntc_256.attr_mod), cl_ntoh64(ntc->data_details.ntc_256.mkey)); break; case SM_BAD_PKEY_TRAP: case SM_BAD_QKEY_TRAP: gid1 = &ntc->data_details.ntc_257_258.gid1; gid2 = &ntc->data_details.ntc_257_258.gid2; OSM_LOG(log, level, "Reporting Security Notice \"%s\" from LID %u, " "GUID 0x%016" PRIx64 " : LID1 %u, LID2 %u, %s 0x%x, " "SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), cl_ntoh16(ntc->data_details.ntc_257_258.lid1), cl_ntoh16(ntc->data_details.ntc_257_258.lid2), cl_ntoh16(ntc->g_or_v.generic.trap_num) == SM_BAD_QKEY_TRAP ? "Q_Key" : "P_Key", cl_ntoh32(ntc->data_details.ntc_257_258.key), cl_ntoh32(ntc->data_details.ntc_257_258.qp1) >> 28, cl_ntoh32(ntc->data_details.ntc_257_258.qp1) & 0xffffff, cl_ntoh32(ntc->data_details.ntc_257_258.qp2) & 0xffffff, inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2)); break; case SM_BAD_SWITCH_PKEY_TRAP: gid1 = &ntc->data_details.ntc_259.gid1; gid2 = &ntc->data_details.ntc_259.gid2; OSM_LOG(log, level, "Reporting Security Notice \"%s\" from switch LID %u, " "GUID 0x%016" PRIx64 " port %d : data_valid 0x%04x, " "LID1 %u, LID2 %u, PKey 0x%04x, " "SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n", ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), cl_ntoh64(gid->unicast.interface_id), ntc->data_details.ntc_259.port_no, cl_ntoh16(ntc->data_details.ntc_259.data_valid), cl_ntoh16(ntc->data_details.ntc_259.lid1), cl_ntoh16(ntc->data_details.ntc_259.lid2), cl_ntoh16(ntc->data_details.ntc_257_258.key), cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) >> 28, cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) & 0xffffff, cl_ntoh32(ntc->data_details.ntc_259.qp2), inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2)); break; default: OSM_LOG(log, level, "Reporting Generic Notice type:%u num:%u (%s)" " from LID:%u GID:%s\n", ib_notice_get_type(ntc), cl_ntoh16(ntc->g_or_v.generic.trap_num), ib_get_trap_str(ntc->g_or_v.generic.trap_num), cl_ntoh16(ntc->issuer_lid), inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); break; } } else OSM_LOG(log, level, "Reporting Vendor Notice type:%u vend:%u dev:%u" " from LID:%u GID:%s\n", ib_notice_get_type(ntc), cl_ntoh32(ib_notice_get_vend_id(ntc)), cl_ntoh16(ntc->g_or_v.vend.dev_id), cl_ntoh16(ntc->issuer_lid), inet_ntop(AF_INET6, ntc->issuer_gid.raw, gid_str, sizeof gid_str)); } ib_api_status_t osm_report_notice(IN osm_log_t * p_log, IN osm_subn_t * p_subn, IN ib_mad_notice_attr_t * p_ntc) { osm_infr_match_ctxt_t context; cl_list_t infr_to_remove_list; osm_infr_t *p_infr_rec; osm_infr_t *p_next_infr_rec; OSM_LOG_ENTER(p_log); /* * we must make sure we are ready for this... * note that the trap receivers might be initialized before * the osm_infr_init call is performed. */ if (p_subn->sa_infr_list.state != CL_INITIALIZED) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Ignoring Notice Reports since Inform List is not initialized yet!\n"); return IB_ERROR; } if (OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_INFO)) log_notice(p_log, OSM_LOG_INFO, p_ntc); /* Create a list that will hold all the infr records that should be removed due to violation. o13-17.1.2 */ cl_list_construct(&infr_to_remove_list); cl_list_init(&infr_to_remove_list, 5); context.p_remove_infr_list = &infr_to_remove_list; context.p_ntc = p_ntc; /* go over all inform info available at the subnet */ /* try match to the given notice and send if match */ cl_qlist_apply_func(&p_subn->sa_infr_list, match_notice_to_inf_rec, &context); /* If we inserted items into the infr_to_remove_list - we need to remove them */ p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); while (p_infr_rec != NULL) { p_next_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); osm_infr_remove_from_db(p_subn, p_log, p_infr_rec); p_infr_rec = p_next_infr_rec; } cl_list_destroy(&infr_to_remove_list); /* report IB traps to plugin */ osm_opensm_report_event(p_subn->p_osm, OSM_EVENT_ID_TRAP, p_ntc); OSM_LOG_EXIT(p_log); return IB_SUCCESS; } opensm-3.3.20/opensm/osm_lid_mgr.c0000644000205000001450000011525312421444354013762 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 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 osm_lid_mgr_t. * This file implements the LID Manager object which is responsible for * assigning LIDs to all ports on the subnet. * * DATA STRUCTURES: * p_subn->port_lid_tbl : a vector pointing from lid to its port. * osm db guid2lid domain : a hash from guid to lid (min lid). * p_subn->port_guid_tbl : a map from guid to discovered port obj. * * ALGORITHM: * * 0. we define a function to obtain the correct port lid: * lid_mgr_get_port_lid( p_mgr, port, &min_lid, &max_lid ): * 0.1 if the port info lid matches the guid2lid return 0 * 0.2 if the port info has a lid and that range is empty in * port_lid_tbl, return 0 and update the port_lid_tbl and * guid2lid * 0.3 else find an empty space in port_lid_tbl, update the * port_lid_tbl and guid2lid, return 1 to flag a change required. * * 1. During initialization: * 1.1 initialize the guid2lid database domain. * 1.2 if reassign_lid is not set: * 1.2.1 read the persistent data for the domain. * 1.2.2 validate no duplicate use of lids and lids are 2^(lmc-1) * * 2. During SM port lid assignment: * 2.1 if reassign_lids is set, make it 2^lmc * 2.2 cleanup all port_lid_tbl and re-fill it according to guid2lid * 2.3 call lid_mgr_get_port_lid for the SM port * 2.4 set the port info * * 3. During all other ports lid assignment: * 3.1 go through all ports in the subnet * 3.1.1 call lid_mgr_get_port_lid * 3.1.2 if a change required send the port info * 3.2 if any change send the signal PENDING... * * 4. Store the guid2lid */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_LID_MGR_C #include #include #include #include #include #include #include #include #include /********************************************************************** lid range item of qlist **********************************************************************/ typedef struct osm_lid_mgr_range { cl_list_item_t item; uint16_t min_lid; uint16_t max_lid; } osm_lid_mgr_range_t; void osm_lid_mgr_construct(IN osm_lid_mgr_t * p_mgr) { memset(p_mgr, 0, sizeof(*p_mgr)); } void osm_lid_mgr_destroy(IN osm_lid_mgr_t * p_mgr) { cl_list_item_t *p_item; OSM_LOG_ENTER(p_mgr->p_log); while ((p_item = cl_qlist_remove_head(&p_mgr->free_ranges)) != cl_qlist_end(&p_mgr->free_ranges)) free((osm_lid_mgr_range_t *) p_item); OSM_LOG_EXIT(p_mgr->p_log); } /********************************************************************** Validate the guid to lid data by making sure that under the current LMC we did not get duplicates. If we do flag them as errors and remove the entry. **********************************************************************/ static void lid_mgr_validate_db(IN osm_lid_mgr_t * p_mgr) { cl_qlist_t guids; osm_db_guid_elem_t *p_item; uint16_t lid; uint16_t min_lid; uint16_t max_lid; uint16_t lmc_mask; boolean_t lids_ok; OSM_LOG_ENTER(p_mgr->p_log); lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); cl_qlist_init(&guids); if (osm_db_guid2lid_guids(p_mgr->p_g2l, &guids)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0310: " "could not get guid list\n"); goto Exit; } while ((p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids)) != (osm_db_guid_elem_t *) cl_qlist_end(&guids)) { if (osm_db_guid2lid_get(p_mgr->p_g2l, p_item->guid, &min_lid, &max_lid)) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0311: " "could not get lid for guid:0x%016" PRIx64 "\n", p_item->guid); else { lids_ok = TRUE; if (min_lid > max_lid || min_lid == 0 || p_item->guid == 0 || max_lid > p_mgr->p_subn->max_ucast_lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0312: " "Illegal LID range [%u:%u] for " "guid:0x%016" PRIx64 "\n", min_lid, max_lid, p_item->guid); lids_ok = FALSE; } else if (min_lid != max_lid && (min_lid & lmc_mask) != min_lid) { /* check that if the lids define a range that is valid for the current LMC mask */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0313: " "LID range [%u:%u] for guid:0x%016" PRIx64 " is not aligned according to mask:0x%04x\n", min_lid, max_lid, p_item->guid, lmc_mask); lids_ok = FALSE; } else { /* check if the lids were not previously assigned */ for (lid = min_lid; lid <= max_lid; lid++) { if (p_mgr->used_lids[lid]) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0314: " "0x%04x for guid:0x%016" PRIx64 " was previously used\n", lid, p_item->guid); lids_ok = FALSE; } } } if (lids_ok) /* mark that it was visited */ for (lid = min_lid; lid <= max_lid; lid++) p_mgr->used_lids[lid] = 1; else if (osm_db_guid2lid_delete(p_mgr->p_g2l, p_item->guid)) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0315: failed to delete entry for " "guid:0x%016" PRIx64 "\n", p_item->guid); } /* got a lid */ free(p_item); } /* all guids */ Exit: OSM_LOG_EXIT(p_mgr->p_log); } ib_api_status_t osm_lid_mgr_init(IN osm_lid_mgr_t * p_mgr, IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); osm_lid_mgr_construct(p_mgr); p_mgr->sm = sm; p_mgr->p_log = sm->p_log; p_mgr->p_subn = sm->p_subn; p_mgr->p_db = sm->p_db; p_mgr->p_lock = sm->p_lock; /* we initialize and restore the db domain of guid to lid map */ p_mgr->p_g2l = osm_db_domain_init(p_mgr->p_db, "guid2lid"); if (!p_mgr->p_g2l) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0316: " "Error initializing Guid-to-Lid persistent database\n"); status = IB_ERROR; goto Exit; } cl_qlist_init(&p_mgr->free_ranges); /* we use the stored guid to lid table if not forced to reassign */ if (!p_mgr->p_subn->opt.reassign_lids) { if (osm_db_restore(p_mgr->p_g2l)) { #ifndef __WIN__ /* * When Windows is BSODing, it might corrupt files that * were previously opened for writing, even if the files * are closed, so we might see corrupted guid2lid file. */ if (p_mgr->p_subn->opt.exit_on_fatal) { osm_log_v2(p_mgr->p_log, OSM_LOG_SYS, FILE_ID, "FATAL: Error restoring Guid-to-Lid " "persistent database\n"); status = IB_ERROR; goto Exit; } else #endif OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0317: Error restoring Guid-to-Lid " "persistent database\n"); } /* we need to make sure we did not get duplicates with current lmc */ lid_mgr_validate_db(p_mgr); } Exit: OSM_LOG_EXIT(p_mgr->p_log); return status; } static uint16_t trim_lid(IN uint16_t lid) { if (lid > IB_LID_UCAST_END_HO || lid < IB_LID_UCAST_START_HO) return 0; return lid; } /********************************************************************** initialize the manager for a new sweep: scans the known persistent assignment and port_lid_tbl re-calculate all empty ranges. cleanup invalid port_lid_tbl entries **********************************************************************/ static int lid_mgr_init_sweep(IN osm_lid_mgr_t * p_mgr) { cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; uint16_t max_defined_lid, max_persistent_lid, max_discovered_lid; uint16_t disc_min_lid, disc_max_lid, db_min_lid, db_max_lid; int status = 0; cl_list_item_t *p_item; boolean_t is_free; osm_lid_mgr_range_t *p_range = NULL; osm_port_t *p_port; cl_qmap_t *p_port_guid_tbl; uint8_t lmc_num_lids = (uint8_t) (1 << p_mgr->p_subn->opt.lmc); uint16_t lmc_mask, req_lid, num_lids, lid; OSM_LOG_ENTER(p_mgr->p_log); lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); /* We must discard previous guid2lid db if this is the first master * sweep and reassign_lids option is TRUE. * If we came out of standby and honor_guid2lid_file option is TRUE, we * must restore guid2lid db. Otherwise if honor_guid2lid_file option is * FALSE we must discard previous guid2lid db. */ if (p_mgr->p_subn->first_time_master_sweep == TRUE && p_mgr->p_subn->opt.reassign_lids == TRUE) { osm_db_clear(p_mgr->p_g2l); memset(p_mgr->used_lids, 0, sizeof(p_mgr->used_lids)); } else if (p_mgr->p_subn->coming_out_of_standby == TRUE) { osm_db_clear(p_mgr->p_g2l); memset(p_mgr->used_lids, 0, sizeof(p_mgr->used_lids)); if (p_mgr->p_subn->opt.honor_guid2lid_file == FALSE) OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Ignore guid2lid file when coming out of standby\n"); else { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Honor current guid2lid file when coming out " "of standby\n"); if (osm_db_restore(p_mgr->p_g2l)) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0306: " "Error restoring Guid-to-Lid " "persistent database. Ignoring it\n"); lid_mgr_validate_db(p_mgr); } } /* we need to cleanup the empty ranges list */ while ((p_item = cl_qlist_remove_head(&p_mgr->free_ranges)) != cl_qlist_end(&p_mgr->free_ranges)) free((osm_lid_mgr_range_t *) p_item); /* first clean up the port_by_lid_tbl */ for (lid = 0; lid < cl_ptr_vector_get_size(p_discovered_vec); lid++) cl_ptr_vector_set(p_discovered_vec, lid, NULL); /* we if are in the first sweep and in reassign lids mode we should ignore all the available info and simply define one huge empty range */ if (p_mgr->p_subn->first_time_master_sweep == TRUE && p_mgr->p_subn->opt.reassign_lids == TRUE) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Skipping all lids as we are reassigning them\n"); p_range = malloc(sizeof(osm_lid_mgr_range_t)); if (p_range) p_range->min_lid = 1; goto AfterScanningLids; } /* go over all discovered ports and mark their entries */ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl); p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid); disc_min_lid = trim_lid(disc_min_lid); disc_max_lid = trim_lid(disc_max_lid); for (lid = disc_min_lid; lid <= disc_max_lid; lid++) cl_ptr_vector_set(p_discovered_vec, lid, p_port); /* make sure the guid2lid entry is valid. If not, clean it. */ if (osm_db_guid2lid_get(p_mgr->p_g2l, cl_ntoh64(osm_port_get_guid(p_port)), &db_min_lid, &db_max_lid)) continue; if (!p_port->p_node->sw || osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) num_lids = lmc_num_lids; else num_lids = 1; if (num_lids != 1 && ((db_min_lid & lmc_mask) != db_min_lid || db_max_lid - db_min_lid + 1 < num_lids)) { /* Not aligned, or not wide enough, then remove the entry */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Cleaning persistent entry for guid:" "0x%016" PRIx64 " illegal range:[0x%x:0x%x]\n", cl_ntoh64(osm_port_get_guid(p_port)), db_min_lid, db_max_lid); osm_db_guid2lid_delete(p_mgr->p_g2l, cl_ntoh64 (osm_port_get_guid(p_port))); for (lid = db_min_lid; lid <= db_max_lid; lid++) p_mgr->used_lids[lid] = 0; } } /* Our task is to find free lid ranges. A lid can be used if 1. a persistent assignment exists 2. the lid is used by a discovered port that does not have a persistent assignment. scan through all lid values of both the persistent table and discovered table. If the lid has an assigned port in the discovered table: * make sure the lid matches the persistent table, or * there is no other persistent assignment for that lid. * else cleanup the port_by_lid_tbl, mark this as empty range. Else if the lid does not have an entry in the persistent table mark it as free. */ /* find the range of lids to scan */ max_discovered_lid = (uint16_t) cl_ptr_vector_get_size(p_discovered_vec); max_persistent_lid = sizeof(p_mgr->used_lids) - 1; /* but the vectors have one extra entry for lid=0 */ if (max_discovered_lid) max_discovered_lid--; if (max_persistent_lid > max_discovered_lid) max_defined_lid = max_persistent_lid; else max_defined_lid = max_discovered_lid; for (lid = 1; lid <= max_defined_lid; lid++) { is_free = TRUE; /* first check to see if the lid is used by a persistent assignment */ if (lid <= max_persistent_lid && p_mgr->used_lids[lid]) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%04x is not free as its mapped by the " "persistent db\n", lid); is_free = FALSE; /* check this is a discovered port */ } else if (lid <= max_discovered_lid && (p_port = cl_ptr_vector_get(p_discovered_vec, lid))) { /* we have a port. Now lets see if we can preserve its lid range. */ /* For that, we need to make sure: 1. The port has a (legal) persistency entry. Then the local lid is free (we will use the persistency value). 2. Can the port keep its local assignment? a. Make sure the lid is aligned. b. Make sure all needed lids (for the lmc) are free according to persistency table. */ /* qualify the guid of the port is not persistently mapped to another range */ if (!osm_db_guid2lid_get(p_mgr->p_g2l, cl_ntoh64 (osm_port_get_guid(p_port)), &db_min_lid, &db_max_lid)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%04x is free as it was " "discovered but mapped by the " "persistent db to [0x%04x:0x%04x]\n", lid, db_min_lid, db_max_lid); } else { /* can the port keep its assignment ? */ /* get the lid range of that port, and the required number of lids we are about to assign to it */ osm_port_get_lid_range_ho(p_port, &disc_min_lid, &disc_max_lid); if (!p_port->p_node->sw || osm_switch_sp0_is_lmc_capable (p_port->p_node->sw, p_mgr->p_subn)) { disc_max_lid = disc_min_lid + lmc_num_lids - 1; num_lids = lmc_num_lids; } else num_lids = 1; /* Make sure the lid is aligned */ if (num_lids != 1 && (disc_min_lid & lmc_mask) != disc_min_lid) { /* The lid cannot be used */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%04x is free as it was " "discovered but not aligned\n", lid); } else { /* check that all needed lids are not persistently mapped */ is_free = FALSE; for (req_lid = disc_min_lid + 1; req_lid <= disc_max_lid; req_lid++) { if (req_lid <= max_persistent_lid && p_mgr->used_lids[req_lid]) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%04x is free as it was discovered " "but mapped\n", lid); is_free = TRUE; break; } } if (is_free == FALSE) { /* This port will use its local lid, and consume the entire required lid range. Thus we can skip that range. */ /* If the disc_max_lid is greater then lid, we can skip right to it, since we've done all neccessary checks on the lids in between. */ if (disc_max_lid > lid) lid = disc_max_lid; } } } } if (is_free) { if (p_range) p_range->max_lid = lid; else { p_range = malloc(sizeof(osm_lid_mgr_range_t)); if (p_range) { p_range->min_lid = lid; p_range->max_lid = lid; } } /* this lid is used so we need to finalize the previous free range */ } else if (p_range) { cl_qlist_insert_tail(&p_mgr->free_ranges, &p_range->item); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "new free lid range [%u:%u]\n", p_range->min_lid, p_range->max_lid); p_range = NULL; } } AfterScanningLids: /* after scanning all known lids we need to extend the last range to the max allowed lid */ if (!p_range) { p_range = malloc(sizeof(osm_lid_mgr_range_t)); /* The p_range can be NULL in one of 2 cases: 1. If max_defined_lid == 0. In this case, we want the entire range. 2. If all lids discovered in the loop where mapped. In this case, no free range exists and we want to define it after the last mapped lid. */ if (p_range) p_range->min_lid = lid; } if (p_range) { p_range->max_lid = p_mgr->p_subn->max_ucast_lid_ho; cl_qlist_insert_tail(&p_mgr->free_ranges, &p_range->item); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "final free lid range [%u:%u]\n", p_range->min_lid, p_range->max_lid); } OSM_LOG_EXIT(p_mgr->p_log); return status; } /********************************************************************** check if the given range of lids is free **********************************************************************/ static boolean_t lid_mgr_is_range_not_persistent(IN osm_lid_mgr_t * p_mgr, IN uint16_t lid, IN uint16_t num_lids) { uint16_t i; for (i = lid; i < lid + num_lids; i++) if (p_mgr->used_lids[i]) return FALSE; return TRUE; } /********************************************************************** find a free lid range **********************************************************************/ static void lid_mgr_find_free_lid_range(IN osm_lid_mgr_t * p_mgr, IN uint8_t num_lids, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid) { uint16_t lid; cl_list_item_t *p_item; cl_list_item_t *p_next_item; osm_lid_mgr_range_t *p_range = NULL; uint8_t lmc_num_lids; uint16_t lmc_mask; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "LMC = %u, number LIDs = %u\n", p_mgr->p_subn->opt.lmc, num_lids); lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc); lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1); /* Search the list of free lid ranges for a range which is big enough */ p_item = cl_qlist_head(&p_mgr->free_ranges); while (p_item != cl_qlist_end(&p_mgr->free_ranges)) { p_next_item = cl_qlist_next(p_item); p_range = (osm_lid_mgr_range_t *) p_item; lid = p_range->min_lid; /* if we require more then one lid we must align to LMC */ if (num_lids > 1) { if ((lid & lmc_mask) != lid) lid = (lid + lmc_num_lids) & lmc_mask; } /* but we can be out of the range */ if (lid + num_lids - 1 <= p_range->max_lid) { /* ok let us use that range */ if (lid + num_lids - 1 == p_range->max_lid) { /* we consumed the entire range */ cl_qlist_remove_item(&p_mgr->free_ranges, p_item); free(p_item); } else /* only update the available range */ p_range->min_lid = lid + num_lids; *p_min_lid = lid; *p_max_lid = (uint16_t) (lid + num_lids - 1); return; } p_item = p_next_item; } /* Couldn't find a free range of lids. */ *p_min_lid = *p_max_lid = 0; /* if we run out of lids, give an error and abort! */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0307: " "OPENSM RAN OUT OF LIDS!!!\n"); CL_ASSERT(0); } static void lid_mgr_cleanup_discovered_port_lid_range(IN osm_lid_mgr_t * p_mgr, IN osm_port_t * p_port) { cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl; uint16_t lid, min_lid, max_lid; uint16_t max_tbl_lid = (uint16_t) (cl_ptr_vector_get_size(p_discovered_vec)); osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid); min_lid = trim_lid(min_lid); max_lid = trim_lid(max_lid); for (lid = min_lid; lid <= max_lid; lid++) if (lid < max_tbl_lid && p_port == cl_ptr_vector_get(p_discovered_vec, lid)) cl_ptr_vector_set(p_discovered_vec, lid, NULL); } /********************************************************************** 0.1 if the port info lid matches the guid2lid return 0 0.2 if the port info has a lid and that range is empty in port_lid_tbl, return 0 and update the port_lid_tbl and guid2lid 0.3 else find an empty space in port_lid_tbl, update the port_lid_tbl and guid2lid, return 1 to flag a change required. **********************************************************************/ static int lid_mgr_get_port_lid(IN osm_lid_mgr_t * p_mgr, IN osm_port_t * p_port, OUT uint16_t * p_min_lid, OUT uint16_t * p_max_lid) { uint16_t lid, min_lid, max_lid; uint64_t guid; uint8_t num_lids = (1 << p_mgr->p_subn->opt.lmc); int lid_changed = 0; uint16_t lmc_mask; OSM_LOG_ENTER(p_mgr->p_log); /* get the lid from the guid2lid */ guid = cl_ntoh64(osm_port_get_guid(p_port)); /* if the port is a base switch port 0 then we only need one lid */ if (p_port->p_node->sw && !osm_switch_sp0_is_lmc_capable(p_port->p_node->sw, p_mgr->p_subn)) num_lids = 1; if (p_mgr->p_subn->first_time_master_sweep == TRUE && p_mgr->p_subn->opt.reassign_lids == TRUE) goto AssignLid; lmc_mask = ~(num_lids - 1); /* if the port matches the guid2lid */ if (!osm_db_guid2lid_get(p_mgr->p_g2l, guid, &min_lid, &max_lid)) { *p_min_lid = min_lid; *p_max_lid = min_lid + num_lids - 1; if (min_lid == cl_ntoh16(osm_port_get_base_lid(p_port))) OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " matches its known lid:%u\n", guid, min_lid); else { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " with lid:%u " "does not match its known lid:%u\n", guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid); lid_mgr_cleanup_discovered_port_lid_range(p_mgr, p_port); /* we still need to send the setting to the target port */ lid_changed = 1; } goto NewLidSet; } else OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " has no persistent lid assigned\n", guid); /* if the port info carries a lid it must be lmc aligned and not mapped by the persistent storage */ min_lid = cl_ntoh16(osm_port_get_base_lid(p_port)); /* we want to ignore the discovered lid if we are also on first sweep of reassign lids flow */ if (min_lid) { /* make sure lid is valid */ if ((min_lid & lmc_mask) == min_lid) { /* is it free */ if (lid_mgr_is_range_not_persistent (p_mgr, min_lid, num_lids)) { *p_min_lid = min_lid; *p_max_lid = min_lid + num_lids - 1; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " lid range:[%u-%u] is free\n", guid, *p_min_lid, *p_max_lid); goto NewLidSet; } else OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " existing lid " "range:[%u:%u] is not free\n", guid, min_lid, min_lid + num_lids - 1); } else OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " existing lid range:" "[%u:%u] is not lmc aligned\n", guid, min_lid, min_lid + num_lids - 1); } AssignLid: /* first cleanup the existing discovered lid range */ lid_mgr_cleanup_discovered_port_lid_range(p_mgr, p_port); /* find an empty space */ lid_mgr_find_free_lid_range(p_mgr, num_lids, p_min_lid, p_max_lid); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "0x%016" PRIx64 " assigned a new lid range:[%u-%u]\n", guid, *p_min_lid, *p_max_lid); lid_changed = 1; NewLidSet: /* update the guid2lid db and used_lids */ osm_db_guid2lid_set(p_mgr->p_g2l, guid, *p_min_lid, *p_max_lid); for (lid = *p_min_lid; lid <= *p_max_lid; lid++) p_mgr->used_lids[lid] = 1; /* make sure the assigned lids are marked in port_lid_tbl */ for (lid = *p_min_lid; lid <= *p_max_lid; lid++) cl_ptr_vector_set(&p_mgr->p_subn->port_lid_tbl, lid, p_port); OSM_LOG_EXIT(p_mgr->p_log); return lid_changed; } /********************************************************************** Set to INIT the remote port of the given physical port **********************************************************************/ static void lid_mgr_set_remote_pi_state_to_init(IN osm_lid_mgr_t * p_mgr, IN osm_physp_t * p_physp) { osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp); if (p_rem_physp == NULL) return; /* but in some rare cases the remote side might be non responsive */ ib_port_info_set_port_state(&p_rem_physp->port_info, IB_LINK_INIT); } static int lid_mgr_set_physp_pi(IN osm_lid_mgr_t * p_mgr, IN osm_port_t * p_port, IN osm_physp_t * p_physp, IN ib_net16_t lid) { uint8_t payload[IB_SMP_DATA_SIZE]; ib_port_info_t *p_pi = (ib_port_info_t *) payload; const ib_port_info_t *p_old_pi; osm_madw_context_t context; osm_node_t *p_node; ib_api_status_t status; uint8_t mtu; uint8_t op_vls; uint8_t port_num; boolean_t send_set = FALSE; boolean_t send_client_rereg = FALSE; boolean_t update_mkey = FALSE; int ret = 0; OSM_LOG_ENTER(p_mgr->p_log); /* Don't bother doing anything if this Physical Port is not valid. This allows simplified code in the caller. */ if (!p_physp) goto Exit; port_num = osm_physp_get_port_num(p_physp); p_node = osm_physp_get_node_ptr(p_physp); if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0) { /* Switch ports that are not numbered 0 should not be set with the following attributes as they are set later (during NO_CHANGE state in link mgr). */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Skipping switch port %u, GUID 0x%016" PRIx64 "\n", port_num, cl_ntoh64(osm_physp_get_port_guid(p_physp))); goto Exit; } p_old_pi = &p_physp->port_info; /* First, copy existing parameters from the PortInfo attribute we already have for this node. Second, update with default values that we know must be set for every Physical Port and the LID and set the neighbor MTU field appropriately. Third, send the SMP to this physical port. */ memcpy(payload, p_old_pi, sizeof(ib_port_info_t)); /* Should never write back a value that is bigger then 3 in the PortPhysicalState field, so cannot simply copy! Actually we want to write there: port physical state - no change link down default state = polling port state - no change */ p_pi->state_info2 = 0x02; ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE); if (ib_port_info_get_link_down_def_state(p_pi) != ib_port_info_get_link_down_def_state(p_old_pi)) send_set = TRUE; /* didn't get PortInfo before */ if (!ib_port_info_get_port_state(p_old_pi)) send_set = TRUE; p_pi->m_key = p_mgr->p_subn->opt.m_key; if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) { update_mkey = TRUE; send_set = TRUE; } p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix; if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix, sizeof(p_pi->subnet_prefix))) send_set = TRUE; p_port->lid = lid; p_pi->base_lid = lid; if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid, sizeof(p_pi->base_lid))) { /* * Reset stored base_lid. * On successful send, we'll update it when we'll get a reply. */ osm_physp_set_base_lid(p_physp, 0); send_set = TRUE; p_mgr->dirty = TRUE; } /* We are updating the ports with our local sm_base_lid if for some reason currently received SM LID is different from our SM LID, need to send client reregister to this port */ p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid; if (memcmp(&p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid, sizeof(p_pi->master_sm_base_lid))) { send_client_rereg = TRUE; send_set = TRUE; } p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period; if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, sizeof(p_pi->m_key_lease_period))) send_set = TRUE; p_pi->mkey_lmc = 0; ib_port_info_set_mpb(p_pi, p_mgr->p_subn->opt.m_key_protect_bits); if (ib_port_info_get_mpb(p_pi) != ib_port_info_get_mpb(p_old_pi)) send_set = TRUE; /* we want to set the timeout for both the switch port 0 and the CA ports */ ib_port_info_set_timeout(p_pi, p_mgr->p_subn->opt.subnet_timeout); if (ib_port_info_get_timeout(p_pi) != ib_port_info_get_timeout(p_old_pi)) send_set = TRUE; if (port_num != 0) { /* CAs don't have a port 0, and for switch port 0, the state bits are ignored. This is not the switch management port */ p_pi->link_width_enabled = p_old_pi->link_width_supported; if (memcmp(&p_pi->link_width_enabled, &p_old_pi->link_width_enabled, sizeof(p_pi->link_width_enabled))) send_set = TRUE; /* p_pi->mkey_lmc is initialized earlier */ ib_port_info_set_lmc(p_pi, p_mgr->p_subn->opt.lmc); if (ib_port_info_get_lmc(p_pi) != ib_port_info_get_lmc(p_old_pi)) send_set = TRUE; /* calc new op_vls and mtu */ op_vls = osm_physp_calc_link_op_vls(p_mgr->p_log, p_mgr->p_subn, p_physp, ib_port_info_get_op_vls(p_old_pi)); mtu = osm_physp_calc_link_mtu(p_mgr->p_log, p_physp, ib_port_info_get_neighbor_mtu(p_old_pi)); ib_port_info_set_neighbor_mtu(p_pi, mtu); if (ib_port_info_get_neighbor_mtu(p_pi) != ib_port_info_get_neighbor_mtu(p_old_pi)) send_set = TRUE; ib_port_info_set_op_vls(p_pi, op_vls); if (ib_port_info_get_op_vls(p_pi) != ib_port_info_get_op_vls(p_old_pi)) send_set = TRUE; /* Several timeout mechanisms: */ ib_port_info_set_phy_and_overrun_err_thd(p_pi, p_mgr->p_subn->opt. local_phy_errors_threshold, p_mgr->p_subn->opt. overrun_errors_threshold); if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold, sizeof(p_pi->error_threshold))) send_set = TRUE; /* To reset the port state machine we can send PortInfo.State = DOWN. (see: 7.2.7 p171 lines:10-19) */ if (mtu != ib_port_info_get_neighbor_mtu(p_old_pi) || op_vls != ib_port_info_get_op_vls(p_old_pi)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Sending Link Down to GUID 0x%016" PRIx64 " port %d due to op_vls or " "mtu change. MTU:%u,%u VL_CAP:%u,%u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), port_num, mtu, ib_port_info_get_neighbor_mtu(p_old_pi), op_vls, ib_port_info_get_op_vls(p_old_pi)); /* we need to make sure the internal DB will follow the fact that the remote port is also going through "down" state into "init"... */ lid_mgr_set_remote_pi_state_to_init(p_mgr, p_physp); ib_port_info_set_port_state(p_pi, IB_LINK_DOWN); if (ib_port_info_get_port_state(p_pi) != ib_port_info_get_port_state(p_old_pi)) send_set = TRUE; } } else if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) { /* * Configure Enh. SP0: * Set MTU according to the mtu_cap. * Set LMC if lmc_esp0 is defined. */ ib_port_info_set_neighbor_mtu(p_pi, ib_port_info_get_mtu_cap (p_old_pi)); if (ib_port_info_get_neighbor_mtu(p_pi) != ib_port_info_get_neighbor_mtu(p_old_pi)) send_set = TRUE; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Updating neighbor_mtu on switch GUID 0x%016" PRIx64 " port 0 to:%u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), ib_port_info_get_neighbor_mtu(p_pi)); /* Configure LMC on enhanced SP0 */ if (p_mgr->p_subn->opt.lmc_esp0) { /* p_pi->mkey_lmc is initialized earlier */ ib_port_info_set_lmc(p_pi, p_mgr->p_subn->opt.lmc); if (ib_port_info_get_lmc(p_pi) != ib_port_info_get_lmc(p_old_pi)) send_set = TRUE; } } context.pi_context.node_guid = osm_node_get_node_guid(p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = TRUE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; /* For ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11: need to set the cli_rereg bit when current SM LID at the Host is different from our SM LID, also if we are in first_time_master_sweep, also if this port was just now discovered, then we should also set the cli_rereg bit (we know that the port was just discovered if its is_new field is set). */ if ((send_client_rereg || p_mgr->p_subn->first_time_master_sweep == TRUE || p_port->is_new) && !p_mgr->p_subn->opt.no_clients_rereg && (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Setting client rereg on %s, port %d\n", p_port->p_node->print_desc, p_port->p_physp->port_num); ib_port_info_set_client_rereg(p_pi, 1); context.pi_context.client_rereg = TRUE; send_set = TRUE; } else { ib_port_info_set_client_rereg(p_pi, 0); context.pi_context.client_rereg = FALSE; } /* We need to send the PortInfo Set request with the new sm_lid in the following cases: 1. There is a change in the values (send_set == TRUE) 2. first_time_master_sweep flag on the subnet is TRUE. This means the SM just became master, and it then needs to send a PortInfo Set to every port. */ if (p_mgr->p_subn->first_time_master_sweep == TRUE) send_set = TRUE; if (!send_set) goto Exit; status = osm_req_set(p_mgr->sm, osm_physp_get_dr_path_ptr(p_physp), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, cl_hton32(osm_physp_get_port_num(p_physp)), FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) ret = -1; /* If we sent a new mkey above, update our guid2mkey map now, on the assumption that the SubnSet succeeds */ if (update_mkey) osm_db_guid2mkey_set(p_mgr->p_subn->p_g2m, cl_ntoh64(p_physp->port_guid), cl_ntoh64(p_pi->m_key)); Exit: OSM_LOG_EXIT(p_mgr->p_log); return ret; } /********************************************************************** Processes our own node Lock must already be held. **********************************************************************/ static int lid_mgr_process_our_sm_node(IN osm_lid_mgr_t * p_mgr) { osm_port_t *p_port; uint16_t min_lid_ho; uint16_t max_lid_ho; int ret; OSM_LOG_ENTER(p_mgr->p_log); /* Acquire our own port object. */ p_port = osm_get_port_by_guid(p_mgr->p_subn, p_mgr->p_subn->sm_port_guid); if (!p_port) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 0308: " "Can't acquire SM's port object, GUID 0x%016" PRIx64 "\n", cl_ntoh64(p_mgr->p_subn->sm_port_guid)); ret = -1; goto Exit; } /* Determine the LID this SM will use for its own port. Be careful. With an LMC > 0, the bottom of the LID range becomes unusable, since port hardware will mask off least significant bits, leaving a LID of 0 (invalid). Therefore, make sure that we always configure the SM with a LID that has non-zero bits, even after LMC masking by hardware. */ lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Current base LID is %u\n", min_lid_ho); /* Update subnet object. */ p_mgr->p_subn->master_sm_base_lid = cl_hton16(min_lid_ho); p_mgr->p_subn->sm_base_lid = cl_hton16(min_lid_ho); OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Assigning SM's port 0x%016" PRIx64 "\n\t\t\t\tto LID range [%u,%u]\n", cl_ntoh64(osm_port_get_guid(p_port)), min_lid_ho, max_lid_ho); /* Set the PortInfo the Physical Port associated with this Port. */ ret = lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp, cl_hton16(min_lid_ho)); Exit: OSM_LOG_EXIT(p_mgr->p_log); return ret; } int osm_lid_mgr_process_sm(IN osm_lid_mgr_t * p_mgr) { int ret; OSM_LOG_ENTER(p_mgr->p_log); CL_ASSERT(p_mgr->p_subn->sm_port_guid); CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock); /* initialize the port_lid_tbl and empty ranges list following the persistent db */ lid_mgr_init_sweep(p_mgr); ret = lid_mgr_process_our_sm_node(p_mgr); CL_PLOCK_RELEASE(p_mgr->p_lock); OSM_LOG_EXIT(p_mgr->p_log); return ret; } /********************************************************************** 1 go through all ports in the subnet. 1.1 call lid_mgr_get_port_lid 1.2 if a change is required send the port info 2 if any change send the signal PENDING... **********************************************************************/ int osm_lid_mgr_process_subnet(IN osm_lid_mgr_t * p_mgr) { cl_qmap_t *p_port_guid_tbl; osm_port_t *p_port; ib_net64_t port_guid; int lid_changed, ret = 0; uint16_t min_lid_ho, max_lid_ho; CL_ASSERT(p_mgr); OSM_LOG_ENTER(p_mgr->p_log); CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock); CL_ASSERT(p_mgr->p_subn->sm_port_guid); p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl; for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl); p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { port_guid = osm_port_get_guid(p_port); /* Our own port is a special case in that we want to assign a LID to ourselves first, since we have to advertise that LID value to the other ports. For that reason, our node is treated separately and we will not add it to any of these lists. */ if (port_guid == p_mgr->p_subn->sm_port_guid) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Skipping our own port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); continue; } /* get the port lid range - we need to send it on first active sweep or if there was a change (the result of lid_mgr_get_port_lid) */ lid_changed = lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho); /* we can call the function to update the port info as it known to look for any field change and will only send an updated if required */ OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Assigned port 0x%016" PRIx64 ", %s LID [%u,%u]\n", cl_ntoh64(port_guid), lid_changed ? "new" : "", min_lid_ho, max_lid_ho); /* the proc returns the fact it sent a set port info */ if (lid_mgr_set_physp_pi(p_mgr, p_port, p_port->p_physp, cl_hton16(min_lid_ho))) ret = -1; } /* all ports */ /* store the guid to lid table in persistent db */ osm_db_store(p_mgr->p_g2l, p_mgr->p_subn->opt.fsync_high_avail_files); CL_PLOCK_RELEASE(p_mgr->p_lock); OSM_LOG_EXIT(p_mgr->p_log); return ret; } opensm-3.3.20/opensm/osm_lin_fwd_rcv.c0000644000205000001450000000763312273221506014640 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_lft_rcv_t. * This object represents the Linear Forwarding Table Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_LIN_FWD_RCV_C #include #include #include #include void osm_lft_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_smp_t *p_smp; uint32_t block_num; osm_switch_t *p_sw; osm_lft_context_t *p_lft_context; uint8_t *p_block; ib_net64_t node_guid; osm_epi_lft_change_event_t lft_change; ib_api_status_t status; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_block = ib_smp_get_payload_ptr(p_smp); block_num = cl_ntoh32(p_smp->attr_mod); /* Acquire the switch object for this switch. */ p_lft_context = osm_madw_get_lft_context_ptr(p_madw); node_guid = p_lft_context->node_guid; if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_sw = osm_get_switch_by_guid(sm->p_subn, node_guid); if (!p_sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0401: " "LFT received for nonexistent node " "0x%" PRIx64 "\n", cl_ntoh64(node_guid)); } else { status = osm_switch_set_lft_block(p_sw, p_block, block_num); if (status == IB_SUCCESS) { if (sm->p_subn->first_time_master_sweep == FALSE) { lft_change.p_sw = p_sw; lft_change.flags = LFT_CHANGED_BLOCK; lft_change.lft_top = 0; lft_change.block_num = block_num; osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_LFT_CHANGE, &lft_change); } } else { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0402: " "Setting forwarding table block %u failed (%s)" ", Switch 0x%" PRIx64 " %s\n", block_num, ib_get_err_str(status), cl_ntoh64(node_guid), p_sw->p_node->print_desc); } } CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_link_mgr.c0000644000205000001450000004363412370646140014152 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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 osm_link_mgr_t. * This file implements the Link Manager object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_LINK_MGR_C #include #include #include #include #include #include #include static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp) { osm_opensm_t *p_osm = sm->p_subn->p_osm; struct osm_routing_engine *re = p_osm->routing_engine_used; ib_net16_t slid; ib_net16_t smlid; uint8_t sl; OSM_LOG_ENTER(sm->p_log); if (!(re && re->path_sl && (slid = osm_physp_get_base_lid(p_physp)))) { /* * Use default SL if routing engine does not provide a * path SL lookup callback. */ OSM_LOG_EXIT(sm->p_log); return sm->p_subn->opt.sm_sl; } smlid = sm->p_subn->sm_base_lid; /* Call into routing engine to find proper SL */ sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl, slid, smlid); OSM_LOG_EXIT(sm->p_log); return sl; } static int link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * p_physp, IN uint8_t port_state) { uint8_t payload[IB_SMP_DATA_SIZE], payload2[IB_SMP_DATA_SIZE]; ib_port_info_t *p_pi = (ib_port_info_t *) payload; ib_mlnx_ext_port_info_t *p_epi = (ib_mlnx_ext_port_info_t *) payload2; const ib_port_info_t *p_old_pi; const ib_mlnx_ext_port_info_t *p_old_epi; osm_madw_context_t context; osm_node_t *p_node; ib_api_status_t status; uint8_t port_num, mtu, op_vls, smsl = OSM_DEFAULT_SL; boolean_t esp0 = FALSE, send_set = FALSE, send_set2 = FALSE; osm_physp_t *p_remote_physp, *physp0 = NULL; int issue_ext = 0, fdr10_change = 0; int ret = 0; ib_net32_t attr_mod, cap_mask; boolean_t update_mkey = FALSE; ib_net64_t m_key = 0; osm_port_t *p_port; OSM_LOG_ENTER(sm->p_log); p_node = osm_physp_get_node_ptr(p_physp); p_old_pi = &p_physp->port_info; port_num = osm_physp_get_port_num(p_physp); memcpy(payload, p_old_pi, sizeof(ib_port_info_t)); if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH || port_num == 0) { /* Need to make sure LID and SMLID fields in PortInfo are not 0 */ if (!p_pi->base_lid) { p_port = osm_get_port_by_guid(sm->p_subn, osm_physp_get_port_guid(p_physp)); p_pi->base_lid = p_port->lid; sm->lid_mgr.dirty = TRUE; send_set = TRUE; } /* we are initializing the ports with our local sm_base_lid */ p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid; if (p_pi->master_sm_base_lid != p_old_pi->master_sm_base_lid) send_set = TRUE; } if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) physp0 = osm_node_get_physp_ptr(p_node, 0); if (port_num == 0) { /* CAs don't have a port 0, and for switch port 0, we need to check if this is enhanced or base port 0. For base port 0 the following parameters are not valid (IBA 1.2.1 p.830 table 146). */ if (!p_node->sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: " "Cannot find switch by guid: 0x%" PRIx64 "\n", cl_ntoh64(p_node->node_info.node_guid)); goto Exit; } if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) { /* Even for base port 0 we might have to set smsl (if we are using lash routing) */ smsl = link_mgr_get_smsl(sm, p_physp); if (smsl != ib_port_info_get_master_smsl(p_old_pi)) { send_set = TRUE; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting SMSL to %d on port 0 GUID 0x%016" PRIx64 "\n", smsl, cl_ntoh64(osm_physp_get_port_guid (p_physp))); /* Enter if base lid and master_sm_lid didn't change */ } else if (send_set == FALSE) { /* This means the switch doesn't support enhanced port 0 and we don't need to change SMSL. Can skip it. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Skipping port 0, GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid (p_physp))); goto Exit; } } else esp0 = TRUE; } /* Should never write back a value that is bigger then 3 in the PortPhysicalState field - so can not simply copy! Actually we want to write there: port physical state - no change, link down default state = polling port state - as requested. */ p_pi->state_info2 = 0x02; ib_port_info_set_port_state(p_pi, port_state); /* Determine ports' M_Key */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p_physp) != 0) m_key = ib_port_info_get_m_key(&physp0->port_info); else m_key = ib_port_info_get_m_key(p_pi); /* Check whether this is base port0 smsl handling only */ if (port_num == 0 && esp0 == FALSE) { ib_port_info_set_master_smsl(p_pi, smsl); goto Send; } /* PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0 */ if (ib_port_info_get_link_down_def_state(p_pi) != ib_port_info_get_link_down_def_state(p_old_pi)) send_set = TRUE; /* didn't get PortInfo before */ if (!ib_port_info_get_port_state(p_old_pi)) send_set = TRUE; /* we only change port fields if we do not change state */ if (port_state == IB_LINK_NO_CHANGE) { /* The following fields are relevant only for CA port, router, or Enh. SP0 */ if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH || port_num == 0) { p_pi->m_key = sm->p_subn->opt.m_key; if (memcmp(&p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key))) { update_mkey = TRUE; send_set = TRUE; } p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix; if (memcmp(&p_pi->subnet_prefix, &p_old_pi->subnet_prefix, sizeof(p_pi->subnet_prefix))) send_set = TRUE; smsl = link_mgr_get_smsl(sm, p_physp); if (smsl != ib_port_info_get_master_smsl(p_old_pi)) { ib_port_info_set_master_smsl(p_pi, smsl); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting SMSL to %d on GUID 0x%016" PRIx64 ", port %d\n", smsl, cl_ntoh64(osm_physp_get_port_guid (p_physp)), port_num); send_set = TRUE; } p_pi->m_key_lease_period = sm->p_subn->opt.m_key_lease_period; if (memcmp(&p_pi->m_key_lease_period, &p_old_pi->m_key_lease_period, sizeof(p_pi->m_key_lease_period))) send_set = TRUE; p_pi->mkey_lmc = 0; ib_port_info_set_mpb(p_pi, sm->p_subn->opt.m_key_protect_bits); if (esp0 == FALSE || sm->p_subn->opt.lmc_esp0) ib_port_info_set_lmc(p_pi, sm->p_subn->opt.lmc); if (ib_port_info_get_lmc(p_old_pi) != ib_port_info_get_lmc(p_pi) || ib_port_info_get_mpb(p_old_pi) != ib_port_info_get_mpb(p_pi)) send_set = TRUE; ib_port_info_set_timeout(p_pi, sm->p_subn->opt. subnet_timeout); if (ib_port_info_get_timeout(p_pi) != ib_port_info_get_timeout(p_old_pi)) send_set = TRUE; } /* Several timeout mechanisms: */ p_remote_physp = osm_physp_get_remote(p_physp); if (port_num != 0 && p_remote_physp) { if (osm_node_get_type(osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_ROUTER) { ib_port_info_set_hoq_lifetime(p_pi, sm->p_subn-> opt. leaf_head_of_queue_lifetime); } else if (osm_node_get_type (osm_physp_get_node_ptr(p_physp)) == IB_NODE_TYPE_SWITCH) { /* Is remote end CA or router (a leaf port) ? */ if (osm_node_get_type (osm_physp_get_node_ptr(p_remote_physp)) != IB_NODE_TYPE_SWITCH) { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. leaf_head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. leaf_vl_stall_count); } else { ib_port_info_set_hoq_lifetime(p_pi, sm-> p_subn-> opt. head_of_queue_lifetime); ib_port_info_set_vl_stall_count(p_pi, sm-> p_subn-> opt. vl_stall_count); } } if (ib_port_info_get_hoq_lifetime(p_pi) != ib_port_info_get_hoq_lifetime(p_old_pi) || ib_port_info_get_vl_stall_count(p_pi) != ib_port_info_get_vl_stall_count(p_old_pi)) send_set = TRUE; } ib_port_info_set_phy_and_overrun_err_thd(p_pi, sm->p_subn->opt. local_phy_errors_threshold, sm->p_subn->opt. overrun_errors_threshold); if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold, sizeof(p_pi->error_threshold))) send_set = TRUE; /* Set the easy common parameters for all port types, then determine the neighbor MTU. */ p_pi->link_width_enabled = p_old_pi->link_width_supported; if (memcmp(&p_pi->link_width_enabled, &p_old_pi->link_width_enabled, sizeof(p_pi->link_width_enabled))) send_set = TRUE; if (sm->p_subn->opt.force_link_speed && (sm->p_subn->opt.force_link_speed != 15 || ib_port_info_get_link_speed_enabled(p_pi) != ib_port_info_get_link_speed_sup(p_pi))) { ib_port_info_set_link_speed_enabled(p_pi, sm->p_subn->opt. force_link_speed); if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed, sizeof(p_pi->link_speed))) send_set = TRUE; } if (sm->p_subn->opt.fdr10 && p_physp->ext_port_info.link_speed_supported & FDR10) { if (sm->p_subn->opt.fdr10 == 1) { /* enable */ if (!(p_physp->ext_port_info.link_speed_enabled & FDR10)) fdr10_change = 1; } else { /* disable */ if (p_physp->ext_port_info.link_speed_enabled & FDR10) fdr10_change = 1; } if (fdr10_change) { p_old_epi = &p_physp->ext_port_info; memcpy(payload2, p_old_epi, sizeof(ib_mlnx_ext_port_info_t)); p_epi->state_change_enable = 0x01; if (sm->p_subn->opt.fdr10 == 1) p_epi->link_speed_enabled = FDR10; else p_epi->link_speed_enabled = 0; send_set2 = TRUE; } } if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p_physp) != 0) { cap_mask = physp0->port_info.capability_mask; } else cap_mask = p_pi->capability_mask; if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) issue_ext = 1; /* Do peer ports support extended link speeds ? */ if (port_num != 0 && p_remote_physp) { osm_physp_t *rphysp0; ib_net32_t rem_cap_mask; if (osm_node_get_type(p_remote_physp->p_node) == IB_NODE_TYPE_SWITCH) { rphysp0 = osm_node_get_physp_ptr(p_remote_physp->p_node, 0); rem_cap_mask = rphysp0->port_info.capability_mask; } else rem_cap_mask = p_remote_physp->port_info.capability_mask; if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS && rem_cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) { if (sm->p_subn->opt.force_link_speed_ext && (sm->p_subn->opt.force_link_speed_ext != IB_LINK_SPEED_EXT_SET_LSES || p_pi->link_speed_ext_enabled != ib_port_info_get_link_speed_ext_sup(p_pi))) { p_pi->link_speed_ext_enabled = sm->p_subn->opt.force_link_speed_ext; if (memcmp(&p_pi->link_speed_ext_enabled, &p_old_pi->link_speed_ext_enabled, sizeof(p_pi->link_speed_ext_enabled))) send_set = TRUE; } } } /* calc new op_vls and mtu */ op_vls = osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp, ib_port_info_get_op_vls(p_old_pi)); mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp, ib_port_info_get_neighbor_mtu(p_old_pi)); ib_port_info_set_neighbor_mtu(p_pi, mtu); if (ib_port_info_get_neighbor_mtu(p_pi) != ib_port_info_get_neighbor_mtu(p_old_pi)) send_set = TRUE; ib_port_info_set_op_vls(p_pi, op_vls); if (ib_port_info_get_op_vls(p_pi) != ib_port_info_get_op_vls(p_old_pi)) send_set = TRUE; /* provide the vl_high_limit from the qos mgr */ if (sm->p_subn->opt.qos && p_physp->vl_high_limit != p_old_pi->vl_high_limit) { send_set = TRUE; p_pi->vl_high_limit = p_physp->vl_high_limit; } } Send: context.pi_context.active_transition = FALSE; if (port_state != IB_LINK_NO_CHANGE && port_state != ib_port_info_get_port_state(p_old_pi)) { send_set = TRUE; if (port_state == IB_LINK_ACTIVE) context.pi_context.active_transition = TRUE; } context.pi_context.node_guid = osm_node_get_node_guid(p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = TRUE; context.pi_context.light_sweep = FALSE; context.pi_context.client_rereg = FALSE; /* We need to send the PortInfoSet request with the new sm_lid in the following cases: 1. There is a change in the values (send_set == TRUE) 2. This is a switch external port (so it wasn't handled yet by osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE, which means the SM just became master, and it then needs to send at PortInfoSet to every port. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num && sm->p_subn->first_time_master_sweep == TRUE) send_set = TRUE; if (!send_set) goto SEND_EPI; attr_mod = cl_hton32(port_num); if (issue_ext) attr_mod |= cl_hton32(1 << 31); /* AM SMSupportExtendedSpeeds */ status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, attr_mod, FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (status) ret = -1; /* If we sent a new mkey above, update our guid2mkey map now, on the assumption that the SubnSet succeeds */ if (update_mkey) osm_db_guid2mkey_set(sm->p_subn->p_g2m, cl_ntoh64(p_physp->port_guid), cl_ntoh64(p_pi->m_key)); SEND_EPI: if (send_set2) { status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload2, sizeof(payload2), IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO, cl_hton32(port_num), FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (status) ret = -1; } Exit: OSM_LOG_EXIT(sm->p_log); return ret; } static int link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node, IN const uint8_t link_state) { osm_physp_t *p_physp, *p_physp_remote; uint32_t i, num_physp; int ret = 0; uint8_t current_state; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Node 0x%" PRIx64 " going to %s\n", cl_ntoh64(osm_node_get_node_guid(p_node)), ib_get_port_state_str(link_state)); /* Set the PortInfo for every Physical Port associated with this Port. Start iterating with port 1, since the linkstate is not applicable to the management port on switches. */ num_physp = osm_node_get_num_physp(p_node); for (i = 0; i < num_physp; i++) { /* Don't bother doing anything if this Physical Port is not valid. or if the state of the port is already better then the specified state. */ p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i); if (!p_physp) continue; current_state = osm_physp_get_port_state(p_physp); if (current_state == IB_LINK_DOWN) continue; /* Set PortState to DOWN in case Remote Physical Port is unreachable. We have to check this for all ports, except port zero. */ p_physp_remote = osm_physp_get_remote(p_physp); if ((i != 0) && (!p_physp_remote || !osm_physp_is_valid(p_physp_remote))) { if (current_state != IB_LINK_INIT) link_mgr_set_physp_pi(sm, p_physp, IB_LINK_DOWN); continue; } /* Normally we only send state update if state is lower then required state. However, we need to send update if no state change required. */ if (link_state != IB_LINK_NO_CHANGE && link_state <= current_state) OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Physical port %u already %s. Skipping\n", p_physp->port_num, ib_get_port_state_str(current_state)); else if (link_mgr_set_physp_pi(sm, p_physp, link_state)) ret = -1; } OSM_LOG_EXIT(sm->p_log); return ret; } int osm_link_mgr_process(osm_sm_t * sm, IN const uint8_t link_state) { cl_qmap_t *p_node_guid_tbl; osm_node_t *p_node; int ret = 0; OSM_LOG_ENTER(sm->p_log); p_node_guid_tbl = &sm->p_subn->node_guid_tbl; CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl); p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) if (link_mgr_process_node(sm, p_node, link_state)) ret = -1; CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); return ret; } opensm-3.3.20/opensm/osm_mcast_fwd_rcv.c0000644000205000001450000001004212273221507015152 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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 osm_mft_rcv_t. * This object represents the Multicast Forwarding Table Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_MCAST_FWD_RCV_C #include #include #include #include #include void osm_mft_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_smp_t *p_smp; uint32_t block_num; uint8_t position; osm_switch_t *p_sw; osm_mft_context_t *p_mft_context; uint16_t *p_block; ib_net64_t node_guid; ib_api_status_t status; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_block = ib_smp_get_payload_ptr(p_smp); block_num = cl_ntoh32(p_smp->attr_mod) & IB_MCAST_BLOCK_ID_MASK_HO; position = (uint8_t) ((cl_ntoh32(p_smp->attr_mod) & IB_MCAST_POSITION_MASK_HO) >> IB_MCAST_POSITION_SHIFT); /* Acquire the switch object for this switch. */ p_mft_context = osm_madw_get_mft_context_ptr(p_madw); node_guid = p_mft_context->node_guid; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting MFT block %u, position %u, " "Switch 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n", block_num, position, cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_sw = osm_get_switch_by_guid(sm->p_subn, node_guid); if (!p_sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0801: " "MFT received for nonexistent node " "0x%016" PRIx64 "\n", cl_ntoh64(node_guid)); } else { status = osm_switch_set_mft_block(p_sw, p_block, (uint16_t) block_num, position); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0802: " "Setting MFT block failed (%s)" ", Switch 0x%016" PRIx64 " (%s), block %u, position %u\n", ib_get_err_str(status), cl_ntoh64(node_guid), p_sw->p_node->print_desc, block_num, position); } } CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_mcast_mgr.c0000644000205000001450000010413612623635774014333 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2010 HNR Consulting. All rights reserved. * Copyright (C) 2012-2013 Tokyo Institute of Technology. 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 osm_mcast_mgr_t. * This file implements the Multicast Manager object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_MCAST_MGR_C #include #include #include #include #include #include #include #include static osm_mcast_work_obj_t *mcast_work_obj_new(IN osm_port_t * p_port) { osm_mcast_work_obj_t *p_obj; /* clean allocated memory to avoid assertion when trying to insert to qlist. see cl_qlist_insert_tail(): CL_ASSERT(p_list_item->p_list != p_list) */ p_obj = malloc(sizeof(*p_obj)); if (p_obj) { memset(p_obj, 0, sizeof(*p_obj)); p_obj->p_port = p_port; } return p_obj; } static void mcast_work_obj_delete(IN osm_mcast_work_obj_t * p_wobj) { free(p_wobj); } int osm_mcast_make_port_list_and_map(cl_qlist_t * list, cl_qmap_t * map, osm_mgrp_box_t * mbox) { cl_map_item_t *map_item; cl_list_item_t *list_item; osm_mgrp_t *mgrp; osm_mcm_port_t *mcm_port; osm_mcast_work_obj_t *wobj; cl_qmap_init(map); cl_qlist_init(list); for (list_item = cl_qlist_head(&mbox->mgrp_list); list_item != cl_qlist_end(&mbox->mgrp_list); list_item = cl_qlist_next(list_item)) { mgrp = cl_item_obj(list_item, mgrp, list_item); for (map_item = cl_qmap_head(&mgrp->mcm_port_tbl); map_item != cl_qmap_end(&mgrp->mcm_port_tbl); map_item = cl_qmap_next(map_item)) { /* Acquire the port object for this port guid, then create the new worker object to build the list. */ mcm_port = cl_item_obj(map_item, mcm_port, map_item); if (cl_qmap_get(map, mcm_port->port->guid) != cl_qmap_end(map)) continue; wobj = mcast_work_obj_new(mcm_port->port); if (!wobj) return -1; cl_qlist_insert_tail(list, &wobj->list_item); cl_qmap_insert(map, mcm_port->port->guid, &wobj->map_item); } } return 0; } void osm_mcast_drop_port_list(cl_qlist_t * list) { while (cl_qlist_count(list)) mcast_work_obj_delete((osm_mcast_work_obj_t *) cl_qlist_remove_head(list)); } void osm_purge_mtree(osm_sm_t * sm, IN osm_mgrp_box_t * mbox) { OSM_LOG_ENTER(sm->p_log); if (mbox->root) osm_mtree_destroy(mbox->root); mbox->root = NULL; OSM_LOG_EXIT(sm->p_log); } static void create_mgrp_switch_map(cl_qmap_t * m, cl_qlist_t * port_list) { osm_mcast_work_obj_t *wobj; osm_port_t *port; osm_switch_t *sw; ib_net64_t guid; cl_list_item_t *i; cl_qmap_init(m); for (i = cl_qlist_head(port_list); i != cl_qlist_end(port_list); i = cl_qlist_next(i)) { wobj = cl_item_obj(i, wobj, list_item); port = wobj->p_port; if (port->p_node->sw) { sw = port->p_node->sw; sw->is_mc_member = 1; } else if (port->p_physp->p_remote_physp) { sw = port->p_physp->p_remote_physp->p_node->sw; sw->num_of_mcm++; } else continue; guid = osm_node_get_node_guid(sw->p_node); if (cl_qmap_get(m, guid) == cl_qmap_end(m)) cl_qmap_insert(m, guid, &sw->mgrp_item); } } static void destroy_mgrp_switch_map(cl_qmap_t * m) { osm_switch_t *sw; cl_map_item_t *i; for (i = cl_qmap_head(m); i != cl_qmap_end(m); i = cl_qmap_next(i)) { sw = cl_item_obj(i, sw, mgrp_item); sw->num_of_mcm = 0; sw->is_mc_member = 0; } cl_qmap_remove_all(m); } /********************************************************************** Calculate the maximal "min hops" from the given switch to any of the group HCAs **********************************************************************/ #ifdef OSM_VENDOR_INTF_ANAFA static float mcast_mgr_compute_avg_hops(osm_sm_t * sm, cl_qmap_t * m, const osm_switch_t * this_sw) { float avg_hops = 0; uint32_t hops = 0; uint32_t num_ports = 0; uint16_t lid; uint32_t least_hops; cl_map_item_t *i; osm_switch_t *sw; OSM_LOG_ENTER(sm->p_log); for (i = cl_qmap_head(m); i != cl_qmap_end(m); i = cl_qmap_next(i)) { sw = cl_item_obj(i, sw, mcast_item); lid = cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0)); least_hops = osm_switch_get_least_hops(this_sw, lid); /* for all host that are MC members and attached to the switch, we should add the (least_hops + 1) * number_of_such_hosts. If switch itself is in the MC, we should add the least_hops only */ hops += (least_hops + 1) * sw->num_of_mcm + least_hops * sw->is_mc_member; num_ports += sw->num_of_mcm + sw->is_mc_member; } /* We shouldn't be here if there aren't any ports in the group. */ CL_ASSERT(num_ports); avg_hops = (float)(hops / num_ports); OSM_LOG_EXIT(sm->p_log); return avg_hops; } #else static float mcast_mgr_compute_max_hops(osm_sm_t * sm, cl_qmap_t * m, const osm_switch_t * this_sw) { uint32_t max_hops = 0, hops; uint16_t lid; cl_map_item_t *i; osm_switch_t *sw; OSM_LOG_ENTER(sm->p_log); /* For each member of the multicast group, compute the number of hops to its base LID. */ for (i = cl_qmap_head(m); i != cl_qmap_end(m); i = cl_qmap_next(i)) { sw = cl_item_obj(i, sw, mgrp_item); lid = cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0)); hops = osm_switch_get_least_hops(this_sw, lid); if (!sw->is_mc_member) hops += 1; if (hops > max_hops) max_hops = hops; } /* Note that at this point we might get (max_hops == 0), which means that there's only one member in the mcast group, and it's the current switch */ OSM_LOG_EXIT(sm->p_log); return (float)max_hops; } #endif /********************************************************************** This function attempts to locate the optimal switch for the center of the spanning tree. The current algorithm chooses a switch with the lowest average hop count to the members of the multicast group. **********************************************************************/ static osm_switch_t *mcast_mgr_find_optimal_switch(osm_sm_t * sm, cl_qlist_t * list) { cl_qmap_t mgrp_sw_map; cl_qmap_t *p_sw_tbl; osm_switch_t *p_sw, *p_best_sw = NULL; float hops = 0; float best_hops = 10000; /* any big # will do */ OSM_LOG_ENTER(sm->p_log); p_sw_tbl = &sm->p_subn->sw_guid_tbl; create_mgrp_switch_map(&mgrp_sw_map, list); for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) { if (!osm_switch_supports_mcast(p_sw)) continue; #ifdef OSM_VENDOR_INTF_ANAFA hops = mcast_mgr_compute_avg_hops(sm, &mgrp_sw_map, p_sw); #else hops = mcast_mgr_compute_max_hops(sm, &mgrp_sw_map, p_sw); #endif OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Switch 0x%016" PRIx64 ", hops = %f\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), hops); if (hops < best_hops) { p_best_sw = p_sw; best_hops = hops; } } if (p_best_sw) OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Best switch is 0x%" PRIx64 " (%s), hops = %f\n", cl_ntoh64(osm_node_get_node_guid(p_best_sw->p_node)), p_best_sw->p_node->print_desc, best_hops); else OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "No multicast capable switches detected\n"); destroy_mgrp_switch_map(&mgrp_sw_map); OSM_LOG_EXIT(sm->p_log); return p_best_sw; } /********************************************************************** This function returns the existing or optimal root switch for the tree. **********************************************************************/ osm_switch_t *osm_mcast_mgr_find_root_switch(osm_sm_t * sm, cl_qlist_t *list) { osm_switch_t *p_sw = NULL; OSM_LOG_ENTER(sm->p_log); /* We always look for the best multicast tree root switch. Otherwise since we always start with a a single join the root will be always on the first switch attached to it. - Very bad ... */ p_sw = mcast_mgr_find_optimal_switch(sm, list); OSM_LOG_EXIT(sm->p_log); return p_sw; } static int mcast_mgr_set_mft_block(osm_sm_t * sm, IN osm_switch_t * p_sw, uint32_t block_num, uint32_t position) { osm_node_t *p_node; osm_physp_t *p_physp; osm_dr_path_t *p_path; osm_madw_context_t context; ib_api_status_t status; uint32_t block_id_ho; osm_mcast_tbl_t *p_tbl; ib_net16_t block[IB_MCAST_BLOCK_SIZE]; int ret = 0; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); p_node = p_sw->p_node; CL_ASSERT(p_node); p_physp = osm_node_get_physp_ptr(p_node, 0); p_path = osm_physp_get_dr_path_ptr(p_physp); /* Send multicast forwarding table blocks to the switch as long as the switch indicates it has blocks needing configuration. */ context.mft_context.node_guid = osm_node_get_node_guid(p_node); context.mft_context.set_method = TRUE; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); if (osm_mcast_tbl_get_block(p_tbl, (uint16_t) block_num, (uint8_t) position, block)) { block_id_ho = block_num + (position << 28); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Writing MFT block %u position %u to switch 0x%" PRIx64 "\n", block_num, position, cl_ntoh64(context.mft_context.node_guid)); status = osm_req_set(sm, p_path, (void *)block, sizeof(block), IB_MAD_ATTR_MCAST_FWD_TBL, cl_hton32(block_id_ho), FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A02: " "Sending multicast fwd. tbl. block 0x%X to %s " "failed (%s)\n", block_id_ho, p_node->print_desc, ib_get_err_str(status)); ret = -1; } } OSM_LOG_EXIT(sm->p_log); return ret; } /********************************************************************** This is part of the recursive function to compute the paths in the spanning tree that emanate from this switch. On input, the p_list contains the group members that must be routed from this switch. **********************************************************************/ static void mcast_mgr_subdivide(osm_sm_t * sm, uint16_t mlid_ho, osm_switch_t * p_sw, cl_qlist_t * p_list, cl_qlist_t * list_array, uint8_t array_size) { uint8_t port_num; boolean_t ignore_existing; osm_mcast_work_obj_t *p_wobj; OSM_LOG_ENTER(sm->p_log); /* For Multicast Groups, we don't want to count on previous configurations - since we can easily generate a storm by loops. */ ignore_existing = TRUE; /* Subdivide the set of ports into non-overlapping subsets that will be routed to other switches. */ while ((p_wobj = (osm_mcast_work_obj_t *) cl_qlist_remove_head(p_list)) != (osm_mcast_work_obj_t *) cl_qlist_end(p_list)) { port_num = osm_switch_recommend_mcast_path(p_sw, p_wobj->p_port, mlid_ho, ignore_existing); if (port_num == OSM_NO_PATH) { /* This typically occurs if the switch does not support multicast and the multicast tree must branch at this switch. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A03: " "Error routing MLID 0x%X through switch 0x%" PRIx64 " %s\n" "\t\t\t\tNo multicast paths from this switch " "for port with LID %u\n", mlid_ho, cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), p_sw->p_node->print_desc, cl_ntoh16(osm_port_get_base_lid (p_wobj->p_port))); mcast_work_obj_delete(p_wobj); continue; } if (port_num >= array_size) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A04: " "Error routing MLID 0x%X through switch 0x%" PRIx64 " %s\n" "\t\t\t\tNo multicast paths from this switch " "to port with LID %u\n", mlid_ho, cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), p_sw->p_node->print_desc, cl_ntoh16(osm_port_get_base_lid (p_wobj->p_port))); mcast_work_obj_delete(p_wobj); continue; } cl_qlist_insert_tail(&list_array[port_num], &p_wobj->list_item); } OSM_LOG_EXIT(sm->p_log); } static void mcast_mgr_purge_list(osm_sm_t * sm, uint16_t mlid, cl_qlist_t * list) { if (OSM_LOG_IS_ACTIVE_V2(sm->p_log, OSM_LOG_ERROR)) { osm_mcast_work_obj_t *wobj; cl_list_item_t *i; for (i = cl_qlist_head(list); i != cl_qlist_end(list); i = cl_qlist_next(i)) { wobj = cl_item_obj(i, wobj, list_item); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A06: " "Unable to route MLID 0x%X for port 0x%" PRIx64 "\n", mlid, cl_ntoh64(osm_port_get_guid(wobj->p_port))); } } osm_mcast_drop_port_list(list); } /********************************************************************** This is the recursive function to compute the paths in the spanning tree that emanate from this switch. On input, the p_list contains the group members that must be routed from this switch. The function returns the newly created mtree node element. **********************************************************************/ static osm_mtree_node_t *mcast_mgr_branch(osm_sm_t * sm, uint16_t mlid_ho, osm_switch_t * p_sw, cl_qlist_t * p_list, uint8_t depth, uint8_t upstream_port, uint8_t * p_max_depth) { uint8_t max_children; osm_mtree_node_t *p_mtn = NULL; cl_qlist_t *list_array = NULL; uint8_t i; ib_net64_t node_guid; osm_mcast_work_obj_t *p_wobj; cl_qlist_t *p_port_list; size_t count; osm_mcast_tbl_t *p_tbl; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); CL_ASSERT(p_list); CL_ASSERT(p_max_depth); node_guid = osm_node_get_node_guid(p_sw->p_node); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Routing MLID 0x%X through switch 0x%" PRIx64 " %s, %u nodes at depth %u\n", mlid_ho, cl_ntoh64(node_guid), p_sw->p_node->print_desc, cl_qlist_count(p_list), depth); CL_ASSERT(cl_qlist_count(p_list) > 0); depth++; if (depth >= 64) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A21: " "Maximal hops number is reached for MLID 0x%x." " Break processing\n", mlid_ho); mcast_mgr_purge_list(sm, mlid_ho, p_list); goto Exit; } if (depth > *p_max_depth) { CL_ASSERT(depth == *p_max_depth + 1); *p_max_depth = depth; } if (osm_switch_supports_mcast(p_sw) == FALSE) { /* This switch doesn't do multicast. Clean-up. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A14: " "Switch 0x%" PRIx64 " %s does not support multicast\n", cl_ntoh64(node_guid), p_sw->p_node->print_desc); /* Deallocate all the work objects on this branch of the tree. */ mcast_mgr_purge_list(sm, mlid_ho, p_list); goto Exit; } p_mtn = osm_mtree_node_new(p_sw); if (p_mtn == NULL) { /* We are unable to continue routing down this leg of the tree. Clean-up. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A15: " "Insufficient memory to build multicast tree\n"); /* Deallocate all the work objects on this branch of the tree. */ mcast_mgr_purge_list(sm, mlid_ho, p_list); goto Exit; } max_children = osm_mtree_node_get_max_children(p_mtn); CL_ASSERT(max_children > 1); /* Prepare an empty list for each port in the switch. TO DO - this list array could probably be moved inside the switch element to save on malloc thrashing. */ list_array = malloc(sizeof(cl_qlist_t) * max_children); if (list_array == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A16: " "Unable to allocate list array\n"); mcast_mgr_purge_list(sm, mlid_ho, p_list); osm_mtree_destroy(p_mtn); p_mtn = NULL; goto Exit; } memset(list_array, 0, sizeof(cl_qlist_t) * max_children); for (i = 0; i < max_children; i++) cl_qlist_init(&list_array[i]); mcast_mgr_subdivide(sm, mlid_ho, p_sw, p_list, list_array, max_children); p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); /* Add the upstream port to the forwarding table unless we're at the root of the spanning tree. */ if (depth > 1) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Adding upstream port %u\n", upstream_port); CL_ASSERT(upstream_port); osm_mcast_tbl_set(p_tbl, mlid_ho, upstream_port); } /* For each port that was allocated some routes, recurse into this function to continue building the tree if the node on the other end of that port is another switch. Otherwise, the node is an endpoint, and we've found a leaf of the tree. Mark leaves with our special pointer value. */ for (i = 0; i < max_children; i++) { const osm_physp_t *p_physp; const osm_physp_t *p_remote_physp; osm_node_t *p_node; const osm_node_t *p_remote_node; p_port_list = &list_array[i]; count = cl_qlist_count(p_port_list); /* There should be no children routed through the upstream port! */ CL_ASSERT(upstream_port == 0 || i != upstream_port || (i == upstream_port && count == 0)); if (count == 0) continue; /* No routes down this port. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Routing %zu destinations via switch port %u\n", count, i); if (i == 0) { /* This means we are adding the switch to the MC group. We do not need to continue looking at the remote port, just needed to add the port to the table */ CL_ASSERT(count == 1); osm_mcast_tbl_set(p_tbl, mlid_ho, i); p_wobj = (osm_mcast_work_obj_t *) cl_qlist_remove_head(p_port_list); mcast_work_obj_delete(p_wobj); continue; } p_node = p_sw->p_node; p_remote_node = osm_node_get_remote_node(p_node, i, NULL); if (!p_remote_node) { /* * If we reached here, it means the minhop table has * invalid entries that leads to disconnected ports. * * A possible reason for the code to reach here is * that ucast cache is enabled, and a leaf switch that * is used as a non-leaf switch in a multicast has been * removed from the fabric. * * When it happens, we should invalidate the cache * and force rerouting of the fabric. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A1E: Tried to route MLID 0x%X through " "disconnected switch 0x%" PRIx64 " port %d\n", mlid_ho, cl_ntoh64(node_guid), i); /* Free memory */ mcast_mgr_purge_list(sm, mlid_ho, p_port_list); /* Invalidate ucast cache */ if (sm->ucast_mgr.p_subn->opt.use_ucast_cache && sm->ucast_mgr.cache_valid) { OSM_LOG(sm->p_log, OSM_LOG_INFO, "Unicast Cache will be invalidated due " "to multicast routing errors\n"); osm_ucast_cache_invalidate(&sm->ucast_mgr); sm->p_subn->force_heavy_sweep = TRUE; } continue; } /* This port routes frames for this mcast group. Therefore, set the appropriate bit in the multicast forwarding table for this switch. */ osm_mcast_tbl_set(p_tbl, mlid_ho, i); if (osm_node_get_type(p_remote_node) == IB_NODE_TYPE_SWITCH) { /* Acquire a pointer to the remote switch then recurse. */ CL_ASSERT(p_remote_node->sw); p_physp = osm_node_get_physp_ptr(p_node, i); CL_ASSERT(p_physp); p_remote_physp = osm_physp_get_remote(p_physp); CL_ASSERT(p_remote_physp); p_mtn->child_array[i] = mcast_mgr_branch(sm, mlid_ho, p_remote_node->sw, p_port_list, depth, osm_physp_get_port_num (p_remote_physp), p_max_depth); } else { /* The neighbor node is not a switch, so this must be a leaf. */ CL_ASSERT(count == 1); p_mtn->child_array[i] = OSM_MTREE_LEAF; p_wobj = (osm_mcast_work_obj_t *) cl_qlist_remove_head(p_port_list); CL_ASSERT(cl_is_qlist_empty(p_port_list)); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Found leaf for port 0x%016" PRIx64 " on switch port %u\n", cl_ntoh64(osm_port_get_guid(p_wobj->p_port)), i); mcast_work_obj_delete(p_wobj); } } free(list_array); Exit: OSM_LOG_EXIT(sm->p_log); return p_mtn; } static ib_api_status_t mcast_mgr_build_spanning_tree(osm_sm_t * sm, osm_mgrp_box_t * mbox) { cl_qlist_t port_list; cl_qmap_t port_map; uint32_t num_ports; osm_switch_t *p_sw; ib_api_status_t status = IB_SUCCESS; uint8_t max_depth = 0; OSM_LOG_ENTER(sm->p_log); /* TO DO - for now, just blow away the old tree. In the future we'll need to construct the tree based on multicast forwarding table information if the user wants to preserve existing multicast routes. */ osm_purge_mtree(sm, mbox); /* build the first "subset" containing all member ports */ if (osm_mcast_make_port_list_and_map(&port_list, &port_map, mbox)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A10: " "Insufficient memory to make port list\n"); status = IB_ERROR; goto Exit; } num_ports = cl_qlist_count(&port_list); if (num_ports < 2) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "MLID 0x%X has %u members - nothing to do\n", mbox->mlid, num_ports); osm_mcast_drop_port_list(&port_list); goto Exit; } /* This function builds the single spanning tree recursively. At each stage, the ports to be reached are divided into non-overlapping subsets of member ports that can be reached through a given switch port. Construction then moves down each branch, and the process starts again with each branch computing for its own subset of the member ports. The maximum recursion depth is at worst the maximum hop count in the subnet, which is spec limited to 64. */ /* Locate the switch around which to create the spanning tree for this multicast group. */ p_sw = osm_mcast_mgr_find_root_switch(sm, &port_list); if (p_sw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A08: " "Unable to locate a suitable switch for group 0x%X\n", mbox->mlid); osm_mcast_drop_port_list(&port_list); status = IB_ERROR; goto Exit; } mbox->root = mcast_mgr_branch(sm, mbox->mlid, p_sw, &port_list, 0, 0, &max_depth); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Configured MLID 0x%X for %u ports, max tree depth = %u\n", mbox->mlid, num_ports, max_depth); Exit: OSM_LOG_EXIT(sm->p_log); return status; } #if 0 /* unused */ void osm_mcast_mgr_set_table(osm_sm_t * sm, IN const osm_mgrp_t * p_mgrp, IN const osm_mtree_node_t * p_mtn) { uint8_t i; uint8_t max_children; osm_mtree_node_t *p_child_mtn; uint16_t mlid_ho; osm_mcast_tbl_t *p_tbl; osm_switch_t *p_sw; OSM_LOG_ENTER(sm->p_log); mlid_ho = cl_ntoh16(osm_mgrp_get_mlid(p_mgrp)); p_sw = osm_mtree_node_get_switch_ptr(p_mtn); CL_ASSERT(p_sw); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Configuring MLID 0x%X on switch 0x%" PRIx64 "\n", mlid_ho, osm_node_get_node_guid(p_sw->p_node)); /* For every child of this tree node, set the corresponding bit in the switch's mcast table. */ p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); max_children = osm_mtree_node_get_max_children(p_mtn); CL_ASSERT(max_children <= osm_switch_get_num_ports(p_sw)); osm_mcast_tbl_clear_mlid(p_tbl, mlid_ho); for (i = 0; i < max_children; i++) { p_child_mtn = osm_mtree_node_get_child(p_mtn, i); if (p_child_mtn == NULL) continue; osm_mcast_tbl_set(p_tbl, mlid_ho, i); } OSM_LOG_EXIT(sm->p_log); } #endif static void mcast_mgr_clear(osm_sm_t * sm, uint16_t mlid) { osm_switch_t *p_sw; cl_qmap_t *p_sw_tbl; osm_mcast_tbl_t *p_mcast_tbl; OSM_LOG_ENTER(sm->p_log); /* Walk the switches and clear the routing entries for this MLID. */ p_sw_tbl = &sm->p_subn->sw_guid_tbl; p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); while (p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl)) { p_mcast_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); osm_mcast_tbl_clear_mlid(p_mcast_tbl, mlid); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); } OSM_LOG_EXIT(sm->p_log); } #if 0 /* TO DO - make this real -- at least update spanning tree */ /********************************************************************** Lock must be held on entry. **********************************************************************/ ib_api_status_t osm_mcast_mgr_process_single(osm_sm_t * sm, IN ib_net16_t const mlid, IN ib_net64_t const port_guid, IN uint8_t const join_state) { uint8_t port_num; uint16_t mlid_ho; ib_net64_t sw_guid; osm_port_t *p_port; osm_physp_t *p_physp; osm_physp_t *p_remote_physp; osm_node_t *p_remote_node; osm_mcast_tbl_t *p_mcast_tbl; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(mlid); CL_ASSERT(port_guid); mlid_ho = cl_ntoh16(mlid); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Attempting to add port 0x%" PRIx64 " to MLID 0x%X, " "\n\t\t\t\tjoin state = 0x%X\n", cl_ntoh64(port_guid), mlid_ho, join_state); /* Acquire the Port object. */ p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A01: " "Unable to acquire port object for 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); status = IB_ERROR; goto Exit; } p_physp = p_port->p_physp; if (p_physp == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A05: " "Unable to acquire phsyical port object for 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); status = IB_ERROR; goto Exit; } p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A11: " "Unable to acquire remote phsyical port object " "for 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); status = IB_ERROR; goto Exit; } p_remote_node = osm_physp_get_node_ptr(p_remote_physp); CL_ASSERT(p_remote_node); sw_guid = osm_node_get_node_guid(p_remote_node); if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A22: " "Remote node not a switch node 0x%" PRIx64 "\n", cl_ntoh64(sw_guid)); status = IB_ERROR; goto Exit; } if (!p_remote_node->sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A12: " "No switch object 0x%" PRIx64 "\n", cl_ntoh64(sw_guid)); status = IB_ERROR; goto Exit; } if (osm_switch_is_in_mcast_tree(p_remote_node->sw, mlid_ho)) { /* We're in luck. The switch attached to this port is already in the multicast group, so we can just add the specified port as a new leaf of the tree. */ if (join_state & (IB_JOIN_STATE_FULL | IB_JOIN_STATE_NON)) { /* This node wants to receive multicast frames. Get the switch port number to which the new member port is attached, then configure this single mcast table. */ port_num = osm_physp_get_port_num(p_remote_physp); CL_ASSERT(port_num); p_mcast_tbl = osm_switch_get_mcast_tbl_ptr(p_remote_node->sw); osm_mcast_tbl_set(p_mcast_tbl, mlid_ho, port_num); } else { if (join_state & IB_JOIN_STATE_SEND_ONLY) OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Success. Nothing to do for send" "only member\n"); else { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A13: " "Unknown join state 0x%X\n", join_state); status = IB_ERROR; goto Exit; } } } else OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Unable to add port\n"); Exit: OSM_LOG_EXIT(sm->p_log); return status; } #endif /********************************************************************** Process the entire group. NOTE : The lock should be held externally! **********************************************************************/ static ib_api_status_t mcast_mgr_process_mlid(osm_sm_t * sm, uint16_t mlid) { ib_api_status_t status = IB_SUCCESS; struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; osm_mgrp_box_t *mbox; OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Processing multicast group with mlid 0x%X\n", mlid); /* Clear the multicast tables to start clean, then build the spanning tree which sets the mcast table bits for each port in the group. */ mcast_mgr_clear(sm, mlid); mbox = osm_get_mbox_by_mlid(sm->p_subn, cl_hton16(mlid)); if (mbox) { if (re && re->mcast_build_stree) status = re->mcast_build_stree(re->context, mbox); else status = mcast_mgr_build_spanning_tree(sm, mbox); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A17: " "Unable to create spanning tree (%s) for mlid " "0x%x\n", ib_get_err_str(status), mlid); } OSM_LOG_EXIT(sm->p_log); return status; } static void mcast_mgr_set_mfttop(IN osm_sm_t * sm, IN osm_switch_t * p_sw) { osm_node_t *p_node; osm_dr_path_t *p_path; osm_physp_t *p_physp; osm_mcast_tbl_t *p_tbl; osm_madw_context_t context; ib_api_status_t status; ib_switch_info_t si; ib_net16_t mcast_top; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); p_node = p_sw->p_node; CL_ASSERT(p_node); p_physp = osm_node_get_physp_ptr(p_node, 0); p_path = osm_physp_get_dr_path_ptr(p_physp); p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); if (sm->p_subn->opt.use_mfttop && p_physp->port_info.capability_mask & IB_PORT_CAP_HAS_MCAST_FDB_TOP) { /* Set the top of the multicast forwarding table. */ si = p_sw->switch_info; if (sm->p_subn->first_time_master_sweep == TRUE) mcast_top = cl_hton16(sm->mlids_init_max); else { if (p_tbl->max_block_in_use == -1) mcast_top = cl_hton16(IB_LID_MCAST_START_HO - 1); else mcast_top = cl_hton16(IB_LID_MCAST_START_HO + (p_tbl->max_block_in_use + 1) * IB_MCAST_BLOCK_SIZE - 1); } if (mcast_top == si.mcast_top) return; si.mcast_top = mcast_top; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting switch MFT top to MLID 0x%x\n", cl_ntoh16(si.mcast_top)); context.si_context.light_sweep = FALSE; context.si_context.node_guid = osm_node_get_node_guid(p_node); context.si_context.set_method = TRUE; context.si_context.lft_top_change = FALSE; status = osm_req_set(sm, p_path, (uint8_t *) & si, sizeof(si), IB_MAD_ATTR_SWITCH_INFO, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A1B: " "Sending SwitchInfo attribute failed (%s)\n", ib_get_err_str(status)); } } static int mcast_mgr_set_mftables(osm_sm_t * sm) { cl_qmap_t *p_sw_tbl = &sm->p_subn->sw_guid_tbl; osm_switch_t *p_sw; osm_mcast_tbl_t *p_tbl; int block_notdone, ret = 0; int16_t block_num, max_block = -1; p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); while (p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl)) { p_sw->mft_block_num = 0; p_sw->mft_position = 0; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); if (osm_mcast_tbl_get_max_block_in_use(p_tbl) > max_block) max_block = osm_mcast_tbl_get_max_block_in_use(p_tbl); mcast_mgr_set_mfttop(sm, p_sw); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); } /* Stripe the MFT blocks across the switches */ for (block_num = 0; block_num <= max_block; block_num++) { block_notdone = 1; while (block_notdone) { block_notdone = 0; p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); while (p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl)) { if (p_sw->mft_block_num == block_num) { block_notdone = 1; if (mcast_mgr_set_mft_block(sm, p_sw, p_sw->mft_block_num, p_sw->mft_position)) ret = -1; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); if (++p_sw->mft_position > p_tbl->max_position) { p_sw->mft_position = 0; p_sw->mft_block_num++; } } p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); } } } return ret; } static int alloc_mfts(osm_sm_t * sm) { int i; cl_map_item_t *item; osm_switch_t *p_sw; for (i = sm->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO; i >= 0; i--) if (sm->p_subn->mboxes[i]) break; if (i < 0) return 0; /* Now, walk switches and (re)allocate multicast tables */ for (item = cl_qmap_head(&sm->p_subn->sw_guid_tbl); item != cl_qmap_end(&sm->p_subn->sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; if (osm_mcast_tbl_realloc(&p_sw->mcast_tbl, i)) return -1; } return 0; } /********************************************************************** This is the function that is invoked during idle time and sweep to handle the process request for mcast groups where join/leave/delete was required. **********************************************************************/ int osm_mcast_mgr_process(osm_sm_t * sm, boolean_t config_all) { int ret = 0; unsigned i; unsigned max_mlid; OSM_LOG_ENTER(sm->p_log); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); /* If there are no switches in the subnet we have nothing to do. */ if (cl_qmap_count(&sm->p_subn->sw_guid_tbl) == 0) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No switches in subnet. Nothing to do\n"); goto exit; } if (alloc_mfts(sm)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0A09: alloc_mfts failed\n"); ret = -1; goto exit; } max_mlid = config_all ? sm->p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO : sm->mlids_req_max; for (i = 0; i <= max_mlid; i++) { if (sm->mlids_req[i] || (config_all && sm->p_subn->mboxes[i])) { sm->mlids_req[i] = 0; mcast_mgr_process_mlid(sm, i + IB_LID_MCAST_START_HO); } } sm->mlids_req_max = 0; ret = mcast_mgr_set_mftables(sm); osm_dump_mcast_routes(sm->p_subn->p_osm); exit: CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); return ret; } opensm-3.3.20/opensm/osm_mcast_tbl.c0000644000205000001450000001720212532057231014305 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_mcast_tbl_t. * This object represents a multicast forwarding table. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_MCAST_TBL_C #include void osm_mcast_tbl_init(IN osm_mcast_tbl_t * p_tbl, IN uint8_t num_ports, IN uint16_t capacity) { CL_ASSERT(p_tbl); CL_ASSERT(num_ports); memset(p_tbl, 0, sizeof(*p_tbl)); p_tbl->max_block_in_use = -1; if (capacity == 0) { /* This switch apparently doesn't support multicast. Everything is initialized to zero already, so return. */ return; } p_tbl->num_entries = capacity; p_tbl->num_ports = num_ports; p_tbl->max_position = (uint8_t) ((ROUNDUP(num_ports, IB_MCAST_MASK_SIZE) / IB_MCAST_MASK_SIZE) - 1); p_tbl->max_block = (uint16_t) ((ROUNDUP(p_tbl->num_entries, IB_MCAST_BLOCK_SIZE) / IB_MCAST_BLOCK_SIZE) - 1); } void osm_mcast_tbl_destroy(IN osm_mcast_tbl_t * p_tbl) { free(p_tbl->p_mask_tbl); } void osm_mcast_tbl_set(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho, IN uint8_t port) { unsigned mlid_offset, mask_offset, bit_mask; int16_t block_num; CL_ASSERT(p_tbl && p_tbl->p_mask_tbl); CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO); CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho); mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; mask_offset = port / IB_MCAST_MASK_SIZE; bit_mask = cl_ntoh16((uint16_t) (1 << (port % IB_MCAST_MASK_SIZE))); (*p_tbl->p_mask_tbl)[mlid_offset][mask_offset] |= bit_mask; block_num = (int16_t) (mlid_offset / IB_MCAST_BLOCK_SIZE); if (block_num > p_tbl->max_block_in_use) p_tbl->max_block_in_use = (uint16_t) block_num; } int osm_mcast_tbl_realloc(IN osm_mcast_tbl_t * p_tbl, IN unsigned mlid_offset) { size_t mft_depth, size; uint16_t (*p_mask_tbl)[][IB_MCAST_POSITION_MAX + 1]; if (mlid_offset < p_tbl->mft_depth) goto done; /* The number of bytes needed in the mask table is: The (maximum bit mask 'position' + 1) times the number of bytes in each bit mask times the number of MLIDs supported by the table. We must always allocate the array with the maximum position since it is (and must be) defined that way the table structure in order to create a pointer to a two dimensional array. */ mft_depth = (mlid_offset / IB_MCAST_BLOCK_SIZE + 1) * IB_MCAST_BLOCK_SIZE; size = mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8; p_mask_tbl = realloc(p_tbl->p_mask_tbl, size); if (!p_mask_tbl) return -1; memset((uint8_t *)p_mask_tbl + p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8, 0, size - p_tbl->mft_depth * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8); p_tbl->p_mask_tbl = p_mask_tbl; p_tbl->mft_depth = mft_depth; done: p_tbl->max_mlid_ho = mlid_offset + IB_LID_MCAST_START_HO; return 0; } boolean_t osm_mcast_tbl_is_port(IN const osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho, IN uint8_t port_num) { unsigned mlid_offset, mask_offset, bit_mask; CL_ASSERT(p_tbl); if (p_tbl->p_mask_tbl) { CL_ASSERT(port_num <= (p_tbl->max_position + 1) * IB_MCAST_MASK_SIZE); CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO); CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho); mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; mask_offset = port_num / IB_MCAST_MASK_SIZE; bit_mask = cl_ntoh16((uint16_t) (1 << (port_num % IB_MCAST_MASK_SIZE))); return (((*p_tbl-> p_mask_tbl)[mlid_offset][mask_offset] & bit_mask) == bit_mask); } return FALSE; } boolean_t osm_mcast_tbl_is_any_port(IN const osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho) { unsigned mlid_offset; uint8_t position; uint16_t result = 0; CL_ASSERT(p_tbl); if (p_tbl->p_mask_tbl) { CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO); CL_ASSERT(mlid_ho <= p_tbl->max_mlid_ho); mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; for (position = 0; position <= p_tbl->max_position; position++) result |= (*p_tbl->p_mask_tbl)[mlid_offset][position]; } return (result != 0); } ib_api_status_t osm_mcast_tbl_set_block(IN osm_mcast_tbl_t * p_tbl, IN const ib_net16_t * p_block, IN int16_t block_num, IN uint8_t position) { uint32_t i; uint16_t mlid_start_ho; CL_ASSERT(p_tbl); CL_ASSERT(p_block); if (block_num > p_tbl->max_block) return IB_INVALID_PARAMETER; if (position > p_tbl->max_position) return IB_INVALID_PARAMETER; mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE); if (mlid_start_ho + IB_MCAST_BLOCK_SIZE - 1 > p_tbl->mft_depth) return IB_INVALID_PARAMETER; for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position] = p_block[i]; if (block_num > p_tbl->max_block_in_use) p_tbl->max_block_in_use = (uint16_t) block_num; return IB_SUCCESS; } void osm_mcast_tbl_clear_mlid(IN osm_mcast_tbl_t * p_tbl, IN uint16_t mlid_ho) { unsigned mlid_offset; CL_ASSERT(p_tbl); CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO); mlid_offset = mlid_ho - IB_LID_MCAST_START_HO; if (p_tbl->p_mask_tbl && mlid_offset < p_tbl->mft_depth) memset((uint8_t *)p_tbl->p_mask_tbl + mlid_offset * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8, 0, (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8); } boolean_t osm_mcast_tbl_get_block(IN osm_mcast_tbl_t * p_tbl, IN int16_t block_num, IN uint8_t position, OUT ib_net16_t * p_block) { uint32_t i; uint16_t mlid_start_ho; CL_ASSERT(p_tbl); CL_ASSERT(p_block); if (block_num > p_tbl->max_block_in_use) return FALSE; if (position > p_tbl->max_position) { /* Caller shouldn't do this for efficiency's sake... */ memset(p_block, 0, IB_SMP_DATA_SIZE); return TRUE; } CL_ASSERT(block_num * IB_MCAST_BLOCK_SIZE <= p_tbl->mft_depth); mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE); for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position]; return TRUE; } opensm-3.3.20/opensm/osm_mcm_port.c0000644000205000001450000000616312104655724014167 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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 osm_mcm_port_t. * This object represents the membership of a port in a multicast group. * This object is part of the OpenSM family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_MCM_PORT_C #include #include osm_mcm_port_t *osm_mcm_port_new(IN osm_port_t *port, IN osm_mgrp_t *mgrp) { osm_mcm_port_t *p_mcm; p_mcm = malloc(sizeof(*p_mcm)); if (p_mcm) { memset(p_mcm, 0, sizeof(*p_mcm)); p_mcm->port = port; p_mcm->mgrp = mgrp; } return p_mcm; } void osm_mcm_port_delete(IN osm_mcm_port_t * p_mcm) { CL_ASSERT(p_mcm); free(p_mcm); } osm_mcm_alias_guid_t *osm_mcm_alias_guid_new(IN osm_mcm_port_t *p_base_mcm_port, IN ib_member_rec_t *mcmr, IN boolean_t proxy) { osm_mcm_alias_guid_t *p_mcm_alias_guid; p_mcm_alias_guid = calloc(1, sizeof(*p_mcm_alias_guid)); if (p_mcm_alias_guid) { p_mcm_alias_guid->alias_guid = mcmr->port_gid.unicast.interface_id; p_mcm_alias_guid->p_base_mcm_port = p_base_mcm_port; p_mcm_alias_guid->port_gid.unicast.prefix = mcmr->port_gid.unicast.prefix; p_mcm_alias_guid->port_gid.unicast.interface_id = mcmr->port_gid.unicast.interface_id; p_mcm_alias_guid->scope_state = mcmr->scope_state; p_mcm_alias_guid->proxy_join = proxy; } return p_mcm_alias_guid; } void osm_mcm_alias_guid_delete(IN OUT osm_mcm_alias_guid_t ** pp_mcm_alias_guid) { free(*pp_mcm_alias_guid); *pp_mcm_alias_guid = NULL; } opensm-3.3.20/opensm/osm_mesh.c0000644000205000001450000011323212104655724013277 00000000000000/* * Copyright (c) 2008-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2008,2009 System Fabric Works, Inc. 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: * routines to analyze certain meshes */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_MESH_C #include #include #include #include #include #define MAX_DEGREE (8) #define MAX_DIMENSION (8) #define LARGE (0x7fffffff) /* * characteristic polynomials for selected 1d through 8d tori */ static const struct mesh_info { int dimension; /* dimension of the torus */ int size[MAX_DIMENSION]; /* size of the torus */ unsigned int degree; /* degree of polynomial */ int poly[MAX_DEGREE+1]; /* polynomial */ } mesh_info[] = { {0, {0}, 0, {0}, }, {1, {2}, 1, {0, -1}, }, {1, {3}, 2, {-1, 0, 1}, }, {1, {5}, 2, {-9, 0, 1}, }, {1, {6}, 2, {-36, 0, 1}, }, {2, {2, 2}, 2, {-4, 0, 1}, }, {2, {3, 2}, 3, {8, 9, 0, -1}, }, {2, {5, 2}, 3, {24, 17, 0, -1}, }, {2, {6, 2}, 3, {32, 24, 0, -1}, }, {2, {3, 3}, 4, {-15, -32, -18, 0, 1}, }, {2, {5, 3}, 4, {-39, -64, -26, 0, 1}, }, {2, {6, 3}, 4, {-48, -80, -33, 0, 1}, }, {2, {5, 5}, 4, {-63, -96, -34, 0, 1}, }, {2, {6, 5}, 4, {-48, -112, -41, 0, 1}, }, {2, {6, 6}, 4, {0, -128, -48, 0, 1}, }, {3, {2, 2, 2}, 3, {16, 12, 0, -1}, }, {3, {3, 2, 2}, 4, {-28, -48, -21, 0, 1}, }, {3, {5, 2, 2}, 4, {-60, -80, -29, 0, 1}, }, {3, {6, 2, 2}, 4, {-64, -96, -36, 0, 1}, }, {3, {3, 3, 2}, 5, {48, 127, 112, 34, 0, -1}, }, {3, {5, 3, 2}, 5, {96, 215, 160, 42, 0, -1}, }, {3, {6, 3, 2}, 5, {96, 232, 184, 49, 0, -1}, }, {3, {5, 5, 2}, 5, {144, 303, 208, 50, 0, -1}, }, {3, {6, 5, 2}, 5, {96, 296, 232, 57, 0, -1}, }, {3, {6, 6, 2}, 5, {0, 256, 256, 64, 0, -1}, }, {3, {3, 3, 3}, 6, {-81, -288, -381, -224, -51, 0, 1}, }, {3, {5, 3, 3}, 6, {-153, -480, -557, -288, -59, 0, 1}, }, {3, {6, 3, 3}, 6, {-144, -480, -591, -320, -66, 0, 1}, }, {3, {5, 5, 3}, 6, {-225, -672, -733, -352, -67, 0, 1}, }, {3, {6, 5, 3}, 6, {-144, -576, -743, -384, -74, 0, 1}, }, {3, {6, 6, 3}, 6, {0, -384, -720, -416, -81, 0, 1}, }, {3, {5, 5, 5}, 6, {-297, -864, -909, -416, -75, 0, 1}, }, {3, {6, 5, 5}, 6, {-144, -672, -895, -448, -82, 0, 1}, }, {3, {6, 6, 5}, 6, {0, -384, -848, -480, -89, 0, 1}, }, {3, {6, 6, 6}, 6, {0, 0, -768, -512, -96, 0, 1}, }, {4, {2, 2, 2, 2}, 4, {-48, -64, -24, 0, 1}, }, {4, {3, 2, 2, 2}, 5, {80, 180, 136, 37, 0, -1}, }, {4, {5, 2, 2, 2}, 5, {144, 276, 184, 45, 0, -1}, }, {4, {6, 2, 2, 2}, 5, {128, 288, 208, 52, 0, -1}, }, {4, {3, 3, 2, 2}, 6, {-132, -416, -487, -256, -54, 0, 1}, }, {4, {5, 3, 2, 2}, 6, {-228, -640, -671, -320, -62, 0, 1}, }, {4, {6, 3, 2, 2}, 6, {-192, -608, -700, -352, -69, 0, 1}, }, {4, {5, 5, 2, 2}, 6, {-324, -864, -855, -384, -70, 0, 1}, }, {4, {6, 5, 2, 2}, 6, {-192, -736, -860, -416, -77, 0, 1}, }, {4, {6, 6, 2, 2}, 6, {0, -512, -832, -448, -84, 0, 1}, }, {4, {3, 3, 3, 2}, 7, {216, 873, 1392, 1101, 440, 75, 0, -1}, }, {4, {5, 3, 3, 2}, 7, {360, 1329, 1936, 1405, 520, 83, 0, -1}, }, {4, {6, 3, 3, 2}, 7, {288, 1176, 1872, 1455, 560, 90, 0, -1}, }, {4, {5, 5, 3, 2}, 7, {504, 1785, 2480, 1709, 600, 91, 0, -1}, }, {4, {6, 5, 3, 2}, 7, {288, 1368, 2272, 1735, 640, 98, 0, -1}, }, {4, {6, 6, 3, 2}, 7, {0, 768, 1920, 1728, 680, 105, 0, -1}, }, {4, {5, 5, 5, 2}, 7, {648, 2241, 3024, 2013, 680, 99, 0, -1}, }, {4, {6, 5, 5, 2}, 7, {288, 1560, 2672, 2015, 720, 106, 0, -1}, }, {4, {6, 6, 5, 2}, 7, {0, 768, 2176, 1984, 760, 113, 0, -1}, }, {4, {6, 6, 6, 2}, 7, {0, 0, 1536, 1920, 800, 120, 0, -1}, }, {4, {3, 3, 3, 3}, 8, {-351, -1728, -3492, -3712, -2202, -704, -100, 0, 1}, }, {4, {5, 3, 3, 3}, 8, {-567, -2592, -4860, -4800, -2658, -800, -108, 0, 1}, }, {4, {6, 3, 3, 3}, 8, {-432, -2160, -4401, -4672, -2733, -848, -115, 0, 1}, }, {4, {5, 5, 3, 3}, 8, {-783, -3456, -6228, -5888, -3114, -896, -116, 0, 1}, }, {4, {6, 5, 3, 3}, 8, {-432, -2448, -5241, -5568, -3165, -944, -123, 0, 1}, }, {4, {6, 6, 3, 3}, 8, {0, -1152, -3888, -5056, -3183, -992, -130, 0, 1}, }, {4, {5, 5, 5, 3}, 8, {-999, -4320, -7596, -6976, -3570, -992, -124, 0, 1}, }, {4, {6, 5, 5, 3}, 8, {-432, -2736, -6081, -6464, -3597, -1040, -131, 0, 1}, }, {4, {6, 6, 5, 3}, 8, {0, -1152, -4272, -5760, -3591, -1088, -138, 0, 1}, }, {4, {6, 6, 6, 3}, 8, {0, 0, -2304, -4864, -3552, -1136, -145, 0, 1}, }, {5, {2, 2, 2, 2, 2}, 5, {128, 240, 160, 40, 0, -1}, }, {5, {3, 2, 2, 2, 2}, 6, {-208, -576, -600, -288, -57, 0, 1}, }, {5, {5, 2, 2, 2, 2}, 6, {-336, -832, -792, -352, -65, 0, 1}, }, {5, {6, 2, 2, 2, 2}, 6, {-256, -768, -816, -384, -72, 0, 1}, }, {5, {3, 3, 2, 2, 2}, 7, {336, 1228, 1776, 1287, 480, 78, 0, -1}, }, {5, {5, 3, 2, 2, 2}, 7, {528, 1772, 2368, 1599, 560, 86, 0, -1}, }, {5, {6, 3, 2, 2, 2}, 7, {384, 1504, 2256, 1644, 600, 93, 0, -1}, }, {5, {5, 5, 2, 2, 2}, 7, {720, 2316, 2960, 1911, 640, 94, 0, -1}, }, {5, {6, 5, 2, 2, 2}, 7, {384, 1760, 2704, 1932, 680, 101, 0, -1}, }, {5, {6, 6, 2, 2, 2}, 7, {0, 1024, 2304, 1920, 720, 108, 0, -1}, }, {5, {3, 3, 3, 2, 2}, 8, {-540, -2448, -4557, -4480, -2481, -752, -103, 0, 1}, }, {5, {5, 3, 3, 2, 2}, 8, {-828, -3504, -6101, -5632, -2945, -848, -111, 0, 1}, }, {5, {6, 3, 3, 2, 2}, 8, {-576, -2784, -5412, -5440, -3015, -896, -118, 0, 1}, }, {5, {5, 5, 3, 2, 2}, 8, {-1116, -4560, -7645, -6784, -3409, -944, -119, 0, 1}, }, {5, {6, 5, 3, 2, 2}, 8, {-576, -3168, -6404, -6400, -3455, -992, -126, 0, 1}, }, {5, {6, 6, 3, 2, 2}, 8, {0, -1536, -4800, -5824, -3468, -1040, -133, 0, 1}, }, {5, {5, 5, 5, 2, 2}, 8, {-1404, -5616, -9189, -7936, -3873, -1040, -127, 0, 1}, }, {5, {6, 5, 5, 2, 2}, 8, {-576, -3552, -7396, -7360, -3895, -1088, -134, 0, 1}, }, {5, {6, 6, 5, 2, 2}, 8, {0, -1536, -5312, -6592, -3884, -1136, -141, 0, 1}, }, {5, {6, 6, 6, 2, 2}, 8, {0, 0, -3072, -5632, -3840, -1184, -148, 0, 1}, }, {6, {2, 2, 2, 2, 2, 2}, 6, {-320, -768, -720, -320, -60, 0, 1}, }, {6, {3, 2, 2, 2, 2, 2}, 7, {512, 1680, 2208, 1480, 520, 81, 0, -1}, }, {6, {5, 2, 2, 2, 2, 2}, 7, {768, 2320, 2848, 1800, 600, 89, 0, -1}, }, {6, {6, 2, 2, 2, 2, 2}, 7, {512, 1920, 2688, 1840, 640, 96, 0, -1}, }, {6, {3, 3, 2, 2, 2, 2}, 8, {-816, -3392, -5816, -5312, -2767, -800, -106, 0, 1}, }, {6, {5, 3, 2, 2, 2, 2}, 8, {-1200, -4672, -7544, -6528, -3239, -896, -114, 0, 1}, }, {6, {6, 3, 2, 2, 2, 2}, 8, {-768, -3584, -6608, -6272, -3304, -944, -121, 0, 1}, }, {6, {5, 5, 2, 2, 2, 2}, 8, {-1584, -5952, -9272, -7744, -3711, -992, -122, 0, 1}, }, {6, {6, 5, 2, 2, 2, 2}, 8, {-768, -4096, -7760, -7296, -3752, -1040, -129, 0, 1}, }, {6, {6, 6, 2, 2, 2, 2}, 8, {0, -2048, -5888, -6656, -3760, -1088, -136, 0, 1}, }, {7, {2, 2, 2, 2, 2, 2, 2}, 7, {768, 2240, 2688, 1680, 560, 84, 0, -1}, }, {7, {3, 2, 2, 2, 2, 2, 2}, 8, {-1216, -4608, -7280, -6208, -3060, -848, -109, 0, 1}, }, {7, {5, 2, 2, 2, 2, 2, 2}, 8, {-1728, -6144, -9200, -7488, -3540, -944, -117, 0, 1}, }, {7, {6, 2, 2, 2, 2, 2, 2}, 8, {-1024, -4608, -8000, -7168, -3600, -992, -124, 0, 1}, }, {8, {2, 2, 2, 2, 2, 2, 2, 2}, 8, {-1792, -6144, -8960, -7168, -3360, -896, -112, 0, 1}, }, /* * mesh errors */ {2, {6, 6}, 4, {-192, -256, -80, 0, 1}, }, {-1, {0,}, 0, {0, }, }, }; /* * per fabric mesh info */ typedef struct _mesh { int num_class; /* number of switch classes */ int *class_type; /* index of first switch found for each class */ int *class_count; /* population of each class */ int dimension; /* mesh dimension */ int *size; /* an array to hold size of mesh */ int dim_order[MAX_DIMENSION]; } mesh_t; typedef struct sort_ctx { lash_t *p_lash; mesh_t *mesh; } sort_ctx_t; typedef struct comp { int index; sort_ctx_t ctx; } comp_t; /* * poly_alloc * * allocate a polynomial of degree n */ static int *poly_alloc(lash_t *p_lash, int n) { osm_log_t *p_log = &p_lash->p_osm->log; int *p; if (!(p = calloc(n+1, sizeof(int)))) OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating poly - out of memory\n"); return p; } /* * print a polynomial */ static char *poly_print(int n, int *coeff) { static char str[(MAX_DEGREE+1)*20]; char *p = str; int i; int first = 1; int t; int sign; str[0] = 0; for (i = 0; i <= n; i++) { if (!coeff[i]) continue; if (coeff[i] < 0) { sign = 1; t = -coeff[i]; } else { sign = 0; t = coeff[i]; } p += sprintf(p, "%s", sign? "-" : (first? "" : "+")); first = 0; if (t != 1 || i == 0) p += sprintf(p, "%d", t); if (i) p += sprintf(p, "x"); if (i > 1) p += sprintf(p, "^%d", i); } return str; } /* * poly_diff * * return a nonzero value if polynomials differ else 0 */ static int poly_diff(unsigned int n, const int *p, switch_t *s) { if (s->node->num_links != n) return 1; return memcmp(p, s->node->poly, n*sizeof(int)); } /* * m_free * * free a square matrix of rank l */ static void m_free(int **m, int l) { int i; if (m) { for (i = 0; i < l; i++) { if (m[i]) free(m[i]); } free(m); } } /* * m_alloc * * allocate a square matrix of rank l */ static int **m_alloc(lash_t *p_lash, int l) { osm_log_t *p_log = &p_lash->p_osm->log; int i; int **m = NULL; do { if (!(m = calloc(l, sizeof(int *)))) break; for (i = 0; i < l; i++) { if (!(m[i] = calloc(l, sizeof(int)))) break; } if (i != l) break; return m; } while (0); OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating matrix - out of memory\n"); m_free(m, l); return NULL; } /* * pm_free * * free a square matrix of rank l of polynomials */ static void pm_free(int ***m, int l) { int i, j; if (m) { for (i = 0; i < l; i++) { if (m[i]) { for (j = 0; j < l; j++) { if (m[i][j]) free(m[i][j]); } free(m[i]); } } free(m); } } /* * pm_alloc * * allocate a square matrix of rank l of polynomials of degree n */ static int ***pm_alloc(lash_t *p_lash, int l, int n) { osm_log_t *p_log = &p_lash->p_osm->log; int i, j; int ***m = NULL; do { if (!(m = calloc(l, sizeof(int **)))) break; for (i = 0; i < l; i++) { if (!(m[i] = calloc(l, sizeof(int *)))) break; for (j = 0; j < l; j++) { if (!(m[i][j] = calloc(n+1, sizeof(int)))) break; } if (j != l) break; } if (i != l) break; return m; } while (0); OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating matrix - out of memory\n"); pm_free(m, l); return NULL; } static int determinant(lash_t *p_lash, int n, int rank, int ***m, int *p); /* * sub_determinant * * compute the determinant of a submatrix of matrix of rank l of polynomials of degree n * with row and col removed in poly. caller must free poly */ static int sub_determinant(lash_t *p_lash, int n, int l, int row, int col, int ***matrix, int **poly) { int ret = -1; int ***m = NULL; int *p = NULL; int i, j, k, x, y; int rank = l - 1; do { if (!(p = poly_alloc(p_lash, n))) { break; } if (rank <= 0) { p[0] = 1; ret = 0; break; } if (!(m = pm_alloc(p_lash, rank, n))) { free(p); p = NULL; break; } x = 0; for (i = 0; i < l; i++) { if (i == row) continue; y = 0; for (j = 0; j < l; j++) { if (j == col) continue; for (k = 0; k <= n; k++) m[x][y][k] = matrix[i][j][k]; y++; } x++; } if (determinant(p_lash, n, rank, m, p)) { free(p); p = NULL; break; } ret = 0; } while (0); pm_free(m, rank); *poly = p; return ret; } /* * determinant * * compute the determinant of matrix m of rank of polynomials of degree deg * and add the result to polynomial p allocated by caller */ static int determinant(lash_t *p_lash, int deg, int rank, int ***m, int *p) { int i, j, k; int *q; int sign = 1; /* * handle simple case of 1x1 matrix */ if (rank == 1) { for (i = 0; i <= deg; i++) p[i] += m[0][0][i]; } /* * handle simple case of 2x2 matrix */ else if (rank == 2) { for (i = 0; i <= deg; i++) { if (m[0][0][i] == 0) continue; for (j = 0; j <= deg; j++) { if (m[1][1][j] == 0) continue; p[i+j] += m[0][0][i]*m[1][1][j]; } } for (i = 0; i <= deg; i++) { if (m[0][1][i] == 0) continue; for (j = 0; j <= deg; j++) { if (m[1][0][j] == 0) continue; p[i+j] -= m[0][1][i]*m[1][0][j]; } } } /* * handle the general case */ else { for (i = 0; i < rank; i++) { if (sub_determinant(p_lash, deg, rank, 0, i, m, &q)) return -1; for (j = 0; j <= deg; j++) { if (m[0][i][j] == 0) continue; for (k = 0; k <= deg; k++) { if (q[k] == 0) continue; p[j+k] += sign*m[0][i][j]*q[k]; } } free(q); sign = -sign; } } return 0; } /* * char_poly * * compute the characteristic polynomial of matrix of rank * by computing the determinant of m-x*I and return in poly * as an array. caller must free poly */ static int char_poly(lash_t *p_lash, int rank, int **matrix, int **poly) { osm_log_t *p_log = &p_lash->p_osm->log; int ret = -1; int i, j; int ***m = NULL; int *p = NULL; int deg = rank; OSM_LOG_ENTER(p_log); do { if (!matrix) break; if (!(p = poly_alloc(p_lash, deg))) break; if (!(m = pm_alloc(p_lash, rank, deg))) { free(p); p = NULL; break; } for (i = 0; i < rank; i++) { for (j = 0; j < rank; j++) { m[i][j][0] = matrix[i][j]; } m[i][i][1] = -1; } if (determinant(p_lash, deg, rank, m, p)) { free(p); p = NULL; break; } ret = 0; } while (0); pm_free(m, rank); *poly = p; OSM_LOG_EXIT(p_log); return ret; } /* * get_switch_metric * * compute the matrix of minimum distances between each of * the adjacent switch nodes to sw along paths * that do not go through sw. do calculation by * relaxation method * allocate space for the matrix and save in node_t structure */ static int get_switch_metric(lash_t *p_lash, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; int ret = -1; unsigned int i, j, change; int sw1, sw2, sw3; switch_t *s = p_lash->switches[sw]; switch_t *s1, *s2, *s3; int **m; mesh_node_t *node = s->node; unsigned int num_links = node->num_links; OSM_LOG_ENTER(p_log); do { if (!(m = m_alloc(p_lash, num_links))) break; for (i = 0; i < num_links; i++) { sw1 = node->links[i]->switch_id; s1 = p_lash->switches[sw1]; /* make all distances big except s1 to itself */ for (sw2 = 0; sw2 < p_lash->num_switches; sw2++) p_lash->switches[sw2]->node->temp = LARGE; s1->node->temp = 0; do { change = 0; for (sw2 = 0; sw2 < p_lash->num_switches; sw2++) { s2 = p_lash->switches[sw2]; if (s2->node->temp == LARGE) continue; for (j = 0; j < s2->node->num_links; j++) { sw3 = s2->node->links[j]->switch_id; s3 = p_lash->switches[sw3]; if (sw3 == sw) continue; if ((s2->node->temp + 1) < s3->node->temp) { s3->node->temp = s2->node->temp + 1; change++; } } } } while (change); for (j = 0; j < num_links; j++) { sw2 = node->links[j]->switch_id; s2 = p_lash->switches[sw2]; m[i][j] = s2->node->temp; } } if (char_poly(p_lash, num_links, m, &node->poly)) { m_free(m, num_links); m = NULL; break; } ret = 0; } while (0); node->matrix = m; OSM_LOG_EXIT(p_log); return ret; } /* * classify_switch * * add switch to histogram of switch types * we keep a reference to the first switch * found of each type as an exemplar */ static void classify_switch(lash_t *p_lash, mesh_t *mesh, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; int i; switch_t *s = p_lash->switches[sw]; switch_t *s1; OSM_LOG_ENTER(p_log); if (!s->node->poly) goto done; for (i = 0; i < mesh->num_class; i++) { s1 = p_lash->switches[mesh->class_type[i]]; if (poly_diff(s->node->num_links, s->node->poly, s1)) continue; mesh->class_count[i]++; goto done; } mesh->class_type[mesh->num_class] = sw; mesh->class_count[mesh->num_class] = 1; mesh->num_class++; done: OSM_LOG_EXIT(p_log); } /* * classify_mesh_type * * try to look up node polynomial in table */ static void classify_mesh_type(lash_t *p_lash, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; int i; switch_t *s = p_lash->switches[sw]; const struct mesh_info *t; OSM_LOG_ENTER(p_log); if (!s->node->poly) goto done; for (i = 1; (t = &mesh_info[i])->dimension != -1; i++) { if (poly_diff(t->degree, t->poly, s)) continue; s->node->type = i; s->node->dimension = t->dimension; OSM_LOG_EXIT(p_log); return; } done: s->node->type = 0; OSM_LOG_EXIT(p_log); return; } /* * remove_edges * * remove type from nodes that have fewer links * than adjacent nodes */ static void remove_edges(lash_t *p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; int sw; mesh_node_t *n, *nn; unsigned i; OSM_LOG_ENTER(p_log); for (sw = 0; sw < p_lash->num_switches; sw++) { n = p_lash->switches[sw]->node; if (!n->type) continue; for (i = 0; i < n->num_links; i++) { nn = p_lash->switches[n->links[i]->switch_id]->node; if (nn->num_links > n->num_links) { OSM_LOG(p_log, OSM_LOG_DEBUG, "removed edge switch %s\n", p_lash->switches[sw]->p_sw->p_node->print_desc); n->type = -1; break; } } } OSM_LOG_EXIT(p_log); } /* * get_local_geometry * * analyze the local geometry around each switch */ static int get_local_geometry(lash_t *p_lash, mesh_t *mesh) { osm_log_t *p_log = &p_lash->p_osm->log; int sw; int status = 0; OSM_LOG_ENTER(p_log); for (sw = 0; sw < p_lash->num_switches; sw++) { /* * skip switches with more links than MAX_DEGREE * since they will never match a known case */ if (p_lash->switches[sw]->node->num_links > MAX_DEGREE) continue; if (get_switch_metric(p_lash, sw)) { status = -1; goto Exit; } classify_mesh_type(p_lash, sw); } remove_edges(p_lash); for (sw = 0; sw < p_lash->num_switches; sw++) { if (p_lash->switches[sw]->node->type < 0) continue; classify_switch(p_lash, mesh, sw); } Exit: OSM_LOG_EXIT(p_log); return status; } static void print_axis(lash_t *p_lash, char *p, int sw, int port) { mesh_node_t *node = p_lash->switches[sw]->node; char *name = p_lash->switches[sw]->p_sw->p_node->print_desc; int c = node->axes[port]; p += sprintf(p, "%s[%d] = ", name, port); if (c) p += sprintf(p, "%s%c -> ", ((c - 1) & 1) ? "-" : "+", 'X' + (c - 1)/2); else p += sprintf(p, "N/A -> "); p += sprintf(p, "%s\n", p_lash->switches[node->links[port]->switch_id]->p_sw->p_node->print_desc); } /* * seed_axes * * assign axes to the links of the seed switch * assumes switch is of type cartesian mesh * axes are numbered 1 to n i.e. +x => 1 -x => 2 etc. * this assumes that if all distances are 2 that * an axis has only 2 nodes so +A and -A collapse to +A */ static void seed_axes(lash_t *p_lash, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; mesh_node_t *node = p_lash->switches[sw]->node; int n = node->num_links; int i, j, c; OSM_LOG_ENTER(p_log); if (!node->matrix || !node->dimension) goto done; for (c = 1; c <= 2*node->dimension; c++) { /* * find the next unassigned axis */ for (i = 0; i < n; i++) { if (!node->axes[i]) break; } node->axes[i] = c++; /* * find the matching opposite direction */ for (j = 0; j < n; j++) { if (node->axes[j] || j == i) continue; if (node->matrix[i][j] != 2) break; } if (j != n) { node->axes[j] = c; } } if (OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_DEBUG)) { char buf[256], *p; for (i = 0; i < n; i++) { p = buf; print_axis(p_lash, p, sw, i); OSM_LOG(p_log, OSM_LOG_DEBUG, "%s", buf); } } done: OSM_LOG_EXIT(p_log); } /* * opposite * * compute the opposite of axis for switch */ static inline int opposite(switch_t *s, int axis) { unsigned i, j; int negaxis = 1 + (1 ^ (axis - 1)); if (!s->node->matrix) return 0; for (i = 0; i < s->node->num_links; i++) { if (s->node->axes[i] == axis) { for (j = 0; j < s->node->num_links; j++) { if (j == i) continue; if (s->node->matrix[i][j] != 2) return negaxis; } return axis; } } return 0; } /* * make_geometry * * induce a geometry on the switches */ static void make_geometry(lash_t *p_lash, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; int num_switches = p_lash->num_switches; int sw1, sw2; switch_t *s, *s1, *s2, *seed; unsigned int i, j, k, l, n, m; unsigned int change; OSM_LOG_ENTER(p_log); s = p_lash->switches[sw]; if (!s->node->matrix) goto done; /* * assign axes to seed switch */ seed_axes(p_lash, sw); seed = p_lash->switches[sw]; /* * induce axes in other switches until * there is no more change */ do { change = 0; /* phase 1 opposites */ for (sw1 = 0; sw1 < num_switches; sw1++) { s1 = p_lash->switches[sw1]; n = s1->node->num_links; /* * ignore chain fragments */ if (n < seed->node->num_links && n <= 2) continue; /* * only process 'mesh' switches */ if (!s1->node->matrix) continue; for (i = 0; i < n; i++) { if (!s1->node->axes[i]) continue; /* * can't tell across if more than one * likely looking link */ m = 0; for (j = 0; j < n; j++) { if (j == i) continue; if (s1->node->matrix[i][j] != 2) m++; } if (m != 1) { continue; } for (j = 0; j < n; j++) { if (j == i) continue; /* Rule out opposite nodes when distance greater than 4 */ if (s1->node->matrix[i][j] != 2 && s1->node->matrix[i][j] <= 4) { if (s1->node->axes[j]) { if (s1->node->axes[j] != opposite(seed, s1->node->axes[i])) { OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 1 mismatch\n"); } } else { s1->node->axes[j] = opposite(seed, s1->node->axes[i]); change++; } } } } } /* phase 2 switch to switch */ for (sw1 = 0; sw1 < num_switches; sw1++) { s1 = p_lash->switches[sw1]; n = s1->node->num_links; if (!s1->node->matrix) continue; for (i = 0; i < n; i++) { int l2 = s1->node->links[i]->link_id; if (!s1->node->axes[i]) continue; if (l2 == -1) { OSM_LOG(p_log, OSM_LOG_DEBUG, "no reverse link\n"); continue; } sw2 = s1->node->links[i]->switch_id; s2 = p_lash->switches[sw2]; if (!s2->node->matrix) continue; if (!s2->node->axes[l2]) { /* * set axis to opposite of s1->axes[i] */ s2->node->axes[l2] = opposite(seed, s1->node->axes[i]); change++; } else { if (s2->node->axes[l2] != opposite(seed, s1->node->axes[i])) { OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 2 mismatch\n"); } } } } /* Phase 3 corners */ for (sw1 = 0; sw1 < num_switches; sw1++) { s = p_lash->switches[sw1]; n = s->node->num_links; if (!s->node->matrix) continue; for (i = 0; i < n; i++) { if (!s->node->axes[i]) continue; for (j = 0; j < n; j++) { if (i == j || !s->node->axes[j] || s->node->matrix[i][j] != 2) continue; s1 = p_lash->switches[s->node->links[i]->switch_id]; s2 = p_lash->switches[s->node->links[j]->switch_id]; /* * find switch (other than s1) that neighbors i and j * have in common */ for (k = 0; k < s1->node->num_links; k++) { if (s1->node->links[k]->switch_id == sw1) continue; for (l = 0; l < s2->node->num_links; l++) { if (s2->node->links[l]->switch_id == sw1) continue; if (s1->node->links[k]->switch_id == s2->node->links[l]->switch_id) { if (s1->node->axes[k]) { if (s1->node->axes[k] != s->node->axes[j]) { OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 3 mismatch\n"); } } else { s1->node->axes[k] = s->node->axes[j]; change++; } if (s2->node->axes[l]) { if (s2->node->axes[l] != s->node->axes[i]) { OSM_LOG(p_log, OSM_LOG_DEBUG, "phase 3 mismatch\n"); } } else { s2->node->axes[l] = s->node->axes[i]; change++; } goto next_j; } } } next_j: ; } } } } while (change); done: OSM_LOG_EXIT(p_log); } /* * return |a| < |b| */ static inline int ltmag(int a, int b) { int a1 = (a >= 0)? a : -a; int b1 = (b >= 0)? b : -b; return (a1 < b1) || (a1 == b1 && a > b); } /* * reorder_node_links * * reorder the links out of a switch in sign/dimension order */ static int reorder_node_links(lash_t *p_lash, mesh_t *mesh, int sw) { osm_log_t *p_log = &p_lash->p_osm->log; switch_t *s = p_lash->switches[sw]; mesh_node_t *node = s->node; int n = node->num_links; link_t **links; int *axes; int i, j, k, l; int c; int next = 0; int dimension = mesh->dimension; if (!(links = calloc(n, sizeof(link_t *)))) { OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating links array - out of memory\n"); return -1; } if (!(axes = calloc(n, sizeof(int)))) { free(links); OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating axes array - out of memory\n"); return -1; } /* * find the links with axes */ for (i = 0; i < dimension; i++) { j = mesh->dim_order[i]; for (k = 1; k <= 2; k++) { c = 2*j + k; if (node->coord[j] > 0) c = opposite(s, c); for (l = 0; l < n; l++) { if (!node->links[l]) continue; if (node->axes[l] == c) { links[next] = node->links[l]; axes[next] = node->axes[l]; node->links[l] = NULL; next++; } } } } /* * get the rest */ for (i = 0; i < n; i++) { if (!node->links[i]) continue; links[next] = node->links[i]; axes[next] = node->axes[i]; node->links[i] = NULL; next++; } for (i = 0; i < n; i++) { node->links[i] = links[i]; node->axes[i] = axes[i]; } free(links); free(axes); return 0; } /* * make_coord */ static int make_coord(lash_t *p_lash, mesh_t *mesh, int seed) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned int i, j, k; int sw; switch_t *s, *s1; unsigned int change; unsigned int dimension = mesh->dimension; int num_switches = p_lash->num_switches; int assigned_axes = 0, unassigned_axes = 0; OSM_LOG_ENTER(p_log); for (sw = 0; sw < num_switches; sw++) { s = p_lash->switches[sw]; s->node->coord = calloc(dimension, sizeof(int)); if (!s->node->coord) { OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating coord - out of memory\n"); OSM_LOG_EXIT(p_log); return -1; } for (i = 0; i < dimension; i++) s->node->coord[i] = (sw == seed) ? 0 : LARGE; for (i = 0; i < s->node->num_links; i++) if (s->node->axes[i] == 0) unassigned_axes++; else assigned_axes++; } OSM_LOG(p_log, OSM_LOG_DEBUG, "%d/%d unassigned/assigned axes\n", unassigned_axes, assigned_axes); do { change = 0; for (sw = 0; sw < num_switches; sw++) { s = p_lash->switches[sw]; if (s->node->coord[0] == LARGE) continue; for (j = 0; j < s->node->num_links; j++) { if (!s->node->axes[j]) continue; s1 = p_lash->switches[s->node->links[j]->switch_id]; for (k = 0; k < dimension; k++) { int coord = s->node->coord[k]; unsigned axis = s->node->axes[j] - 1; if (k == axis/2) coord += (axis & 1)? -1 : +1; if (ltmag(coord, s1->node->coord[k])) { s1->node->coord[k] = coord; change++; } } } } } while (change); OSM_LOG_EXIT(p_log); return 0; } /* * measure geometry */ static int measure_geometry(lash_t *p_lash, mesh_t *mesh) { osm_log_t *p_log = &p_lash->p_osm->log; int i, j; int sw; switch_t *s; int dimension = mesh->dimension; int num_switches = p_lash->num_switches; int max[MAX_DIMENSION]; int min[MAX_DIMENSION]; int size[MAX_DIMENSION]; int max_size; int max_index; OSM_LOG_ENTER(p_log); mesh->size = calloc(dimension, sizeof(int)); if (!mesh->size) { OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating size - out of memory\n"); OSM_LOG_EXIT(p_log); return -1; } for (i = 0; i < dimension; i++) { max[i] = -LARGE; min[i] = LARGE; } for (sw = 0; sw < num_switches; sw++) { s = p_lash->switches[sw]; for (i = 0; i < dimension; i++) { if (s->node->coord[i] == LARGE) continue; if (s->node->coord[i] > max[i]) max[i] = s->node->coord[i]; if (s->node->coord[i] < min[i]) min[i] = s->node->coord[i]; } } for (i = 0; i < dimension; i++) mesh->size[i] = size[i] = max[i] - min[i] + 1; /* * find an order of dimensions that places largest * sizes first since this seems to work best with LASH */ for (j = 0; j < dimension; j++) { max_size = -1; max_index = -1; for (i = 0; i < dimension; i++) { if (size[i] > max_size) { max_size = size[i]; max_index = i; } } mesh->dim_order[j] = max_index; size[max_index] = -1; } OSM_LOG_EXIT(p_log); return 0; } /* * reorder links */ static int reorder_links(lash_t *p_lash, mesh_t *mesh) { osm_log_t *p_log = &p_lash->p_osm->log; int sw; int num_switches = p_lash->num_switches; OSM_LOG_ENTER(p_log); for (sw = 0; sw < num_switches; sw++) { if (reorder_node_links(p_lash, mesh, sw)) { OSM_LOG_EXIT(p_log); return -1; } } OSM_LOG_EXIT(p_log); return 0; } /* * compare two switches in a sort */ static int compare_switches(const void *p1, const void *p2) { const comp_t *cp1 = p1, *cp2 = p2; const sort_ctx_t *ctx = &cp1->ctx; switch_t *s1 = ctx->p_lash->switches[cp1->index]; switch_t *s2 = ctx->p_lash->switches[cp2->index]; int i, j; int ret; for (i = 0; i < ctx->mesh->dimension; i++) { j = ctx->mesh->dim_order[i]; ret = s1->node->coord[j] - s2->node->coord[j]; if (ret) return ret; } return 0; } /* * sort_switches - reorder switch array */ static void sort_switches(lash_t *p_lash, mesh_t *mesh) { unsigned int i, j; unsigned int num_switches = p_lash->num_switches; comp_t *comp; int *reverse; switch_t *s; switch_t **switches; comp = malloc(num_switches * sizeof(comp_t)); reverse = malloc(num_switches * sizeof(int)); switches = malloc(num_switches * sizeof(switch_t *)); if (!comp || !reverse || !switches) { OSM_LOG(&p_lash->p_osm->log, OSM_LOG_ERROR, "Failed memory allocation - switches not sorted!\n"); goto Exit; } for (i = 0; i < num_switches; i++) { comp[i].index = i; comp[i].ctx.mesh = mesh; comp[i].ctx.p_lash = p_lash; } qsort(comp, num_switches, sizeof(comp_t), compare_switches); for (i = 0; i < num_switches; i++) reverse[comp[i].index] = i; for (i = 0; i < num_switches; i++) { s = p_lash->switches[comp[i].index]; switches[i] = s; s->id = i; for (j = 0; j < s->node->num_links; j++) s->node->links[j]->switch_id = reverse[s->node->links[j]->switch_id]; } for (i = 0; i < num_switches; i++) p_lash->switches[i] = switches[i]; Exit: if (switches) free(switches); if (comp) free(comp); if (reverse) free(reverse); } /* * osm_mesh_delete - free per mesh resources */ static void mesh_delete(mesh_t *mesh) { if (mesh) { if (mesh->class_type) free(mesh->class_type); if (mesh->class_count) free(mesh->class_count); if (mesh->size) free(mesh->size); free(mesh); } } /* * osm_mesh_create - allocate per mesh resources */ static mesh_t *mesh_create(lash_t *p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; mesh_t *mesh; if(!(mesh = calloc(1, sizeof(mesh_t)))) goto err; if (!(mesh->class_type = calloc(p_lash->num_switches, sizeof(int)))) goto err; if (!(mesh->class_count = calloc(p_lash->num_switches, sizeof(int)))) goto err; return mesh; err: mesh_delete(mesh); OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating mesh - out of memory\n"); return NULL; } /* * osm_mesh_node_delete - cleanup per switch resources */ void osm_mesh_node_delete(lash_t *p_lash, switch_t *sw) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned i; mesh_node_t *node = sw->node; unsigned num_ports = sw->p_sw->num_ports; OSM_LOG_ENTER(p_log); if (node) { for (i = 0; i < num_ports; i++) if (node->links[i]) free(node->links[i]); if (node->poly) free(node->poly); if (node->matrix) { for (i = 0; i < node->num_links; i++) { if (node->matrix[i]) free(node->matrix[i]); } free(node->matrix); } if (node->axes) free(node->axes); if (node->coord) free(node->coord); free(node); sw->node = NULL; } OSM_LOG_EXIT(p_log); } /* * osm_mesh_node_create - allocate per switch resources */ int osm_mesh_node_create(lash_t *p_lash, switch_t *sw) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned i; mesh_node_t *node; unsigned num_ports = sw->p_sw->num_ports; OSM_LOG_ENTER(p_log); if (!(node = sw->node = calloc(1, sizeof(mesh_node_t) + num_ports * sizeof(link_t *)))) goto err; for (i = 0; i < num_ports; i++) if (!(node->links[i] = calloc(1, sizeof(link_t) + num_ports * sizeof(int)))) goto err; if (!(node->axes = calloc(num_ports, sizeof(int)))) goto err; for (i = 0; i < num_ports; i++) { node->links[i]->switch_id = NONE; } OSM_LOG_EXIT(p_log); return 0; err: osm_mesh_node_delete(p_lash, sw); OSM_LOG(p_log, OSM_LOG_ERROR, "Failed allocating mesh node - out of memory\n"); OSM_LOG_EXIT(p_log); return -1; } static void dump_mesh(lash_t *p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; int sw; int num_switches = p_lash->num_switches; int dimension; int i, j, k, n; switch_t *s, *s2; char buf[256]; OSM_LOG_ENTER(p_log); for (sw = 0; sw < num_switches; sw++) { s = p_lash->switches[sw]; dimension = s->node->dimension; n = sprintf(buf, "["); for (i = 0; i < dimension; i++) { n += snprintf(buf + n, sizeof(buf) - n, "%2d", s->node->coord[i]); if (n > sizeof(buf)) n = sizeof(buf); if (i != dimension - 1) { n += snprintf(buf + n, sizeof(buf) - n, "%s", ","); if (n > sizeof(buf)) n = sizeof(buf); } } n += snprintf(buf + n, sizeof(buf) - n, "]"); if (n > sizeof(buf)) n = sizeof(buf); for (j = 0; j < s->node->num_links; j++) { s2 = p_lash->switches[s->node->links[j]->switch_id]; n += snprintf(buf + n, sizeof(buf) - n, " [%d]->[", j); if (n > sizeof(buf)) n = sizeof(buf); for (k = 0; k < dimension; k++) { n += snprintf(buf + n, sizeof(buf) - n, "%2d", s2->node->coord[k]); if (n > sizeof(buf)) n = sizeof(buf); if (k != dimension - 1) { n += snprintf(buf + n, sizeof(buf) - n, ","); if (n > sizeof(buf)) n = sizeof(buf); } } n += snprintf(buf + n, sizeof(buf) - n, "]"); if (n > sizeof(buf)) n = sizeof(buf); } OSM_LOG(p_log, OSM_LOG_DEBUG, "%s\n", buf); } OSM_LOG_EXIT(p_log); } /* * osm_do_mesh_analysis */ int osm_do_mesh_analysis(lash_t *p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; mesh_t *mesh; int max_class_num = 0; int max_class_type = -1; int i; switch_t *s; char buf[256], *p; OSM_LOG_ENTER(p_log); mesh = mesh_create(p_lash); if (!mesh) goto err; if (get_local_geometry(p_lash, mesh)) goto err; if (mesh->num_class == 0) { OSM_LOG(p_log, OSM_LOG_INFO, "found no likely mesh nodes - done\n"); goto done; } /* * find dominant switch class */ OSM_LOG(p_log, OSM_LOG_INFO, "found %d node class%s\n", mesh->num_class, (mesh->num_class == 1) ? "" : "es"); for (i = 0; i < mesh->num_class; i++) { OSM_LOG(p_log, OSM_LOG_INFO, "class[%d] has %d members with type = %d\n", i, mesh->class_count[i], p_lash->switches[mesh->class_type[i]]->node->type); if (mesh->class_count[i] > max_class_num) { max_class_num = mesh->class_count[i]; max_class_type = mesh->class_type[i]; } } s = p_lash->switches[max_class_type]; p = buf; p += sprintf(p, "%snode shape is ", (mesh->num_class == 1) ? "" : "most common "); if (s->node->type) { const struct mesh_info *t = &mesh_info[s->node->type]; for (i = 0; i < t->dimension; i++) { p += sprintf(p, "%s%d%s", i? " x " : "", t->size[i], (t->size[i] == 6)? "+" : ""); } p += sprintf(p, " mesh\n"); mesh->dimension = t->dimension; } else { p += sprintf(p, "unknown geometry\n"); } OSM_LOG(p_log, OSM_LOG_INFO, "%s", buf); OSM_LOG(p_log, OSM_LOG_INFO, "poly = %s\n", poly_print(s->node->num_links, s->node->poly)); if (s->node->type) { make_geometry(p_lash, max_class_type); if (make_coord(p_lash, mesh, max_class_type)) goto err; if (measure_geometry(p_lash, mesh)) goto err; if (reorder_links(p_lash, mesh)) goto err; sort_switches(p_lash, mesh); p = buf; p += sprintf(p, "found "); for (i = 0; i < mesh->dimension; i++) p += sprintf(p, "%s%d", i? " x " : "", mesh->size[i]); p += sprintf(p, " mesh\n"); OSM_LOG(p_log, OSM_LOG_INFO, "%s", buf); } if (OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_DEBUG)) dump_mesh(p_lash); done: mesh_delete(mesh); OSM_LOG_EXIT(p_log); return 0; err: mesh_delete(mesh); OSM_LOG_EXIT(p_log); return -1; } opensm-3.3.20/opensm/osm_mtree.c0000644000205000001450000000606212272264653013464 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 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 osm_mtree_node_t. * This file implements the Multicast Tree object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #define FILE_ID OSM_FILE_MTREE_C #include #include osm_mtree_node_t *osm_mtree_node_new(IN const osm_switch_t * p_sw) { osm_mtree_node_t *p_mtn; uint32_t i; p_mtn = malloc(sizeof(osm_mtree_node_t) + sizeof(void *) * (p_sw->num_ports - 1)); if (!p_mtn) return NULL; memset(p_mtn, 0, sizeof(*p_mtn)); p_mtn->p_sw = p_sw; p_mtn->max_children = p_sw->num_ports; for (i = 0; i < p_mtn->max_children; i++) p_mtn->child_array[i] = NULL; return p_mtn; } void osm_mtree_destroy(IN osm_mtree_node_t * p_mtn) { uint8_t i; if (p_mtn == NULL) return; for (i = 0; i < p_mtn->max_children; i++) if ((p_mtn->child_array[i] != NULL) && (p_mtn->child_array[i] != OSM_MTREE_LEAF)) osm_mtree_destroy(p_mtn->child_array[i]); free(p_mtn); } #if 0 static void mtree_dump(IN osm_mtree_node_t * p_mtn) { uint32_t i; if (p_mtn == NULL) return; printf("GUID:0x%016" PRIx64 " max_children:%u\n", cl_ntoh64(p_mtn->p_sw->p_node->node_info.node_guid), p_mtn->max_children); if (p_mtn->child_array != NULL) { for (i = 0; i < p_mtn->max_children; i++) { printf("i=%d\n", i); if ((p_mtn->child_array[i] != NULL) && (p_mtn->child_array[i] != OSM_MTREE_LEAF)) mtree_dump(p_mtn->child_array[i]); } } } #endif opensm-3.3.20/opensm/osm_multicast.c0000644000205000001450000003523512616420637014357 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 multicast functions. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_MULTICAST_C #include #include #include #include #include static osm_mgrp_box_t *mgrp_box_new(uint16_t mlid) { osm_mgrp_box_t *mbox = malloc(sizeof(*mbox)); if (!mbox) return NULL; memset(mbox, 0, sizeof(*mbox)); mbox->mlid = mlid; cl_qlist_init(&mbox->mgrp_list); return mbox; } void mgrp_box_delete(osm_mgrp_box_t *mbox) { osm_mtree_destroy(mbox->root); free(mbox); } void mgrp_delete(IN osm_mgrp_t * p_mgrp) { osm_mcm_alias_guid_t *p_mcm_alias_guid, *p_next_mcm_alias_guid; osm_mcm_port_t *p_mcm_port, *p_next_mcm_port; CL_ASSERT(p_mgrp); p_next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_head(&p_mgrp->mcm_alias_port_tbl); while (p_next_mcm_alias_guid != (osm_mcm_alias_guid_t *) cl_qmap_end(&p_mgrp->mcm_alias_port_tbl)) { p_mcm_alias_guid = p_next_mcm_alias_guid; p_next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_next(&p_mcm_alias_guid->map_item); osm_mcm_alias_guid_delete(&p_mcm_alias_guid); } p_next_mcm_port = (osm_mcm_port_t *) cl_qmap_head(&p_mgrp->mcm_port_tbl); while (p_next_mcm_port != (osm_mcm_port_t *) cl_qmap_end(&p_mgrp->mcm_port_tbl)) { p_mcm_port = p_next_mcm_port; p_next_mcm_port = (osm_mcm_port_t *) cl_qmap_next(&p_mcm_port->map_item); osm_mcm_port_delete(p_mcm_port); } free(p_mgrp); } void osm_mgrp_box_delete(osm_mgrp_box_t *mbox) { osm_mgrp_t *mgrp; while (cl_qlist_count(&mbox->mgrp_list)) { mgrp = cl_item_obj(cl_qlist_remove_head(&mbox->mgrp_list), mgrp, list_item); mgrp_delete(mgrp); } mgrp_box_delete(mbox); } osm_mgrp_t *osm_mgrp_new(IN osm_subn_t * subn, IN ib_net16_t mlid, IN ib_member_rec_t * mcmr) { osm_mgrp_t *p_mgrp; osm_mgrp_box_t *mbox; p_mgrp = (osm_mgrp_t *) malloc(sizeof(*p_mgrp)); if (!p_mgrp) return NULL; memset(p_mgrp, 0, sizeof(*p_mgrp)); cl_qmap_init(&p_mgrp->mcm_port_tbl); cl_qmap_init(&p_mgrp->mcm_alias_port_tbl); p_mgrp->mlid = mlid; p_mgrp->mcmember_rec = *mcmr; mbox = osm_get_mbox_by_mlid(subn, p_mgrp->mlid); if (!mbox && !(mbox = mgrp_box_new(cl_ntoh16(p_mgrp->mlid)))) { free(p_mgrp); return NULL; } cl_qlist_insert_tail(&mbox->mgrp_list, &p_mgrp->list_item); subn->mboxes[mbox->mlid - IB_LID_MCAST_START_HO] = mbox; cl_fmap_insert(&subn->mgrp_mgid_tbl, &p_mgrp->mcmember_rec.mgid, &p_mgrp->map_item); subn->p_osm->sa.dirty = TRUE; return p_mgrp; } void osm_mgrp_cleanup(osm_subn_t * subn, osm_mgrp_t * mgrp) { osm_mgrp_box_t *mbox; osm_mcm_alias_guid_t *mcm_alias_guid; osm_mcm_port_t *mcm_port; if (mgrp->full_members) return; while (cl_qmap_count(&mgrp->mcm_alias_port_tbl)) { mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_head(&mgrp->mcm_alias_port_tbl); cl_qmap_remove_item(&mgrp->mcm_alias_port_tbl, &mcm_alias_guid->map_item); osm_mcm_alias_guid_delete(&mcm_alias_guid); } while (cl_qmap_count(&mgrp->mcm_port_tbl)) { mcm_port = (osm_mcm_port_t *) cl_qmap_head(&mgrp->mcm_port_tbl); cl_qmap_remove_item(&mgrp->mcm_port_tbl, &mcm_port->map_item); cl_qlist_remove_item(&mcm_port->port->mcm_list, &mcm_port->list_item); osm_mcm_port_delete(mcm_port); } if (mgrp->well_known) return; cl_fmap_remove_item(&subn->mgrp_mgid_tbl, &mgrp->map_item); mbox = osm_get_mbox_by_mlid(subn, mgrp->mlid); cl_qlist_remove_item(&mbox->mgrp_list, &mgrp->list_item); if (cl_is_qlist_empty(&mbox->mgrp_list)) { subn->mboxes[cl_ntoh16(mgrp->mlid) - IB_LID_MCAST_START_HO] = NULL; mgrp_box_delete(mbox); } free(mgrp); subn->p_osm->sa.dirty = TRUE; } static void mgrp_send_notice(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp, unsigned num) { ib_mad_notice_attr_t notice; ib_api_status_t status; notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT; /* is generic subn mgt type */ ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */ notice.g_or_v.generic.trap_num = CL_HTON16(num); /* The sm_base_lid is saved in network order already. */ notice.issuer_lid = subn->sm_base_lid; /* following o14-12.1.11 and table 120 p726 */ /* we need to provide the MGID */ memcpy(¬ice.data_details.ntc_64_67.gid, &mgrp->mcmember_rec.mgid, sizeof(ib_gid_t)); /* According to page 653 - the issuer gid in this case of trap is the SM gid, since the SM is the initiator of this trap. */ notice.issuer_gid.unicast.prefix = subn->opt.subnet_prefix; notice.issuer_gid.unicast.interface_id = subn->sm_port_guid; if ((status = osm_report_notice(log, subn, ¬ice))) OSM_LOG(log, OSM_LOG_ERROR, "ERR 7601: " "Error sending trap reports (%s)\n", ib_get_err_str(status)); } static boolean_t is_qmap_empty_for_port(IN const cl_qmap_t * const p_map, IN const osm_port_t *port) { size_t count = 0; cl_map_item_t *item; osm_mcm_alias_guid_t *mcm_alias_guid; for (item = cl_qmap_head(p_map); item != cl_qmap_end(p_map); item = cl_qmap_next(item)) { mcm_alias_guid = (osm_mcm_alias_guid_t *) item; if (mcm_alias_guid->p_base_mcm_port->port == port) { count++; break; } } return (count == 0); } static boolean_t is_qmap_empty_for_mcm_port(IN const cl_qmap_t * const p_map, IN const osm_mcm_port_t *mcm_port) { size_t count = 0; cl_map_item_t *item; osm_mcm_alias_guid_t *mcm_alias_guid; for (item = cl_qmap_head(p_map); item != cl_qmap_end(p_map); item = cl_qmap_next(item)) { mcm_alias_guid = (osm_mcm_alias_guid_t *) item; if (mcm_alias_guid->p_base_mcm_port == mcm_port) { count++; break; } } return (count == 0); } static osm_mcm_alias_guid_t *insert_alias_guid(IN osm_mgrp_t * mgrp, IN osm_mcm_alias_guid_t * p_mcm_alias_guid) { osm_mcm_alias_guid_t *p_mcm_alias_guid_check; /* insert into mcm alias guid table */ p_mcm_alias_guid_check = (osm_mcm_alias_guid_t *) cl_qmap_insert(&mgrp->mcm_alias_port_tbl, p_mcm_alias_guid->alias_guid, &p_mcm_alias_guid->map_item); if (p_mcm_alias_guid_check != (osm_mcm_alias_guid_t *) &p_mcm_alias_guid->map_item) { /* alias GUID is a duplicate */ osm_mcm_alias_guid_delete(&p_mcm_alias_guid); return p_mcm_alias_guid_check; } return NULL; } osm_mcm_port_t *osm_mgrp_add_port(IN osm_subn_t * subn, osm_log_t * log, IN osm_mgrp_t * mgrp, osm_port_t *port, IN ib_member_rec_t *mcmr, IN boolean_t proxy) { osm_mcm_port_t *mcm_port; osm_mcm_alias_guid_t *p_mcm_alias_guid, *p_mcm_alias_guid_check; cl_map_item_t *prev_item; uint8_t prev_join_state = 0, join_state = mcmr->scope_state; uint8_t prev_scope; if (OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_VERBOSE)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(log, OSM_LOG_VERBOSE, "GUID 0x%016" PRIx64 " Port 0x%016" PRIx64 " joining " "MC group %s (mlid 0x%x)\n", cl_ntoh64(mcmr->port_gid.unicast.interface_id), cl_ntoh64(port->guid), inet_ntop(AF_INET6, mgrp->mcmember_rec.mgid.raw, gid_str, sizeof(gid_str)), cl_ntoh16(mgrp->mlid)); } mcm_port = osm_mcm_port_new(port, mgrp); if (!mcm_port) return NULL; p_mcm_alias_guid = osm_mcm_alias_guid_new(mcm_port, mcmr, proxy); if (!p_mcm_alias_guid) { osm_mcm_port_delete(mcm_port); return NULL; } /* prev_item = cl_qmap_insert(...) 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. */ prev_item = cl_qmap_insert(&mgrp->mcm_port_tbl, port->guid, &mcm_port->map_item); if (prev_item != &mcm_port->map_item) { /* mcm port already exists */ osm_mcm_port_delete(mcm_port); mcm_port = (osm_mcm_port_t *) prev_item; p_mcm_alias_guid->p_base_mcm_port = (osm_mcm_port_t *) prev_item; p_mcm_alias_guid_check = insert_alias_guid(mgrp, p_mcm_alias_guid); if (p_mcm_alias_guid_check) { /* alias GUID already exists */ p_mcm_alias_guid = p_mcm_alias_guid_check; ib_member_get_scope_state(p_mcm_alias_guid->scope_state, &prev_scope, &prev_join_state); p_mcm_alias_guid->scope_state = ib_member_set_scope_state(prev_scope, prev_join_state | join_state); } } else { insert_alias_guid(mgrp, p_mcm_alias_guid); cl_qlist_insert_tail(&port->mcm_list, &mcm_port->list_item); osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid); } /* o15.0.1.11: copy the join state */ mcmr->scope_state = p_mcm_alias_guid->scope_state; if ((join_state & IB_JOIN_STATE_FULL) && !(prev_join_state & IB_JOIN_STATE_FULL) && ++mgrp->full_members == 1) mgrp_send_notice(subn, log, mgrp, SM_MGID_CREATED_TRAP); /* 66 */ subn->p_osm->sa.dirty = TRUE; return mcm_port; } boolean_t osm_mgrp_remove_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp, osm_mcm_alias_guid_t * mcm_alias_guid, ib_member_rec_t *mcmr) { uint8_t join_state = mcmr->scope_state & 0xf; uint8_t port_join_state, new_join_state; boolean_t mgrp_deleted = FALSE; /* * according to the same o15-0.1.14 we get the stored * JoinState and the request JoinState and they must be * opposite to leave - otherwise just update it */ port_join_state = mcm_alias_guid->scope_state & 0x0F; new_join_state = port_join_state & ~join_state; if (OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_VERBOSE)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(log, OSM_LOG_VERBOSE, "GUID 0x%" PRIx64 " Port 0x%" PRIx64 " leaving MC group %s (mlid 0x%x)\n", cl_ntoh64(mcm_alias_guid->alias_guid), cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid), inet_ntop(AF_INET6, mgrp->mcmember_rec.mgid.raw, gid_str, sizeof(gid_str)), cl_ntoh16(mgrp->mlid)); } if (new_join_state & IB_JOIN_STATE_FULL || (new_join_state && (mgrp->full_members > (port_join_state & IB_JOIN_STATE_FULL) ? 1 : 0))) { mcm_alias_guid->scope_state = new_join_state | (mcm_alias_guid->scope_state & 0xf0); OSM_LOG(log, OSM_LOG_DEBUG, "updating GUID 0x%" PRIx64 " port 0x%" PRIx64 " JoinState 0x%x -> 0x%x\n", cl_ntoh64(mcm_alias_guid->alias_guid), cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid), port_join_state, new_join_state); mcmr->scope_state = mcm_alias_guid->scope_state; } else { mcmr->scope_state = mcm_alias_guid->scope_state & 0xf0; OSM_LOG(log, OSM_LOG_DEBUG, "removing alias GUID 0x%" PRIx64 "\n", cl_ntoh64(mcm_alias_guid->alias_guid)); cl_qmap_remove_item(&mgrp->mcm_alias_port_tbl, &mcm_alias_guid->map_item); if (is_qmap_empty_for_port(&mgrp->mcm_alias_port_tbl, mcm_alias_guid->p_base_mcm_port->port)) { /* last alias in mcast group for this port */ OSM_LOG(log, OSM_LOG_DEBUG, "removing port 0x%" PRIx64 "\n", cl_ntoh64(mcm_alias_guid->p_base_mcm_port->port->guid)); cl_qmap_remove_item(&mgrp->mcm_port_tbl, &mcm_alias_guid->p_base_mcm_port->map_item); cl_qlist_remove_item(&mcm_alias_guid->p_base_mcm_port->port->mcm_list, &mcm_alias_guid->p_base_mcm_port->list_item); if (is_qmap_empty_for_mcm_port(&mgrp->mcm_alias_port_tbl, mcm_alias_guid->p_base_mcm_port)) /* last alias in mcast group for this mcm port */ osm_mcm_port_delete(mcm_alias_guid->p_base_mcm_port); osm_sm_reroute_mlid(&subn->p_osm->sm, mgrp->mlid); } osm_mcm_alias_guid_delete(&mcm_alias_guid); } /* no more full members so the group will be deleted after re-route but only if it is not a well known group */ if ((port_join_state & IB_JOIN_STATE_FULL) && !(new_join_state & IB_JOIN_STATE_FULL) && --mgrp->full_members == 0) { mgrp_send_notice(subn, log, mgrp, SM_MGID_DESTROYED_TRAP); /* 67 */ osm_mgrp_cleanup(subn, mgrp); mgrp_deleted = TRUE; } subn->p_osm->sa.dirty = TRUE; return (mgrp_deleted); } void osm_mgrp_delete_port(osm_subn_t * subn, osm_log_t * log, osm_mgrp_t * mgrp, osm_port_t * port) { osm_mcm_alias_guid_t *mcm_alias_guid, *next_mcm_alias_guid; ib_member_rec_t mcmrec; boolean_t mgrp_deleted = FALSE; next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_head(&mgrp->mcm_alias_port_tbl); while (next_mcm_alias_guid != (osm_mcm_alias_guid_t *) cl_qmap_end(&mgrp->mcm_alias_port_tbl) && !mgrp_deleted) { mcm_alias_guid = next_mcm_alias_guid; next_mcm_alias_guid = (osm_mcm_alias_guid_t *) cl_qmap_next(&next_mcm_alias_guid->map_item); if (mcm_alias_guid->p_base_mcm_port->port == port) { mcmrec.scope_state = 0xf; mgrp_deleted = osm_mgrp_remove_port(subn, log, mgrp, mcm_alias_guid, &mcmrec); } } } osm_mcm_port_t *osm_mgrp_get_mcm_port(IN const osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid) { cl_map_item_t *item = cl_qmap_get(&p_mgrp->mcm_port_tbl, port_guid); if (item != cl_qmap_end(&p_mgrp->mcm_port_tbl)) return (osm_mcm_port_t *) item; return NULL; } osm_mcm_alias_guid_t *osm_mgrp_get_mcm_alias_guid(IN const osm_mgrp_t * p_mgrp, IN ib_net64_t port_guid) { cl_map_item_t *item = cl_qmap_get(&p_mgrp->mcm_alias_port_tbl, port_guid); if (item != cl_qmap_end(&p_mgrp->mcm_alias_port_tbl)) return (osm_mcm_alias_guid_t *) item; return NULL; } opensm-3.3.20/opensm/osm_node.c0000644000205000001450000001771712600531631013272 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 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 osm_node_t. * This object represents an Infiniband Node. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_NODE_C #include #include void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num, IN const osm_madw_t * p_madw) { ib_net64_t port_guid; ib_smp_t *p_smp; ib_node_info_t *p_ni; p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); port_guid = p_ni->port_guid; CL_ASSERT(port_num < p_node->physp_tbl_size); osm_physp_init(&p_node->physp_table[port_num], port_guid, port_num, p_node, osm_madw_get_bind_handle(p_madw), p_smp->hop_count, p_smp->initial_path); } osm_node_t *osm_node_new(IN const osm_madw_t * p_madw) { osm_node_t *p_node; ib_smp_t *p_smp; ib_node_info_t *p_ni; uint8_t i; uint32_t size; p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); /* The node object already contains one physical port object. Therefore, subtract 1 from the number of physical ports used by the switch. This is not done for CA's since they need to occupy 1 more physp than they physically have since we still reserve room for a "port 0". */ size = p_ni->num_ports; p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size); if (!p_node) return NULL; memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size); p_node->node_info = *p_ni; p_node->physp_tbl_size = size + 1; p_node->physp_discovered = malloc(sizeof(uint8_t) * p_node->physp_tbl_size); if (!p_node->physp_discovered) { free(p_node); return NULL; } memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size); /* Construct Physical Port objects owned by this Node. Then, initialize the Physical Port through with we discovered this port. For switches, all ports have the same GUID. For CAs and routers, each port has a different GUID, so we only know the GUID for the port that responded to our Get(NodeInfo). */ for (i = 0; i < p_node->physp_tbl_size; i++) osm_physp_construct(&p_node->physp_table[i]); if (p_ni->node_type == IB_NODE_TYPE_SWITCH) for (i = 0; i <= p_ni->num_ports; i++) osm_node_init_physp(p_node, i, p_madw); else osm_node_init_physp(p_node, ib_node_info_get_local_port_num(p_ni), p_madw); p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN); return p_node; } static void node_destroy(IN osm_node_t * p_node) { uint16_t i; /* Cleanup all physports */ for (i = 0; i < p_node->physp_tbl_size; i++) osm_physp_destroy(&p_node->physp_table[i]); /* cleanup printable node_desc field */ if (p_node->print_desc) free(p_node->print_desc); /* cleanup physp_discovered array */ free(p_node->physp_discovered); } void osm_node_delete(IN OUT osm_node_t ** p_node) { CL_ASSERT(p_node && *p_node); node_destroy(*p_node); free(*p_node); *p_node = NULL; } void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; p_physp = osm_node_get_physp_ptr(p_node, port_num); p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); if (p_physp->p_remote_physp) p_physp->p_remote_physp->p_remote_physp = NULL; if (p_remote_physp->p_remote_physp) p_remote_physp->p_remote_physp->p_remote_physp = NULL; osm_physp_link(p_physp, p_remote_physp); } void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); if (osm_node_link_exists(p_node, port_num, p_remote_node, remote_port_num)) { p_physp = osm_node_get_physp_ptr(p_node, port_num); p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); osm_physp_unlink(p_physp, p_remote_physp); } } boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); p_physp = osm_node_get_physp_ptr(p_node, port_num); p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); return osm_physp_link_exists(p_physp, p_remote_physp); } boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node, IN uint8_t port_num, IN osm_node_t * p_remote_node, IN uint8_t remote_port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); p_physp = osm_node_get_physp_ptr(p_node, port_num); p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); return (p_physp && p_remote_physp); } boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num) { osm_physp_t *p_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); p_physp = osm_node_get_physp_ptr(p_node, port_num); return osm_physp_has_any_link(p_physp); } osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node, IN uint8_t port_num, OUT uint8_t * p_remote_port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !osm_physp_has_any_link(p_physp)) return NULL; p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_port_num) *p_remote_port_num = osm_physp_get_port_num(p_remote_physp); return osm_physp_get_node_ptr(p_remote_physp); } /********************************************************************** The lock must be held before calling this function. **********************************************************************/ ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node, IN uint32_t port_num) { osm_physp_t *p_physp; osm_physp_t *p_remote_physp; CL_ASSERT(port_num < p_node->physp_tbl_size); p_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_physp) { p_remote_physp = osm_physp_get_remote(p_physp); return osm_physp_get_base_lid(p_remote_physp); } return 0; } opensm-3.3.20/opensm/osm_node_desc_rcv.c0000644000205000001450000001034512273221507015134 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_nd_rcv_t. * This object represents the NodeDescription Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_NODE_DESC_RCV_C #include #include #include #include #include static void nd_rcv_process_nd(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const ib_node_desc_t * p_nd) { char *tmp_desc; char print_desc[IB_NODE_DESCRIPTION_SIZE + 1]; OSM_LOG_ENTER(sm->p_log); memcpy(&p_node->node_desc.description, p_nd, sizeof(*p_nd)); /* also set up a printable version */ memcpy(print_desc, p_nd, sizeof(*p_nd)); print_desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; tmp_desc = remap_node_name(sm->p_subn->p_osm->node_name_map, cl_ntoh64(osm_node_get_node_guid(p_node)), print_desc); /* make a copy for this node to "own" */ if (p_node->print_desc) free(p_node->print_desc); p_node->print_desc = tmp_desc; #ifdef ENABLE_OSM_PERF_MGR /* update the perfmgr entry if available */ osm_perfmgr_update_nodename(&sm->p_subn->p_osm->perfmgr, cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc); #endif /* ENABLE_OSM_PERF_MGR */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Node 0x%" PRIx64 ", Description = %s\n", cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc); OSM_LOG_EXIT(sm->p_log); } void osm_nd_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_node_desc_t *p_nd; ib_smp_t *p_smp; osm_node_t *p_node; ib_net64_t node_guid; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } p_nd = ib_smp_get_payload_ptr(p_smp); /* Acquire the node object and add the node description. */ node_guid = osm_madw_get_nd_context_ptr(p_madw)->node_guid; CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_node = osm_get_node_by_guid(sm->p_subn, node_guid); if (!p_node) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0B01: " "NodeDescription received for nonexistent node " "0x%" PRIx64 "\n", cl_ntoh64(node_guid)); else nd_rcv_process_nd(sm, p_node, p_nd); CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_node_info_rcv.c0000644000205000001450000007443512600531654015164 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_ni_rcv_t. * This object represents the NodeInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_NODE_INFO_RCV_C #include #include #include #include #include #include #include #include #include #include #include static void report_duplicated_guid(IN osm_sm_t * sm, osm_physp_t * p_physp, osm_node_t * p_neighbor_node, const uint8_t port_num) { osm_physp_t *p_old, *p_new; osm_dr_path_t path; p_old = p_physp->p_remote_physp; p_new = osm_node_get_physp_ptr(p_neighbor_node, port_num); OSM_LOG(sm->p_log, OSM_LOG_SYS | OSM_LOG_ERROR, "ERR 0D01: " "Found duplicated node GUID.\n" "Node 0x%" PRIx64 " port %u is reachable from remote node " "0x%" PRIx64 " port %u and remote node 0x%" PRIx64 " port %u.\n" "Paths are:\n", cl_ntoh64(p_physp->p_node->node_info.node_guid), p_physp->port_num, p_old ? cl_ntoh64(p_old->p_node->node_info.node_guid) : 0, p_old ? p_old->port_num : 0, p_new ? cl_ntoh64(p_new->p_node->node_info.node_guid) : 0, p_new ? p_new->port_num : 0); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_physp), FILE_ID, OSM_LOG_ERROR); path = *osm_physp_get_dr_path_ptr(p_new); if (osm_dr_path_extend(&path, port_num)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D05: " "DR path with hop count %d couldn't be extended\n", path.hop_count); osm_dump_dr_path_v2(sm->p_log, &path, FILE_ID, OSM_LOG_ERROR); } static void requery_dup_node_info(IN osm_sm_t * sm, osm_physp_t * p_physp, unsigned count) { osm_madw_context_t context; osm_dr_path_t path; cl_status_t status; if (!p_physp->p_remote_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0D: " "DR path couldn't be extended due to NULL remote physp\n"); return; } path = *osm_physp_get_dr_path_ptr(p_physp->p_remote_physp); if (osm_dr_path_extend(&path, p_physp->p_remote_physp->port_num)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D08: " "DR path with hop count %d couldn't be extended\n", path.hop_count); return; } context.ni_context.node_guid = p_physp->p_remote_physp->p_node->node_info.port_guid; context.ni_context.port_num = p_physp->p_remote_physp->port_num; context.ni_context.dup_node_guid = p_physp->p_node->node_info.node_guid; context.ni_context.dup_port_num = p_physp->port_num; context.ni_context.dup_count = count; status = osm_req_get(sm, &path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D02: " "Failure initiating NodeInfo request (%s)\n", ib_get_err_str(status)); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_set_links(IN osm_sm_t * sm, osm_node_t * p_node, const uint8_t port_num, const osm_ni_context_t * p_ni_context) { osm_node_t *p_neighbor_node; osm_physp_t *p_physp, *p_remote_physp; OSM_LOG_ENTER(sm->p_log); /* A special case exists in which the node we're trying to link is our own node. In this case, the guid value in the ni_context will be zero. */ if (p_ni_context->node_guid == 0) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Nothing to link for our own node 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); goto _exit; } p_neighbor_node = osm_get_node_by_guid(sm->p_subn, p_ni_context->node_guid); if (PF(!p_neighbor_node)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D10: " "Unexpected removal of neighbor node 0x%" PRIx64 "\n", cl_ntoh64(p_ni_context->node_guid)); goto _exit; } /* When setting the link, ports on both sides of the link should be initialized */ CL_ASSERT(osm_node_link_has_valid_ports(p_node, port_num, p_neighbor_node, p_ni_context->port_num)); if (osm_node_link_exists(p_node, port_num, p_neighbor_node, p_ni_context->port_num)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Link already exists\n"); goto _exit; } p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD0E: " "Failed to find physp for port %d of Node GUID 0x%" PRIx64 "\n", port_num, cl_ntoh64(osm_node_get_node_guid(p_node))); goto _exit; } /* * If the link went UP, after we already discovered it, we shouldn't * set the link between the ports and resweep. */ if (osm_physp_get_port_state(p_physp) == IB_LINK_DOWN && p_node->physp_discovered[port_num]) { /* Link down on another side. Don't create a link*/ p_node->physp_discovered[port_num] = 0; sm->p_subn->force_heavy_sweep = TRUE; goto _exit; } if (osm_node_has_any_link(p_node, port_num) && sm->p_subn->force_heavy_sweep == FALSE && (!p_ni_context->dup_count || (p_ni_context->dup_node_guid == osm_node_get_node_guid(p_node) && p_ni_context->dup_port_num == port_num))) { /* Uh oh... This could be reconnected ports, but also duplicated GUID (2 nodes have the same guid) or a 12x link with lane reversal that is not configured correctly. We will try to recover by querying NodeInfo again. In order to catch even fast port moving to new location(s) and back we will count up to 5. Some crazy reconnections (newly created switch loop right before targeted CA) will not be catched this way. So in worst case - report GUID duplication and request new discovery. When switch node is targeted NodeInfo querying will be done in opposite order, this is much stronger check, unfortunately it is impossible with CAs. */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD0F: " "Failed to find physp for port %d of Node GUID 0x%" PRIx64 "\n", port_num, cl_ntoh64(osm_node_get_node_guid(p_node))); goto _exit; } if (p_ni_context->dup_count > 5) { report_duplicated_guid(sm, p_physp, p_neighbor_node, p_ni_context->port_num); sm->p_subn->force_heavy_sweep = TRUE; } else if (p_node->sw) requery_dup_node_info(sm, p_physp->p_remote_physp, p_ni_context->dup_count + 1); else requery_dup_node_info(sm, p_physp, p_ni_context->dup_count + 1); } /* When there are only two nodes with exact same guids (connected back to back) - the previous check for duplicated guid will not catch them. But the link will be from the port to itself... Enhanced Port 0 is an exception to this */ if (osm_node_get_node_guid(p_node) == p_ni_context->node_guid && port_num == p_ni_context->port_num && port_num != 0 && cl_qmap_count(&sm->p_subn->sw_guid_tbl) == 0) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Duplicate GUID found by link from a port to itself:" "node 0x%" PRIx64 ", port number %u\n", cl_ntoh64(osm_node_get_node_guid(p_node)), port_num); p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1D: " "Failed to find physp for port %d of Node GUID 0x%" PRIx64 "\n", port_num, cl_ntoh64(osm_node_get_node_guid(p_node))); goto _exit; } osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_physp), FILE_ID, OSM_LOG_VERBOSE); if (sm->p_subn->opt.exit_on_fatal == TRUE) { osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "Errors on subnet. Duplicate GUID found " "by link from a port to itself. " "See verbose opensm.log for more details\n"); exit(1); } } OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Creating new link between:\n\t\t\t\tnode 0x%" PRIx64 ", port number %u and\n\t\t\t\tnode 0x%" PRIx64 ", port number %u\n", cl_ntoh64(osm_node_get_node_guid(p_node)), port_num, cl_ntoh64(p_ni_context->node_guid), p_ni_context->port_num); if (sm->ucast_mgr.cache_valid) osm_ucast_cache_check_new_link(&sm->ucast_mgr, p_node, port_num, p_neighbor_node, p_ni_context->port_num); p_physp = osm_node_get_physp_ptr(p_node, port_num); p_remote_physp = osm_node_get_physp_ptr(p_neighbor_node, p_ni_context->port_num); if (!p_physp || !p_remote_physp) goto _exit; osm_node_link(p_node, port_num, p_neighbor_node, p_ni_context->port_num); osm_db_neighbor_set(sm->p_subn->p_neighbor, cl_ntoh64(osm_physp_get_port_guid(p_physp)), port_num, cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), p_ni_context->port_num); osm_db_neighbor_set(sm->p_subn->p_neighbor, cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), p_ni_context->port_num, cl_ntoh64(osm_physp_get_port_guid(p_physp)), port_num); _exit: OSM_LOG_EXIT(sm->p_log); } static void ni_rcv_get_port_info(IN osm_sm_t * sm, IN osm_node_t * node, IN const osm_madw_t * madw) { osm_madw_context_t context; osm_physp_t *physp; ib_node_info_t *ni; unsigned port; ib_api_status_t status; int mlnx_epi_supported = 0; ni = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(madw)); port = ib_node_info_get_local_port_num(ni); if (sm->p_subn->opt.fdr10) mlnx_epi_supported = is_mlnx_ext_port_info_supported(ni->device_id); physp = osm_node_get_physp_ptr(node, port); if (!physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1E: " "Failed to find physp for port %d of Node GUID 0x%" PRIx64 "\n", port, cl_ntoh64(osm_node_get_node_guid(node))); return; } context.pi_context.node_guid = osm_node_get_node_guid(node); context.pi_context.port_guid = osm_physp_get_port_guid(physp); context.pi_context.set_method = FALSE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp), IB_MAD_ATTR_PORT_INFO, cl_hton32(port), TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD02: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); if (mlnx_epi_supported) { status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp), IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO, cl_hton32(port), TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0B: " "Failure initiating MLNX ExtPortInfo request (%s)\n", ib_get_err_str(status)); } } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t * p_physp) { ib_api_status_t status = IB_SUCCESS; osm_madw_context_t context; OSM_LOG_ENTER(sm->p_log); context.nd_context.node_guid = osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp)); status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_NODE_DESC, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D03: " "Failure initiating NodeDescription request (%s)\n", ib_get_err_str(status)); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_get_node_desc(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { ib_node_info_t *p_ni; ib_smp_t *p_smp; uint8_t port_num; osm_physp_t *p_physp = NULL; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); port_num = ib_node_info_get_local_port_num(p_ni); /* Request PortInfo & NodeDescription attributes for the port that responded to the NodeInfo attribute. Because this is a channel adapter or router, we are not allowed to request PortInfo for the other ports. Set the context union properly, so the recipient knows which node & port are relevant. */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1F: " "Failed to find physp for port %d of Node GUID 0x%" PRIx64 "\n", port_num, cl_ntoh64(osm_node_get_node_guid(p_node))); return; } osm_req_get_node_desc(sm, p_physp); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_new_ca_or_router(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { OSM_LOG_ENTER(sm->p_log); ni_rcv_get_port_info(sm, p_node, p_madw); /* A node guid of 0 is the corner case that indicates we discovered our own node. Initialize the subnet object with the SM's own port guid. */ if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0) sm->p_subn->sm_port_guid = p_node->node_info.port_guid; OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_existing_ca_or_router(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_port_t *p_port; osm_port_t *p_port_check; uint8_t port_num; osm_dr_path_t *p_dr_path; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); port_num = ib_node_info_get_local_port_num(p_ni); /* Determine if we have encountered this node through a previously undiscovered port. If so, build the new port object. */ p_port = osm_get_port_by_guid(sm->p_subn, p_ni->port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Creating new port object with GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_node_init_physp(p_node, port_num, p_madw); p_port = osm_port_new(p_ni, p_node); if (PF(p_port == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D04: " "Unable to create new port object\n"); goto Exit; } /* Add the new port object to the database. */ p_port_check = (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl, p_ni->port_guid, &p_port->map_item); if (PF(p_port_check != p_port)) { /* We should never be here! Somehow, this port GUID already exists in the table. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D12: " "Port 0x%" PRIx64 " already in the database!\n", cl_ntoh64(p_ni->port_guid)); osm_port_delete(&p_port); goto Exit; } p_alias_guid = osm_alias_guid_new(p_ni->port_guid, p_port); if (PF(!p_alias_guid)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D11: " "alias guid memory allocation failed" " for port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); goto alias_done; } /* insert into alias guid table */ p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D13: " "Duplicate alias port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_alias_guid_delete(&p_alias_guid); osm_port_delete(&p_port); goto Exit; } alias_done: /* If we are a master, then this means the port is new on the subnet. Mark it as new - need to send trap 64 for these ports. The condition that we are master is true, since if we are in discovering state (meaning we woke up from standby or we are just initializing), then these ports may be new to us, but are not new on the subnet. If we are master, then the subnet as we know it is the updated one, and any new ports we encounter should cause trap 64. C14-72.1.1 */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) p_port->is_new = 1; } else { osm_physp_t *p_physp = osm_node_get_physp_ptr(p_node, port_num); if (PF(p_physp == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1C: " "No physical port found for node GUID 0x%" PRIx64 " port %u. Might be duplicate port GUID\n", cl_ntoh64(p_node->node_info.node_guid), port_num); goto Exit; } /* Update the DR Path to the port, in case the old one is no longer available. */ p_dr_path = osm_physp_get_dr_path_ptr(p_physp); osm_dr_path_init(p_dr_path, p_smp->hop_count, p_smp->initial_path); } ni_rcv_get_port_info(sm, p_node, p_madw); Exit: OSM_LOG_EXIT(sm->p_log); } static void ni_rcv_process_switch(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { ib_api_status_t status = IB_SUCCESS; osm_physp_t *p_physp; osm_madw_context_t context; osm_dr_path_t *path; ib_smp_t *p_smp; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_physp = osm_node_get_physp_ptr(p_node, 0); /* update DR path of already initialized switch port 0 */ path = osm_physp_get_dr_path_ptr(p_physp); osm_dr_path_init(path, p_smp->hop_count, p_smp->initial_path); context.si_context.node_guid = osm_node_get_node_guid(p_node); context.si_context.set_method = FALSE; context.si_context.light_sweep = FALSE; context.si_context.lft_top_change = FALSE; /* Request a SwitchInfo attribute */ status = osm_req_get(sm, path, IB_MAD_ATTR_SWITCH_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) /* continue despite error */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D06: " "Failure initiating SwitchInfo request (%s)\n", ib_get_err_str(status)); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_existing_switch(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { OSM_LOG_ENTER(sm->p_log); /* If this switch has already been probed during this sweep, then don't bother reprobing it. */ if (p_node->discovery_count == 1) ni_rcv_process_switch(sm, p_node, p_madw); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_new_switch(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { OSM_LOG_ENTER(sm->p_log); ni_rcv_process_switch(sm, p_node, p_madw); /* A node guid of 0 is the corner case that indicates we discovered our own node. Initialize the subnet object with the SM's own port guid. */ if (osm_madw_get_ni_context_ptr(p_madw)->node_guid == 0) sm->p_subn->sm_port_guid = p_node->node_info.port_guid; OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must NOT be held before calling this function. **********************************************************************/ static void ni_rcv_process_new(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { osm_node_t *p_node; osm_node_t *p_node_check; osm_port_t *p_port; osm_port_t *p_port_check; osm_router_t *p_rtr = NULL; osm_router_t *p_rtr_check; cl_qmap_t *p_rtr_guid_tbl; ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_ni_context_t *p_ni_context; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; uint8_t port_num; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); p_ni_context = osm_madw_get_ni_context_ptr(p_madw); port_num = ib_node_info_get_local_port_num(p_ni); osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Discovered new %s node," "\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id)); if (PF(port_num > p_ni->num_ports)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0A: " "New %s node GUID 0x%" PRIx64 "is non-compliant and " "is being ignored since the " "local port num %u > num ports %u\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), port_num, p_ni->num_ports); goto Exit; } p_node = osm_node_new(p_madw); if (PF(p_node == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D07: " "Unable to create new node object\n"); goto Exit; } /* Create a new port object to represent this node's physical ports in the port table. */ p_port = osm_port_new(p_ni, p_node); if (PF(p_port == NULL)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D14: " "Unable to create new port object\n"); osm_node_delete(&p_node); goto Exit; } /* Add the new port object to the database. */ p_port_check = (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl, p_ni->port_guid, &p_port->map_item); if (PF(p_port_check != p_port)) { /* We should never be here! Somehow, this port GUID already exists in the table. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D15: " "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n", cl_ntoh64(p_ni->port_guid)); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_port->p_physp), FILE_ID, OSM_LOG_ERROR); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr(p_port_check-> p_physp), FILE_ID, OSM_LOG_ERROR); osm_port_delete(&p_port); osm_node_delete(&p_node); goto Exit; } p_alias_guid = osm_alias_guid_new(p_ni->port_guid, p_port); if (PF(!p_alias_guid)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D18: " "alias guid memory allocation failed" " for port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); goto alias_done2; } /* insert into alias guid table */ p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D19: " "Duplicate alias port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_ni->port_guid)); osm_alias_guid_delete(&p_alias_guid); } alias_done2: /* If we are a master, then this means the port is new on the subnet. Mark it as new - need to send trap 64 on these ports. The condition that we are master is true, since if we are in discovering state (meaning we woke up from standby or we are just initializing), then these ports may be new to us, but are not new on the subnet. If we are master, then the subnet as we know it is the updated one, and any new ports we encounter should cause trap 64. C14-72.1.1 */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) p_port->is_new = 1; /* If there were RouterInfo or other router attribute, this would be elsewhere */ if (p_ni->node_type == IB_NODE_TYPE_ROUTER) { if (PF((p_rtr = osm_router_new(p_port)) == NULL)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1A: " "Unable to create new router object\n"); else { p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl; p_rtr_check = (osm_router_t *) cl_qmap_insert(p_rtr_guid_tbl, p_ni->port_guid, &p_rtr->map_item); if (PF(p_rtr_check != p_rtr)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1B: " "Unable to add port GUID:0x%016" PRIx64 " to router table\n", cl_ntoh64(p_ni->port_guid)); } } p_node_check = (osm_node_t *) cl_qmap_insert(&sm->p_subn->node_guid_tbl, p_ni->node_guid, &p_node->map_item); if (PF(p_node_check != p_node)) { /* This node must have been inserted by another thread. This is unexpected, but is not an error. We can simply clean-up, since the other thread will see this processing through to completion. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Discovery race detected at node 0x%" PRIx64 "\n", cl_ntoh64(p_ni->node_guid)); osm_node_delete(&p_node); p_node = p_node_check; ni_rcv_set_links(sm, p_node, port_num, p_ni_context); goto Exit; } else ni_rcv_set_links(sm, p_node, port_num, p_ni_context); p_node->discovery_count++; ni_rcv_get_node_desc(sm, p_node, p_madw); switch (p_ni->node_type) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: ni_rcv_process_new_ca_or_router(sm, p_node, p_madw); break; case IB_NODE_TYPE_SWITCH: ni_rcv_process_new_switch(sm, p_node, p_madw); break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: " "Unknown node type %u with GUID 0x%" PRIx64 "\n", p_ni->node_type, cl_ntoh64(p_ni->node_guid)); break; } Exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void ni_rcv_process_existing(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_ni_context_t *p_ni_context; uint8_t port_num; OSM_LOG_ENTER(sm->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); p_ni_context = osm_madw_get_ni_context_ptr(p_madw); port_num = ib_node_info_get_local_port_num(p_ni); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Rediscovered %s node 0x%" PRIx64 " TID 0x%" PRIx64 ", discovered %u times already\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id), p_node->discovery_count); if (PF(port_num > p_ni->num_ports)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0C: " "Existing %s node GUID 0x%" PRIx64 "is non-compliant " "and is being ignored since the " "local port num %u > num ports %u\n", ib_get_node_type_str(p_ni->node_type), cl_ntoh64(p_ni->node_guid), port_num, p_ni->num_ports); goto Exit; } /* If we haven't already encountered this existing node on this particular sweep, then process further. */ p_node->discovery_count++; switch (p_ni->node_type) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: ni_rcv_process_existing_ca_or_router(sm, p_node, p_madw); break; case IB_NODE_TYPE_SWITCH: ni_rcv_process_existing_switch(sm, p_node, p_madw); break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D09: " "Unknown node type %u with GUID 0x%" PRIx64 "\n", p_ni->node_type, cl_ntoh64(p_ni->node_guid)); break; } if ( p_ni->sys_guid != p_node->node_info.sys_guid) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Updated SysImageGUID: 0x%" PRIx64 " for node 0x%" PRIx64 "\n", cl_ntoh64(p_ni->sys_guid), cl_ntoh64(p_ni->node_guid)); } ni_rcv_set_links(sm, p_node, port_num, p_ni_context); p_node->node_info = *p_ni; Exit: OSM_LOG_EXIT(sm->p_log); } void osm_ni_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_node_info_t *p_ni; ib_smp_t *p_smp; osm_node_t *p_node; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_ni = ib_smp_get_payload_ptr(p_smp); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_NODE_INFO); if (PF(p_ni->node_guid == 0)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: " "Got Zero Node GUID! Found on the directed route:\n"); osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); goto Exit; } if (PF(p_ni->port_guid == 0)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D17: " "Got Zero Port GUID! Found on the directed route:\n"); osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); goto Exit; } if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } /* Determine if this node has already been discovered, and process accordingly. During processing of this node, hold the shared lock. */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_node = osm_get_node_by_guid(sm->p_subn, p_ni->node_guid); osm_dump_node_info_v2(sm->p_log, p_ni, FILE_ID, OSM_LOG_DEBUG); if (!p_node) ni_rcv_process_new(sm, p_madw); else ni_rcv_process_existing(sm, p_node, p_madw); CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_opensm.c0000644000205000001450000004067712533620210013644 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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 osm_opensm_t. * This object represents the opensm super object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_OPENSM_C #include #include #include #include #include #include #include #include #include #include struct routing_engine_module { const char *name; int (*setup) (struct osm_routing_engine *, osm_opensm_t *); }; extern int osm_ucast_minhop_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_updn_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dnup_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_file_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_ftree_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_lash_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dor_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_torus2QoS_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_sssp_setup(struct osm_routing_engine *, osm_opensm_t *); extern int osm_ucast_dfsssp_setup(struct osm_routing_engine *, osm_opensm_t *); const static struct routing_engine_module routing_modules[] = { {"minhop", osm_ucast_minhop_setup}, {"updn", osm_ucast_updn_setup}, {"dnup", osm_ucast_dnup_setup}, {"file", osm_ucast_file_setup}, {"ftree", osm_ucast_ftree_setup}, {"lash", osm_ucast_lash_setup}, {"dor", osm_ucast_dor_setup}, {"torus-2QoS", osm_ucast_torus2QoS_setup}, {"dfsssp", osm_ucast_dfsssp_setup}, {"sssp", osm_ucast_sssp_setup}, {NULL, NULL} }; const char *osm_routing_engine_type_str(IN osm_routing_engine_type_t type) { switch (type) { case OSM_ROUTING_ENGINE_TYPE_NONE: return "none"; case OSM_ROUTING_ENGINE_TYPE_MINHOP: return "minhop"; case OSM_ROUTING_ENGINE_TYPE_UPDN: return "updn"; case OSM_ROUTING_ENGINE_TYPE_DNUP: return "dnup"; case OSM_ROUTING_ENGINE_TYPE_FILE: return "file"; case OSM_ROUTING_ENGINE_TYPE_FTREE: return "ftree"; case OSM_ROUTING_ENGINE_TYPE_LASH: return "lash"; case OSM_ROUTING_ENGINE_TYPE_DOR: return "dor"; case OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS: return "torus-2QoS"; case OSM_ROUTING_ENGINE_TYPE_DFSSSP: return "dfsssp"; case OSM_ROUTING_ENGINE_TYPE_SSSP: return "sssp"; default: break; } return "unknown"; } osm_routing_engine_type_t osm_routing_engine_type(IN const char *str) { /* For legacy reasons, consider a NULL pointer and the string * "null" as the minhop routing engine. */ if (!str || !strcasecmp(str, "null") || !strcasecmp(str, "minhop")) return OSM_ROUTING_ENGINE_TYPE_MINHOP; else if (!strcasecmp(str, "none")) return OSM_ROUTING_ENGINE_TYPE_NONE; else if (!strcasecmp(str, "updn")) return OSM_ROUTING_ENGINE_TYPE_UPDN; else if (!strcasecmp(str, "dnup")) return OSM_ROUTING_ENGINE_TYPE_DNUP; else if (!strcasecmp(str, "file")) return OSM_ROUTING_ENGINE_TYPE_FILE; else if (!strcasecmp(str, "ftree")) return OSM_ROUTING_ENGINE_TYPE_FTREE; else if (!strcasecmp(str, "lash")) return OSM_ROUTING_ENGINE_TYPE_LASH; else if (!strcasecmp(str, "dor")) return OSM_ROUTING_ENGINE_TYPE_DOR; else if (!strcasecmp(str, "torus-2QoS")) return OSM_ROUTING_ENGINE_TYPE_TORUS_2QOS; else if (!strcasecmp(str, "sssp")) return OSM_ROUTING_ENGINE_TYPE_SSSP; else if (!strcasecmp(str, "dfsssp")) return OSM_ROUTING_ENGINE_TYPE_DFSSSP; else return OSM_ROUTING_ENGINE_TYPE_UNKNOWN; } static void append_routing_engine(osm_opensm_t *osm, struct osm_routing_engine *routing_engine) { struct osm_routing_engine *r; routing_engine->next = NULL; if (!osm->routing_engine_list) { osm->routing_engine_list = routing_engine; return; } r = osm->routing_engine_list; while (r->next) r = r->next; r->next = routing_engine; } static struct osm_routing_engine *setup_routing_engine(osm_opensm_t *osm, const char *name) { struct osm_routing_engine *re; const struct routing_engine_module *m; if (!strcmp(name, "no_fallback")) { osm->no_fallback_routing_engine = TRUE; return NULL; } for (m = routing_modules; m->name && *m->name; m++) { if (!strcmp(m->name, name)) { re = malloc(sizeof(struct osm_routing_engine)); if (!re) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "memory allocation failed\n"); return NULL; } memset(re, 0, sizeof(struct osm_routing_engine)); re->name = m->name; re->type = osm_routing_engine_type(m->name); if (m->setup(re, osm)) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "setup of routing" " engine \'%s\' failed\n", name); free(re); return NULL; } OSM_LOG(&osm->log, OSM_LOG_DEBUG, "\'%s\' routing engine set up\n", re->name); if (re->type == OSM_ROUTING_ENGINE_TYPE_MINHOP) osm->default_routing_engine = re; return re; } } OSM_LOG(&osm->log, OSM_LOG_ERROR, "cannot find or setup routing engine \'%s\'\n", name); return NULL; } static void setup_routing_engines(osm_opensm_t *osm, const char *engine_names) { char *name, *str, *p; struct osm_routing_engine *re; if (engine_names && *engine_names) { str = strdup(engine_names); name = strtok_r(str, ", \t\n", &p); while (name && *name) { re = setup_routing_engine(osm, name); if (re) append_routing_engine(osm, re); name = strtok_r(NULL, ", \t\n", &p); } free(str); } if (!osm->default_routing_engine) setup_routing_engine(osm, "minhop"); } void osm_opensm_construct(IN osm_opensm_t * p_osm) { memset(p_osm, 0, sizeof(*p_osm)); p_osm->osm_version = OSM_VERSION; osm_subn_construct(&p_osm->subn); osm_db_construct(&p_osm->db); osm_log_construct(&p_osm->log); } void osm_opensm_construct_finish(IN osm_opensm_t * p_osm) { osm_sm_construct(&p_osm->sm); osm_sa_construct(&p_osm->sa); osm_mad_pool_construct(&p_osm->mad_pool); p_osm->mad_pool_constructed = TRUE; osm_vl15_construct(&p_osm->vl15); p_osm->vl15_constructed = TRUE; } static void destroy_routing_engines(osm_opensm_t *osm) { struct osm_routing_engine *r, *next; next = osm->routing_engine_list; while (next) { r = next; next = r->next; if (r->destroy) r->destroy(r->context); free(r); } } static void destroy_plugins(osm_opensm_t *osm) { osm_epi_plugin_t *p; /* remove from the list, and destroy it */ while (!cl_is_qlist_empty(&osm->plugin_list)){ p = (osm_epi_plugin_t *)cl_qlist_remove_head(&osm->plugin_list); /* plugin is responsible for freeing its own resources */ osm_epi_destroy(p); } } void osm_opensm_destroy(IN osm_opensm_t * p_osm) { /* in case of shutdown through exit proc - no ^C */ osm_exit_flag = TRUE; /* * First of all, clear the is_sm bit. */ if (p_osm->sm.mad_ctrl.h_bind) osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, FALSE); #ifdef ENABLE_OSM_PERF_MGR /* Shutdown the PerfMgr */ osm_perfmgr_shutdown(&p_osm->perfmgr); #endif /* ENABLE_OSM_PERF_MGR */ osm_congestion_control_shutdown(&p_osm->cc); /* shut down the SM * - make sure the SM sweeper thread exited * - unbind from QP0 messages */ osm_sm_shutdown(&p_osm->sm); /* shut down the SA * - unbind from QP1 messages */ osm_sa_shutdown(&p_osm->sa); /* cleanup all messages on VL15 fifo that were not sent yet */ osm_vl15_shutdown(&p_osm->vl15, &p_osm->mad_pool); /* shut down the dispatcher - so no new messages cross */ cl_disp_shutdown(&p_osm->disp); if (p_osm->sa_set_disp_initialized) cl_disp_shutdown(&p_osm->sa_set_disp); /* dump SA DB */ if ((p_osm->sm.p_subn->sm_state == IB_SMINFO_STATE_MASTER) && p_osm->subn.opt.sa_db_dump) osm_sa_db_file_dump(p_osm); /* do the destruction in reverse order as init */ destroy_plugins(p_osm); destroy_routing_engines(p_osm); osm_sa_destroy(&p_osm->sa); osm_sm_destroy(&p_osm->sm); #ifdef ENABLE_OSM_PERF_MGR osm_perfmgr_destroy(&p_osm->perfmgr); #endif /* ENABLE_OSM_PERF_MGR */ osm_congestion_control_destroy(&p_osm->cc); } void osm_opensm_destroy_finish(IN osm_opensm_t * p_osm) { osm_db_destroy(&p_osm->db); if (p_osm->vl15_constructed && p_osm->mad_pool_constructed) osm_vl15_destroy(&p_osm->vl15, &p_osm->mad_pool); if (p_osm->mad_pool_constructed) osm_mad_pool_destroy(&p_osm->mad_pool); p_osm->vl15_constructed = FALSE; p_osm->mad_pool_constructed = FALSE; osm_vendor_delete(&p_osm->p_vendor); osm_subn_destroy(&p_osm->subn); cl_disp_destroy(&p_osm->disp); if (p_osm->sa_set_disp_initialized) cl_disp_destroy(&p_osm->sa_set_disp); #ifdef HAVE_LIBPTHREAD pthread_cond_destroy(&p_osm->stats.cond); pthread_mutex_destroy(&p_osm->stats.mutex); #else cl_event_destroy(&p_osm->stats.event); #endif if (p_osm->node_name_map) close_node_name_map(p_osm->node_name_map); cl_plock_destroy(&p_osm->lock); osm_log_destroy(&p_osm->log); } static void load_plugins(osm_opensm_t *osm, const char *plugin_names) { osm_epi_plugin_t *epi; char *p_names, *name, *p; p_names = strdup(plugin_names); name = strtok_r(p_names, ", \t\n", &p); while (name && *name) { epi = osm_epi_construct(osm, name); if (!epi) osm_log_v2(&osm->log, OSM_LOG_ERROR, FILE_ID, "ERR 1000: cannot load plugin \'%s\'\n", name); else cl_qlist_insert_tail(&osm->plugin_list, &epi->list); name = strtok_r(NULL, " \t\n", &p); } free(p_names); } ib_api_status_t osm_opensm_init(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt) { ib_api_status_t status; /* Can't use log macros here, since we're initializing the log */ osm_opensm_construct(p_osm); if (p_opt->daemon) p_osm->log.daemon = 1; status = osm_log_init_v2(&p_osm->log, p_opt->force_log_flush, p_opt->log_flags, p_opt->log_file, p_opt->log_max_size, p_opt->accum_log_file); if (status != IB_SUCCESS) return status; p_osm->log.log_prefix = p_opt->log_prefix; /* If there is a log level defined - add the OSM_VERSION to it */ osm_log_v2(&p_osm->log, osm_log_get_level(&p_osm->log) & (OSM_LOG_SYS ^ 0xFF), FILE_ID, "%s\n", p_osm->osm_version); /* Write the OSM_VERSION to the SYS_LOG */ osm_log_v2(&p_osm->log, OSM_LOG_SYS, FILE_ID, "%s\n", p_osm->osm_version); /* Format Waived */ OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "[\n"); /* Format Waived */ status = cl_plock_init(&p_osm->lock); if (status != IB_SUCCESS) goto Exit; #ifdef HAVE_LIBPTHREAD pthread_mutex_init(&p_osm->stats.mutex, NULL); pthread_cond_init(&p_osm->stats.cond, NULL); #else status = cl_event_init(&p_osm->stats.event, FALSE); if (status != IB_SUCCESS) goto Exit; #endif if (p_opt->single_thread) { OSM_LOG(&p_osm->log, OSM_LOG_INFO, "Forcing single threaded dispatcher\n"); status = cl_disp_init(&p_osm->disp, 1, "opensm"); } else { /* * Normal behavior is to initialize the dispatcher with * one thread per CPU, as specified by a thread count of '0'. */ status = cl_disp_init(&p_osm->disp, 0, "opensm"); } if (status != IB_SUCCESS) goto Exit; /* Unless OpenSM runs in single threaded mode, we create new single * threaded dispatcher for SA Set and Delete requets. */ p_osm->sa_set_disp_initialized = FALSE; if (!p_opt->single_thread) { status = cl_disp_init(&p_osm->sa_set_disp, 1, "subnadmin_set"); if (status != IB_SUCCESS) goto Exit; p_osm->sa_set_disp_initialized = TRUE; } /* the DB is in use by subn so init before */ status = osm_db_init(&p_osm->db, &p_osm->log); if (status != IB_SUCCESS) goto Exit; status = osm_subn_init(&p_osm->subn, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; p_osm->p_vendor = osm_vendor_new(&p_osm->log, p_opt->transaction_timeout); if (p_osm->p_vendor == NULL) status = IB_INSUFFICIENT_RESOURCES; Exit: OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n"); /* Format Waived */ return status; } ib_api_status_t osm_opensm_init_finish(IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt) { ib_api_status_t status; osm_opensm_construct_finish(p_osm); p_osm->subn.sm_port_guid = p_opt->guid; status = osm_mad_pool_init(&p_osm->mad_pool); if (status != IB_SUCCESS) goto Exit; status = osm_vl15_init(&p_osm->vl15, p_osm->p_vendor, &p_osm->log, &p_osm->stats, &p_osm->subn, p_opt->max_wire_smps, p_opt->max_wire_smps2, p_opt->max_smps_timeout); if (status != IB_SUCCESS) goto Exit; status = osm_sm_init(&p_osm->sm, &p_osm->subn, &p_osm->db, p_osm->p_vendor, &p_osm->mad_pool, &p_osm->vl15, &p_osm->log, &p_osm->stats, &p_osm->disp, &p_osm->lock); if (status != IB_SUCCESS) goto Exit; status = osm_sa_init(&p_osm->sm, &p_osm->sa, &p_osm->subn, p_osm->p_vendor, &p_osm->mad_pool, &p_osm->log, &p_osm->stats, &p_osm->disp, p_opt->single_thread ? NULL : &p_osm->sa_set_disp, &p_osm->lock); if (status != IB_SUCCESS) goto Exit; cl_qlist_init(&p_osm->plugin_list); if (p_opt->event_plugin_name) load_plugins(p_osm, p_opt->event_plugin_name); #ifdef ENABLE_OSM_PERF_MGR status = osm_perfmgr_init(&p_osm->perfmgr, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; #endif /* ENABLE_OSM_PERF_MGR */ status = osm_congestion_control_init(&p_osm->cc, p_osm, p_opt); if (status != IB_SUCCESS) goto Exit; p_osm->no_fallback_routing_engine = FALSE; setup_routing_engines(p_osm, p_opt->routing_engine_names); p_osm->routing_engine_used = OSM_ROUTING_ENGINE_TYPE_NONE; p_osm->node_name_map = open_node_name_map(p_opt->node_name_map_name); Exit: OSM_LOG(&p_osm->log, OSM_LOG_FUNCS, "]\n"); /* Format Waived */ return status; } ib_api_status_t osm_opensm_bind(IN osm_opensm_t * p_osm, IN ib_net64_t guid) { ib_api_status_t status; OSM_LOG_ENTER(&p_osm->log); status = osm_sm_bind(&p_osm->sm, guid); if (status != IB_SUCCESS) goto Exit; status = osm_sa_bind(&p_osm->sa, guid); if (status != IB_SUCCESS) goto Exit; #ifdef ENABLE_OSM_PERF_MGR status = osm_perfmgr_bind(&p_osm->perfmgr, guid); if (status != IB_SUCCESS) goto Exit; #endif /* ENABLE_OSM_PERF_MGR */ status = osm_congestion_control_bind(&p_osm->cc, guid); if (status != IB_SUCCESS) goto Exit; /* setting IS_SM in capability mask */ OSM_LOG(&p_osm->log, OSM_LOG_INFO, "Setting IS_SM on port 0x%016" PRIx64 "\n", cl_ntoh64(guid)); osm_vendor_set_sm(p_osm->sm.mad_ctrl.h_bind, TRUE); Exit: OSM_LOG_EXIT(&p_osm->log); return status; } void osm_opensm_report_event(osm_opensm_t *osm, osm_epi_event_id_t event_id, void *event_data) { cl_list_item_t *item; for (item = cl_qlist_head(&osm->plugin_list); !osm_exit_flag && item != cl_qlist_end(&osm->plugin_list); item = cl_qlist_next(item)) { osm_epi_plugin_t *p = (osm_epi_plugin_t *)item; if (p->impl->report) p->impl->report(p->plugin_data, event_id, event_data); } } opensm-3.3.20/opensm/osm_pkey.c0000644000205000001450000004111612654644603013320 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 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 opensm pkey manipulation functions. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_PKEY_C #include #include #include #include #include #include void osm_pkey_tbl_construct(IN osm_pkey_tbl_t * p_pkey_tbl) { cl_map_construct(&p_pkey_tbl->accum_pkeys); cl_ptr_vector_construct(&p_pkey_tbl->blocks); cl_ptr_vector_construct(&p_pkey_tbl->new_blocks); cl_map_construct(&p_pkey_tbl->keys); } void osm_pkey_tbl_destroy(IN osm_pkey_tbl_t * p_pkey_tbl) { ib_pkey_table_t *p_block; uint16_t num_blocks, i; num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->blocks)); for (i = 0; i < num_blocks; i++) if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, i))) free(p_block); cl_ptr_vector_destroy(&p_pkey_tbl->blocks); num_blocks = (uint16_t) (cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks)); for (i = 0; i < num_blocks; i++) if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, i))) free(p_block); cl_ptr_vector_destroy(&p_pkey_tbl->new_blocks); cl_map_remove_all(&p_pkey_tbl->accum_pkeys); cl_map_destroy(&p_pkey_tbl->accum_pkeys); cl_map_remove_all(&p_pkey_tbl->keys); cl_map_destroy(&p_pkey_tbl->keys); } ib_api_status_t osm_pkey_tbl_init(IN osm_pkey_tbl_t * p_pkey_tbl) { cl_map_init(&p_pkey_tbl->accum_pkeys, 1); cl_ptr_vector_init(&p_pkey_tbl->blocks, 0, 1); cl_ptr_vector_init(&p_pkey_tbl->new_blocks, 0, 1); cl_map_init(&p_pkey_tbl->keys, 1); cl_qlist_init(&p_pkey_tbl->pending); p_pkey_tbl->last_pkey_idx = 0; p_pkey_tbl->used_blocks = 0; p_pkey_tbl->max_blocks = 0; p_pkey_tbl->rcv_blocks_cnt = 0; p_pkey_tbl->indx0_pkey = 0; return IB_SUCCESS; } void osm_pkey_tbl_init_new_blocks(IN const osm_pkey_tbl_t * p_pkey_tbl) { ib_pkey_table_t *p_block; size_t b, num_blocks = cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks); for (b = 0; b < num_blocks; b++) if ((p_block = cl_ptr_vector_get(&p_pkey_tbl->new_blocks, b))) memset(p_block, 0, sizeof(*p_block)); } ib_api_status_t osm_pkey_tbl_set(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t block, IN ib_pkey_table_t * p_tbl, IN boolean_t allow_both_pkeys) { uint16_t b, i; ib_pkey_table_t *p_pkey_block; uint16_t *p_prev_pkey; ib_net16_t pkey, pkey_base; /* make sure the block is allocated */ if (cl_ptr_vector_get_size(&p_pkey_tbl->blocks) > block) p_pkey_block = (ib_pkey_table_t *) cl_ptr_vector_get(&p_pkey_tbl->blocks, block); else p_pkey_block = NULL; if (!p_pkey_block) { p_pkey_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t)); if (!p_pkey_block) return IB_ERROR; memset(p_pkey_block, 0, sizeof(ib_pkey_table_t)); cl_ptr_vector_set(&p_pkey_tbl->blocks, block, p_pkey_block); } /* sets the block values */ memcpy(p_pkey_block, p_tbl, sizeof(ib_pkey_table_t)); /* NOTE: as the spec does not require uniqueness of PKeys in tables there is no other way but to refresh the entire keys map. Moreover, if the same key exists but with full membership it should have precedence over the key with limited membership ! */ cl_map_remove_all(&p_pkey_tbl->keys); for (b = 0; b < cl_ptr_vector_get_size(&p_pkey_tbl->blocks); b++) { p_pkey_block = cl_ptr_vector_get(&p_pkey_tbl->blocks, b); if (!p_pkey_block) continue; for (i = 0; i < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; i++) { pkey = p_pkey_block->pkey_entry[i]; if (ib_pkey_is_invalid(pkey)) continue; if (allow_both_pkeys) pkey_base = pkey; else pkey_base = ib_pkey_get_base(pkey); /* If allow_both_pkeys is FALSE, ignore the PKey Full Member bit in the key but store the pointer to the table element as the map value */ p_prev_pkey = cl_map_get(&p_pkey_tbl->keys, pkey_base); /* we only insert if no previous or it is not full member and allow_both_pkeys is FALSE */ if ((p_prev_pkey == NULL) || (allow_both_pkeys == FALSE && cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey))) cl_map_insert(&p_pkey_tbl->keys, pkey_base, &(p_pkey_block->pkey_entry[i]) ); } } return IB_SUCCESS; } /* Store the given pkey (along with it's overall index) in the accum_pkeys array. */ cl_status_t osm_pkey_tbl_set_accum_pkeys(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t pkey, IN uint16_t pkey_idx) { uintptr_t ptr = pkey_idx + 1; /* 0 means not found so bias by 1 */ uint16_t *p_prev_pkey_idx; cl_status_t status = CL_SUCCESS; if (pkey_idx >= p_pkey_tbl->last_pkey_idx) p_pkey_tbl->last_pkey_idx = pkey_idx + 1; p_prev_pkey_idx = (uint16_t *) cl_map_get(&p_pkey_tbl->accum_pkeys, pkey); if (p_prev_pkey_idx != NULL) cl_map_remove(&p_pkey_tbl->accum_pkeys, pkey); if (cl_map_insert(&p_pkey_tbl->accum_pkeys, pkey, (void *) ptr) == NULL) status = CL_INSUFFICIENT_MEMORY; return status; } /* + * Find the next last pkey index +*/ void osm_pkey_find_last_accum_pkey_index(IN osm_pkey_tbl_t * p_pkey_tbl) { void *ptr; uintptr_t pkey_idx_ptr; uint16_t pkey_idx, last_pkey_idx = 0; cl_map_iterator_t map_iter = cl_map_head(&p_pkey_tbl->accum_pkeys); while (map_iter != cl_map_end(&p_pkey_tbl->accum_pkeys)) { ptr = (uint16_t *) cl_map_obj(map_iter); CL_ASSERT(ptr); pkey_idx_ptr = (uintptr_t) ptr; pkey_idx = pkey_idx_ptr; if (pkey_idx > last_pkey_idx) last_pkey_idx = pkey_idx; map_iter = cl_map_next(map_iter); } p_pkey_tbl->last_pkey_idx = last_pkey_idx; } /* Store the given pkey in the "new" blocks array. Also, make sure the regular block exists. */ ib_api_status_t osm_pkey_tbl_set_new_entry(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t block_idx, IN uint8_t pkey_idx, IN uint16_t pkey) { ib_pkey_table_t *p_block; if (!(p_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_idx))) { p_block = (ib_pkey_table_t *) malloc(sizeof(ib_pkey_table_t)); if (!p_block) return IB_ERROR; memset(p_block, 0, sizeof(ib_pkey_table_t)); cl_ptr_vector_set(&p_pkey_tbl->new_blocks, block_idx, p_block); } p_block->pkey_entry[pkey_idx] = pkey; if (p_pkey_tbl->used_blocks <= block_idx) p_pkey_tbl->used_blocks = block_idx + 1; return IB_SUCCESS; } boolean_t osm_pkey_find_next_free_entry(IN osm_pkey_tbl_t * p_pkey_tbl, OUT uint16_t * p_block_idx, OUT uint8_t * p_pkey_idx) { ib_pkey_table_t *p_new_block; CL_ASSERT(p_block_idx); CL_ASSERT(p_pkey_idx); while (*p_block_idx < p_pkey_tbl->max_blocks) { if (*p_pkey_idx > IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) { *p_pkey_idx = 0; (*p_block_idx)++; if (*p_block_idx >= p_pkey_tbl->max_blocks) return FALSE; } p_new_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, *p_block_idx); if (!p_new_block || ib_pkey_is_invalid(p_new_block->pkey_entry[*p_pkey_idx])) return TRUE; else (*p_pkey_idx)++; } return FALSE; } ib_api_status_t osm_pkey_tbl_get_block_and_idx(IN osm_pkey_tbl_t * p_pkey_tbl, IN uint16_t * p_pkey, OUT uint16_t * p_block_idx, OUT uint8_t * p_pkey_idx) { uint16_t num_of_blocks; uint16_t block_index; ib_pkey_table_t *block; CL_ASSERT(p_block_idx != NULL); CL_ASSERT(p_pkey_idx != NULL); num_of_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->blocks); for (block_index = 0; block_index < num_of_blocks; block_index++) { block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); if ((block->pkey_entry <= p_pkey) && (p_pkey < block->pkey_entry + IB_NUM_PKEY_ELEMENTS_IN_BLOCK)) { *p_block_idx = block_index; *p_pkey_idx = (uint8_t) (p_pkey - block->pkey_entry); return IB_SUCCESS; } } return IB_NOT_FOUND; } static boolean_t match_pkey(IN const ib_net16_t * pkey1, IN const ib_net16_t * pkey2) { /* if both pkeys are not full member - this is not a match */ if (!(ib_pkey_is_full_member(*pkey1) || ib_pkey_is_full_member(*pkey2))) return FALSE; /* compare if the bases are the same. if they are - then this is a match */ if (ib_pkey_get_base(*pkey1) != ib_pkey_get_base(*pkey2)) return FALSE; return TRUE; } boolean_t osm_physp_share_this_pkey(IN const osm_physp_t * p_physp1, IN const osm_physp_t * p_physp2, IN ib_net16_t pkey, IN boolean_t allow_both_pkeys) { ib_net16_t *pkey1, *pkey2; ib_net16_t full_pkey, limited_pkey; if (allow_both_pkeys) { full_pkey = pkey | IB_PKEY_TYPE_MASK; limited_pkey = pkey & ~IB_PKEY_TYPE_MASK; pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, full_pkey); if (!pkey1) pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, limited_pkey); pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, full_pkey); if (!pkey2) pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, limited_pkey); } else { pkey1 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp1))->keys, ib_pkey_get_base(pkey)); pkey2 = cl_map_get(&(osm_physp_get_pkey_tbl(p_physp2))->keys, ib_pkey_get_base(pkey)); } return (pkey1 && pkey2 && match_pkey(pkey1, pkey2)); } ib_net16_t osm_physp_find_common_pkey(IN const osm_physp_t * p_physp1, IN const osm_physp_t * p_physp2, IN boolean_t allow_both_pkeys) { ib_net16_t *pkey1, *pkey2; uint64_t pkey1_base, pkey2_base; const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; cl_map_iterator_t map_iter1, map_iter2; pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp1); pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp2); map_iter1 = cl_map_head(&pkey_tbl1->keys); map_iter2 = cl_map_head(&pkey_tbl2->keys); /* we rely on the fact the map are sorted by pkey */ while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); if (match_pkey(pkey1, pkey2)) return *pkey1; /* advance the lower value if they are not equal */ pkey1_base = cl_map_key(map_iter1); pkey2_base = cl_map_key(map_iter2); if (pkey2_base == pkey1_base) { map_iter1 = cl_map_next(map_iter1); map_iter2 = cl_map_next(map_iter2); } else if (pkey2_base < pkey1_base) map_iter2 = cl_map_next(map_iter2); else map_iter1 = cl_map_next(map_iter1); } if (!allow_both_pkeys) return 0; /* When using allow_both_pkeys, the keys in pkey tables are the pkey value including membership bit. Therefore, in order to complete the search, we also need to compare port\s 1 full pkeys with port 2 limited pkeys, and port 2 full pkeys with port 1 full pkeys. */ map_iter1 = cl_map_head(&pkey_tbl1->keys); map_iter2 = cl_map_head(&pkey_tbl2->keys); /* comparing pkey_tbl1 full with pkey_tbl2 limited */ while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); if (!ib_pkey_is_full_member(*pkey1)) { map_iter1 = cl_map_next(map_iter1); continue; } if (ib_pkey_is_full_member(*pkey2)) { map_iter2 = cl_map_next(map_iter2); continue; } if (match_pkey(pkey1, pkey2)) return *pkey1; /* advance the lower value if they are not equal */ pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1)); pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2)); if (pkey2_base == pkey1_base) { map_iter1 = cl_map_next(map_iter1); map_iter2 = cl_map_next(map_iter2); } else if (pkey2_base < pkey1_base) map_iter2 = cl_map_next(map_iter2); else map_iter1 = cl_map_next(map_iter1); } map_iter1 = cl_map_head(&pkey_tbl1->keys); map_iter2 = cl_map_head(&pkey_tbl2->keys); /* comparing pkey_tbl1 limited with pkey_tbl2 full */ while ((map_iter1 != cl_map_end(&pkey_tbl1->keys)) && (map_iter2 != cl_map_end(&pkey_tbl2->keys))) { pkey1 = (ib_net16_t *) cl_map_obj(map_iter1); pkey2 = (ib_net16_t *) cl_map_obj(map_iter2); if (ib_pkey_is_full_member(*pkey1)) { map_iter1 = cl_map_next(map_iter1); continue; } if (!ib_pkey_is_full_member(*pkey2)) { map_iter2 = cl_map_next(map_iter2); continue; } if (match_pkey(pkey1, pkey2)) return *pkey1; /* advance the lower value if they are not equal */ pkey1_base = ib_pkey_get_base(cl_map_key(map_iter1)); pkey2_base = ib_pkey_get_base(cl_map_key(map_iter2)); if (pkey2_base == pkey1_base) { map_iter1 = cl_map_next(map_iter1); map_iter2 = cl_map_next(map_iter2); } else if (pkey2_base < pkey1_base) map_iter2 = cl_map_next(map_iter2); else map_iter1 = cl_map_next(map_iter1); } return 0; } boolean_t osm_physp_share_pkey(IN osm_log_t * p_log, IN const osm_physp_t * p_physp_1, IN const osm_physp_t * p_physp_2, IN boolean_t allow_both_pkeys) { const osm_pkey_tbl_t *pkey_tbl1, *pkey_tbl2; if (p_physp_1 == p_physp_2) return TRUE; pkey_tbl1 = osm_physp_get_pkey_tbl(p_physp_1); pkey_tbl2 = osm_physp_get_pkey_tbl(p_physp_2); /* The spec: 10.9.2 does not require each phys port to have PKey Table. So actually if it does not, we need to use the default port instead. HACK: meanwhile we will ignore the check */ if (cl_is_map_empty(&pkey_tbl1->keys) || cl_is_map_empty(&pkey_tbl2->keys)) return TRUE; return !ib_pkey_is_invalid(osm_physp_find_common_pkey (p_physp_1, p_physp_2, allow_both_pkeys)); } boolean_t osm_port_share_pkey(IN osm_log_t * p_log, IN const osm_port_t * p_port_1, IN const osm_port_t * p_port_2, IN boolean_t allow_both_pkeys) { osm_physp_t *p_physp1, *p_physp2; boolean_t ret; OSM_LOG_ENTER(p_log); if (!p_port_1 || !p_port_2) { ret = FALSE; goto Exit; } p_physp1 = p_port_1->p_physp; p_physp2 = p_port_2->p_physp; if (!p_physp1 || !p_physp2) { ret = FALSE; goto Exit; } ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2, allow_both_pkeys); Exit: OSM_LOG_EXIT(p_log); return ret; } boolean_t osm_physp_has_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, IN const osm_physp_t * p_physp) { ib_net16_t *p_pkey, pkey_base; const osm_pkey_tbl_t *pkey_tbl; boolean_t res = FALSE; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Search for PKey: 0x%04x\n", cl_ntoh16(pkey)); /* if the pkey given is an invalid pkey - return TRUE. */ if (ib_pkey_is_invalid(pkey)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Given invalid PKey - we treat it loosely and allow it\n"); res = TRUE; goto Exit; } pkey_base = ib_pkey_get_base(pkey); pkey_tbl = osm_physp_get_pkey_tbl(p_physp); p_pkey = cl_map_get(&pkey_tbl->keys, pkey_base); if (p_pkey) { res = TRUE; OSM_LOG(p_log, OSM_LOG_DEBUG, "PKey 0x%04x was found\n", cl_ntoh16(pkey)); } else OSM_LOG(p_log, OSM_LOG_DEBUG, "PKey 0x%04x was not found\n", cl_ntoh16(pkey)); Exit: OSM_LOG_EXIT(p_log); return res; } void osm_pkey_tbl_set_indx0_pkey(IN osm_log_t * p_log, IN ib_net16_t pkey, IN boolean_t full, OUT osm_pkey_tbl_t * p_pkey_tbl) { p_pkey_tbl->indx0_pkey = (full == TRUE) ? pkey | cl_hton16(0x8000) : pkey; OSM_LOG(p_log, OSM_LOG_DEBUG, "pkey 0x%04x set at indx0\n", cl_ntoh16(p_pkey_tbl->indx0_pkey)); } opensm-3.3.20/opensm/osm_pkey_mgr.c0000644000205000001450000006630512654626072014174 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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 the P_Key Manager (Partition Manager). * This is part of the OpenSM. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_PKEY_MGR_C #include #include #include #include static void clear_accum_pkey_index(osm_pkey_tbl_t * p_pkey_tbl, uint16_t pkey_index); /* The max number of pkeys/pkey blocks for a physical port is located in a different place for switch external ports (SwitchInfo) and the rest of the ports (NodeInfo). */ static uint16_t pkey_mgr_get_physp_max_pkeys(IN const osm_physp_t * p_physp) { osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); uint16_t num_pkeys = 0; if (!p_node->sw || (osm_physp_get_port_num(p_physp) == 0)) num_pkeys = cl_ntoh16(p_node->node_info.partition_cap); else num_pkeys = cl_ntoh16(p_node->sw->switch_info.enforce_cap); return num_pkeys; } static uint16_t pkey_mgr_get_physp_max_blocks(IN const osm_physp_t * p_physp) { return ((pkey_mgr_get_physp_max_pkeys(p_physp) + 31) / 32); } /* * Insert new pending pkey entry to the specific port pkey table * pending pkeys. New entries are inserted at the back. */ static void pkey_mgr_process_physical_port(IN osm_log_t * p_log, IN osm_sm_t * sm, IN const ib_net16_t pkey, IN osm_physp_t * p_physp) { osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); osm_pkey_tbl_t *p_pkey_tbl; ib_net16_t *p_orig_pkey; osm_pending_pkey_t *p_pending; p_pkey_tbl = &p_physp->pkeys; p_pending = (osm_pending_pkey_t *) calloc(1, sizeof(osm_pending_pkey_t)); if (!p_pending) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0502: " "Failed to allocate new pending pkey entry for node " "0x%016" PRIx64 " port %u\n", cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp)); return; } p_pending->pkey = pkey; if (sm->p_subn->opt.allow_both_pkeys) p_orig_pkey = cl_map_get(&p_pkey_tbl->keys, pkey); else p_orig_pkey = cl_map_get(&p_pkey_tbl->keys, ib_pkey_get_base(pkey)); if (!p_orig_pkey) { p_pending->is_new = TRUE; } else { CL_ASSERT(ib_pkey_get_base(*p_orig_pkey) == ib_pkey_get_base(pkey)); p_pending->is_new = FALSE; if (osm_pkey_tbl_get_block_and_idx(p_pkey_tbl, p_orig_pkey, &p_pending->block, &p_pending->index) != IB_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0503: " "Failed to obtain P_Key 0x%04x block and index " "for node 0x%016" PRIx64 " port %u\n", cl_ntoh16(ib_pkey_get_base(pkey)), cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp)); free(p_pending); return; } if (p_physp->pkeys.indx0_pkey) { /* * Remove the pkey that should be at index 0 from * accum pkey if current position is not index 0 */ if (((sm->p_subn->opt.allow_both_pkeys && pkey == p_physp->pkeys.indx0_pkey) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(pkey) == ib_pkey_get_base(p_physp->pkeys.indx0_pkey))) && (p_pending->block != 0 || p_pending->index != 0)) { p_pending->is_new = TRUE; clear_accum_pkey_index(p_pkey_tbl, p_pending->block * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + p_pending->index); } if (p_pending->block == 0 && p_pending->index == 0) { /* Move the pkey away from index 0 */ if ((sm->p_subn->opt.allow_both_pkeys && pkey != p_physp->pkeys.indx0_pkey) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(pkey) != ib_pkey_get_base(p_physp->pkeys.indx0_pkey))) { p_pending->is_new = TRUE; clear_accum_pkey_index(p_pkey_tbl, 0); } } } else { /* If index 0 is occupied by non-default, it should reoccupied by pkey 0x7FFF */ if (p_pending->block == 0 && p_pending->index == 0) { if (ib_pkey_get_base(pkey) != IB_DEFAULT_PARTIAL_PKEY) { p_pending->is_new = TRUE; clear_accum_pkey_index(p_pkey_tbl, 0); } /* Need to move default pkey to index 0 */ } else if ((sm->p_subn->opt.allow_both_pkeys && pkey == IB_DEFAULT_PKEY) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(pkey) == IB_DEFAULT_PARTIAL_PKEY)) { p_pending->is_new = TRUE; clear_accum_pkey_index(p_pkey_tbl, p_pending->block * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + p_pending->index); } } } if (p_pending->is_new == TRUE) cl_qlist_insert_tail(&p_pkey_tbl->pending, (cl_list_item_t *) p_pending); else cl_qlist_insert_head(&p_pkey_tbl->pending, (cl_list_item_t *) p_pending); OSM_LOG(p_log, OSM_LOG_DEBUG, "pkey 0x%04x was %s for node 0x%016" PRIx64 " port %u\n", cl_ntoh16(pkey), p_pending->is_new ? "inserted" : "updated", cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp)); } static void pkey_mgr_process_partition_table(osm_log_t * p_log, osm_sm_t * sm, const osm_prtn_t * p_prtn, const boolean_t full) { const cl_map_t *p_tbl = full ? &p_prtn->full_guid_tbl : &p_prtn->part_guid_tbl; cl_map_iterator_t i, i_next; ib_net16_t pkey = p_prtn->pkey; osm_physp_t *p_physp; if (full) pkey |= cl_hton16(0x8000); i_next = cl_map_head(p_tbl); while (i_next != cl_map_end(p_tbl)) { i = i_next; i_next = cl_map_next(i); p_physp = cl_map_obj(i); if (p_physp) pkey_mgr_process_physical_port(p_log, sm, pkey, p_physp); } } static ib_api_status_t pkey_mgr_update_pkey_entry(IN osm_sm_t * sm, IN const osm_physp_t * p_physp, IN const ib_pkey_table_t * block, IN const uint16_t block_index) { osm_madw_context_t context; osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); osm_physp_t *physp0; uint32_t attr_mod; ib_net64_t m_key; context.pkey_context.node_guid = osm_node_get_node_guid(p_node); context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp); context.pkey_context.set_method = TRUE; attr_mod = block_index; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p_physp) != 0) { attr_mod |= osm_physp_get_port_num(p_physp) << 16; physp0 = osm_node_get_physp_ptr(p_node, 0); m_key = ib_port_info_get_m_key(&physp0->port_info); } else m_key = ib_port_info_get_m_key(&p_physp->port_info); return osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), (uint8_t *) block, sizeof(*block), IB_MAD_ATTR_P_KEY_TABLE, cl_hton32(attr_mod), FALSE, m_key, CL_DISP_MSGID_NONE, &context); } static ib_api_status_t pkey_mgr_enforce_partition(IN osm_log_t * p_log, osm_sm_t * sm, IN osm_physp_t * p_physp, IN osm_partition_enforce_type_enum enforce_type) { osm_madw_context_t context; uint8_t payload[IB_SMP_DATA_SIZE]; ib_port_info_t *p_pi; ib_net64_t m_key; osm_physp_t *physp0; ib_api_status_t status; uint8_t enforce_bits; p_pi = &p_physp->port_info; if (enforce_type == OSM_PARTITION_ENFORCE_TYPE_BOTH) enforce_bits = 0xc; else if (enforce_type == OSM_PARTITION_ENFORCE_TYPE_IN) enforce_bits = 0x8; else enforce_bits = 0x4; if ((p_pi->vl_enforce & 0xc) == enforce_bits * (enforce_type != OSM_PARTITION_ENFORCE_TYPE_OFF)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "No need to update PortInfo for " "node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh64(osm_node_get_node_guid (osm_physp_get_node_ptr(p_physp))), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); return IB_SUCCESS; } memcpy(payload, p_pi, sizeof(ib_port_info_t)); p_pi = (ib_port_info_t *) payload; p_pi->vl_enforce &= ~0xc; if (enforce_type != OSM_PARTITION_ENFORCE_TYPE_OFF) p_pi->vl_enforce |= enforce_bits; p_pi->state_info2 = 0; ib_port_info_set_port_state(p_pi, IB_LINK_NO_CHANGE); physp0 = osm_node_get_physp_ptr(p_physp->p_node, 0); m_key = ib_port_info_get_m_key(&physp0->port_info); context.pi_context.node_guid = osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp)); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = TRUE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, cl_hton32(osm_physp_get_port_num(p_physp)), FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0511: " "Failed to set PortInfo for " "node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh64(osm_node_get_node_guid (osm_physp_get_node_ptr(p_physp))), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); else OSM_LOG(p_log, OSM_LOG_DEBUG, "Set PortInfo for node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh64(osm_node_get_node_guid (osm_physp_get_node_ptr(p_physp))), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); return status; } static void clear_accum_pkey_index(osm_pkey_tbl_t * p_pkey_tbl, uint16_t pkey_index) { uint16_t pkey_idx_bias, pkey_idx; void *ptr; uintptr_t pkey_idx_ptr; cl_map_iterator_t map_iter, map_iter_temp; map_iter = cl_map_head(&p_pkey_tbl->accum_pkeys); pkey_idx_bias = pkey_index + 1; // adjust for pkey index bias in accum_pkeys while (map_iter != cl_map_end(&p_pkey_tbl->accum_pkeys)) { map_iter_temp = cl_map_next(map_iter); ptr = (uint16_t *) cl_map_obj(map_iter); CL_ASSERT(ptr); pkey_idx_ptr = (uintptr_t) ptr; pkey_idx = pkey_idx_ptr; if (pkey_idx == pkey_idx_bias) { cl_map_remove_item(&p_pkey_tbl->accum_pkeys, map_iter); if (p_pkey_tbl->last_pkey_idx == pkey_idx) osm_pkey_find_last_accum_pkey_index(p_pkey_tbl); break; } map_iter = map_iter_temp; } } static int last_accum_pkey_index(osm_pkey_tbl_t * p_pkey_tbl, uint16_t * p_block_idx, uint8_t * p_pkey_idx) { if (p_pkey_tbl->last_pkey_idx) { *p_block_idx = (p_pkey_tbl->last_pkey_idx - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; *p_pkey_idx = (p_pkey_tbl->last_pkey_idx - 1) % IB_NUM_PKEY_ELEMENTS_IN_BLOCK; return 1; } return 0; } static int pkey_mgr_update_port(osm_log_t * p_log, osm_sm_t * sm, const osm_port_t * const p_port) { osm_physp_t *p_physp; osm_node_t *p_node; ib_pkey_table_t *block, *new_block; osm_pkey_tbl_t *p_pkey_tbl; uint16_t block_index; uint8_t pkey_index; uint16_t last_free_block_index = 0; uint8_t last_free_pkey_index = 0; uint16_t num_of_blocks; uint16_t max_num_of_blocks; ib_api_status_t status; osm_pending_pkey_t *p_pending; boolean_t found; ib_pkey_table_t empty_block; int ret = 0, full = 0; void *ptr; uintptr_t pkey_idx_ptr; uint16_t pkey_idx; p_physp = p_port->p_physp; if (!p_physp) return FALSE; memset(&empty_block, 0, sizeof(ib_pkey_table_t)); p_node = osm_physp_get_node_ptr(p_physp); p_pkey_tbl = &p_physp->pkeys; num_of_blocks = osm_pkey_tbl_get_num_blocks(p_pkey_tbl); max_num_of_blocks = pkey_mgr_get_physp_max_blocks(p_physp); if (p_pkey_tbl->max_blocks > max_num_of_blocks) { OSM_LOG(p_log, OSM_LOG_INFO, "Max number of blocks reduced from %u to %u " "for node 0x%016" PRIx64 " port %u (%s)\n", p_pkey_tbl->max_blocks, max_num_of_blocks, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); } p_pkey_tbl->max_blocks = max_num_of_blocks; osm_pkey_tbl_init_new_blocks(p_pkey_tbl); p_pkey_tbl->used_blocks = 0; /* process every pending pkey in order - first must be "updated" last are "new" */ p_pending = (osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl->pending); while (p_pending != (osm_pending_pkey_t *) cl_qlist_end(&p_pkey_tbl->pending)) { found = FALSE; ptr = NULL; if (p_pending->is_new == FALSE) { block_index = p_pending->block; pkey_index = p_pending->index; found = TRUE; } else { ptr = cl_map_get(&p_pkey_tbl->accum_pkeys,p_pending->pkey); if (ptr != NULL) { pkey_idx_ptr = (uintptr_t) ptr; pkey_idx = pkey_idx_ptr; pkey_idx--; /* adjust pkey index for bias */ block_index = pkey_idx / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_index = pkey_idx % IB_NUM_PKEY_ELEMENTS_IN_BLOCK; if (((sm->p_subn->opt.allow_both_pkeys && p_pending->pkey == p_physp->pkeys.indx0_pkey) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(p_pending->pkey) == ib_pkey_get_base(p_physp->pkeys.indx0_pkey))) || ((p_pending->pkey != p_physp->pkeys.indx0_pkey && pkey_idx == 0))) { clear_accum_pkey_index(p_pkey_tbl, pkey_idx); cl_qlist_insert_tail(&p_pkey_tbl->pending, (cl_list_item_t *)p_pending); p_pending = (osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl->pending); continue; } else found = TRUE; } if (!found) { if (!p_pkey_tbl->indx0_pkey && ((sm->p_subn->opt.allow_both_pkeys && p_pending->pkey == IB_DEFAULT_PKEY) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(p_pending->pkey) == IB_DEFAULT_PARTIAL_PKEY))) { block_index = 0; pkey_index = 0; } else if ((sm->p_subn->opt.allow_both_pkeys && p_pending->pkey == p_pkey_tbl->indx0_pkey) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(p_pending->pkey) == ib_pkey_get_base(p_pkey_tbl->indx0_pkey))) { block_index = 0; pkey_index = 0; } else if (last_accum_pkey_index(p_pkey_tbl, &last_free_block_index, &last_free_pkey_index)) { block_index = last_free_block_index; pkey_index = last_free_pkey_index + 1; if (pkey_index >= IB_NUM_PKEY_ELEMENTS_IN_BLOCK) { block_index++; pkey_index -= IB_NUM_PKEY_ELEMENTS_IN_BLOCK; } } else { block_index = 0; pkey_index = 1; } if (block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index >= pkey_mgr_get_physp_max_pkeys(p_physp)) { if ((sm->p_subn->opt.allow_both_pkeys && p_pending->pkey != IB_DEFAULT_PKEY) || (!sm->p_subn->opt.allow_both_pkeys && ib_pkey_get_base(p_pending->pkey) != IB_DEFAULT_PARTIAL_PKEY)) { last_free_block_index = 0; last_free_pkey_index = 1; found = osm_pkey_find_next_free_entry(p_pkey_tbl, &last_free_block_index, &last_free_pkey_index); } else found = FALSE; if (!found) full = 1; else { block_index = last_free_block_index; pkey_index = last_free_pkey_index; if (block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index >= pkey_mgr_get_physp_max_pkeys(p_physp)) { full = 1; found = FALSE; } else { OSM_LOG(p_log, OSM_LOG_INFO, "Reusing PKeyTable block index %u pkey index %u " "for pkey 0x%x on 0x%016" PRIx64 " port %u (%s)\n", block_index, pkey_index, cl_ntoh16(p_pending->pkey), cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); clear_accum_pkey_index(p_pkey_tbl, block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index); } } if (full) OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0512: " "Failed to set PKey 0x%04x because Pkey table is full " "for node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh16(p_pending->pkey), cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); } else found = TRUE; } } if (found) { if (IB_SUCCESS != osm_pkey_tbl_set_new_entry(p_pkey_tbl, block_index, pkey_index, p_pending->pkey)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0505: " "Failed to set PKey 0x%04x in block %u idx %u " "for node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh16(p_pending->pkey), block_index, pkey_index, cl_ntoh64(osm_node_get_node_guid (p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); } if (ptr == NULL && CL_SUCCESS != osm_pkey_tbl_set_accum_pkeys(p_pkey_tbl, p_pending->pkey, block_index * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + pkey_index)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0508: " "Failed to set accum_pkeys PKey 0x%04x " "in block %u idx %u for node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh16(p_pending->pkey), block_index, pkey_index, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); } } free(p_pending); p_pending = (osm_pending_pkey_t *) cl_qlist_remove_head(&p_pkey_tbl-> pending); } p_pkey_tbl->indx0_pkey = 0; /* now look for changes and store */ for (block_index = 0; block_index < num_of_blocks; block_index++) { block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index); new_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); if (!new_block) new_block = &empty_block; if (block && !memcmp(new_block, block, sizeof(*block))) continue; status = pkey_mgr_update_pkey_entry(sm, p_physp, new_block, block_index); if (status == IB_SUCCESS) OSM_LOG(p_log, OSM_LOG_DEBUG, "Updated pkey table block %u for node 0x%016" PRIx64 " port %u (%s)\n", block_index, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0506: " "pkey_mgr_update_pkey_entry() failed to update " "pkey table block %u for node 0x%016" PRIx64 " port %u (%s)\n", block_index, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(p_physp), p_physp->p_node->print_desc); ret = -1; } } return ret; } static int last_used_pkey_index(const osm_port_t * const p_port, const osm_pkey_tbl_t * p_pkey_tbl, uint16_t * p_last_index) { ib_pkey_table_t *last_block; uint16_t index, last_index = 0; CL_ASSERT(p_last_index); last_block = osm_pkey_tbl_new_block_get(p_pkey_tbl, p_pkey_tbl->used_blocks - 1); if (!last_block) return 1; if (p_pkey_tbl->used_blocks == p_pkey_tbl->max_blocks) last_index = cl_ntoh16(p_port->p_node->node_info.partition_cap) % IB_NUM_PKEY_ELEMENTS_IN_BLOCK; if (last_index == 0) last_index = IB_NUM_PKEY_ELEMENTS_IN_BLOCK; index = last_index; do { index--; if (!ib_pkey_is_invalid(last_block->pkey_entry[index])) break; } while (index != 0); *p_last_index = index; return 0; } static int update_peer_block(osm_log_t * p_log, osm_sm_t * sm, osm_physp_t * peer, osm_pkey_tbl_t * p_peer_pkey_tbl, ib_pkey_table_t * new_peer_block, uint16_t peer_block_idx, osm_node_t * p_node) { int ret = 0; ib_pkey_table_t *peer_block; peer_block = osm_pkey_tbl_block_get(p_peer_pkey_tbl, peer_block_idx); if (!peer_block || memcmp(peer_block, new_peer_block, sizeof(*peer_block))) { if (pkey_mgr_update_pkey_entry(sm, peer, new_peer_block, peer_block_idx) != IB_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0509: " "pkey_mgr_update_pkey_entry() failed to update " "pkey table block %u for node 0x%016" PRIx64 " port %u (%s)\n", peer_block_idx, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(peer), p_node->print_desc); ret = -1; } } return ret; } static int new_pkey_exists(osm_pkey_tbl_t * p_pkey_tbl, ib_net16_t pkey) { uint16_t num_blocks; uint16_t block_index; ib_pkey_table_t *block; uint16_t pkey_idx; num_blocks = (uint16_t) cl_ptr_vector_get_size(&p_pkey_tbl->new_blocks); for (block_index = 0; block_index < num_blocks; block_index++) { block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); if (!block) continue; for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_idx++) { if (block->pkey_entry[pkey_idx] == pkey) return 1; } } return 0; } static int pkey_mgr_update_peer_port(osm_log_t * p_log, osm_sm_t * sm, const osm_subn_t * p_subn, const osm_port_t * const p_port, osm_partition_enforce_type_enum enforce_type) { osm_physp_t *p_physp, *peer; osm_node_t *p_node; ib_pkey_table_t *block; const osm_pkey_tbl_t *p_pkey_tbl; osm_pkey_tbl_t *p_peer_pkey_tbl; uint16_t block_index, peer_block_idx; uint16_t peer_max_blocks; uint16_t last_index; ib_pkey_table_t new_peer_block; uint16_t pkey_idx, peer_pkey_idx; ib_net16_t pkey, full_pkey; int ret = 0, loop_exit = 0; p_physp = p_port->p_physp; if (!p_physp) return -1; peer = osm_physp_get_remote(p_physp); if (!peer) return -1; p_node = osm_physp_get_node_ptr(peer); if (!p_node->sw || !p_node->sw->switch_info.enforce_cap) return 0; if (enforce_type == OSM_PARTITION_ENFORCE_TYPE_OFF) { pkey_mgr_enforce_partition(p_log, sm, peer, OSM_PARTITION_ENFORCE_TYPE_OFF); return ret; } p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp); peer_max_blocks = pkey_mgr_get_physp_max_blocks(peer); p_peer_pkey_tbl = &peer->pkeys; peer_block_idx = 0; peer_pkey_idx = 0; for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++) { if (loop_exit) break; block = osm_pkey_tbl_new_block_get(p_pkey_tbl, block_index); if (!block) continue; for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; pkey_idx++) { pkey = block->pkey_entry[pkey_idx]; if (ib_pkey_is_invalid(pkey)) continue; if (!ib_pkey_is_full_member(pkey)) { full_pkey = pkey | IB_PKEY_TYPE_MASK; if (new_pkey_exists(&p_physp->pkeys, full_pkey)) continue; } new_peer_block.pkey_entry[peer_pkey_idx] = pkey; if (peer_block_idx >= peer_max_blocks) { loop_exit = 1; break; } if (++peer_pkey_idx == IB_NUM_PKEY_ELEMENTS_IN_BLOCK) { if (update_peer_block(p_log, sm, peer, p_peer_pkey_tbl, &new_peer_block, peer_block_idx, p_node)) ret = -1; peer_pkey_idx = 0; peer_block_idx++; } } } if (peer_block_idx < peer_max_blocks) { if (peer_pkey_idx) { /* Handle partial last block */ for (; peer_pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK; peer_pkey_idx++) new_peer_block.pkey_entry[peer_pkey_idx] = 0; if (update_peer_block(p_log, sm, peer, p_peer_pkey_tbl, &new_peer_block, peer_block_idx, p_node)) ret = -1; } else peer_block_idx--; p_peer_pkey_tbl->used_blocks = peer_block_idx + 1; if (p_peer_pkey_tbl->used_blocks == peer_max_blocks) { /* Is last used pkey index beyond switch peer port capacity ? */ if (!last_used_pkey_index(p_port, p_peer_pkey_tbl, &last_index)) { last_index += peer_block_idx * IB_NUM_PKEY_ELEMENTS_IN_BLOCK; if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) <= last_index) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0507: " "Not enough pkey entries (%u <= %u) on switch 0x%016" PRIx64 " port %u (%s). Clearing Enforcement bit\n", cl_ntoh16(p_node->sw->switch_info.enforce_cap), last_index, cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(peer), p_node->print_desc); enforce_type = OSM_PARTITION_ENFORCE_TYPE_OFF; ret = -1; } } } } else { p_peer_pkey_tbl->used_blocks = peer_max_blocks; enforce_type = OSM_PARTITION_ENFORCE_TYPE_OFF; } if (!ret) OSM_LOG(p_log, OSM_LOG_DEBUG, "Pkey table was successfully updated for node 0x%016" PRIx64 " port %u (%s)\n", cl_ntoh64(osm_node_get_node_guid(p_node)), osm_physp_get_port_num(peer), p_node->print_desc); if (pkey_mgr_enforce_partition(p_log, sm, peer, enforce_type)) ret = -1; return ret; } int osm_pkey_mgr_process(IN osm_opensm_t * p_osm) { cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_prtn_t *p_prtn; osm_port_t *p_port; osm_switch_t *p_sw; osm_physp_t *p_physp; osm_node_t *p_remote_node; uint8_t i; int ret = 0; CL_ASSERT(p_osm); OSM_LOG_ENTER(&p_osm->log); CL_PLOCK_EXCL_ACQUIRE(&p_osm->lock); if (osm_prtn_make_partitions(&p_osm->log, &p_osm->subn) != IB_SUCCESS) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 0510: " "osm_prtn_make_partitions() failed\n"); ret = -1; goto _err; } /* populate the pending pkey entries by scanning all partitions */ p_tbl = &p_osm->subn.prtn_pkey_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { p_prtn = (osm_prtn_t *) p_next; p_next = cl_qmap_next(p_next); pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm, p_prtn, FALSE); pkey_mgr_process_partition_table(&p_osm->log, &p_osm->sm, p_prtn, TRUE); } /* calculate and set new pkey tables */ p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); if (pkey_mgr_update_port(&p_osm->log, &p_osm->sm, p_port)) ret = -1; if ((osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH) && pkey_mgr_update_peer_port(&p_osm->log, &p_osm->sm, &p_osm->subn, p_port, p_osm->subn.opt.part_enforce_enum)) ret = -1; } /* clear partition enforcement on inter-switch links */ p_tbl = &p_osm->subn.sw_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { p_sw = (osm_switch_t *) p_next; p_next = cl_qmap_next(p_next); for (i = 1; i < p_sw->num_ports; i++) { p_physp = osm_node_get_physp_ptr(p_sw->p_node, i); if (p_physp && p_physp->p_remote_physp) p_remote_node = p_physp->p_remote_physp->p_node; else continue; if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) continue; if(! (p_physp->port_info.vl_enforce & 0xc )) continue; /* clear partition enforcement */ if (pkey_mgr_enforce_partition(&p_osm->log, &p_osm->sm, p_physp, OSM_PARTITION_ENFORCE_TYPE_OFF)) ret = -1; } } _err: CL_PLOCK_RELEASE(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; } opensm-3.3.20/opensm/osm_pkey_rcv.c0000644000205000001450000001101712273221507014156 00000000000000/* * Copyright (c) 2004-2009 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_PKEY_RCV_C #include #include #include #include #include #include /* * WE ONLY RECEIVE GET or SET responses */ void osm_pkey_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_pkey_table_t *p_pkey_tbl; ib_smp_t *p_smp; osm_port_t *p_port; osm_physp_t *p_physp; osm_node_t *p_node; osm_pkey_context_t *p_context; ib_net64_t port_guid; ib_net64_t node_guid; uint8_t port_num; uint16_t block_num; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_pkey_context_ptr(p_madw); p_pkey_tbl = ib_smp_get_payload_ptr(p_smp); port_guid = p_context->port_guid; node_guid = p_context->node_guid; CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit2; } cl_plock_excl_acquire(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4806: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); block_num = (uint16_t) ((cl_ntoh32(p_smp->attr_mod)) & 0x0000FFFF); /* in case of a non switch node the attr modifier should be ignored */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { port_num = (uint8_t) (((cl_ntoh32(p_smp->attr_mod)) & 0x00FF0000) >> 16); p_physp = osm_node_get_physp_ptr(p_node, port_num); } else { p_physp = p_port->p_physp; port_num = p_physp->port_num; } /* We do not care if this is a result of a set or get - all we want is to update the subnet. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Got GetResp(PKey) block:%u port_num %u with GUID 0x%" PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", block_num, port_num, cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); /* Determine if we encountered a new Physical Port. If so, ignore it. */ if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4807: " "Got invalid port number %u\n", port_num); goto Exit; } osm_dump_pkey_block_v2(sm->p_log, port_guid, block_num, port_num, p_pkey_tbl, FILE_ID, OSM_LOG_DEBUG); osm_physp_set_pkey_tbl(sm->p_log, sm->p_subn, p_physp, p_pkey_tbl, block_num, p_context->set_method); Exit: cl_plock_release(sm->p_lock); Exit2: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_port.c0000644000205000001450000004756212600531672013337 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 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 osm_physp_t. * This object represents an Infiniband Port. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_PORT_C #include #include #include #include #include #include void osm_physp_construct(IN osm_physp_t * p_physp) { memset(p_physp, 0, sizeof(*p_physp)); osm_dr_path_construct(&p_physp->dr_path); cl_ptr_vector_construct(&p_physp->slvl_by_port); osm_pkey_tbl_construct(&p_physp->pkeys); } void osm_physp_destroy(IN osm_physp_t * p_physp) { size_t num_slvl, i; /* the physp might be uninitialized */ if (p_physp->port_guid) { if (p_physp->p_guids) free(p_physp->p_guids); /* free the SL2VL Tables */ num_slvl = cl_ptr_vector_get_size(&p_physp->slvl_by_port); for (i = 0; i < num_slvl; i++) free(cl_ptr_vector_get(&p_physp->slvl_by_port, i)); cl_ptr_vector_destroy(&p_physp->slvl_by_port); /* free the P_Key Tables */ osm_pkey_tbl_destroy(&p_physp->pkeys); memset(p_physp, 0, sizeof(*p_physp)); osm_dr_path_construct(&p_physp->dr_path); /* clear dr_path */ } } void osm_physp_init(IN osm_physp_t * p_physp, IN ib_net64_t port_guid, IN uint8_t port_num, IN const struct osm_node *p_node, IN osm_bind_handle_t h_bind, IN uint8_t hop_count, IN const uint8_t * p_initial_path) { uint16_t num_slvl, i; ib_slvl_table_t *p_slvl; CL_ASSERT(p_node); osm_physp_construct(p_physp); p_physp->port_guid = port_guid; p_physp->port_num = port_num; p_physp->healthy = TRUE; p_physp->need_update = 2; p_physp->p_node = (struct osm_node *)p_node; osm_dr_path_init(&p_physp->dr_path, hop_count, p_initial_path); /* allocate enough SL2VL tables */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) /* we need node num ports + 1 SL2VL tables */ num_slvl = osm_node_get_num_physp(p_node) + 1; else /* An end node - we need only one SL2VL */ num_slvl = 1; cl_ptr_vector_init(&p_physp->slvl_by_port, num_slvl, 1); for (i = 0; i < num_slvl; i++) { p_slvl = (ib_slvl_table_t *) malloc(sizeof(ib_slvl_table_t)); if (!p_slvl) break; memset(p_slvl, 0, sizeof(ib_slvl_table_t)); cl_ptr_vector_set(&p_physp->slvl_by_port, i, p_slvl); } /* initialize the pkey table */ osm_pkey_tbl_init(&p_physp->pkeys); } void osm_port_delete(IN OUT osm_port_t ** pp_port) { free(*pp_port); *pp_port = NULL; } osm_port_t *osm_port_new(IN const ib_node_info_t * p_ni, IN osm_node_t * p_parent_node) { osm_port_t *p_port; ib_net64_t port_guid; osm_physp_t *p_physp; uint8_t port_num; p_port = malloc(sizeof(*p_port)); if (!p_port) return NULL; memset(p_port, 0, sizeof(*p_port)); cl_qlist_init(&p_port->mcm_list); p_port->p_node = (struct osm_node *)p_parent_node; port_guid = p_ni->port_guid; p_port->guid = port_guid; port_num = p_ni->node_type == IB_NODE_TYPE_SWITCH ? 0 : ib_node_info_get_local_port_num(p_ni); /* Get the pointers to the physical node objects "owned" by this logical port GUID. For switches, port '0' is owned; for HCA's and routers, only the singular part that has this GUID is owned. */ p_physp = osm_node_get_physp_ptr(p_parent_node, port_num); if (!p_physp) return NULL; CL_ASSERT(port_guid == osm_physp_get_port_guid(p_physp)); p_port->p_physp = p_physp; return p_port; } void osm_port_get_lid_range_ho(IN const osm_port_t * p_port, IN uint16_t * p_min_lid, IN uint16_t * p_max_lid) { uint8_t lmc; *p_min_lid = cl_ntoh16(osm_port_get_base_lid(p_port)); lmc = osm_port_get_lmc(p_port); *p_max_lid = (uint16_t) (*p_min_lid + (1 << lmc) - 1); } uint8_t osm_physp_calc_link_mtu(IN osm_log_t * p_log, IN const osm_physp_t * p_physp, IN uint8_t current_mtu) { const osm_physp_t *p_remote_physp; uint8_t mtu; uint8_t remote_mtu; OSM_LOG_ENTER(p_log); p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) { /* use the available MTU */ mtu = ib_port_info_get_mtu_cap(&p_physp->port_info); remote_mtu = ib_port_info_get_mtu_cap(&p_remote_physp->port_info); OSM_LOG(p_log, OSM_LOG_DEBUG, "Remote port 0x%016" PRIx64 " port = %u : " "MTU = %u. This Port MTU: %u\n", cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), osm_physp_get_port_num(p_remote_physp), remote_mtu, mtu); if (mtu != remote_mtu) { if (mtu > remote_mtu) mtu = remote_mtu; if (mtu != current_mtu) OSM_LOG(p_log, OSM_LOG_VERBOSE, "MTU mismatch between ports." "\n\t\t\t\tPort 0x%016" PRIx64 ", port %u" " and port 0x%016" PRIx64 ", port %u." "\n\t\t\t\tUsing lower MTU of %u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), osm_physp_get_port_num(p_physp), cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), osm_physp_get_port_num(p_remote_physp), mtu); } } else mtu = ib_port_info_get_neighbor_mtu(&p_physp->port_info); if (mtu == 0) { OSM_LOG(p_log, OSM_LOG_DEBUG, "ERR 4101: " "Invalid MTU = 0. Forcing correction to 256\n"); mtu = 1; } OSM_LOG_EXIT(p_log); return mtu; } uint8_t osm_physp_calc_link_op_vls(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN const osm_physp_t * p_physp, IN uint8_t current_op_vls) { const osm_physp_t *p_remote_physp; uint8_t op_vls; uint8_t remote_op_vls; OSM_LOG_ENTER(p_log); p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) { /* use the available VLCap */ op_vls = ib_port_info_get_vl_cap(&p_physp->port_info); remote_op_vls = ib_port_info_get_vl_cap(&p_remote_physp->port_info); OSM_LOG(p_log, OSM_LOG_DEBUG, "Remote port 0x%016" PRIx64 " port = 0x%X : " "VL_CAP = %u. This port VL_CAP = %u\n", cl_ntoh64(osm_physp_get_port_guid(p_remote_physp)), osm_physp_get_port_num(p_remote_physp), remote_op_vls, op_vls); if (op_vls != remote_op_vls) { if (op_vls > remote_op_vls) op_vls = remote_op_vls; if (op_vls != current_op_vls) OSM_LOG(p_log, OSM_LOG_VERBOSE, "OP_VLS mismatch between ports." "\n\t\t\t\tPort 0x%016" PRIx64 ", port 0x%X" " and port 0x%016" PRIx64 ", port 0x%X." "\n\t\t\t\tUsing lower OP_VLS of %u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), osm_physp_get_port_num(p_physp), cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), osm_physp_get_port_num(p_remote_physp), op_vls); } } else op_vls = ib_port_info_get_op_vls(&p_physp->port_info); if (op_vls == 0) { /* for non compliant implementations */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n"); op_vls = 1; } /* support user limitation of max_op_vls */ if (op_vls > p_subn->opt.max_op_vls) op_vls = p_subn->opt.max_op_vls; OSM_LOG_EXIT(p_log); return op_vls; } static inline uint64_t ptr_to_key(void const *p) { uint64_t k = 0; memcpy(&k, p, sizeof(void *)); return k; } static inline void *key_to_ptr(uint64_t k) { void *p = 0; memcpy(&p, &k, sizeof(void *)); return p; } /********************************************************************** Traverse the fabric from the SM node following the DR path given and add every phys port traversed to the map. Avoid tracking the first and last phys ports (going into the first switch and into the target port). **********************************************************************/ static cl_status_t physp_get_dr_physp_set(IN osm_log_t * p_log, IN osm_subn_t const *p_subn, IN osm_dr_path_t const *p_path, OUT cl_map_t * p_physp_map) { osm_port_t *p_port; osm_physp_t *p_physp; osm_node_t *p_node; uint8_t hop; cl_status_t status = CL_SUCCESS; OSM_LOG_ENTER(p_log); /* find the OSM node */ p_port = osm_get_port_by_guid(p_subn, p_subn->sm_port_guid); if (!p_port) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4103: " "Failed to find the SM own port by guid\n"); status = CL_ERROR; goto Exit; } /* get the node of the SM */ p_node = p_port->p_node; /* traverse the path adding the nodes to the table start after the first dummy hop and stop just before the last one */ for (hop = 1; hop < p_path->hop_count - 1; hop++) { /* go out using the phys port of the path */ p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]); /* make sure we got a valid port and it has a remote port */ if (!p_physp) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4104: " "DR Traversal stopped on invalid port at hop:%u\n", hop); status = CL_ERROR; goto Exit; } /* we track the ports we go out along the path */ if (hop > 1) cl_map_insert(p_physp_map, ptr_to_key(p_physp), NULL); OSM_LOG(p_log, OSM_LOG_DEBUG, "Traversed through node: 0x%016" PRIx64 " port:%u\n", cl_ntoh64(p_node->node_info.node_guid), p_path->path[hop]); if (!(p_physp = osm_physp_get_remote(p_physp))) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4106: " "DR Traversal stopped on missing remote physp at hop:%u\n", hop); status = CL_ERROR; goto Exit; } p_node = osm_physp_get_node_ptr(p_physp); } Exit: OSM_LOG_EXIT(p_log); return status; } static void physp_update_new_dr_path(IN osm_physp_t const *p_dest_physp, IN cl_map_t * p_visited_map, IN osm_bind_handle_t * h_bind) { cl_list_t tmpPortsList; osm_physp_t *p_physp, *p_src_physp = NULL; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; uint8_t i = 0; osm_dr_path_t *p_dr_path; cl_list_construct(&tmpPortsList); cl_list_init(&tmpPortsList, 10); cl_list_insert_head(&tmpPortsList, p_dest_physp); /* get the output port where we need to come from */ p_physp = (osm_physp_t *) cl_map_get(p_visited_map, ptr_to_key(p_dest_physp)); while (p_physp != NULL) { cl_list_insert_head(&tmpPortsList, p_physp); /* get the input port through where we reached the output port */ p_src_physp = p_physp; p_physp = (osm_physp_t *) cl_map_get(p_visited_map, ptr_to_key(p_physp)); /* if we reached a null p_physp - this means we are at the begining of the path. Break. */ if (p_physp == NULL) break; /* get the output port */ p_physp = (osm_physp_t *) cl_map_get(p_visited_map, ptr_to_key(p_physp)); } memset(path_array, 0, sizeof(path_array)); p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList); while (p_physp != NULL) { i++; path_array[i] = p_physp->port_num; p_physp = (osm_physp_t *) cl_list_remove_head(&tmpPortsList); } if (p_src_physp) { p_dr_path = osm_physp_get_dr_path_ptr(p_src_physp); osm_dr_path_init(p_dr_path, i, path_array); } cl_list_destroy(&tmpPortsList); } void osm_physp_replace_dr_path_with_alternate_dr_path(IN osm_log_t * p_log, IN osm_subn_t const *p_subn, IN osm_physp_t const *p_dest_physp, IN osm_bind_handle_t * h_bind) { cl_map_t physp_map; cl_map_t visited_map; osm_dr_path_t *p_dr_path; cl_list_t *p_currPortsList; cl_list_t *p_nextPortsList; osm_port_t *p_port; osm_physp_t *p_physp, *p_remote_physp; ib_net64_t port_guid; boolean_t next_list_is_full = TRUE, reached_dest = FALSE; uint8_t num_ports, port_num; p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t)); if (!p_nextPortsList) return; /* initialize the map of all port participating in current dr path not including first and last switches */ cl_map_construct(&physp_map); cl_map_init(&physp_map, 4); cl_map_construct(&visited_map); cl_map_init(&visited_map, 4); p_dr_path = osm_physp_get_dr_path_ptr(p_dest_physp); physp_get_dr_physp_set(p_log, p_subn, p_dr_path, &physp_map); /* BFS from OSM port until we find the target physp but avoid going through mapped ports */ cl_list_construct(p_nextPortsList); cl_list_init(p_nextPortsList, 10); port_guid = p_subn->sm_port_guid; CL_ASSERT(port_guid); p_port = osm_get_port_by_guid(p_subn, port_guid); if (!p_port) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4105: No SM port object\n"); goto Exit; } /* HACK: We are assuming SM is running on HCA, so when getting the default port we'll get the port connected to the rest of the subnet. If SM is running on SWITCH - we should try to get a dr path from all switch ports. */ p_physp = p_port->p_physp; CL_ASSERT(p_physp); cl_list_insert_tail(p_nextPortsList, p_physp); while (next_list_is_full == TRUE) { next_list_is_full = FALSE; p_currPortsList = p_nextPortsList; p_nextPortsList = (cl_list_t *) malloc(sizeof(cl_list_t)); if (!p_nextPortsList) { p_nextPortsList = p_currPortsList; goto Exit; } cl_list_construct(p_nextPortsList); cl_list_init(p_nextPortsList, 10); p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList); while (p_physp != NULL) { /* If we are in a switch - need to go out through all the other physical ports of the switch */ num_ports = osm_node_get_num_physp(p_physp->p_node); for (port_num = 1; port_num < num_ports; port_num++) { if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) p_remote_physp = osm_node_get_physp_ptr(p_physp-> p_node, port_num); else /* this is HCA or router - the remote port is just the port connected on the other side */ p_remote_physp = p_physp->p_remote_physp; /* make sure that all of the following occurred: 1. The port isn't NULL 2. This is not the port we came from 3. The port is not in the physp_map 4. This port haven't been visited before */ if (p_remote_physp && p_remote_physp != p_physp && cl_map_get(&physp_map, ptr_to_key(p_remote_physp)) == NULL && cl_map_get(&visited_map, ptr_to_key (p_remote_physp)) == NULL) { /* Insert the port into the visited_map, and save its source port */ cl_map_insert(&visited_map, ptr_to_key (p_remote_physp), p_physp); /* Is this the p_dest_physp? */ if (p_remote_physp == p_dest_physp) { /* update the new dr path */ physp_update_new_dr_path (p_dest_physp, &visited_map, h_bind); reached_dest = TRUE; break; } /* add the p_remote_physp to the nextPortsList */ cl_list_insert_tail(p_nextPortsList, p_remote_physp); next_list_is_full = TRUE; } } p_physp = (osm_physp_t *) cl_list_remove_head(p_currPortsList); if (reached_dest == TRUE) { /* free the rest of the currPortsList */ while (p_physp != NULL) p_physp = (osm_physp_t *) cl_list_remove_head (p_currPortsList); /* free the nextPortsList, if items were added to it */ p_physp = (osm_physp_t *) cl_list_remove_head(p_nextPortsList); while (p_physp != NULL) p_physp = (osm_physp_t *) cl_list_remove_head (p_nextPortsList); next_list_is_full = FALSE; } } cl_list_destroy(p_currPortsList); free(p_currPortsList); } /* cleanup */ Exit: cl_list_destroy(p_nextPortsList); free(p_nextPortsList); cl_map_destroy(&physp_map); cl_map_destroy(&visited_map); } boolean_t osm_link_is_healthy(IN const osm_physp_t * p_physp) { osm_physp_t *p_remote_physp; CL_ASSERT(p_physp); p_remote_physp = p_physp->p_remote_physp; if (p_remote_physp != NULL) return ((p_physp->healthy) & (p_remote_physp->healthy)); /* the other side is not known - consider the link as healthy */ return TRUE; } void osm_physp_set_pkey_tbl(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN osm_physp_t * p_physp, IN ib_pkey_table_t * p_pkey_tbl, IN uint16_t block_num, IN boolean_t is_set) { uint16_t max_blocks; CL_ASSERT(p_pkey_tbl); /* (14.2.5.7) - the block number valid values are 0-2047, and are further limited by the size of the P_Key table specified by the PartitionCap on the node. */ if (!p_physp->p_node->sw || p_physp->port_num == 0) /* The maximum blocks is defined in the node info: partition cap for CA, router, and switch management ports. */ max_blocks = (cl_ntoh16(p_physp->p_node->node_info.partition_cap) + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; else /* This is a switch, and not a management port. The maximum blocks is defined in the switch info: partition enforcement cap. */ max_blocks = (cl_ntoh16(p_physp->p_node->sw->switch_info.enforce_cap) + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; if (block_num >= max_blocks) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4108: " "Got illegal update for block number:%u max:%u " "for GUID: %" PRIx64 " port number:%u\n", block_num, max_blocks, cl_ntoh64(p_physp->p_node->node_info.node_guid), p_physp->port_num); return; } /* decrement block received counter */ if(!is_set) p_physp->pkeys.rcv_blocks_cnt--; osm_pkey_tbl_set(&p_physp->pkeys, block_num, p_pkey_tbl, p_subn->opt.allow_both_pkeys); } osm_alias_guid_t *osm_alias_guid_new(IN const ib_net64_t alias_guid, IN osm_port_t *p_base_port) { osm_alias_guid_t *p_alias_guid; p_alias_guid = calloc(1, sizeof(*p_alias_guid)); if (p_alias_guid) { p_alias_guid->alias_guid = alias_guid; p_alias_guid->p_base_port = p_base_port; } return p_alias_guid; } void osm_alias_guid_delete(IN OUT osm_alias_guid_t ** pp_alias_guid) { free(*pp_alias_guid); *pp_alias_guid = NULL; } void osm_physp_set_port_info(IN osm_physp_t * p_physp, IN const ib_port_info_t * p_pi, IN const struct osm_sm * p_sm) { CL_ASSERT(p_pi); CL_ASSERT(osm_physp_is_valid(p_physp)); if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) { /* If PortState is down, only copy PortState */ /* and PortPhysicalState per C14-24-2.1 */ ib_port_info_set_port_state(&p_physp->port_info, IB_LINK_DOWN); ib_port_info_set_port_phys_state (ib_port_info_get_port_phys_state(p_pi), &p_physp->port_info); } else { p_physp->port_info = *p_pi; /* The MKey in p_pi can only be considered valid if it's * for a HCA/router or switch port 0, and it's either * non-zero or the MKeyProtect bits are also zero. */ if ((osm_node_get_type(p_physp->p_node) != IB_NODE_TYPE_SWITCH || p_physp->port_num == 0) && (p_pi->m_key != 0 || ib_port_info_get_mpb(p_pi) == 0)) osm_db_guid2mkey_set(p_sm->p_subn->p_g2m, cl_ntoh64(p_physp->port_guid), cl_ntoh64(p_pi->m_key)); } } opensm-3.3.20/opensm/osm_port_info_rcv.c0000644000205000001450000006100512571112507015207 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_pi_rcv_t. * This object represents the PortInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_PORT_INFO_RCV_C #include #include #include #include #include #include #include #include #include #include #include #include static void pi_rcv_check_and_fix_lid(osm_log_t * log, ib_port_info_t * pi, osm_physp_t * p) { if (PF(cl_ntoh16(pi->base_lid) > IB_LID_UCAST_END_HO)) { OSM_LOG(log, OSM_LOG_ERROR, "ERR 0F04: " "Got invalid base LID %u from the network. " "Corrected to %u\n", cl_ntoh16(pi->base_lid), cl_ntoh16(p->port_info.base_lid)); pi->base_lid = p->port_info.base_lid; } } static void pi_rcv_process_endport(IN osm_sm_t * sm, IN osm_physp_t * p_physp, IN const ib_port_info_t * p_pi) { osm_madw_context_t context; ib_api_status_t status; ib_net64_t port_guid; int extended; uint8_t rate, mtu, mpb; unsigned data_vls; cl_qmap_t *p_sm_tbl; osm_remote_sm_t *p_sm; OSM_LOG_ENTER(sm->p_log); port_guid = osm_physp_get_port_guid(p_physp); /* HACK extended port 0 should be handled too! */ if (osm_physp_get_port_num(p_physp) != 0 && ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN) { /* track the minimal endport MTU, rate, and operational VLs */ mtu = ib_port_info_get_mtu_cap(p_pi); if (mtu < sm->p_subn->min_ca_mtu) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Setting endport minimal MTU to:%u defined by port:0x%" PRIx64 "\n", mtu, cl_ntoh64(port_guid)); sm->p_subn->min_ca_mtu = mtu; } extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; rate = ib_port_info_compute_rate(p_pi, extended); if (rate < sm->p_subn->min_ca_rate) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Setting endport minimal rate to:%u defined by port:0x%" PRIx64 "\n", rate, cl_ntoh64(port_guid)); sm->p_subn->min_ca_rate = rate; } data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1); if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1)) data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1); if (data_vls >= IB_MAX_NUM_VLS) data_vls = IB_MAX_NUM_VLS - 1; if ((uint8_t)data_vls < sm->p_subn->min_data_vls) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Setting endport minimal data VLs to:%u defined by port:0x%" PRIx64 "\n", data_vls, cl_ntoh64(port_guid)); sm->p_subn->min_data_vls = data_vls; } } /* Check M_Key vs M_Key protect, can we control the port ? */ mpb = ib_port_info_get_mpb(p_pi); if (mpb > 0 && p_pi->m_key == 0) { OSM_LOG(sm->p_log, OSM_LOG_INFO, "Port 0x%" PRIx64 " has unknown M_Key, protection level %u\n", cl_ntoh64(port_guid), mpb); } if (port_guid != sm->p_subn->sm_port_guid) { p_sm_tbl = &sm->p_subn->sm_guid_tbl; if (p_pi->capability_mask & IB_PORT_CAP_IS_SM) { /* * Before querying the SM - we want to make sure we * clean its state, so if the querying fails we * recognize that this SM is not active. */ p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid); if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) /* clean it up */ p_sm->smi.pri_state = 0xF0 & p_sm->smi.pri_state; if (sm->p_subn->opt.ignore_other_sm) OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Ignoring SM on port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); else { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Detected another SM. Requesting SMInfo " "from port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); /* This port indicates it's an SM and it's not our own port. Acquire the SMInfo Attribute. */ memset(&context, 0, sizeof(context)); context.smi_context.set_method = FALSE; context.smi_context.port_guid = port_guid; status = osm_req_get(sm, osm_physp_get_dr_path_ptr (p_physp), IB_MAD_ATTR_SM_INFO, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F05: " "Failure requesting SMInfo (%s) " "from port 0x%" PRIx64 "\n", ib_get_err_str(status), cl_ntoh64(port_guid)); } } else { p_sm = (osm_remote_sm_t *) cl_qmap_remove(p_sm_tbl, port_guid); if (p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) free(p_sm); } } OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void pi_rcv_process_switch_port0(IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp, IN ib_port_info_t * p_pi) { ib_api_status_t status; osm_madw_context_t context; uint8_t port, num_ports; OSM_LOG_ENTER(sm->p_log); if (p_physp->need_update) sm->p_subn->ignore_existing_lfts = TRUE; pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp); /* Update the PortInfo attribute */ osm_physp_set_port_info(p_physp, p_pi, sm); /* Determine if base switch port 0 */ if (p_node->sw && !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) /* PortState is not used on BSP0 but just in case it is DOWN */ p_physp->port_info = *p_pi; /* Now, query PortInfo for the switch external ports */ num_ports = osm_node_get_num_physp(p_node); context.pi_context.node_guid = osm_node_get_node_guid(p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = FALSE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; for (port = 1; port < num_ports; port++) { status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_PORT_INFO, cl_hton32(port), FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F16: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); } pi_rcv_process_endport(sm, p_physp, p_pi); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void pi_rcv_process_switch_ext_port(IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp, IN ib_port_info_t * p_pi) { ib_api_status_t status = IB_SUCCESS; osm_madw_context_t context; osm_physp_t *p_remote_physp, *physp0; osm_node_t *p_remote_node; ib_net64_t m_key; unsigned data_vls; uint8_t port_num; uint8_t remote_port_num; osm_dr_path_t path; int mlnx_epi_supported = 0; OSM_LOG_ENTER(sm->p_log); /* Check the state of the physical port. If there appears to be something on the other end of the wire, then ask for NodeInfo. Ignore the switch management port. */ port_num = osm_physp_get_port_num(p_physp); if (sm->p_subn->opt.fdr10) mlnx_epi_supported = is_mlnx_ext_port_info_supported(p_node->node_info.device_id); /* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch, and we got switchInfo of our local switch. Do not continue probing through the switch. */ switch (ib_port_info_get_port_state(p_pi)) { case IB_LINK_DOWN: p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) { p_remote_node = osm_physp_get_node_ptr(p_remote_physp); remote_port_num = osm_physp_get_port_num(p_remote_physp); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Unlinking local node 0x%" PRIx64 ", port %u" "\n\t\t\t\tand remote node 0x%" PRIx64 ", port %u\n", cl_ntoh64(osm_node_get_node_guid (p_node)), port_num, cl_ntoh64(osm_node_get_node_guid (p_remote_node)), remote_port_num); if (sm->ucast_mgr.cache_valid) osm_ucast_cache_add_link(&sm->ucast_mgr, p_physp, p_remote_physp); osm_node_unlink(p_node, (uint8_t) port_num, p_remote_node, (uint8_t) remote_port_num); } break; case IB_LINK_INIT: case IB_LINK_ARMED: case IB_LINK_ACTIVE: physp0 = osm_node_get_physp_ptr(p_node, 0); if (mlnx_epi_supported) { m_key = ib_port_info_get_m_key(&physp0->port_info); context.pi_context.node_guid = osm_node_get_node_guid(p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p_physp); context.pi_context.set_method = FALSE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO, cl_hton32(port_num), FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F11: " "Failure initiating MLNX ExtPortInfo request (%s)\n", ib_get_err_str(status)); } if (sm->p_subn->in_sweep_hop_0 == FALSE) { /* To avoid looping forever, only probe the port if it is NOT the port that responded to the SMP. Request node info from the other end of this link: 1) Copy the current path from the parent node. 2) Extend the path to the next hop thru this port. 3) Request node info with the new path */ if (p_pi->local_port_num != osm_physp_get_port_num(p_physp)) { path = *osm_physp_get_dr_path_ptr(p_physp); if (osm_dr_path_extend(&path, osm_physp_get_port_num (p_physp))) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F08: " "DR path with hop count %d couldn't be extended\n", path.hop_count); break; } memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = osm_physp_get_port_num(p_physp); status = osm_req_get(sm, &path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F02: " "Failure initiating NodeInfo request (%s)\n", ib_get_err_str(status)); } else OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Skipping SMP responder port %u\n", p_pi->local_port_num); } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: " "Unknown link state = %u, port = %u\n", ib_port_info_get_port_state(p_pi), p_pi->local_port_num); break; } if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw && !ib_switch_info_get_state_change(&p_node->sw->switch_info) && p_node->sw->need_update == 1) p_node->sw->need_update = 0; if (p_physp->need_update) sm->p_subn->ignore_existing_lfts = TRUE; /* Update the PortInfo attribute. */ osm_physp_set_port_info(p_physp, p_pi, sm); if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) goto Exit; p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) { p_remote_node = osm_physp_get_node_ptr(p_remote_physp); if (p_remote_node->sw) { data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1); if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1)) data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1); if (data_vls >= IB_MAX_NUM_VLS) data_vls = IB_MAX_NUM_VLS - 1; if ((uint8_t)data_vls < sm->p_subn->min_sw_data_vls) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Setting switch port minimal data VLs " "to:%u defined by node:0x%" PRIx64 ", port:%u\n", data_vls, cl_ntoh64(osm_node_get_node_guid(p_node)), port_num); sm->p_subn->min_sw_data_vls = data_vls; } } } Exit: OSM_LOG_EXIT(sm->p_log); } static void pi_rcv_process_ca_or_router_port(IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp, IN ib_port_info_t * p_pi) { OSM_LOG_ENTER(sm->p_log); UNUSED_PARAM(p_node); pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp); osm_physp_set_port_info(p_physp, p_pi, sm); pi_rcv_process_endport(sm, p_physp, p_pi); OSM_LOG_EXIT(sm->p_log); } #define IBM_VENDOR_ID (0x5076) static void get_pkey_table(IN osm_log_t * p_log, IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp) { osm_madw_context_t context; ib_api_status_t status; osm_dr_path_t path; osm_physp_t *physp0; ib_net64_t m_key; uint8_t port_num; uint16_t block_num, max_blocks; uint32_t attr_mod_ho; OSM_LOG_ENTER(p_log); path = *osm_physp_get_dr_path_ptr(p_physp); context.pkey_context.node_guid = osm_node_get_node_guid(p_node); context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp); context.pkey_context.set_method = FALSE; port_num = p_physp->port_num; if (!p_node->sw || port_num == 0) /* The maximum blocks is defined by the node info partition cap for CA, router, and switch management ports. */ max_blocks = (cl_ntoh16(p_node->node_info.partition_cap) + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; else { /* This is a switch, and not a management port. The maximum blocks is defined in the switch info partition enforcement cap. */ /* Check for IBM eHCA firmware defect in reporting partition enforcement cap */ if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) == IBM_VENDOR_ID) p_node->sw->switch_info.enforce_cap = 0; /* Bail out if this is a switch with no partition enforcement capability */ if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0) goto Exit; max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) + IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK; } p_physp->pkeys.rcv_blocks_cnt = max_blocks; for (block_num = 0; block_num < max_blocks; block_num++) { if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH || osm_physp_get_port_num(p_physp) == 0) { attr_mod_ho = block_num; m_key = ib_port_info_get_m_key(&p_physp->port_info); } else { attr_mod_ho = block_num | (port_num << 16); physp0 = osm_node_get_physp_ptr(p_node, 0); m_key = ib_port_info_get_m_key(&physp0->port_info); } status = osm_req_get(sm, &path, IB_MAD_ATTR_P_KEY_TABLE, cl_hton32(attr_mod_ho), FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0F12: " "Failure initiating PKeyTable request (%s)\n", ib_get_err_str(status)); goto Exit; } } Exit: OSM_LOG_EXIT(p_log); } static void pi_rcv_get_pkey_slvl_vla_tables(IN osm_sm_t * sm, IN osm_node_t * p_node, IN osm_physp_t * p_physp) { OSM_LOG_ENTER(sm->p_log); get_pkey_table(sm->p_log, sm, p_node, p_physp); OSM_LOG_EXIT(sm->p_log); } static int osm_pi_rcv_update_self(IN osm_sm_t *sm, IN osm_physp_t *p_physp, IN ib_port_info_t *p_pi) { if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN) return 0; if (sm->p_subn->need_update || p_physp->need_update > 1 || ib_port_info_get_port_state(p_pi) == IB_LINK_INIT) return 1; return 0; } static void pi_rcv_process_set(IN osm_sm_t * sm, IN osm_node_t * p_node, IN uint8_t port_num, IN osm_madw_t * p_madw) { osm_physp_t *p_physp; ib_net64_t port_guid; ib_smp_t *p_smp; ib_port_info_t *p_pi; osm_pi_context_t *p_context; osm_log_level_t level; OSM_LOG_ENTER(sm->p_log); p_context = osm_madw_get_pi_context_ptr(p_madw); CL_ASSERT(p_node); p_physp = osm_node_get_physp_ptr(p_node, port_num); CL_ASSERT(p_physp); port_guid = osm_physp_get_port_guid(p_physp); p_smp = osm_madw_get_smp_ptr(p_madw); p_pi = ib_smp_get_payload_ptr(p_smp); /* check for error */ if (cl_ntoh16(p_smp->status) & 0x7fff) { /* If port already ACTIVE, don't treat status 7 as error */ if (p_context->active_transition && (cl_ntoh16(p_smp->status) & 0x7fff) == 0x1c) { level = OSM_LOG_INFO; OSM_LOG(sm->p_log, OSM_LOG_INFO, "Received error status 0x%x for SetResp() during ACTIVE transition\n", cl_ntoh16(p_smp->status) & 0x7fff); /* Should there be a subsequent Get to validate that port is ACTIVE ? */ } else { level = OSM_LOG_ERROR; OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F10: " "Received error status for SetResp()\n"); } osm_dump_port_info_v2(sm->p_log, osm_node_get_node_guid(p_node), port_guid, port_num, p_pi, FILE_ID, level); } OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received logical SetResp() for GUID 0x%" PRIx64 ", port num %u" "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 " TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), port_num, cl_ntoh64(osm_node_get_node_guid(p_node)), cl_ntoh64(p_smp->trans_id)); osm_physp_set_port_info(p_physp, p_pi, sm); OSM_LOG_EXIT(sm->p_log); } static int osm_pi_rcv_update_neighbor(IN osm_physp_t *p_physp) { osm_physp_t *p_rem_physp = p_physp->p_remote_physp; osm_node_t *p_node; /* * Our own port - this is the only case where CA port * is discovered before its' neighbor port */ if (!p_rem_physp) return p_physp->need_update; p_node = osm_physp_get_node_ptr(p_rem_physp); CL_ASSERT(p_node); /* CA/RTR to CA/RTR connection */ if (!p_node->sw) return p_physp->need_update; return (ib_switch_info_get_state_change(&p_node->sw->switch_info) ? 1 : p_physp->need_update); } void osm_pi_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_port_info_t *p_pi; ib_smp_t *p_smp; osm_port_t *p_port; osm_physp_t *p_physp; osm_dr_path_t *p_dr_path; osm_node_t *p_node; osm_pi_context_t *p_context; ib_net64_t port_guid, node_guid; uint8_t port_num; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_pi_context_ptr(p_madw); p_pi = ib_smp_get_payload_ptr(p_smp); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO); /* * Attribute modifier has already been validated upon MAD receive, * which means that port_num has to be valid - it originated from * the request attribute modifier. */ port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod); port_guid = p_context->port_guid; node_guid = p_context->node_guid; osm_dump_port_info_v2(sm->p_log, node_guid, port_guid, port_num, p_pi, FILE_ID, OSM_LOG_DEBUG); /* On receipt of client reregister, clear the reregister bit so reregistering won't be sent again and again */ if (p_context->set_method && (ib_port_info_get_client_rereg(p_pi) || p_context->client_rereg)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Client reregister received on response\n"); ib_port_info_set_client_rereg(p_pi, 0); p_context->client_rereg = FALSE; } /* we might get a response during a light sweep looking for a change in the status of a remote port that did not respond in earlier sweeps. So if the context of the Get was light_sweep - we do not need to do anything with the response - just flag that we need a heavy sweep */ if (p_context->light_sweep == TRUE) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Got light sweep response from remote port of parent node " "GUID 0x%" PRIx64 " port 0x%016" PRIx64 ", Commencing heavy sweep\n", cl_ntoh64(node_guid), cl_ntoh64(port_guid)); sm->p_subn->force_heavy_sweep = TRUE; sm->p_subn->ignore_existing_lfts = TRUE; goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (PF(!p_port)) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); if (PF(p_pi->local_port_num > p_node->node_info.num_ports)) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F15: " "Received PortInfo for port GUID 0x%" PRIx64 " is " "non-compliant and is being ignored since the " "local port num %u > num ports %u\n", cl_ntoh64(port_guid), p_pi->local_port_num, p_node->node_info.num_ports); goto Exit; } /* If we were setting the PortInfo, then receiving this attribute was not part of sweeping the subnet. In this case, just update the PortInfo attribute. In an unfortunate blunder, the IB spec defines the return method for Set() as a GetResp(). Thus, we can't use the method (what would have been SetResp()) to determine our course of action. So, we have to carry this extra boolean around to determine if we were doing Get() or Set(). */ if (p_context->set_method) pi_rcv_process_set(sm, p_node, port_num, p_madw); else { /* This PortInfo arrived because we did a Get() method, most likely due to a subnet sweep in progress. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Discovered port num %u with GUID 0x%" PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", port_num, cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); p_physp = osm_node_get_physp_ptr(p_node, port_num); CL_ASSERT(p_physp); /* Update the directed route path to this port in case the old path is no longer usable. */ p_dr_path = osm_physp_get_dr_path_ptr(p_physp); osm_dr_path_init(p_dr_path, p_smp->hop_count, p_smp->initial_path); p_physp->need_update = osm_pi_rcv_update_self(sm, p_physp, p_pi); switch (osm_node_get_type(p_node)) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: if (!p_node->physp_discovered[port_num]) { p_port->discovery_count++; p_node->physp_discovered[port_num] = 1; } p_physp->need_update = osm_pi_rcv_update_neighbor(p_physp); pi_rcv_process_ca_or_router_port(sm, p_node, p_physp, p_pi); break; case IB_NODE_TYPE_SWITCH: if (!p_node->physp_discovered[port_num]) { p_port->discovery_count++; p_node->physp_discovered[port_num] = 1; } if (port_num == 0) pi_rcv_process_switch_port0(sm, p_node, p_physp, p_pi); else pi_rcv_process_switch_ext_port(sm, p_node, p_physp, p_pi); break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: " "Unknown node type %u with GUID 0x%" PRIx64 "\n", osm_node_get_type(p_node), cl_ntoh64(node_guid)); break; } /* Get the tables on the physp. */ if (p_physp->need_update || (p_node->sw && p_node->sw->need_update)) pi_rcv_get_pkey_slvl_vla_tables(sm, p_node, p_physp); } CL_PLOCK_RELEASE(sm->p_lock); Exit: /* Release the lock before jumping here!! */ OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_mlnx_ext_port_info_rcv.c0000644000205000001450000001035212312552420017117 00000000000000/* * Copyright (c) 2011 Mellanox Technologies LTD. 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 osm_mlnx_epi_rcv_t. * This object represents the MLNX ExtendedPortInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_MLNX_EXT_PORT_INFO_RCV_C #include #include #include #include #include #include #include #include #include void osm_mlnx_epi_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_mlnx_ext_port_info_t *p_pi; ib_smp_t *p_smp; osm_port_t *p_port; osm_physp_t *p_physp; osm_node_t *p_node; osm_pi_context_t *p_context; ib_net64_t port_guid, node_guid; uint8_t port_num, portnum, start_port = 1; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(sm); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_pi_context_ptr(p_madw); p_pi = ib_smp_get_payload_ptr(p_smp); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO); port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod); port_guid = p_context->port_guid; node_guid = p_context->node_guid; osm_dump_mlnx_ext_port_info_v2(sm->p_log, node_guid, port_guid, port_num, p_pi, FILE_ID, OSM_LOG_DEBUG); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); if (!(cl_ntoh16(p_smp->status) & 0x7fff)) { if (port_num != 255) { p_physp = osm_node_get_physp_ptr(p_node, port_num); CL_ASSERT(p_physp); p_physp->ext_port_info = *p_pi; } else { /* Handle all ports on set/set resp */ if (p_node->sw && ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)) start_port = 0; for (portnum = start_port; portnum < osm_node_get_num_physp(p_node); portnum++) { p_physp = osm_node_get_physp_ptr(p_node, portnum); CL_ASSERT(p_physp); p_physp->ext_port_info = *p_pi; } } } else OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(p_smp->status) & 0x7fff); CL_PLOCK_RELEASE(sm->p_lock); Exit: /* Release the lock before jumping here!! */ OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_remote_sm.c0000644000205000001450000000436012104655725014337 00000000000000/* * Copyright (c) 2004-2009 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 osm_sm_t. * This object represents the remote SM object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #define FILE_ID OSM_FILE_REMOTE_SM_C #include void osm_remote_sm_construct(IN osm_remote_sm_t * p_sm) { memset(p_sm, 0, sizeof(*p_sm)); } void osm_remote_sm_destroy(IN osm_remote_sm_t * p_sm) { memset(p_sm, 0, sizeof(*p_sm)); } void osm_remote_sm_init(IN osm_remote_sm_t * p_sm, IN const ib_sm_info_t * p_smi) { CL_ASSERT(p_sm); osm_remote_sm_construct(p_sm); p_sm->smi = *p_smi; return; } opensm-3.3.20/opensm/osm_req.c0000644000205000001450000003103112604753736013135 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_req_t. * This object represents the generic attribute requester. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_REQ_C #include #include #include #include #include #include #include #include #include /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static ib_net64_t req_determine_mkey(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path) { osm_node_t *p_node; osm_port_t *p_sm_port; osm_physp_t *p_physp; ib_net64_t dest_port_guid = 0, m_key; uint8_t hop; OSM_LOG_ENTER(sm->p_log); p_physp = NULL; p_sm_port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid); /* hop_count == 0: destination port guid is SM */ if (p_path->hop_count == 0) { dest_port_guid = sm->p_subn->sm_port_guid; goto Remote_Guid; } if (p_sm_port) { p_node = p_sm_port->p_node; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) p_physp = osm_node_get_physp_ptr(p_node, p_path->path[1]); else p_physp = p_sm_port->p_physp; } /* hop_count == 1: outgoing physp is SM physp */ for (hop = 2; p_physp && hop <= p_path->hop_count; hop++) { p_physp = p_physp->p_remote_physp; if (!p_physp) break; p_node = p_physp->p_node; p_physp = osm_node_get_physp_ptr(p_node, p_path->path[hop]); } /* At this point, p_physp points at the outgoing physp on the last hop, or NULL if we don't know it. */ if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1107: Outgoing physp is null on non-hop_0!\n"); osm_dump_dr_path_v2(sm->p_log, p_path, FILE_ID, OSM_LOG_ERROR); dest_port_guid = 0; goto Remote_Guid; } if (p_physp->p_remote_physp) { dest_port_guid = p_physp->p_remote_physp->port_guid; goto Remote_Guid; } OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port guid unknown, " "using persistent DB\n"); if (!osm_db_neighbor_get(sm->p_subn->p_neighbor, cl_ntoh64(p_physp->port_guid), p_physp->port_num, &dest_port_guid, NULL)) { dest_port_guid = cl_hton64(dest_port_guid); } Remote_Guid: if (dest_port_guid) { if (!osm_db_guid2mkey_get(sm->p_subn->p_g2m, cl_ntoh64(dest_port_guid), &m_key)) { m_key = cl_hton64(m_key); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Found mkey for guid 0x%" PRIx64 "\n", cl_ntoh64(dest_port_guid)); } else { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port mkey unknown, using default\n"); m_key = sm->p_subn->opt.m_key; } } else { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Target port guid unknown, using default\n"); m_key = sm->p_subn->opt.m_key; } OSM_LOG_EXIT(sm->p_log); return m_key; } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ ib_api_status_t osm_req_get(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context) { osm_madw_t *p_madw; ib_api_status_t status = IB_SUCCESS; ib_net64_t m_key_calc; ib_net64_t tid; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_path); CL_ASSERT(attr_id); /* do nothing if we are exiting ... */ if (osm_exit_flag) goto Exit; /* p_context may be NULL. */ p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1101: Unable to acquire MAD\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); if (tid == 0) tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); if (sm->p_subn->opt.m_key_lookup == TRUE) { if (find_mkey == TRUE) m_key_calc = req_determine_mkey(sm, p_path); else m_key_calc = m_key; } else m_key_calc = sm->p_subn->opt.m_key; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 ", MKey 0x%016" PRIx64 "\n", ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id), cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc)); ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_GET, tid, attr_id, attr_mod, p_path->hop_count, m_key_calc, p_path->path, IB_LID_PERMISSIVE, IB_LID_PERMISSIVE); p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; p_madw->resp_expected = TRUE; p_madw->fail_msg = err_msg; /* Fill in the mad wrapper context for the recipient. In this case, the only thing the recipient needs is the guid value. */ if (p_context) p_madw->context = *p_context; osm_vl15_post(sm->p_vl15, p_madw); Exit: OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN const uint8_t * p_payload, IN size_t payload_size, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, IN ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context) { osm_madw_t *p_madw = NULL; ib_net64_t m_key_calc; ib_net64_t tid; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_path); CL_ASSERT(attr_id); CL_ASSERT(p_payload); /* do nothing if we are exiting ... */ if (osm_exit_flag) goto Exit; /* p_context may be NULL. */ p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1102: Unable to acquire MAD\n"); goto Exit; } tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); if (tid == 0) tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); if (sm->p_subn->opt.m_key_lookup == TRUE) { if (find_mkey == TRUE) m_key_calc = req_determine_mkey(sm, p_path); else m_key_calc = m_key; } else m_key_calc = sm->p_subn->opt.m_key; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 ", MKey 0x%016" PRIx64 "\n", ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id), cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc)); ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_SET, tid, attr_id, attr_mod, p_path->hop_count, m_key_calc, p_path->path, IB_LID_PERMISSIVE, IB_LID_PERMISSIVE); p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE; p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE; p_madw->resp_expected = TRUE; p_madw->fail_msg = err_msg; /* Fill in the mad wrapper context for the recipient. In this case, the only thing the recipient needs is the guid value. */ if (p_context) p_madw->context = *p_context; memcpy(osm_madw_get_smp_ptr(p_madw)->data, p_payload, payload_size); Exit: OSM_LOG_EXIT(sm->p_log); return p_madw; } void osm_send_req_mad(IN osm_sm_t * sm, IN osm_madw_t *p_madw) { CL_ASSERT(p_madw); CL_ASSERT(sm); osm_vl15_post(sm->p_vl15, p_madw); } /********************************************************************** The plock MAY or MAY NOT be held before calling this function. **********************************************************************/ ib_api_status_t osm_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path, IN const uint8_t * p_payload, IN size_t payload_size, IN ib_net16_t attr_id, IN ib_net32_t attr_mod, IN boolean_t find_mkey, IN ib_net64_t m_key, IN cl_disp_msgid_t err_msg, IN const osm_madw_context_t * p_context) { osm_madw_t *p_madw; ib_api_status_t status = IB_SUCCESS; p_madw = osm_prepare_req_set(sm, p_path, p_payload, payload_size, attr_id, attr_mod, find_mkey, m_key, err_msg, p_context); if (p_madw == NULL) status = IB_INSUFFICIENT_RESOURCES; else osm_send_req_mad(sm, p_madw); return status; } int osm_send_trap144(osm_sm_t * sm, ib_net16_t local) { osm_madw_t *madw; ib_smp_t *smp; ib_mad_notice_attr_t *ntc; osm_port_t *port, *smport; ib_port_info_t *pi; port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid); if (!port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n", cl_ntoh64(sm->p_subn->sm_port_guid)); return -1; } pi = &port->p_physp->port_info; /* don't bother with sending trap when SMA supports this */ if (!local && pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC)) return 0; smport = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid); if (!smport) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1106: cannot find master SM port by guid 0x%" PRIx64 "\n", cl_ntoh64(sm->master_sm_guid)); return -1; } madw = osm_mad_pool_get(sm->p_mad_pool, osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl), MAD_BLOCK_SIZE, NULL); if (madw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1105: Unable to acquire MAD\n"); return -1; } madw->mad_addr.dest_lid = smport->p_physp->port_info.base_lid; madw->mad_addr.addr_type.smi.source_lid = pi->base_lid; madw->resp_expected = TRUE; madw->fail_msg = CL_DISP_MSGID_NONE; smp = osm_madw_get_smp_ptr(madw); memset(smp, 0, sizeof(*smp)); smp->base_ver = 1; smp->mgmt_class = IB_MCLASS_SUBN_LID; smp->class_ver = 1; smp->method = IB_MAD_METHOD_TRAP; smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); if (smp->trans_id == 0) smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id) & (uint64_t)(0xFFFFFFFF)); smp->attr_id = IB_MAD_ATTR_NOTICE; ntc = (ib_mad_notice_attr_t *) smp->data; ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO; ib_notice_set_prod_type_ho(ntc, osm_node_get_type(port->p_node)); ntc->g_or_v.generic.trap_num = cl_hton16(SM_LOCAL_CHANGES_TRAP); /* 144 */ ntc->issuer_lid = pi->base_lid; ntc->data_details.ntc_144.lid = pi->base_lid; ntc->data_details.ntc_144.local_changes = local ? TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0; ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask; ntc->data_details.ntc_144.change_flgs = local; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n", cl_ntoh64(smp->trans_id), cl_ntoh16(madw->mad_addr.dest_lid)); osm_vl15_post(sm->p_vl15, madw); return 0; } opensm-3.3.20/opensm/osm_resp.c0000644000205000001450000001125212104655725013314 00000000000000/* * Copyright (c) 2004-2009 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 osm_resp_t. * This object represents the generic attribute responder. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_RESP_C #include #include #include #include #include #include #include #include static void resp_make_resp_smp(IN osm_sm_t * sm, IN const ib_smp_t * p_src_smp, IN ib_net16_t status, IN const uint8_t * p_payload, OUT ib_smp_t * p_dest_smp) { OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_dest_smp); CL_ASSERT(p_src_smp); CL_ASSERT(!ib_smp_is_response(p_src_smp)); *p_dest_smp = *p_src_smp; if (p_src_smp->method == IB_MAD_METHOD_GET || p_src_smp->method == IB_MAD_METHOD_SET) { p_dest_smp->method = IB_MAD_METHOD_GET_RESP; p_dest_smp->status = status; } else if (p_src_smp->method == IB_MAD_METHOD_TRAP) { p_dest_smp->method = IB_MAD_METHOD_TRAP_REPRESS; p_dest_smp->status = 0; } else { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1302: " "src smp method unsupported 0x%X\n", p_src_smp->method); goto Exit; } if (p_src_smp->mgmt_class == IB_MCLASS_SUBN_DIR) p_dest_smp->status |= IB_SMP_DIRECTION; p_dest_smp->dr_dlid = p_dest_smp->dr_slid; p_dest_smp->dr_slid = p_dest_smp->dr_dlid; memcpy(&p_dest_smp->data, p_payload, IB_SMP_DATA_SIZE); Exit: OSM_LOG_EXIT(sm->p_log); } ib_api_status_t osm_resp_send(IN osm_sm_t * sm, IN const osm_madw_t * p_req_madw, IN ib_net16_t mad_status, IN const uint8_t * p_payload) { const ib_smp_t *p_req_smp; ib_smp_t *p_smp; osm_madw_t *p_madw; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_req_madw); CL_ASSERT(p_payload); /* do nothing if we are exiting ... */ if (osm_exit_flag) goto Exit; p_madw = osm_mad_pool_get(sm->p_mad_pool, osm_madw_get_bind_handle(p_req_madw), MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 1301: Unable to acquire MAD\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } /* Copy the request smp to the response smp, then just update the necessary fields. */ p_smp = osm_madw_get_smp_ptr(p_madw); p_req_smp = osm_madw_get_smp_ptr(p_req_madw); resp_make_resp_smp(sm, p_req_smp, mad_status, p_payload, p_smp); p_madw->mad_addr.dest_lid = p_req_madw->mad_addr.addr_type.smi.source_lid; p_madw->mad_addr.addr_type.smi.source_lid = p_req_madw->mad_addr.dest_lid; p_madw->resp_expected = FALSE; p_madw->fail_msg = CL_DISP_MSGID_NONE; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to %s (0x%X)" "\n\t\t\t\tattribute modifier 0x%X, TID 0x%" PRIx64 "\n", ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh16(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->trans_id)); osm_vl15_post(sm->p_vl15, p_madw); Exit: OSM_LOG_EXIT(sm->p_log); return status; } opensm-3.3.20/opensm/osm_sa.c0000644000205000001450000012347412571116177012761 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2014 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. 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 osm_sa_t. * This object represents the Subnet Administration object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_C #include #include #include #include #include #include #include #include #include #include #include #include #include #define OSM_SA_INITIAL_TID_VALUE 0xabc extern void osm_cpi_rcv_process(IN void *context, IN void *data); extern void osm_gir_rcv_process(IN void *context, IN void *data); extern void osm_infr_rcv_process(IN void *context, IN void *data); extern void osm_infir_rcv_process(IN void *context, IN void *data); extern void osm_lftr_rcv_process(IN void *context, IN void *data); extern void osm_lr_rcv_process(IN void *context, IN void *data); extern void osm_mcmr_rcv_process(IN void *context, IN void *data); extern void osm_mftr_rcv_process(IN void *context, IN void *data); extern void osm_mpr_rcv_process(IN void *context, IN void *data); extern void osm_nr_rcv_process(IN void *context, IN void *data); extern void osm_pr_rcv_process(IN void *context, IN void *data); extern void osm_pkey_rec_rcv_process(IN void *context, IN void *data); extern void osm_pir_rcv_process(IN void *context, IN void *data); extern void osm_sr_rcv_process(IN void *context, IN void *data); extern void osm_slvl_rec_rcv_process(IN void *context, IN void *data); extern void osm_smir_rcv_process(IN void *context, IN void *data); extern void osm_sir_rcv_process(IN void *context, IN void *data); extern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data); extern void osm_sr_rcv_lease_cb(IN void *context); void osm_sa_construct(IN osm_sa_t * p_sa) { memset(p_sa, 0, sizeof(*p_sa)); p_sa->state = OSM_SA_STATE_INIT; p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE; cl_timer_construct(&p_sa->sr_timer); } void osm_sa_shutdown(IN osm_sa_t * p_sa) { OSM_LOG_ENTER(p_sa->p_log); cl_timer_stop(&p_sa->sr_timer); /* unbind from the mad service */ osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl); /* remove any registered dispatcher message */ cl_disp_unregister(p_sa->nr_disp_h); cl_disp_unregister(p_sa->pir_disp_h); cl_disp_unregister(p_sa->gir_disp_h); cl_disp_unregister(p_sa->lr_disp_h); cl_disp_unregister(p_sa->pr_disp_h); #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) cl_disp_unregister(p_sa->mpr_disp_h); #endif cl_disp_unregister(p_sa->smir_disp_h); cl_disp_unregister(p_sa->mcmr_disp_h); cl_disp_unregister(p_sa->sr_disp_h); cl_disp_unregister(p_sa->infr_disp_h); cl_disp_unregister(p_sa->infir_disp_h); cl_disp_unregister(p_sa->vlarb_disp_h); cl_disp_unregister(p_sa->slvl_disp_h); cl_disp_unregister(p_sa->pkey_disp_h); cl_disp_unregister(p_sa->lft_disp_h); cl_disp_unregister(p_sa->sir_disp_h); cl_disp_unregister(p_sa->mft_disp_h); if (p_sa->p_set_disp) { cl_disp_unregister(p_sa->mcmr_set_disp_h); cl_disp_unregister(p_sa->infr_set_disp_h); cl_disp_unregister(p_sa->sr_set_disp_h); cl_disp_unregister(p_sa->gir_set_disp_h); } osm_sa_mad_ctrl_destroy(&p_sa->mad_ctrl); OSM_LOG_EXIT(p_sa->p_log); } void osm_sa_destroy(IN osm_sa_t * p_sa) { OSM_LOG_ENTER(p_sa->p_log); p_sa->state = OSM_SA_STATE_INIT; cl_timer_destroy(&p_sa->sr_timer); OSM_LOG_EXIT(p_sa->p_log); } ib_api_status_t osm_sa_init(IN osm_sm_t * p_sm, IN osm_sa_t * p_sa, IN osm_subn_t * p_subn, IN osm_vendor_t * p_vendor, IN osm_mad_pool_t * p_mad_pool, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_dispatcher_t * p_set_disp, IN cl_plock_t * p_lock) { ib_api_status_t status; OSM_LOG_ENTER(p_log); p_sa->sm = p_sm; p_sa->p_subn = p_subn; p_sa->p_vendor = p_vendor; p_sa->p_mad_pool = p_mad_pool; p_sa->p_log = p_log; p_sa->p_disp = p_disp; p_sa->p_set_disp = p_set_disp; p_sa->p_lock = p_lock; p_sa->state = OSM_SA_STATE_READY; status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl, p_sa, p_sa->p_mad_pool, p_sa->p_vendor, p_subn, p_log, p_stats, p_disp, p_set_disp); if (status != IB_SUCCESS) goto Exit; status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa); if (status != IB_SUCCESS) goto Exit; status = IB_INSUFFICIENT_RESOURCES; p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO, osm_cpi_rcv_process, p_sa); if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD, osm_nr_rcv_process, p_sa); if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD, osm_pir_rcv_process, p_sa); if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD, osm_gir_rcv_process, p_sa); if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD, osm_lr_rcv_process, p_sa); if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD, osm_pr_rcv_process, p_sa); if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) p_sa->mpr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD, osm_mpr_rcv_process, p_sa); if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; #endif p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD, osm_smir_rcv_process, p_sa); if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->mcmr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD, osm_mcmr_rcv_process, p_sa); if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD, osm_sr_rcv_process, p_sa); if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO, osm_infr_rcv_process, p_sa); if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->infir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD, osm_infir_rcv_process, p_sa); if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD, osm_vlarb_rec_rcv_process, p_sa); if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD, osm_slvl_rec_rcv_process, p_sa); if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD, osm_pkey_rec_rcv_process, p_sa); if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD, osm_lftr_rcv_process, p_sa); if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->sir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD, osm_sir_rcv_process, p_sa); if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD, osm_mftr_rcv_process, p_sa); if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; /* * When p_set_disp is defined, it means that we use different dispatcher * for SA Set requests, and we need to register handlers for it. */ if (p_set_disp) { p_sa->gir_set_disp_h = cl_disp_register(p_set_disp, OSM_MSG_MAD_GUIDINFO_RECORD, osm_gir_rcv_process, p_sa); if (p_sa->gir_set_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->mcmr_set_disp_h = cl_disp_register(p_set_disp, OSM_MSG_MAD_MCMEMBER_RECORD, osm_mcmr_rcv_process, p_sa); if (p_sa->mcmr_set_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->sr_set_disp_h = cl_disp_register(p_set_disp, OSM_MSG_MAD_SERVICE_RECORD, osm_sr_rcv_process, p_sa); if (p_sa->sr_set_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sa->infr_set_disp_h = cl_disp_register(p_set_disp, OSM_MSG_MAD_INFORM_INFO, osm_infr_rcv_process, p_sa); if (p_sa->infr_set_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_log); return status; } ib_api_status_t osm_sa_bind(IN osm_sa_t * p_sa, IN ib_net64_t port_guid) { ib_api_status_t status; OSM_LOG_ENTER(p_sa->p_log); status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid); if (status != IB_SUCCESS) { OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: " "SA MAD Controller bind failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_sa->p_log); return status; } ib_api_status_t osm_sa_send(osm_sa_t *sa, IN osm_madw_t * p_madw, IN boolean_t resp_expected) { ib_api_status_t status; cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent); status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected); if (status != IB_SUCCESS) { cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: " "osm_vendor_send failed, status = %s\n", ib_get_err_str(status)); } return status; } void osm_sa_send_error(IN osm_sa_t * sa, IN const osm_madw_t * p_madw, IN ib_net16_t sa_status) { osm_madw_t *p_resp_madw; ib_sa_mad_t *p_resp_sa_mad; ib_sa_mad_t *p_sa_mad; OSM_LOG_ENTER(sa->p_log); /* avoid races - if we are exiting - exit */ if (osm_exit_flag) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Ignoring requested send after exit\n"); goto Exit; } p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr); if (p_resp_madw == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: " "Unable to acquire response MAD\n"); goto Exit; } p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); /* Copy the MAD header back into the response mad */ *p_resp_sa_mad = *p_sa_mad; p_resp_sa_mad->status = sa_status; if (p_resp_sa_mad->method == IB_MAD_METHOD_SET) p_resp_sa_mad->method = IB_MAD_METHOD_GET; else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE) p_resp_sa_mad->attr_offset = 0; p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; /* * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ p_resp_sa_mad->sm_key = 0; /* * o15-0.2.7 - The PathRecord Attribute ID shall be used in * the response (to a SubnAdmGetMulti(MultiPathRecord) */ if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD) p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD; if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_FRAMES)) osm_dump_sa_mad_v2(sa->p_log, p_resp_sa_mad, FILE_ID, OSM_LOG_FRAMES); osm_sa_send(sa, p_resp_madw, FALSE); Exit: OSM_LOG_EXIT(sa->p_log); } void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size, cl_qlist_t *list) { cl_list_item_t *item; osm_madw_t *resp_madw; ib_sa_mad_t *sa_mad, *resp_sa_mad; unsigned num_rec, i; #ifndef VENDOR_RMPP_SUPPORT unsigned trim_num_rec; #endif unsigned char *p; sa_mad = osm_madw_get_sa_mad_ptr(madw); num_rec = cl_qlist_count(list); /* * C15-0.1.30: * If we do a SubnAdmGet and got more than one record it is an error! */ if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: " "Got %u records for SubnAdmGet(%s) comp_mask 0x%016" PRIx64 "from requester LID %u\n", num_rec, ib_get_sa_attr_str(sa_mad->attr_id), cl_ntoh64(sa_mad->comp_mask), cl_ntoh16(madw->mad_addr.dest_lid)); osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS); goto Exit; } #ifndef VENDOR_RMPP_SUPPORT trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size; if (trim_num_rec < num_rec) { OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Number of records:%u trimmed to:%u to fit in one MAD\n", num_rec, trim_num_rec); num_rec = trim_num_rec; } #endif OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec); if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) { osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS); goto Exit; } /* * Get a MAD to reply. Address of Mad is in the received mad_wrapper */ resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind, num_rec * attr_size + IB_SA_MAD_HDR_SIZE, &madw->mad_addr); if (!resp_madw) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: " "osm_mad_pool_get failed\n"); osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw); /* Copy the MAD header back into the response mad. Set the 'R' bit and the payload length, Then copy all records from the list into the response payload. */ memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE); if (resp_sa_mad->method == IB_MAD_METHOD_SET) resp_sa_mad->method = IB_MAD_METHOD_GET; resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ resp_sa_mad->sm_key = 0; /* Fill in the offset (paylen will be done by the rmpp SAR) */ resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0; p = ib_sa_mad_get_payload_ptr(resp_sa_mad); #ifndef VENDOR_RMPP_SUPPORT /* we support only one packet RMPP - so we will set the first and last flags for gettable */ if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) { resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE; } #else /* forcefully define the packet as RMPP one */ if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; #endif for (i = 0; i < num_rec; i++) { item = cl_qlist_remove_head(list); memcpy(p, ((osm_sa_item_t *)item)->resp.data, attr_size); p += attr_size; free(item); } osm_dump_sa_mad_v2(sa->p_log, resp_sa_mad, FILE_ID, OSM_LOG_FRAMES); osm_sa_send(sa, resp_madw, FALSE); Exit: /* need to set the mem free ... */ item = cl_qlist_remove_head(list); while (item != cl_qlist_end(list)) { free(item); item = cl_qlist_remove_head(list); } } /* * SA DB Dumper * */ struct opensm_dump_context { osm_opensm_t *p_osm; FILE *file; }; static int opensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name, void (*dump_func) (osm_opensm_t * p_osm, FILE * file)) { char path[1024]; char path_tmp[1032]; FILE *file; int fd, status = 0; snprintf(path, sizeof(path), "%s/%s", p_osm->subn.opt.dump_files_dir, file_name); snprintf(path_tmp, sizeof(path_tmp), "%s.tmp", path); file = fopen(path_tmp, "w"); if (!file) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C01: " "cannot open file \'%s\': %s\n", path_tmp, strerror(errno)); return -1; } if (chmod(path_tmp, S_IRUSR | S_IWUSR)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0C: " "cannot change access permissions of file " "\'%s\' : %s\n", path_tmp, strerror(errno)); fclose(file); return -1; } dump_func(p_osm, file); if (p_osm->subn.opt.fsync_high_avail_files) { if (fflush(file) == 0) { fd = fileno(file); if (fd != -1) { if (fsync(fd) == -1) OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C08: fsync() failed (%s) for %s\n", strerror(errno), path_tmp); } else OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C09: " "fileno() failed for %s\n", path_tmp); } else OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0A: " "fflush() failed (%s) for %s\n", strerror(errno), path_tmp); } fclose(file); status = rename(path_tmp, path); if (status) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C0B: " "Failed to rename file:%s (err:%s)\n", path_tmp, strerror(errno)); } return status; } static void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt) { FILE *file = ((struct opensm_dump_context *)cxt)->file; osm_mcm_alias_guid_t *p_mcm_alias_guid = (osm_mcm_alias_guid_t *) p_map_item; fprintf(file, "mcm_port: " "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " " "scope_state=0x%02x proxy_join=0x%x" "\n\n", cl_ntoh64(p_mcm_alias_guid->port_gid.unicast.prefix), cl_ntoh64(p_mcm_alias_guid->port_gid.unicast.interface_id), p_mcm_alias_guid->scope_state, p_mcm_alias_guid->proxy_join); } static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt) { struct opensm_dump_context dump_context; osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm; FILE *file = ((struct opensm_dump_context *)cxt)->file; fprintf(file, "MC Group 0x%04x %s:" " mgid=0x%016" PRIx64 ":0x%016" PRIx64 " port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x" " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x" " scope_state=0x%02x proxy_join=0x%x" "\n\n", cl_ntoh16(p_mgrp->mlid), p_mgrp->well_known ? " (well known)" : "", cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix), cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id), cl_ntoh32(p_mgrp->mcmember_rec.qkey), cl_ntoh16(p_mgrp->mcmember_rec.mlid), p_mgrp->mcmember_rec.mtu, p_mgrp->mcmember_rec.tclass, cl_ntoh16(p_mgrp->mcmember_rec.pkey), p_mgrp->mcmember_rec.rate, p_mgrp->mcmember_rec.pkt_life, cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop), p_mgrp->mcmember_rec.scope_state, p_mgrp->mcmember_rec.proxy_join); dump_context.p_osm = p_osm; dump_context.file = file; cl_qmap_apply_func(&p_mgrp->mcm_alias_port_tbl, mcast_mgr_dump_one_port, &dump_context); } static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt) { FILE *file = ((struct opensm_dump_context *)cxt)->file; osm_infr_t *p_infr = (osm_infr_t *) p_list_item; ib_inform_info_record_t *p_iir = &p_infr->inform_record; fprintf(file, "InformInfo Record:" " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64 " subscriber_enum=0x%x" " InformInfo:" " gid=0x%016" PRIx64 ":0x%016" PRIx64 " lid_range_begin=0x%x" " lid_range_end=0x%x" " is_generic=0x%x" " subscribe=0x%x" " trap_type=0x%x" " trap_num=0x%x" " qpn_resp_time_val=0x%x" " node_type=0x%06x" " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x" " remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x" "\n\n", cl_ntoh64(p_iir->subscriber_gid.unicast.prefix), cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id), cl_ntoh16(p_iir->subscriber_enum), cl_ntoh64(p_iir->inform_info.gid.unicast.prefix), cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id), cl_ntoh16(p_iir->inform_info.lid_range_begin), cl_ntoh16(p_iir->inform_info.lid_range_end), p_iir->inform_info.is_generic, p_iir->inform_info.subscribe, cl_ntoh16(p_iir->inform_info.trap_type), cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num), cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val), cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)), cl_ntoh16(p_infr->report_addr.dest_lid), p_infr->report_addr.path_bits, p_infr->report_addr.static_rate, cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp), cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey), p_infr->report_addr.addr_type.gsi.pkey_ix, p_infr->report_addr.addr_type.gsi.service_level); } static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt) { FILE *file = ((struct opensm_dump_context *)cxt)->file; osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; ib_service_record_t *p_sr = &p_svcr->service_record; fprintf(file, "Service Record: id=0x%016" PRIx64 " gid=0x%016" PRIx64 ":0x%016" PRIx64 " pkey=0x%x" " lease=0x%x" " key=0x%02x%02x%02x%02x%02x%02x%02x%02x" ":0x%02x%02x%02x%02x%02x%02x%02x%02x" " name=\'%s\'" " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x" ":0x%02x%02x%02x%02x%02x%02x%02x%02x" " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x" " data32=0x%08x%08x:0x%08x%08x" " data64=0x%016" PRIx64 ":0x%016" PRIx64 " modified_time=0x%x lease_period=0x%x\n\n", cl_ntoh64(p_sr->service_id), cl_ntoh64(p_sr->service_gid.unicast.prefix), cl_ntoh64(p_sr->service_gid.unicast.interface_id), cl_ntoh16(p_sr->service_pkey), cl_ntoh32(p_sr->service_lease), p_sr->service_key[0], p_sr->service_key[1], p_sr->service_key[2], p_sr->service_key[3], p_sr->service_key[4], p_sr->service_key[5], p_sr->service_key[6], p_sr->service_key[7], p_sr->service_key[8], p_sr->service_key[9], p_sr->service_key[10], p_sr->service_key[11], p_sr->service_key[12], p_sr->service_key[13], p_sr->service_key[14], p_sr->service_key[15], p_sr->service_name, p_sr->service_data8[0], p_sr->service_data8[1], p_sr->service_data8[2], p_sr->service_data8[3], p_sr->service_data8[4], p_sr->service_data8[5], p_sr->service_data8[6], p_sr->service_data8[7], p_sr->service_data8[8], p_sr->service_data8[9], p_sr->service_data8[10], p_sr->service_data8[11], p_sr->service_data8[12], p_sr->service_data8[13], p_sr->service_data8[14], p_sr->service_data8[15], cl_ntoh16(p_sr->service_data16[0]), cl_ntoh16(p_sr->service_data16[1]), cl_ntoh16(p_sr->service_data16[2]), cl_ntoh16(p_sr->service_data16[3]), cl_ntoh16(p_sr->service_data16[4]), cl_ntoh16(p_sr->service_data16[5]), cl_ntoh16(p_sr->service_data16[6]), cl_ntoh16(p_sr->service_data16[7]), cl_ntoh32(p_sr->service_data32[0]), cl_ntoh32(p_sr->service_data32[1]), cl_ntoh32(p_sr->service_data32[2]), cl_ntoh32(p_sr->service_data32[3]), cl_ntoh64(p_sr->service_data64[0]), cl_ntoh64(p_sr->service_data64[1]), p_svcr->modified_time, p_svcr->lease_period); } static void sa_dump_one_port_guidinfo(cl_map_item_t * p_map_item, void *cxt) { FILE *file = ((struct opensm_dump_context *)cxt)->file; osm_port_t *p_port = (osm_port_t *) p_map_item; uint32_t max_block; int block_num; if (!p_port->p_physp->p_guids) return; max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) / GUID_TABLE_MAX_ENTRIES; for (block_num = 0; block_num < max_block; block_num++) { fprintf(file, "GUIDInfo Record:" " base_guid=0x%016" PRIx64 " lid=0x%04x block_num=0x%x" " guid0=0x%016" PRIx64 " guid1=0x%016" PRIx64 " guid2=0x%016" PRIx64 " guid3=0x%016" PRIx64 " guid4=0x%016" PRIx64 " guid5=0x%016" PRIx64 " guid6=0x%016" PRIx64 " guid7=0x%016" PRIx64 "\n\n", cl_ntoh64((*p_port->p_physp->p_guids)[0]), cl_ntoh16(osm_port_get_base_lid(p_port)), block_num, cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 1]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 2]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 3]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 4]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 5]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 6]), cl_ntoh64((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES + 7])); } } static void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file) { struct opensm_dump_context dump_context; osm_mgrp_t *p_mgrp; dump_context.p_osm = p_osm; dump_context.file = file; OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump guidinfo\n"); cl_qmap_apply_func(&p_osm->subn.port_guid_tbl, sa_dump_one_port_guidinfo, &dump_context); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast\n"); for (p_mgrp = (osm_mgrp_t *) cl_fmap_head(&p_osm->subn.mgrp_mgid_tbl); p_mgrp != (osm_mgrp_t *) cl_fmap_end(&p_osm->subn.mgrp_mgid_tbl); p_mgrp = (osm_mgrp_t *) cl_fmap_next(&p_mgrp->map_item)) sa_dump_one_mgrp(p_mgrp, &dump_context); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform\n"); cl_qlist_apply_func(&p_osm->subn.sa_infr_list, sa_dump_one_inform, &dump_context); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services\n"); cl_qlist_apply_func(&p_osm->subn.sa_sr_list, sa_dump_one_service, &dump_context); } int osm_sa_db_file_dump(osm_opensm_t * p_osm) { int res = 1; cl_plock_acquire(&p_osm->lock); if (p_osm->sa.dirty) { res = opensm_dump_to_file( p_osm, "opensm-sa.dump", sa_dump_all_sa); if (!res) p_osm->sa.dirty = FALSE; } cl_plock_release(&p_osm->lock); return res; } /* * SA DB Loader */ static osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid, ib_member_rec_t * p_mcm_rec) { ib_net64_t comp_mask; osm_mgrp_t *p_mgrp; cl_plock_excl_acquire(&p_osm->lock); p_mgrp = osm_get_mgrp_by_mgid(&p_osm->subn, &p_mcm_rec->mgid); if (p_mgrp) { if (p_mgrp->mlid == mlid) { OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "mgrp %04x is already here.", cl_ntoh16(mlid)); goto _out; } OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "mlid %04x is already used by another MC group. Will " "request clients reregistration.\n", cl_ntoh16(mlid)); p_mgrp = NULL; goto _out; } comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL; if (!(p_mgrp = osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa, comp_mask, p_mcm_rec)) || p_mgrp->mlid != mlid) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot create MC group with mlid 0x%04x and mgid " "0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid), cl_ntoh64(p_mcm_rec->mgid.unicast.prefix), cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id)); p_mgrp = NULL; } _out: cl_plock_release(&p_osm->lock); return p_mgrp; } static int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr, uint32_t modified_time, uint32_t lease_period) { osm_svcr_t *p_svcr; int ret = 0; cl_plock_excl_acquire(&p_osm->lock); if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "ServiceRecord already exists\n"); goto _out; } if (!(p_svcr = osm_svcr_new(sr))) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot allocate new service struct\n"); ret = -1; goto _out; } p_svcr->modified_time = modified_time; p_svcr->lease_period = lease_period; OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n"); osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr); if (lease_period != 0xffffffff) cl_timer_trim(&p_osm->sa.sr_timer, 1000); _out: cl_plock_release(&p_osm->lock); return ret; } static int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir, osm_mad_addr_t * addr) { osm_infr_t infr, *p_infr; int ret = 0; infr.h_bind = p_osm->sa.mad_ctrl.h_bind; infr.sa = &p_osm->sa; /* other possible way to restore mad_addr partially is to extract qpn from InformInfo and to find lid by gid */ infr.report_addr = *addr; infr.inform_record = *iir; cl_plock_excl_acquire(&p_osm->lock); if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "InformInfo Record already exists\n"); goto _out; } if (!(p_infr = osm_infr_new(&infr))) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot allocate new infr struct\n"); ret = -1; goto _out; } OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n"); osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr); _out: cl_plock_release(&p_osm->lock); return ret; } static int load_guidinfo(osm_opensm_t * p_osm, ib_net64_t base_guid, ib_guidinfo_record_t *gir) { osm_port_t *p_port; uint32_t max_block; int i, ret = 0; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; cl_plock_excl_acquire(&p_osm->lock); p_port = osm_get_port_by_guid(&p_osm->subn, base_guid); if (!p_port) goto _out; if (!p_port->p_physp->p_guids) { max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) / GUID_TABLE_MAX_ENTRIES; p_port->p_physp->p_guids = calloc(max_block * GUID_TABLE_MAX_ENTRIES, sizeof(ib_net64_t)); if (!p_port->p_physp->p_guids) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot allocate GUID table for port " "GUID 0x%" PRIx64 "\n", cl_ntoh64(p_port->p_physp->port_guid)); goto _out; } } for (i = 0; i < GUID_TABLE_MAX_ENTRIES; i++) { if (!gir->guid_info.guid[i]) continue; /* skip block 0 index 0 */ if (gir->block_num == 0 && i == 0) continue; if (gir->block_num * GUID_TABLE_MAX_ENTRIES + i > p_port->p_physp->port_info.guid_cap) break; p_alias_guid = osm_alias_guid_new(gir->guid_info.guid[i], p_port); if (!p_alias_guid) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "Alias guid %d memory allocation failed" " for port GUID 0x%" PRIx64 "\n", gir->block_num * GUID_TABLE_MAX_ENTRIES + i, cl_ntoh64(p_port->p_physp->port_guid)); goto _out; } p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&p_osm->subn.alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate */ OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "Duplicate alias port GUID 0x%" PRIx64 " index %d base port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_alias_guid->alias_guid), gir->block_num * GUID_TABLE_MAX_ENTRIES + i, cl_ntoh64(p_alias_guid->p_base_port->guid)); osm_alias_guid_delete(&p_alias_guid); goto _out; } } memcpy(&(*p_port->p_physp->p_guids)[gir->block_num * GUID_TABLE_MAX_ENTRIES], &gir->guid_info, sizeof(ib_guid_info_t)); osm_queue_guidinfo(&p_osm->sa, p_port, gir->block_num); _out: cl_plock_release(&p_osm->lock); return ret; } #define UNPACK_FUNC(name,x) \ static int unpack_##name##x(char *p, uint##x##_t *val_ptr) \ { \ char *q; \ unsigned long long num; \ num = strtoull(p, &q, 16); \ if (num > ~((uint##x##_t)0x0) \ || q == p || (!isspace(*q) && *q != ':')) { \ *val_ptr = 0; \ return -1; \ } \ *val_ptr = cl_hton##x((uint##x##_t)num); \ return (int)(q - p); \ } #define cl_hton8(x) (x) UNPACK_FUNC(net, 8); UNPACK_FUNC(net, 16); UNPACK_FUNC(net, 32); UNPACK_FUNC(net, 64); static int unpack_string(char *p, uint8_t * buf, unsigned len) { char *q = p; char delim = ' '; if (*q == '\'' || *q == '\"') delim = *q++; while (--len && *q && *q != delim) *buf++ = *q++; *buf = '\0'; if (*q == delim && delim != ' ') q++; return (int)(q - p); } static int unpack_string64(char *p, uint8_t * buf) { return unpack_string(p, buf, 64); } #define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \ p = strstr(p, name); \ if (!p) { \ OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \ "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \ file_name, lineno, (name)); \ ret = -2; \ goto _error; \ } \ p += strlen(name); \ _ret = unpack_##x(p, (val_ptr)); \ if (_ret < 0) { \ OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \ "PARSE ERROR: %s:%u: cannot parse "#x" value " \ "after \"%s\"\n", file_name, lineno, (name)); \ ret = _ret; \ goto _error; \ } \ p += _ret; \ } static void sa_db_file_load_handle_mgrp(osm_opensm_t * p_osm, osm_mgrp_t * p_mgrp) { /* decide whether to delete the mgrp object or not */ if (p_mgrp->full_members == 0 && !p_mgrp->well_known) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Closing MC group 0x%016" PRIx64 ":0x%016" PRIx64 " - no full members were added to not well known " "group\n", cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id)); osm_mgrp_cleanup(&p_osm->subn, p_mgrp); } } int osm_sa_db_file_load(osm_opensm_t * p_osm) { char line[1024]; char *file_name; FILE *file; int ret = 0; osm_mgrp_t *p_next_mgrp = NULL; osm_mgrp_t *p_prev_mgrp = NULL; unsigned rereg_clients = 0; unsigned lineno; if (!p_osm->subn.first_time_master_sweep) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Not first sweep - skip SA DB restore\n"); return 0; } file_name = p_osm->subn.opt.sa_db_file; if (!file_name) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "sa db file name is not specifed. Skip restore\n"); return 0; } file = fopen(file_name, "r"); if (!file) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: " "Can't open sa db file \'%s\'. Skip restoring\n", file_name); return -1; } OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Restoring SA DB from file \'%s\'\n", file_name); lineno = 0; while (fgets(line, sizeof(line) - 1, file) != NULL) { char *p; uint8_t val; lineno++; p = line; while (isspace(*p)) p++; if (*p == '#') continue; if (!strncmp(p, "MC Group", 8)) { ib_member_rec_t mcm_rec; ib_net16_t mlid; p_next_mgrp = NULL; memset(&mcm_rec, 0, sizeof(mcm_rec)); PARSE_AHEAD(p, net16, " 0x", &mlid); PARSE_AHEAD(p, net64, " mgid=0x", &mcm_rec.mgid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &mcm_rec.mgid.unicast.interface_id); PARSE_AHEAD(p, net64, " port_gid=0x", &mcm_rec.port_gid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &mcm_rec.port_gid.unicast.interface_id); PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey); PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid); PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu); PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass); PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey); PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate); PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life); PARSE_AHEAD(p, net32, " sl_flow_hop=0x", &mcm_rec.sl_flow_hop); PARSE_AHEAD(p, net8, " scope_state=0x", &mcm_rec.scope_state); PARSE_AHEAD(p, net8, " proxy_join=0x", &val); mcm_rec.proxy_join = val; p_next_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec); if (!p_next_mgrp) rereg_clients = 1; if (cl_ntoh16(mlid) > p_osm->sm.mlids_init_max) p_osm->sm.mlids_init_max = cl_ntoh16(mlid); } else if (p_next_mgrp && !strncmp(p, "mcm_port", 8)) { ib_member_rec_t mcmr; ib_net64_t guid; osm_port_t *port; boolean_t proxy; PARSE_AHEAD(p, net64, " port_gid=0x", &mcmr.port_gid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &mcmr.port_gid.unicast.interface_id); PARSE_AHEAD(p, net8, " scope_state=0x", &mcmr.scope_state); PARSE_AHEAD(p, net8, " proxy_join=0x", &val); proxy = val; guid = mcmr.port_gid.unicast.interface_id; port = osm_get_port_by_alias_guid(&p_osm->subn, guid); if (port && cl_qmap_get(&p_next_mgrp->mcm_port_tbl, guid) == cl_qmap_end(&p_next_mgrp->mcm_port_tbl) && !osm_mgrp_add_port(&p_osm->subn, &p_osm->log, p_next_mgrp, port, &mcmr, proxy)) rereg_clients = 1; } else if (!strncmp(p, "Service Record:", 15)) { ib_service_record_t s_rec; uint32_t modified_time, lease_period; p_next_mgrp = NULL; memset(&s_rec, 0, sizeof(s_rec)); PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id); PARSE_AHEAD(p, net64, " gid=0x", &s_rec.service_gid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &s_rec.service_gid.unicast.interface_id); PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey); PARSE_AHEAD(p, net32, " lease=0x", &s_rec.service_lease); PARSE_AHEAD(p, net64, " key=0x", (ib_net64_t *) (&s_rec.service_key[0])); PARSE_AHEAD(p, net64, ":0x", (ib_net64_t *) (&s_rec.service_key[8])); PARSE_AHEAD(p, string64, " name=", s_rec.service_name); PARSE_AHEAD(p, net64, " data8=0x", (ib_net64_t *) (&s_rec.service_data8[0])); PARSE_AHEAD(p, net64, ":0x", (ib_net64_t *) (&s_rec.service_data8[8])); PARSE_AHEAD(p, net64, " data16=0x", (ib_net64_t *) (&s_rec.service_data16[0])); PARSE_AHEAD(p, net64, ":0x", (ib_net64_t *) (&s_rec.service_data16[4])); PARSE_AHEAD(p, net64, " data32=0x", (ib_net64_t *) (&s_rec.service_data32[0])); PARSE_AHEAD(p, net64, ":0x", (ib_net64_t *) (&s_rec.service_data32[2])); PARSE_AHEAD(p, net64, " data64=0x", &s_rec.service_data64[0]); PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]); PARSE_AHEAD(p, net32, " modified_time=0x", &modified_time); PARSE_AHEAD(p, net32, " lease_period=0x", &lease_period); if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time), cl_ntoh32(lease_period))) rereg_clients = 1; } else if (!strncmp(p, "InformInfo Record:", 18)) { ib_inform_info_record_t i_rec; osm_mad_addr_t rep_addr; ib_net16_t val16; p_next_mgrp = NULL; memset(&i_rec, 0, sizeof(i_rec)); memset(&rep_addr, 0, sizeof(rep_addr)); PARSE_AHEAD(p, net64, " subscriber_gid=0x", &i_rec.subscriber_gid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &i_rec.subscriber_gid.unicast.interface_id); PARSE_AHEAD(p, net16, " subscriber_enum=0x", &i_rec.subscriber_enum); PARSE_AHEAD(p, net64, " gid=0x", &i_rec.inform_info.gid.unicast.prefix); PARSE_AHEAD(p, net64, ":0x", &i_rec.inform_info.gid.unicast. interface_id); PARSE_AHEAD(p, net16, " lid_range_begin=0x", &i_rec.inform_info.lid_range_begin); PARSE_AHEAD(p, net16, " lid_range_end=0x", &i_rec.inform_info.lid_range_end); PARSE_AHEAD(p, net8, " is_generic=0x", &i_rec.inform_info.is_generic); PARSE_AHEAD(p, net8, " subscribe=0x", &i_rec.inform_info.subscribe); PARSE_AHEAD(p, net16, " trap_type=0x", &i_rec.inform_info.trap_type); PARSE_AHEAD(p, net16, " trap_num=0x", &i_rec.inform_info.g_or_v.generic.trap_num); PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x", &i_rec.inform_info.g_or_v.generic. qpn_resp_time_val); PARSE_AHEAD(p, net32, " node_type=0x", (uint32_t *) & i_rec.inform_info.g_or_v. generic.reserved2); PARSE_AHEAD(p, net16, " rep_addr: lid=0x", &rep_addr.dest_lid); PARSE_AHEAD(p, net8, " path_bits=0x", &rep_addr.path_bits); PARSE_AHEAD(p, net8, " static_rate=0x", &rep_addr.static_rate); PARSE_AHEAD(p, net32, " remote_qp=0x", &rep_addr.addr_type.gsi.remote_qp); PARSE_AHEAD(p, net32, " remote_qkey=0x", &rep_addr.addr_type.gsi.remote_qkey); PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16); rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16); PARSE_AHEAD(p, net8, " sl=0x", &rep_addr.addr_type.gsi.service_level); if (load_infr(p_osm, &i_rec, &rep_addr)) rereg_clients = 1; } else if (!strncmp(p, "GUIDInfo Record:", 16)) { ib_guidinfo_record_t gi_rec; ib_net64_t base_guid; p_next_mgrp = NULL; memset(&gi_rec, 0, sizeof(gi_rec)); PARSE_AHEAD(p, net64, " base_guid=0x", &base_guid); PARSE_AHEAD(p, net16, " lid=0x", &gi_rec.lid); PARSE_AHEAD(p, net8, " block_num=0x", &gi_rec.block_num); PARSE_AHEAD(p, net64, " guid0=0x", &gi_rec.guid_info.guid[0]); PARSE_AHEAD(p, net64, " guid1=0x", &gi_rec.guid_info.guid[1]); PARSE_AHEAD(p, net64, " guid2=0x", &gi_rec.guid_info.guid[2]); PARSE_AHEAD(p, net64, " guid3=0x", &gi_rec.guid_info.guid[3]); PARSE_AHEAD(p, net64, " guid4=0x", &gi_rec.guid_info.guid[4]); PARSE_AHEAD(p, net64, " guid5=0x", &gi_rec.guid_info.guid[5]); PARSE_AHEAD(p, net64, " guid6=0x", &gi_rec.guid_info.guid[6]); PARSE_AHEAD(p, net64, " guid7=0x", &gi_rec.guid_info.guid[7]); if (load_guidinfo(p_osm, base_guid, &gi_rec)) rereg_clients = 1; } /* * p_next_mgrp points to the multicast group now being parsed. * p_prev_mgrp points to the last multicast group we parsed. * We decide whether to keep or delete each multicast group * only when we finish parsing it's member records. if the * group has full members, or it is a "well known group" we * keep it. */ if (p_prev_mgrp != p_next_mgrp) { if (p_prev_mgrp) sa_db_file_load_handle_mgrp(p_osm, p_prev_mgrp); p_prev_mgrp = p_next_mgrp; } } if (p_next_mgrp) sa_db_file_load_handle_mgrp(p_osm, p_prev_mgrp); /* * If loading succeeded, do whatever 'no_clients_rereg' says. * If loading failed at some point, turn off the 'no_clients_rereg' * option (turn on re-registration requests). */ if (rereg_clients) p_osm->subn.opt.no_clients_rereg = FALSE; /* We've just finished loading SA DB file - clear the "dirty" flag */ p_osm->sa.dirty = FALSE; _error: fclose(file); return ret; } opensm-3.3.20/opensm/osm_sa_class_port_info.c0000644000205000001450000001566212312552420016210 00000000000000/* * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_cpi_rcv_t. * This object represents the ClassPortInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_CLASS_PORT_INFO_C #include #include #include #define MAX_MSECS_TO_RTV 24 /* Precalculated table in msec (index is related to encoded value) */ /* 4.096 usec * 2 ** n (where n = 8 - 31) */ const static uint32_t msecs_to_rtv_table[MAX_MSECS_TO_RTV] = { 1, 2, 4, 8, 16, 33, 67, 134, 268, 536, 1073, 2147, 4294, 8589, 17179, 34359, 68719, 137438, 274877, 549755, 1099511, 2199023, 4398046, 8796093 }; static void cpi_rcv_respond(IN osm_sa_t * sa, IN const osm_madw_t * p_madw) { osm_madw_t *p_resp_madw; const ib_sa_mad_t *p_sa_mad; ib_sa_mad_t *p_resp_sa_mad; ib_class_port_info_t *p_resp_cpi; ib_gid_t zero_gid; uint32_t cap_mask2; uint8_t rtv; OSM_LOG_ENTER(sa->p_log); memset(&zero_gid, 0, sizeof(ib_gid_t)); /* Get a MAD to reply. Address of Mad is in the received mad_wrapper */ p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr); if (!p_resp_madw) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1408: " "Unable to allocate MAD\n"); goto Exit; } p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw); memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE); p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ p_resp_sa_mad->sm_key = 0; p_resp_cpi = (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_mad); /* finally do it (the job) man ! */ p_resp_cpi->base_ver = 1; p_resp_cpi->class_ver = 2; /* Calculate encoded response time value */ /* transaction timeout is in msec */ if (sa->p_subn->opt.transaction_timeout > msecs_to_rtv_table[MAX_MSECS_TO_RTV - 1]) rtv = MAX_MSECS_TO_RTV - 1; else { for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) { if (sa->p_subn->opt.transaction_timeout <= msecs_to_rtv_table[rtv]) break; } } rtv += 8; ib_class_set_resp_time_val(p_resp_cpi, rtv); p_resp_cpi->redir_gid = zero_gid; p_resp_cpi->redir_tc_sl_fl = 0; p_resp_cpi->redir_lid = 0; p_resp_cpi->redir_pkey = 0; p_resp_cpi->redir_qp = CL_NTOH32(1); p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY; p_resp_cpi->trap_gid = zero_gid; p_resp_cpi->trap_tc_sl_fl = 0; p_resp_cpi->trap_lid = 0; p_resp_cpi->trap_pkey = 0; p_resp_cpi->trap_hop_qp = 0; p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY; /* set specific capability mask bits */ /* we do not support the following options/optional records: OSM_CAP_IS_SUBN_OPT_RECS_SUP : RandomForwardingTableRecord, ServiceAssociationRecord other optional records supported "under the table" OSM_CAP_IS_MULTIPATH_SUP: TraceRecord OSM_CAP_IS_REINIT_SUP: For reinitialization functionality. So not sending traps, but supporting Get(Notice) and Set(Notice). */ /* Note host notation replaced later */ #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED | OSM_CAP_IS_MULTIPATH_SUP; #else p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP | OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED; #endif cap_mask2 = OSM_CAP2_IS_FULL_PORTINFO_REC_SUPPORTED | OSM_CAP2_IS_EXTENDED_SPEEDS_SUPPORTED | OSM_CAP2_IS_ALIAS_GUIDS_SUPPORTED | OSM_CAP2_IS_MULTICAST_SERVICE_RECS_SUPPORTED | OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED; if (sa->p_subn->opt.use_mfttop) cap_mask2 |= OSM_CAP2_IS_MCAST_TOP_SUPPORTED; if (sa->p_subn->opt.qos) cap_mask2 |= OSM_CAP2_IS_QOS_SUPPORTED; ib_class_set_cap_mask2(p_resp_cpi, cap_mask2); if (!sa->p_subn->opt.disable_multicast) p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP; p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_FRAMES)) osm_dump_sa_mad_v2(sa->p_log, p_resp_sa_mad, FILE_ID, OSM_LOG_FRAMES); osm_sa_send(sa, p_resp_madw, FALSE); Exit: OSM_LOG_EXIT(sa->p_log); } /********************************************************************** * This code actually handles the call **********************************************************************/ void osm_cpi_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_sa_mad; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); /* we only support GET */ if (p_sa_mad->method != IB_MAD_METHOD_GET) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1403: " "Unsupported Method (%s) for ClassPortInfo request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO); /* CLASS PORT INFO does not really look at the SMDB - no lock required. */ cpi_rcv_respond(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_informinfo.c0000644000205000001450000004731112314616647015204 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_infr_rcv_t. * This object represents the InformInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_INFORMINFO_C #include #include #include #include #include #include #include #include #define SA_IIR_RESP_SIZE SA_ITEM_RESP_SIZE(inform_rec) #define SA_II_RESP_SIZE SA_ITEM_RESP_SIZE(inform) typedef struct osm_iir_search_ctxt { const ib_inform_info_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; ib_gid_t subscriber_gid; ib_net16_t subscriber_enum; osm_sa_t *sa; osm_physp_t *p_req_physp; ib_net64_t sm_key; } osm_iir_search_ctxt_t; /********************************************************************** o13-14.1.1: Except for Set(InformInfo) requests with Inform- Info:LIDRangeBegin=0xFFFF, managers that support event forwarding shall, upon receiving a Set(InformInfo), verify that the requester originating the Set(InformInfo) and a Trap() source identified by Inform- can access each other - can use path record to verify that. **********************************************************************/ static boolean_t validate_ports_access_rights(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec) { boolean_t valid = TRUE; osm_physp_t *p_requester_physp; osm_port_t *p_port; ib_net64_t portguid; uint16_t lid_range_begin, lid_range_end, lid; OSM_LOG_ENTER(sa->p_log); /* get the requester physp from the request address */ p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, &p_infr_rec->report_addr); if (ib_gid_is_notzero(&p_infr_rec->inform_record.inform_info.gid)) { /* a gid is defined */ portguid = p_infr_rec->inform_record.inform_info.gid.unicast. interface_id; p_port = osm_get_port_by_guid(sa->p_subn, portguid); if (p_port == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: " "Invalid port guid: 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); valid = FALSE; goto Exit; } /* make sure that the requester and destination port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey (sa->p_log, p_port->p_physp, p_requester_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "port and requester don't share pkey\n"); valid = FALSE; goto Exit; } } else { size_t lids_size; /* gid is zero - check if LID range is defined */ lid_range_begin = cl_ntoh16(p_infr_rec->inform_record.inform_info. lid_range_begin); /* if lid is 0xFFFF - meaning all endports managed by the manager */ if (lid_range_begin == 0xFFFF) goto Exit; lid_range_end = cl_ntoh16(p_infr_rec->inform_record.inform_info. lid_range_end); lids_size = cl_ptr_vector_get_size(&sa->p_subn->port_lid_tbl); /* lid_range_end is set to zero if no range desired. In this case - just make it equal to the lid_range_begin. */ if (lid_range_end == 0) lid_range_end = lid_range_begin; else if (lid_range_end >= lids_size) lid_range_end = lids_size - 1; if (lid_range_begin >= lids_size) { /* requested lids are out of range */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4302: " "Given LIDs (%u-%u) are out of range (%zu)\n", lid_range_begin, lid_range_end, lids_size); valid = FALSE; goto Exit; } /* go over all defined lids within the range and make sure that the requester port can access them according to current partitioning. */ for (lid = lid_range_begin; lid <= lid_range_end; lid++) { p_port = osm_get_port_by_lid_ho(sa->p_subn, lid); if (p_port == NULL) continue; /* make sure that the requester and destination port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey (sa->p_log, p_port->p_physp, p_requester_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "port and requester don't share pkey\n"); valid = FALSE; goto Exit; } } } Exit: OSM_LOG_EXIT(sa->p_log); return valid; } static boolean_t validate_infr(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec) { boolean_t valid = TRUE; OSM_LOG_ENTER(sa->p_log); valid = validate_ports_access_rights(sa, p_infr_rec); if (!valid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Invalid Access for InformInfo\n"); valid = FALSE; } OSM_LOG_EXIT(sa->p_log); return valid; } /********************************************************************** o13-12.1.1: Confirm a valid request for event subscription by responding with an InformInfo attribute that is a copy of the data in the Set(InformInfo) request. **********************************************************************/ static void infr_rcv_respond(IN osm_sa_t * sa, IN osm_madw_t * p_madw) { cl_qlist_t rec_list; osm_sa_item_t *item; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Generating successful InformInfo response\n"); item = malloc(SA_II_RESP_SIZE); if (!item) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4303: " "rec_item alloc failed\n"); goto Exit; } memcpy(&item->resp.inform, ib_sa_mad_get_payload_ptr(osm_madw_get_sa_mad_ptr(p_madw)), sizeof(ib_inform_info_t)); cl_qlist_init(&rec_list); cl_qlist_insert_tail(&rec_list, &item->list_item); osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa, IN const osm_infr_t * p_infr, osm_iir_search_ctxt_t * p_ctxt) { ib_net64_t comp_mask; ib_net64_t portguid; osm_port_t *p_subscriber_port; osm_physp_t *p_subscriber_physp; const osm_physp_t *p_req_physp; osm_sa_item_t *p_rec_item; OSM_LOG_ENTER(sa->p_log); comp_mask = p_ctxt->comp_mask; p_req_physp = p_ctxt->p_req_physp; if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID && memcmp(&p_infr->inform_record.subscriber_gid, &p_ctxt->subscriber_gid, sizeof(p_infr->inform_record.subscriber_gid))) goto Exit; if (comp_mask & IB_IIR_COMPMASK_ENUM && p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum) goto Exit; /* Implement any other needed search cases */ /* Ensure pkey is shared before returning any records */ portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id; p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid); if (p_subscriber_port == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: " "Invalid subscriber port guid: 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); goto Exit; } /* get the subscriber InformInfo physical port */ p_subscriber_physp = p_subscriber_port->p_physp; /* make sure that the requester and subscriber port can access each other according to the current partitioning. */ if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_subscriber_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "requester and subscriber ports don't share pkey\n"); goto Exit; } p_rec_item = malloc(SA_IIR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: " "rec_item alloc failed\n"); goto Exit; } memcpy(&p_rec_item->resp.inform_rec, &p_infr->inform_record, sizeof(ib_inform_info_record_t)); /* * Per C15-0.2-1.16, InformInfoRecords shall always be * provided with the QPN set to 0, except for the case * of a trusted request, in which case the actual * subscriber QPN shall be returned. */ if (p_ctxt->sm_key == 0) ib_inform_info_set_qpn(&p_rec_item->resp.inform_rec.inform_info, 0); cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_inform_info_rec_by_comp_mask_cb(IN cl_list_item_t * p_list_item, IN void *context) { const osm_infr_t *p_infr = (osm_infr_t *) p_list_item; osm_iir_search_ctxt_t *p_ctxt = context; sa_inform_info_rec_by_comp_mask(p_ctxt->sa, p_infr, p_ctxt); } /********************************************************************** Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD **********************************************************************/ static void infr_rcv_process_get_method(osm_sa_t * sa, IN osm_madw_t * p_madw) { char gid_str[INET6_ADDRSTRLEN]; ib_sa_mad_t *p_rcvd_mad; const ib_inform_info_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_iir_search_ctxt_t context; osm_physp_t *p_req_physp; osm_sa_item_t *item; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_inform_info_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4309: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_inform_info_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.subscriber_gid = p_rcvd_rec->subscriber_gid; context.subscriber_enum = p_rcvd_rec->subscriber_enum; context.sa = sa; context.p_req_physp = p_req_physp; context.sm_key = p_rcvd_mad->sm_key; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Query Subscriber GID:%s(%02X) Enum:0x%X(%02X)\n", inet_ntop(AF_INET6, p_rcvd_rec->subscriber_gid.raw, gid_str, sizeof gid_str), (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0, cl_ntoh16(p_rcvd_rec->subscriber_enum), (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0); cl_qlist_apply_func(&sa->p_subn->sa_infr_list, sa_inform_info_rec_by_comp_mask_cb, &context); /* clear reserved and pad fields in InformInfoRecord */ for (item = (osm_sa_item_t *) cl_qlist_head(&rec_list); item != (osm_sa_item_t *) cl_qlist_end(&rec_list); item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) { memset(item->resp.inform_rec.reserved, 0, sizeof(item->resp.inform_rec.reserved)); memset(item->resp.inform_rec.pad, 0, sizeof(item->resp.inform_rec.pad)); } cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } /********************************************************************* Received a Set(InformInfo) MAD **********************************************************************/ static void infr_rcv_process_set_method(osm_sa_t * sa, IN osm_madw_t * p_madw) { ib_sa_mad_t *p_sa_mad; ib_inform_info_t *p_recvd_inform_info; osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ osm_infr_t *p_infr; ib_net32_t qpn; uint8_t resp_time_val; ib_api_status_t res; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_inform_info = (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); #if 0 if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_inform_info_v2(sa->p_log, p_recvd_inform_info, FILE_ID, OSM_LOG_DEBUG); #endif /* Grab the lock */ cl_plock_excl_acquire(sa->p_lock); /* define the inform record */ inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ inform_info_rec.report_addr = p_madw->mad_addr; /* we will need to know the mad srvc to send back through */ inform_info_rec.h_bind = p_madw->h_bind; inform_info_rec.sa = sa; /* update the subscriber GID according to mad address */ res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr, &inform_info_rec.inform_record. subscriber_gid); if (res != IB_SUCCESS) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308: " "Subscribe Request from unknown LID: %u\n", cl_ntoh16(p_madw->mad_addr.dest_lid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* HACK: enum is always 0 (currently) */ inform_info_rec.inform_record.subscriber_enum = 0; /* Subscribe values above 1 are undefined */ if (p_recvd_inform_info->subscribe > 1) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430A: " "Invalid subscribe: %d\n", p_recvd_inform_info->subscribe); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * Per C15-0.2-1.16, SubnAdmSet(InformInfo) subscriptions for * SM security traps shall be provided only if they come from a * trusted source. */ if ((p_sa_mad->sm_key == 0) && p_recvd_inform_info->is_generic && ((cl_ntoh16(p_recvd_inform_info->g_or_v.generic.trap_num) >= 256) && (cl_ntoh16(p_recvd_inform_info->g_or_v.generic.trap_num) <= 259))) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430B " "Request for security trap from non-trusted requester: " "Given SM_Key:0x%016" PRIx64 "\n", cl_ntoh64(p_sa_mad->sm_key)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * MODIFICATIONS DONE ON INCOMING REQUEST: * * QPN: * Internally we keep the QPN field of the InformInfo updated * so we can simply compare it in the record - when finding such. */ if (p_recvd_inform_info->subscribe) { ib_inform_info_set_qpn(&inform_info_rec.inform_record. inform_info, inform_info_rec.report_addr.addr_type. gsi.remote_qp); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Subscribe Request with QPN: 0x%06X\n", cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi. remote_qp)); } else { ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v. generic.qpn_resp_time_val, &qpn, &resp_time_val); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "UnSubscribe Request with QPN: 0x%06X\n", cl_ntoh32(qpn)); } /* If record exists with matching InformInfo */ p_infr = osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec); /* check to see if the request was for subscribe */ if (p_recvd_inform_info->subscribe) { /* validate the request for a new or update InformInfo */ if (validate_infr(sa, &inform_info_rec) != TRUE) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: " "Failed to validate a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* ok - we can try and create a new entry */ if (p_infr == NULL) { /* Create the instance of the osm_infr_t object */ p_infr = osm_infr_new(&inform_info_rec); if (p_infr == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: " "Failed to create a new inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Adding event subscription for port 0x%" PRIx64 "\n", cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.interface_id)); /* Add this new osm_infr_t object to subnet object */ osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr); } else /* Update the old instance of the osm_infr_t object */ p_infr->inform_record = inform_info_rec.inform_record; /* We got an UnSubscribe request */ } else if (p_infr == NULL) { cl_plock_release(sa->p_lock); /* No Such Item - So Error */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: " "Failed to UnSubscribe to non existing inform object\n"); /* o13-13.1.1: we need to set the subscribe bit to 0 */ p_recvd_inform_info->subscribe = 0; osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } else { /* Delete this object from the subnet list of informs */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Removing event subscription for port 0x%" PRIx64 "\n", cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.interface_id)); osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr); } cl_plock_release(sa->p_lock); /* send the success response */ infr_rcv_respond(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); } void osm_infr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; ib_sa_mad_t *p_sa_mad; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO); if (p_sa_mad->method != IB_MAD_METHOD_SET) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s) for InformInfo\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } infr_rcv_process_set_method(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); } void osm_infir_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; ib_sa_mad_t *p_sa_mad; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD); if (p_sa_mad->method != IB_MAD_METHOD_GET && p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s) for InformInfoRecord\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } infr_rcv_process_get_method(sa, p_madw); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_lft_record.c0000644000205000001450000001666412314616647015170 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_lftr_rcv_t. * This object represents the LinearForwardingTable Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SA_LFT_RECORD_C #include #include #include #include #include #define SA_LFTR_RESP_SIZE SA_ITEM_RESP_SIZE(lft_rec) typedef struct osm_lftr_search_ctxt { const ib_lft_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_lftr_search_ctxt_t; static ib_api_status_t lftr_rcv_new_lftr(IN osm_sa_t * sa, IN const osm_switch_t * p_sw, IN cl_qlist_t * p_list, IN ib_net16_t lid, IN uint16_t block) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_LFTR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4402: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New LinearForwardingTable: sw 0x%016" PRIx64 "\n\t\t\t\tblock 0x%02X lid %u\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), block, cl_ntoh16(lid)); memset(p_rec_item, 0, SA_LFTR_RESP_SIZE); p_rec_item->resp.lft_rec.lid = lid; p_rec_item->resp.lft_rec.block_num = cl_hton16(block); /* copy the lft block */ osm_switch_get_lft_block(p_sw, block, p_rec_item->resp.lft_rec.lft); cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void lftr_rcv_by_comp_mask(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_lftr_search_ctxt_t *p_ctxt = cxt; const osm_switch_t *p_sw = (osm_switch_t *) p_map_item; const ib_lft_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; osm_sa_t *sa = p_ctxt->sa; ib_net64_t const comp_mask = p_ctxt->comp_mask; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; osm_port_t *p_port; uint16_t min_lid_ho, max_lid_ho; uint16_t min_block, max_block, block; const osm_physp_t *p_physp; /* In switches, the port guid is the node guid. */ p_port = osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid); if (!p_port) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4405: " "Failed to find Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); return; } /* check that the requester physp and the current physp are under the same partition. */ p_physp = p_port->p_physp; if (!p_physp) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4406: " "Failed to find default physical Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); return; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) return; /* get the port 0 of the switch */ osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); /* compare the lids - if required */ if (comp_mask & IB_LFTR_COMPMASK_LID) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing lid:%u to port lid range: %u .. %u\n", cl_ntoh16(p_rcvd_rec->lid), min_lid_ho, max_lid_ho); /* ok we are ready for range check */ if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) || max_lid_ho < cl_ntoh16(p_rcvd_rec->lid)) return; } /* now we need to decide which blocks to output */ max_block = osm_switch_get_max_block_id_in_use(p_sw); if (comp_mask & IB_LFTR_COMPMASK_BLOCK) { min_block = cl_ntoh16(p_rcvd_rec->block_num); if (min_block > max_block) return; max_block = min_block; } else /* use as many blocks as "in use" */ min_block = 0; /* so we can add these blocks one by one ... */ for (block = min_block; block <= max_block; block++) lftr_rcv_new_lftr(sa, p_sw, p_ctxt->p_list, osm_port_get_base_lid(p_port), block); } void osm_lftr_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_lft_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_lftr_search_ctxt_t context; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_lft_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_LFT_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4408: " "Unsupported Method (%s) for LFTRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4407: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; /* Go over all switches */ cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl, lftr_rcv_by_comp_mask, &context); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_lft_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_mft_record.c0000644000205000001450000002062712314616647015163 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_mftr_rcv_t. * This object represents the MulticastForwardingTable Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SA_MFT_RECORD_C #include #include #include #include #include #define SA_MFTR_RESP_SIZE SA_ITEM_RESP_SIZE(mft_rec) typedef struct osm_mftr_search_ctxt { const ib_mft_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_mftr_search_ctxt_t; static ib_api_status_t mftr_rcv_new_mftr(IN osm_sa_t * sa, IN osm_switch_t * p_sw, IN cl_qlist_t * p_list, IN ib_net16_t lid, IN uint16_t block, IN uint8_t position) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; uint16_t position_block_num; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_MFTR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A02: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New MulticastForwardingTable: sw 0x%016" PRIx64 "\n\t\t\t\tblock %u position %u lid %u\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), block, position, cl_ntoh16(lid)); position_block_num = ((uint16_t) position << 12) | (block & IB_MCAST_BLOCK_ID_MASK_HO); memset(p_rec_item, 0, SA_MFTR_RESP_SIZE); p_rec_item->resp.mft_rec.lid = lid; p_rec_item->resp.mft_rec.position_block_num = cl_hton16(position_block_num); /* copy the mft block */ osm_switch_get_mft_block(p_sw, block, position, p_rec_item->resp.mft_rec.mft); cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void mftr_rcv_by_comp_mask(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_mftr_search_ctxt_t *p_ctxt = cxt; osm_switch_t *p_sw = (osm_switch_t *) p_map_item; const ib_mft_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; osm_sa_t *sa = p_ctxt->sa; ib_net64_t const comp_mask = p_ctxt->comp_mask; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; osm_port_t *p_port; uint16_t min_lid_ho, max_lid_ho; uint16_t position_block_num_ho; uint16_t min_block, max_block, block; const osm_physp_t *p_physp; uint8_t min_position, max_position, position; /* In switches, the port guid is the node guid. */ p_port = osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid); if (!p_port) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A05: " "Failed to find Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); return; } /* check that the requester physp and the current physp are under the same partition. */ p_physp = p_port->p_physp; if (!p_physp) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A06: " "Failed to find default physical Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); return; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) return; /* get the port 0 of the switch */ osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); /* compare the lids - if required */ if (comp_mask & IB_MFTR_COMPMASK_LID) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing lid:%u to port lid range: %u .. %u\n", cl_ntoh16(p_rcvd_rec->lid), min_lid_ho, max_lid_ho); /* ok we are ready for range check */ if (min_lid_ho > cl_ntoh16(p_rcvd_rec->lid) || max_lid_ho < cl_ntoh16(p_rcvd_rec->lid)) return; } if (!osm_switch_supports_mcast(p_sw)) return; /* Are there any blocks in use ? */ if (osm_switch_get_mft_max_block_in_use(p_sw) == -1) return; position_block_num_ho = cl_ntoh16(p_rcvd_rec->position_block_num); /* now we need to decide which blocks to output */ if (comp_mask & IB_MFTR_COMPMASK_BLOCK) { max_block = min_block = position_block_num_ho & IB_MCAST_BLOCK_ID_MASK_HO; if (max_block > osm_switch_get_mft_max_block_in_use(p_sw)) return; } else { /* use as many blocks as needed */ min_block = 0; max_block = osm_switch_get_mft_max_block_in_use(p_sw); } /* need to decide which positions to output */ if (comp_mask & IB_MFTR_COMPMASK_POSITION) { min_position = max_position = (position_block_num_ho & 0xF000) >> 12; if (max_position > osm_switch_get_mft_max_position(p_sw)) return; } else { /* use as many positions as needed */ min_position = 0; max_position = osm_switch_get_mft_max_position(p_sw); } /* so we can add these one by one ... */ for (block = min_block; block <= max_block; block++) for (position = min_position; position <= max_position; position++) mftr_rcv_new_mftr(sa, p_sw, p_ctxt->p_list, osm_port_get_base_lid(p_port), block, position); } void osm_mftr_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_mft_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_mftr_search_ctxt_t context; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_mft_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_MFT_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A08: " "Unsupported Method (%s) for MFTRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4A07: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; /* Go over all switches */ cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl, mftr_rcv_by_comp_mask, &context); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_mft_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_link_record.c0000644000205000001450000003414412314616647015331 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_lr_rcv_t. * This object represents the LinkRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SA_LINK_RECORD_C #include #include #include #include #include #include #define SA_LR_RESP_SIZE SA_ITEM_RESP_SIZE(link_rec) static void lr_rcv_build_physp_link(IN osm_sa_t * sa, IN ib_net16_t from_lid, IN ib_net16_t to_lid, IN uint8_t from_port, IN uint8_t to_port, IN cl_qlist_t * p_list) { osm_sa_item_t *p_lr_item; p_lr_item = malloc(SA_LR_RESP_SIZE); if (p_lr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1801: " "Unable to acquire link record\n" "\t\t\t\tFrom port %u\n" "\t\t\t\tTo port %u\n" "\t\t\t\tFrom lid %u\n" "\t\t\t\tTo lid %u\n", from_port, to_port, cl_ntoh16(from_lid), cl_ntoh16(to_lid)); return; } memset(p_lr_item, 0, SA_LR_RESP_SIZE); p_lr_item->resp.link_rec.from_port_num = from_port; p_lr_item->resp.link_rec.to_port_num = to_port; p_lr_item->resp.link_rec.to_lid = to_lid; p_lr_item->resp.link_rec.from_lid = from_lid; cl_qlist_insert_tail(p_list, &p_lr_item->list_item); } static ib_net16_t get_base_lid(IN const osm_physp_t * p_physp) { if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) p_physp = osm_node_get_physp_ptr(p_physp->p_node, 0); return osm_physp_get_base_lid(p_physp); } static void lr_rcv_get_physp_link(IN osm_sa_t * sa, IN const ib_link_record_t * p_lr, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list, IN const osm_physp_t * p_req_physp) { uint8_t src_port_num; uint8_t dest_port_num; ib_net16_t from_base_lid; ib_net16_t to_base_lid; ib_net16_t lmc_mask; OSM_LOG_ENTER(sa->p_log); /* If only one end of the link is specified, determine the other side. */ if (p_src_physp) { if (p_dest_physp) { /* Ensure the two physp's are actually connected. If not, bail out. */ if (osm_physp_get_remote(p_src_physp) != p_dest_physp) goto Exit; } else { p_dest_physp = osm_physp_get_remote(p_src_physp); if (p_dest_physp == NULL) goto Exit; } } else { if (p_dest_physp) { p_src_physp = osm_physp_get_remote(p_dest_physp); if (p_src_physp == NULL) goto Exit; } else goto Exit; /* no physp's, so nothing to do */ } /* Check that the p_src_physp, p_dest_physp and p_req_physp all share a pkey (doesn't have to be the same p_key). */ if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Source and Dest PhysPorts do not share PKey\n"); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_src_physp, p_req_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Source and Requester PhysPorts do not share PKey\n"); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester and Dest PhysPorts do not share PKey\n"); goto Exit; } src_port_num = osm_physp_get_port_num(p_src_physp); dest_port_num = osm_physp_get_port_num(p_dest_physp); if (comp_mask & IB_LR_COMPMASK_FROM_PORT) if (src_port_num != p_lr->from_port_num) goto Exit; if (comp_mask & IB_LR_COMPMASK_TO_PORT) if (dest_port_num != p_lr->to_port_num) goto Exit; from_base_lid = get_base_lid(p_src_physp); to_base_lid = get_base_lid(p_dest_physp); lmc_mask = ~((1 << sa->p_subn->opt.lmc) - 1); lmc_mask = cl_hton16(lmc_mask); if (comp_mask & IB_LR_COMPMASK_FROM_LID) if (from_base_lid != (p_lr->from_lid & lmc_mask)) goto Exit; if (comp_mask & IB_LR_COMPMASK_TO_LID) if (to_base_lid != (p_lr->to_lid & lmc_mask)) goto Exit; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Acquiring link record\n" "\t\t\t\tsrc port 0x%" PRIx64 " (port %u)" ", dest port 0x%" PRIx64 " (port %u)\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), src_port_num, cl_ntoh64(osm_physp_get_port_guid(p_dest_physp)), dest_port_num); lr_rcv_build_physp_link(sa, from_base_lid, to_base_lid, src_port_num, dest_port_num, p_list); Exit: OSM_LOG_EXIT(sa->p_log); } static void lr_rcv_get_port_links(IN osm_sa_t * sa, IN const ib_link_record_t * p_lr, IN const osm_port_t * p_src_port, IN const osm_port_t * p_dest_port, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list, IN const osm_physp_t * p_req_physp) { const osm_physp_t *p_src_physp; const osm_physp_t *p_dest_physp; const cl_qmap_t *p_node_tbl; osm_node_t *p_node; uint8_t port_num; uint8_t num_ports; uint8_t dest_num_ports; uint8_t dest_port_num; OSM_LOG_ENTER(sa->p_log); if (p_src_port) { if (p_dest_port) { /* Build an LR for every link connected between both ports. The inner function will discard physp combinations that do not actually connect. Don't bother screening for that here. */ num_ports = osm_node_get_num_physp(p_src_port->p_node); dest_num_ports = osm_node_get_num_physp(p_dest_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_src_port->p_node, port_num); for (dest_port_num = 1; dest_port_num < dest_num_ports; dest_port_num++) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, dest_port_num); /* both physical ports should be with data */ if (p_src_physp && p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, p_dest_physp, comp_mask, p_list, p_req_physp); } } } else { /* Build an LR for every link connected from the source port. */ if (comp_mask & IB_LR_COMPMASK_FROM_PORT) { port_num = p_lr->from_port_num; /* If the port number is out of the range of the p_src_port, then this couldn't be a relevant record. */ if (port_num < p_src_port->p_node->physp_tbl_size) { p_src_physp = osm_node_get_physp_ptr(p_src_port-> p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } } else { num_ports = osm_node_get_num_physp(p_src_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_src_port-> p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } } } } else { if (p_dest_port) { /* Build an LR for every link connected to the dest port. */ if (comp_mask & IB_LR_COMPMASK_TO_PORT) { port_num = p_lr->to_port_num; /* If the port number is out of the range of the p_dest_port, then this couldn't be a relevant record. */ if (port_num < p_dest_port->p_node->physp_tbl_size) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, port_num); if (p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, NULL, p_dest_physp, comp_mask, p_list, p_req_physp); } } else { num_ports = osm_node_get_num_physp(p_dest_port->p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_dest_physp = osm_node_get_physp_ptr(p_dest_port-> p_node, port_num); if (p_dest_physp) lr_rcv_get_physp_link (sa, p_lr, NULL, p_dest_physp, comp_mask, p_list, p_req_physp); } } } else { /* Process the world (recurse once back into this function). */ p_node_tbl = &sa->p_subn->node_guid_tbl; p_node = (osm_node_t *) cl_qmap_head(p_node_tbl); while (p_node != (osm_node_t *) cl_qmap_end(p_node_tbl)) { num_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < num_ports; port_num++) { p_src_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_src_physp) lr_rcv_get_physp_link (sa, p_lr, p_src_physp, NULL, comp_mask, p_list, p_req_physp); } p_node = (osm_node_t *) cl_qmap_next(&p_node-> map_item); } } } OSM_LOG_EXIT(sa->p_log); } /********************************************************************** Returns the SA status to return to the client. **********************************************************************/ static ib_net16_t lr_rcv_get_end_points(IN osm_sa_t * sa, IN const osm_madw_t * p_madw, OUT const osm_port_t ** pp_src_port, OUT const osm_port_t ** pp_dest_port) { const ib_link_record_t *p_lr; const ib_sa_mad_t *p_sa_mad; ib_net64_t comp_mask; ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; OSM_LOG_ENTER(sa->p_log); /* Determine what fields are valid and then get a pointer to the source and destination port objects, if possible. */ p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_lr = (ib_link_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); comp_mask = p_sa_mad->comp_mask; *pp_src_port = NULL; *pp_dest_port = NULL; if (comp_mask & IB_LR_COMPMASK_FROM_LID) { *pp_src_port = osm_get_port_by_lid(sa->p_subn, p_lr->from_lid); if (!*pp_src_port) { /* This 'error' is the client's fault (bad lid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No source port with LID %u\n", cl_ntoh16(p_lr->from_lid)); sa_status = IB_SA_MAD_STATUS_NO_RECORDS; goto Exit; } } if (comp_mask & IB_LR_COMPMASK_TO_LID) { *pp_dest_port = osm_get_port_by_lid(sa->p_subn, p_lr->to_lid); if (!*pp_dest_port) { /* This 'error' is the client's fault (bad lid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No dest port with LID %u\n", cl_ntoh16(p_lr->to_lid)); sa_status = IB_SA_MAD_STATUS_NO_RECORDS; goto Exit; } } Exit: OSM_LOG_EXIT(sa->p_log); return sa_status; } void osm_lr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; const ib_link_record_t *p_lr; const ib_sa_mad_t *p_sa_mad; const osm_port_t *p_src_port; const osm_port_t *p_dest_port; cl_qlist_t lr_list; ib_net16_t status; osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_lr = ib_sa_mad_get_payload_ptr(p_sa_mad); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_LINK_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_sa_mad->method != IB_MAD_METHOD_GET && p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1804: " "Unsupported Method (%s) for LinkRecord request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1805: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_link_record_v2(sa->p_log, p_lr, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&lr_list); /* Most SA functions (including this one) are read-only on the subnet object, so we grab the lock non-exclusively. */ status = lr_rcv_get_end_points(sa, p_madw, &p_src_port, &p_dest_port); if (status == IB_SA_MAD_STATUS_SUCCESS) lr_rcv_get_port_links(sa, p_lr, p_src_port, p_dest_port, p_sa_mad->comp_mask, &lr_list, p_req_physp); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_link_record_t), &lr_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_mad_ctrl.c0000644000205000001450000004075412452606342014621 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_sa_mad_ctrl_t. * This object is part of the SA object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_SA_MAD_CTRL_C #include #include #include #include #include #include /****f* opensm: SA/sa_mad_ctrl_disp_done_callback * NAME * sa_mad_ctrl_disp_done_callback * * DESCRIPTION * This function is the Dispatcher callback that indicates * a received MAD has been processed by the recipient. * * SYNOPSIS */ static void sa_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data) { osm_sa_mad_ctrl_t *p_ctrl = context; osm_madw_t *p_madw = p_data; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); /* Return the MAD & wrapper to the pool. */ osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); OSM_LOG_EXIT(p_ctrl->p_log); } /************/ /****f* opensm: SA/sa_mad_ctrl_process * NAME * sa_mad_ctrl_process * * DESCRIPTION * This function handles known methods for received MADs. * * SYNOPSIS */ static void sa_mad_ctrl_process(IN osm_sa_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw, IN boolean_t is_get_request) { ib_sa_mad_t *p_sa_mad; cl_disp_reg_handle_t h_disp; cl_status_t status; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; uint64_t last_dispatched_msg_queue_time_msec; uint32_t num_messages; OSM_LOG_ENTER(p_ctrl->p_log); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); /* If the dispatcher is showing us that it is overloaded there is no point in placing the request in. We should instead provide immediate response - IB_RESOURCE_BUSY But how do we know? The dispatcher reports back the number of outstanding messages and the time the last message stayed in the queue. HACK: Actually, we cannot send a mad from within the receive callback; thus - we will just drop it. */ if (!is_get_request && p_ctrl->p_set_disp) { h_disp = p_ctrl->h_set_disp; goto SKIP_QUEUE_CHECK; } h_disp = p_ctrl->h_disp; cl_disp_get_queue_status(h_disp, &num_messages, &last_dispatched_msg_queue_time_msec); if (num_messages > 1 && p_ctrl->p_subn->opt.max_msg_fifo_timeout && last_dispatched_msg_queue_time_msec > p_ctrl->p_subn->opt.max_msg_fifo_timeout) { OSM_LOG(p_ctrl->p_log, OSM_LOG_INFO, /* "Responding BUSY status since the dispatcher is already" */ "Dropping MAD since the dispatcher is already" " overloaded with %u messages and queue time of:" "%" PRIu64 "[msec]\n", num_messages, last_dispatched_msg_queue_time_msec); /* send a busy response */ /* osm_sa_send_error(p_ctrl->p_resp, p_madw, IB_RESOURCE_BUSY); */ /* return the request to the pool */ osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } SKIP_QUEUE_CHECK: /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_sa_mad->attr_id) { case IB_MAD_ATTR_CLASS_PORT_INFO: msg_id = OSM_MSG_MAD_CLASS_PORT_INFO; break; case IB_MAD_ATTR_NODE_RECORD: msg_id = OSM_MSG_MAD_NODE_RECORD; break; case IB_MAD_ATTR_PORTINFO_RECORD: msg_id = OSM_MSG_MAD_PORTINFO_RECORD; break; case IB_MAD_ATTR_LINK_RECORD: msg_id = OSM_MSG_MAD_LINK_RECORD; break; case IB_MAD_ATTR_SMINFO_RECORD: msg_id = OSM_MSG_MAD_SMINFO_RECORD; break; case IB_MAD_ATTR_SERVICE_RECORD: msg_id = OSM_MSG_MAD_SERVICE_RECORD; break; case IB_MAD_ATTR_PATH_RECORD: msg_id = OSM_MSG_MAD_PATH_RECORD; break; case IB_MAD_ATTR_MCMEMBER_RECORD: msg_id = OSM_MSG_MAD_MCMEMBER_RECORD; break; case IB_MAD_ATTR_INFORM_INFO: msg_id = OSM_MSG_MAD_INFORM_INFO; break; case IB_MAD_ATTR_VLARB_RECORD: msg_id = OSM_MSG_MAD_VL_ARB_RECORD; break; case IB_MAD_ATTR_SLVL_RECORD: msg_id = OSM_MSG_MAD_SLVL_TBL_RECORD; break; case IB_MAD_ATTR_PKEY_TBL_RECORD: msg_id = OSM_MSG_MAD_PKEY_TBL_RECORD; break; case IB_MAD_ATTR_LFT_RECORD: msg_id = OSM_MSG_MAD_LFT_RECORD; break; case IB_MAD_ATTR_GUIDINFO_RECORD: msg_id = OSM_MSG_MAD_GUIDINFO_RECORD; break; case IB_MAD_ATTR_INFORM_INFO_RECORD: msg_id = OSM_MSG_MAD_INFORM_INFO_RECORD; break; case IB_MAD_ATTR_SWITCH_INFO_RECORD: msg_id = OSM_MSG_MAD_SWITCH_INFO_RECORD; break; case IB_MAD_ATTR_MFT_RECORD: msg_id = OSM_MSG_MAD_MFT_RECORD; break; #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) case IB_MAD_ATTR_MULTIPATH_RECORD: msg_id = OSM_MSG_MAD_MULTIPATH_RECORD; break; #endif default: OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A01: " "Unsupported attribute 0x%X (%s)\n", cl_ntoh16(p_sa_mad->attr_id), ib_get_sa_attr_str(p_sa_mad->attr_id)); osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_ERROR); } if (msg_id != CL_DISP_MSGID_NONE) { /* Post this MAD to the dispatcher for asynchronous processing by the appropriate controller. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(msg_id)); status = cl_disp_post(h_disp, msg_id, p_madw, sa_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A02: " "Dispatcher post message failed (%s) for attribute 0x%X (%s)\n", CL_STATUS_MSG(status), cl_ntoh16(p_sa_mad->attr_id), ib_get_sa_attr_str(p_sa_mad->attr_id)); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } } else { /* There is an unknown MAD attribute type for which there is no recipient. Simply retire the MAD here. */ cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SA/sa_mad_ctrl_rcv_callback * NAME * sa_mad_ctrl_rcv_callback * * DESCRIPTION * This is the callback from the transport layer for received MADs. * * SYNOPSIS */ static void sa_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, IN void *context, IN osm_madw_t * p_req_madw) { osm_sa_mad_ctrl_t *p_ctrl = context; ib_sa_mad_t *p_sa_mad; boolean_t is_get_request = FALSE; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); /* A MAD was received from the wire, possibly in response to a request. */ cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd); OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u SA MADs received\n", p_ctrl->p_stats->sa_mads_rcvd); /* * C15-0.1.3 requires not responding to any MAD if the SM is * not in active state! * We will not respond if the sm_state is not MASTER, or if the * first_time_master_sweep flag (of the subnet) is TRUE - this * flag indicates that the master still didn't finish its first * sweep, so the subnet is not up and stable yet. */ if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) { cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored); OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, "Received SA MAD while SM not MASTER. MAD ignored\n"); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } if (p_ctrl->p_subn->first_time_master_sweep == TRUE) { cl_atomic_inc(&p_ctrl->p_stats->sa_mads_ignored); OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, "Received SA MAD while SM in first sweep. MAD ignored\n"); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES)) osm_dump_sa_mad_v2(p_ctrl->p_log, p_sa_mad, FILE_ID, OSM_LOG_FRAMES); /* * C15-0.1.5 - Table 185: SA Header - p884 * SM_key should be either 0 or match the current SM_Key * otherwise discard the MAD. */ if (p_sa_mad->sm_key != 0 && p_sa_mad->sm_key != p_ctrl->p_subn->opt.sa_key) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A04: " "Non-Zero MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%" PRIx64 "; SA MAD ignored for method 0x%X attribute 0x%X (%s)\n", cl_ntoh64(p_sa_mad->sm_key), cl_ntoh64(p_ctrl->p_subn->opt.sa_key), p_sa_mad->method, cl_ntoh16(p_sa_mad->attr_id), ib_get_sa_attr_str(p_sa_mad->attr_id)); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } switch (p_sa_mad->method) { case IB_MAD_METHOD_REPORT_RESP: /* we do not really do anything with report represses - just retire the transaction */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Received Report Repress. Retiring the transaction\n"); if (p_req_madw) osm_mad_pool_put(p_ctrl->p_mad_pool, p_req_madw); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); break; case IB_MAD_METHOD_GET: case IB_MAD_METHOD_GETTABLE: #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) case IB_MAD_METHOD_GETMULTI: #endif is_get_request = TRUE; case IB_MAD_METHOD_SET: case IB_MAD_METHOD_DELETE: /* if we are closing down simply do nothing */ if (osm_exit_flag) osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); else sa_mad_ctrl_process(p_ctrl, p_madw, is_get_request); break; default: cl_atomic_inc(&p_ctrl->p_stats->sa_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A05: " "Unsupported method = 0x%X\n", p_sa_mad->method); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SA/sa_mad_ctrl_send_err_callback * NAME * sa_mad_ctrl_send_err_callback * * DESCRIPTION * This is the callback from the transport layer for send errors * on MADs that were expecting a response. * * SYNOPSIS */ static void sa_mad_ctrl_send_err_callback(IN void *context, IN osm_madw_t * p_madw) { osm_sa_mad_ctrl_t *p_ctrl = context; cl_status_t status; OSM_LOG_ENTER(p_ctrl->p_log); /* We should never be here since the SA never originates a request. Unless we generated a Report(Notice) */ CL_ASSERT(p_madw); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A06: " "MAD completed in error (%s): " "%s(%s), attr_mod 0x%x, LID %u, TID 0x%" PRIx64 "\n", ib_get_err_str(p_madw->status), ib_get_sa_method_str(p_madw->p_mad->method), ib_get_sa_attr_str(p_madw->p_mad->attr_id), cl_ntoh32(p_madw->p_mad->attr_mod), cl_ntoh16(p_madw->mad_addr.dest_lid), cl_ntoh64(p_madw->p_mad->trans_id)); osm_dump_sa_mad_v2(p_ctrl->p_log, osm_madw_get_sa_mad_ptr(p_madw), FILE_ID, OSM_LOG_ERROR); /* An error occurred. No response was received to a request MAD. Retire the original request MAD. */ if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) { OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw))); if (p_ctrl->p_set_disp && (p_madw->p_mad->method == IB_MAD_METHOD_SET || p_madw->p_mad->method == IB_MAD_METHOD_DELETE)) status = cl_disp_post(p_ctrl->h_set_disp, osm_madw_get_err_msg(p_madw), p_madw, sa_mad_ctrl_disp_done_callback, p_ctrl); else status = cl_disp_post(p_ctrl->h_disp, osm_madw_get_err_msg(p_madw), p_madw, sa_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A07: " "Dispatcher post message failed (%s)\n", CL_STATUS_MSG(status)); } } else /* No error message was provided, just retire the MAD. */ osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ void osm_sa_mad_ctrl_construct(IN osm_sa_mad_ctrl_t * p_ctrl) { CL_ASSERT(p_ctrl); memset(p_ctrl, 0, sizeof(*p_ctrl)); p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; p_ctrl->h_set_disp = CL_DISP_INVALID_HANDLE; } void osm_sa_mad_ctrl_destroy(IN osm_sa_mad_ctrl_t * p_ctrl) { CL_ASSERT(p_ctrl); cl_disp_unregister(p_ctrl->h_disp); cl_disp_unregister(p_ctrl->h_set_disp); } ib_api_status_t osm_sa_mad_ctrl_init(IN osm_sa_mad_ctrl_t * p_ctrl, IN osm_sa_t * sa, IN osm_mad_pool_t * p_mad_pool, IN osm_vendor_t * p_vendor, IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_dispatcher_t * p_set_disp) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); osm_sa_mad_ctrl_construct(p_ctrl); p_ctrl->sa = sa; p_ctrl->p_log = p_log; p_ctrl->p_disp = p_disp; p_ctrl->p_set_disp = p_set_disp; p_ctrl->p_mad_pool = p_mad_pool; p_ctrl->p_vendor = p_vendor; p_ctrl->p_stats = p_stats; p_ctrl->p_subn = p_subn; p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL, p_ctrl); if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A08: " "Dispatcher registration failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } if (p_set_disp) { p_ctrl->h_set_disp = cl_disp_register(p_set_disp, CL_DISP_MSGID_NONE, NULL, p_ctrl); if (p_ctrl->h_set_disp == CL_DISP_INVALID_HANDLE) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1A0A: " "SA set dispatcher registration failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } } Exit: OSM_LOG_EXIT(p_log); return status; } ib_api_status_t osm_sa_mad_ctrl_bind(IN osm_sa_mad_ctrl_t * p_ctrl, IN ib_net64_t port_guid) { osm_bind_info_t bind_info; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_ctrl->p_log); if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A09: " "Multiple binds not allowed\n"); status = IB_ERROR; goto Exit; } bind_info.class_version = 2; bind_info.is_responder = TRUE; bind_info.is_report_processor = FALSE; bind_info.is_trap_processor = FALSE; bind_info.mad_class = IB_MCLASS_SUBN_ADM; bind_info.port_guid = port_guid; bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE; bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE; bind_info.timeout = p_ctrl->sa->p_subn->opt.transaction_timeout; bind_info.retries = p_ctrl->sa->p_subn->opt.transaction_retries; OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, "Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info, p_ctrl->p_mad_pool, sa_mad_ctrl_rcv_callback, sa_mad_ctrl_send_err_callback, p_ctrl); if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { status = IB_ERROR; OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A10: " "Vendor specific bind failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); return status; } ib_api_status_t osm_sa_mad_ctrl_unbind(IN osm_sa_mad_ctrl_t * p_ctrl) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_ctrl->p_log); if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 1A11: " "No previous bind\n"); status = IB_ERROR; goto Exit; } osm_vendor_unbind(p_ctrl->h_bind); Exit: OSM_LOG_EXIT(p_ctrl->p_log); return status; } opensm-3.3.20/opensm/osm_sa_mcmember_record.c0000644000205000001450000016227012662547430016164 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_mcmr_recv_t. * This object represents the MCMemberRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_MCMEMBER_RECORD_C #include #include #include #include #include #include #include #include #include #include #define SA_MCM_RESP_SIZE SA_ITEM_RESP_SIZE(mc_rec) #define JOIN_MC_COMP_MASK (IB_MCR_COMPMASK_MGID | \ IB_MCR_COMPMASK_PORT_GID | \ IB_MCR_COMPMASK_JOIN_STATE) #define REQUIRED_MC_CREATE_COMP_MASK (IB_MCR_COMPMASK_MGID | \ IB_MCR_COMPMASK_PORT_GID | \ IB_MCR_COMPMASK_JOIN_STATE | \ IB_MCR_COMPMASK_QKEY | \ IB_MCR_COMPMASK_TCLASS | \ IB_MCR_COMPMASK_PKEY | \ IB_MCR_COMPMASK_FLOW | \ IB_MCR_COMPMASK_SL) #define IPV4_BCAST_MGID_PREFIX CL_HTON64(0xff10401b00000000ULL) #define IPV4_BCAST_MGID_INT_ID CL_HTON64(0x00000000ffffffffULL) static int validate_other_comp_fields(osm_log_t * p_log, ib_net64_t comp_mask, const ib_member_rec_t * p_mcmr, osm_mgrp_t * p_mgrp, osm_log_level_t log_level); /********************************************************************* Copy certain fields between two mcmember records used during the process of join request to copy data from the mgrp to the port record. **********************************************************************/ static void copy_from_create_mc_rec(IN ib_member_rec_t * dest, IN const ib_member_rec_t * src) { dest->qkey = src->qkey; dest->mlid = src->mlid; dest->tclass = src->tclass; dest->pkey = src->pkey; dest->sl_flow_hop = src->sl_flow_hop; dest->scope_state = ib_member_set_scope_state(src->scope_state >> 4, dest->scope_state & 0x0F); dest->mtu = src->mtu; dest->rate = src->rate; dest->pkt_life = src->pkt_life; } /********************************************************************* Return mlid to the pool of free mlids. But this implementation is not a pool - it simply scans through the MGRP database for unused mlids... *********************************************************************/ static void free_mlid(IN osm_sa_t * sa, IN uint16_t mlid) { UNUSED_PARAM(sa); UNUSED_PARAM(mlid); } /********************************************************************* Get a new unused mlid by scanning all the used ones in the subnet. **********************************************************************/ /* Special Case IPv6 Solicited Node Multicast (SNM) addresses */ /* 0xff1Z601bXXXX0000 : 0x00000001ffYYYYYY */ /* Where Z is the scope, XXXX is the P_Key, and * YYYYYY is the last 24 bits of the port guid */ #define PREFIX_MASK CL_HTON64(0xff10ffff0000ffffULL) #define PREFIX_SIGNATURE CL_HTON64(0xff10601b00000000ULL) #define INT_ID_MASK CL_HTON64(0xfffffff1ff000000ULL) #define INT_ID_SIGNATURE CL_HTON64(0x00000001ff000000ULL) static int compare_ipv6_snm_mgids(const void *m1, const void *m2) { return memcmp(m1, m2, sizeof(ib_gid_t) - 3); } static ib_net16_t find_ipv6_snm_mlid(osm_subn_t *subn, ib_gid_t *mgid) { osm_mgrp_t *m = (osm_mgrp_t *)cl_fmap_match(&subn->mgrp_mgid_tbl, mgid, compare_ipv6_snm_mgids); if (m != (osm_mgrp_t *)cl_fmap_end(&subn->mgrp_mgid_tbl)) return m->mlid; return 0; } static unsigned match_ipv6_snm_mgid(ib_gid_t * mgid) { return ((mgid->unicast.prefix & PREFIX_MASK) == PREFIX_SIGNATURE && (mgid->unicast.interface_id & INT_ID_MASK) == INT_ID_SIGNATURE); } static ib_net16_t get_new_mlid(osm_sa_t * sa, ib_member_rec_t * mcmr) { osm_subn_t *p_subn = sa->p_subn; ib_net16_t requested_mlid = mcmr->mlid; unsigned i, max; if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO && cl_ntoh16(requested_mlid) <= p_subn->max_mcast_lid_ho && !osm_get_mbox_by_mlid(p_subn, requested_mlid)) return requested_mlid; if (sa->p_subn->opt.consolidate_ipv6_snm_req && match_ipv6_snm_mgid(&mcmr->mgid) && (requested_mlid = find_ipv6_snm_mlid(sa->p_subn, &mcmr->mgid))) { char str[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Special Case Solicited Node Mcast Join for MGID %s\n", inet_ntop(AF_INET6, mcmr->mgid.raw, str, sizeof(str))); return requested_mlid; } max = p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO + 1; for (i = 0; i < max; i++) if (!sa->p_subn->mboxes[i]) return cl_hton16(i + IB_LID_MCAST_START_HO); return 0; } static inline boolean_t check_join_comp_mask(ib_net64_t comp_mask) { return ((comp_mask & JOIN_MC_COMP_MASK) == JOIN_MC_COMP_MASK); } static boolean_t check_create_comp_mask(ib_net64_t comp_mask, ib_member_rec_t * p_recvd_mcmember_rec) { return ((comp_mask & REQUIRED_MC_CREATE_COMP_MASK) == REQUIRED_MC_CREATE_COMP_MASK); } /********************************************************************** Generate the response MAD **********************************************************************/ static void mcmr_rcv_respond(IN osm_sa_t * sa, IN osm_madw_t * p_madw, IN ib_member_rec_t * p_mcmember_rec) { cl_qlist_t rec_list; osm_sa_item_t *item; OSM_LOG_ENTER(sa->p_log); item = malloc(SA_MCM_RESP_SIZE); if (!item) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B16: " "rec_item alloc failed\n"); goto Exit; } item->resp.mc_rec = *p_mcmember_rec; /* Fill in the mtu, rate, and packet lifetime selectors */ item->resp.mc_rec.mtu &= 0x3f; item->resp.mc_rec.mtu |= IB_PATH_SELECTOR_EXACTLY << 6; item->resp.mc_rec.rate &= 0x3f; item->resp.mc_rec.rate |= IB_PATH_SELECTOR_EXACTLY << 6; item->resp.mc_rec.pkt_life &= 0x3f; item->resp.mc_rec.pkt_life |= IB_PATH_SELECTOR_EXACTLY << 6; cl_qlist_init(&rec_list); cl_qlist_insert_tail(&rec_list, &item->list_item); osm_sa_respond(sa, p_madw, sizeof(ib_member_rec_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } /********************************************************************* In joining an existing group, or when querying the mc groups, we make sure the following components provided match: MTU and RATE HACK: Currently we ignore the PKT_LIFETIME field. **********************************************************************/ static boolean_t validate_more_comp_fields(osm_log_t * p_log, const osm_mgrp_t * p_mgrp, const ib_member_rec_t * p_recvd_mcmember_rec, ib_net64_t comp_mask) { uint8_t mtu_sel; uint8_t mtu_required; uint8_t mtu_mgrp; uint8_t rate_sel; uint8_t rate_required; uint8_t rate_mgrp; if (comp_mask & IB_MCR_COMPMASK_MTU_SEL) { mtu_sel = (uint8_t) (p_recvd_mcmember_rec->mtu >> 6); /* Clearing last 2 bits */ mtu_required = (uint8_t) (p_recvd_mcmember_rec->mtu & 0x3F); mtu_mgrp = (uint8_t) (p_mgrp->mcmember_rec.mtu & 0x3F); switch (mtu_sel) { case 0: /* Greater than MTU specified */ if (mtu_mgrp <= mtu_required) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has MTU %x, " "which is not greater than %x\n", mtu_mgrp, mtu_required); return FALSE; } break; case 1: /* Less than MTU specified */ if (mtu_mgrp >= mtu_required) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has MTU %x, " "which is not less than %x\n", mtu_mgrp, mtu_required); return FALSE; } break; case 2: /* Exactly MTU specified */ if (mtu_mgrp != mtu_required) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has MTU %x, " "which is not equal to %x\n", mtu_mgrp, mtu_required); return FALSE; } break; default: break; } } /* what about rate ? */ if (comp_mask & IB_MCR_COMPMASK_RATE_SEL) { rate_sel = (uint8_t) (p_recvd_mcmember_rec->rate >> 6); /* Clearing last 2 bits */ rate_required = (uint8_t) (p_recvd_mcmember_rec->rate & 0x3F); rate_mgrp = (uint8_t) (p_mgrp->mcmember_rec.rate & 0x3F); switch (rate_sel) { case 0: /* Greater than RATE specified */ if (ib_path_compare_rates(rate_mgrp, rate_required) <= 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has RATE %x, " "which is not greater than %x\n", rate_mgrp, rate_required); return FALSE; } break; case 1: /* Less than RATE specified */ if (ib_path_compare_rates(rate_mgrp, rate_required) >= 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has RATE %x, " "which is not less than %x\n", rate_mgrp, rate_required); return FALSE; } break; case 2: /* Exactly RATE specified */ if (ib_path_compare_rates(rate_mgrp, rate_required)) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested mcast group has RATE %x, " "which is not equal to %x\n", rate_mgrp, rate_required); return FALSE; } break; default: break; } } return TRUE; } /********************************************************************* In joining an existing group, we make sure the following components are physically realizable: MTU and RATE **********************************************************************/ static boolean_t validate_port_caps(osm_log_t * p_log, const osm_mgrp_t * p_mgrp, const osm_physp_t * p_physp) { const ib_port_info_t *p_pi; uint8_t mtu_required; uint8_t mtu_mgrp; uint8_t rate_required; uint8_t rate_mgrp; int extended; mtu_required = ib_port_info_get_neighbor_mtu(&p_physp->port_info); mtu_mgrp = (uint8_t) (p_mgrp->mcmember_rec.mtu & 0x3F); if (mtu_required < mtu_mgrp) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Port's MTU %x is less than %x\n", mtu_required, mtu_mgrp); return FALSE; } p_pi = &p_physp->port_info; extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; rate_required = ib_port_info_compute_rate(p_pi, extended); rate_mgrp = (uint8_t) (p_mgrp->mcmember_rec.rate & 0x3F); if (ib_path_compare_rates(rate_required, rate_mgrp) < 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Port's RATE %x is less than %x\n", rate_required, rate_mgrp); return FALSE; } return TRUE; } /********************************************************************** * o15-0.2.1: If SA supports UD multicast, then if SA receives a SubnAdmSet() * or SubnAdmDelete() method that would modify an existing * MCMemberRecord, SA shall not modify that MCMemberRecord and shall * return an error status of ERR_REQ_INVALID in response in the * following cases: * 1. Saved MCMemberRecord.ProxyJoin is not set and the request is * issued by a requester with a GID other than the Port-GID. * 2. Saved MCMemberRecord.ProxyJoin is set and the requester is not * part of the partition for that MCMemberRecord. **********************************************************************/ static boolean_t validate_modify(IN osm_sa_t * sa, IN osm_mgrp_t * p_mgrp, IN osm_mad_addr_t * p_mad_addr, IN ib_member_rec_t * p_recvd_mcmember_rec, OUT osm_mcm_alias_guid_t ** pp_mcm_alias_guid) { ib_net64_t portguid; ib_gid_t request_gid; osm_physp_t *p_request_physp; ib_api_status_t res; portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; *pp_mcm_alias_guid = osm_mgrp_get_mcm_alias_guid(p_mgrp, portguid); /* o15-0.2.1: If this is a new port being added - nothing to check */ if (!*pp_mcm_alias_guid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "This is a new port in the MC group\n"); return TRUE; } /* We validate the request according the the proxy_join. Check if the proxy_join is set or not */ if ((*pp_mcm_alias_guid)->proxy_join == FALSE) { /* The proxy_join is not set. Modifying can by done only if the requester GID == PortGID */ res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, p_mad_addr, &request_gid); if (res != IB_SUCCESS) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Could not find port for requested address\n"); return FALSE; } if ((*pp_mcm_alias_guid)->p_base_mcm_port->port->guid != request_gid.unicast.interface_id || (*pp_mcm_alias_guid)->port_gid.unicast.prefix != request_gid.unicast.prefix) { ib_gid_t base_port_gid; char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; base_port_gid.unicast.prefix = (*pp_mcm_alias_guid)->port_gid.unicast.prefix; base_port_gid.unicast.interface_id = (*pp_mcm_alias_guid)->p_base_mcm_port->port->guid; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "No ProxyJoin but different ports: stored:" "%s request:%s\n", inet_ntop(AF_INET6, base_port_gid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, request_gid.raw, gid_str2, sizeof gid_str2)); return FALSE; } } else { /* The proxy_join is set. Modification allowed only if the requester is part of the partition for this MCMemberRecord */ p_request_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, p_mad_addr); if (p_request_physp == NULL) return FALSE; if (!osm_physp_has_pkey(sa->p_log, p_mgrp->mcmember_rec.pkey, p_request_physp)) { /* the request port is not part of the partition for this mgrp */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requesting port 0x%016" PRIx64 " has no PKey 0x%04x\n", cl_ntoh64(p_request_physp->port_guid), cl_ntoh16(p_mgrp->mcmember_rec.pkey)); return FALSE; } } return TRUE; } /* * Check legality of the requested MGID DELETE * o15-0.1.14 = VALID DELETE: * To be a valid delete MAD needs to: * 1 the MADs PortGID and MGID components match the PortGID and * MGID of a stored MCMemberRecord; * 2 the MADs JoinState component contains at least one bit set to 1 * in the same position as that stored MCMemberRecords JoinState * has a bit set to 1, * i.e., the logical AND of the two JoinState components * is not all zeros; * 3 the MADs JoinState component does not have some bits set * which are not set in the stored MCMemberRecords JoinState component; * 4 either the stored MCMemberRecord:ProxyJoin is reset (0), and the * MADs source is the stored PortGID; * OR * the stored MCMemberRecord:ProxyJoin is set (1), (see o15- * 0.1.2:); and the MADs source is a member of the partition indicated * by the stored MCMemberRecord:P_Key. */ static boolean_t validate_delete(IN osm_sa_t * sa, IN osm_mgrp_t * p_mgrp, IN osm_mad_addr_t * p_mad_addr, IN ib_member_rec_t * p_recvd_mcmember_rec, OUT osm_mcm_alias_guid_t ** pp_mcm_alias_guid) { ib_net64_t portguid; portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; *pp_mcm_alias_guid = osm_mgrp_get_mcm_alias_guid(p_mgrp, portguid); /* 1 */ if (!*pp_mcm_alias_guid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Failed to find the port in the MC group\n"); return FALSE; } /* 2 */ if (!(p_recvd_mcmember_rec->scope_state & 0x0F & (*pp_mcm_alias_guid)->scope_state)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Could not find any matching bits in the stored " "and requested JoinStates\n"); return FALSE; } /* 3 */ if (((p_recvd_mcmember_rec->scope_state & 0x0F) | (0x0F & (*pp_mcm_alias_guid)->scope_state)) != (0x0F & (*pp_mcm_alias_guid)->scope_state)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Some bits in the request JoinState (0x%X) are not " "set in the stored port (0x%X)\n", (p_recvd_mcmember_rec->scope_state & 0x0F), (0x0F & (*pp_mcm_alias_guid)->scope_state)); return FALSE; } /* 4 */ /* Validate according the the proxy_join (o15-0.1.2) */ if (validate_modify(sa, p_mgrp, p_mad_addr, p_recvd_mcmember_rec, pp_mcm_alias_guid) == FALSE) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "proxy_join validation failure\n"); return FALSE; } return TRUE; } /* * Check legality of the requested MGID (note this does not hold for SA * created MGIDs) * * Implementing o15-0.1.5: * A multicast GID is considered to be invalid if: * 1. It does not comply with the rules as specified in 4.1.1 "GID Usage and * Properties" on page 145: * * 14) The multicast GID format is (bytes are comma sep): * 0xff,,,,

,

,

,

,

,

,

,

,,,, * Fl 4bit = Flags (b) * Sc 4bit = Scope (c) * Si 16bit = Signature (2) * P 64bit = GID Prefix (should be a subnet unique ID - normally Subnet Prefix) * Id 32bit = Unique ID in the Subnet (might be MLID or P_Key ?) * * a) 8-bits of 11111111 at the start of the GID identifies this as being a * multicast GID. * b) Flags is a set of four 1-bit flags: 000T with three flags reserved * and defined as zero (0). The T flag is defined as follows: * i) T = 0 indicates this is a permanently assigned (i.e. wellknown) * multicast GID. See RFC 2373 and RFC 2375 as reference * for these permanently assigned GIDs. * ii) T = 1 indicates this is a non-permanently assigned (i.e. transient) * multicast GID. * c) Scope is a 4-bit multicast scope value used to limit the scope of * the multicast group. The following table defines scope value and * interpretation. * * Multicast Address Scope Values: * 0x2 Link-local * 0x5 Site-local * 0x8 Organization-local * 0xE Global * * 2. It contains the SA-specific signature of 0xA01B and has the link-local * scope bits set. (EZ: the idea here is that SA created MGIDs are the * only source for this signature with link-local scope) */ static boolean_t validate_requested_mgid(IN osm_sa_t * sa, IN const ib_member_rec_t * p_mcm_rec) { uint16_t signature; boolean_t valid = TRUE; OSM_LOG_ENTER(sa->p_log); /* 14-a: mcast GID must start with 0xFF */ if (p_mcm_rec->mgid.multicast.header[0] != 0xFF) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B01: " "Invalid prefix 0x%02X in requested MGID, " "must be 0xFF\n", cl_ntoh16(p_mcm_rec->mgid.multicast.header[0])); valid = FALSE; goto Exit; } /* the MGID signature can mark IPoIB or SA assigned MGIDs */ memcpy(&signature, &(p_mcm_rec->mgid.multicast.raw_group_id), sizeof(signature)); signature = cl_ntoh16(signature); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MGID Signed as 0x%04X\n", signature); /* * We skip any checks for MGIDs that follow IPoIB * GID structure as defined by the IETF ipoib-link-multicast. * * For IPv4 over IB, the signature will be "0x401B". * * | 8 | 4 | 4 | 16 bits | 16 bits | 48 bits | 32 bits | * +--------+----+----+-----------------+---------+----------+---------+ * |11111111|0001|scop||< P_Key >|00.......0|| * +--------+----+----+-----------------+---------+----------+---------+ * * For IPv6 over IB, the signature will be "0x601B". * * | 8 | 4 | 4 | 16 bits | 16 bits | 80 bits | * +--------+----+----+-----------------+---------+--------------------+ * |11111111|0001|scop||< P_Key >|000.............0001| * +--------+----+----+-----------------+---------+--------------------+ * */ if (signature == 0x401B || signature == 0x601B) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Skipping MGID Validation for IPoIB Signed (0x%04X) MGIDs\n", signature); goto Exit; } /* 14-b: the 3 upper bits in the "flags" should be zero: */ if (p_mcm_rec->mgid.multicast.header[1] & 0xE0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B28: " "Requested MGID invalid, uses Reserved Flags: flags=0x%X\n", (p_mcm_rec->mgid.multicast.header[1] & 0xE0) >> 4); valid = FALSE; goto Exit; } /* 2 - now what if the link local format 0xA01B is used - the scope should not be link local */ if (signature == 0xA01B && (p_mcm_rec->mgid.multicast.header[1] & 0x0F) == IB_MC_SCOPE_LINK_LOCAL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B24: " "Requested MGID invalid, " "uses 0xA01B signature but with link-local scope\n"); valid = FALSE; goto Exit; } /* * For SA assigned MGIDs (signature 0xA01B): * There is no real way to make sure the GID Prefix is really unique. * If we could enforce using the Subnet Prefix for that purpose it would * have been nice. But the spec does not require it. */ Exit: OSM_LOG_EXIT(sa->p_log); return valid; } /********************************************************************** Check if the requested new MC group parameters are realizable. Also set the default MTU and Rate if not provided by the user. **********************************************************************/ static boolean_t mgrp_request_is_realizable(IN osm_sa_t * sa, IN ib_net64_t comp_mask, IN ib_member_rec_t * p_mcm_rec, IN const osm_physp_t * p_physp) { uint8_t mtu_sel = 2; /* exactly */ uint8_t mtu_required, mtu, port_mtu; uint8_t rate_sel = 2; /* exactly */ uint8_t rate_required, rate, port_rate; const ib_port_info_t *p_pi; osm_log_t *p_log = sa->p_log; int extended; OSM_LOG_ENTER(sa->p_log); /* * End of o15-0.2.3 specifies: * .... * The entity may also supply the other components such as HopLimit, * MTU, etc. during group creation time. If these components are not * provided during group creation time, SA will provide them for the * group. The values chosen are vendor-dependent and beyond the scope * of the specification. * * so we might also need to assign RATE/MTU if they are not comp * masked in. */ p_pi = &p_physp->port_info; port_mtu = p_physp ? ib_port_info_get_mtu_cap(p_pi) : 0; if (!(comp_mask & IB_MCR_COMPMASK_MTU) || !(comp_mask & IB_MCR_COMPMASK_MTU_SEL) || (mtu_sel = (p_mcm_rec->mtu >> 6)) == 3) mtu = port_mtu ? port_mtu : sa->p_subn->min_ca_mtu; else { mtu_required = (uint8_t) (p_mcm_rec->mtu & 0x3F); mtu = mtu_required; switch (mtu_sel) { case 0: /* Greater than MTU specified */ if (port_mtu && mtu_required >= port_mtu) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested MTU %x >= the port\'s mtu:%x\n", mtu_required, port_mtu); return FALSE; } /* we provide the largest MTU possible if we can */ if (port_mtu) mtu = port_mtu; else if (mtu_required < sa->p_subn->min_ca_mtu) mtu = sa->p_subn->min_ca_mtu; else mtu++; break; case 1: /* Less than MTU specified */ /* use the smaller of the two: a. one lower then the required b. the mtu of the requesting port (if exists) */ if (port_mtu && mtu_required > port_mtu) mtu = port_mtu; else mtu--; break; case 2: /* Exactly MTU specified */ default: break; } /* make sure it still is in the range */ if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Calculated MTU %x is out of range\n", mtu); return FALSE; } } p_mcm_rec->mtu = (mtu_sel << 6) | mtu; if (p_physp) { extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; port_rate = ib_port_info_compute_rate(p_pi, extended); } else port_rate = 0; if (!(comp_mask & IB_MCR_COMPMASK_RATE) || !(comp_mask & IB_MCR_COMPMASK_RATE_SEL) || (rate_sel = (p_mcm_rec->rate >> 6)) == 3) rate = port_rate ? port_rate : sa->p_subn->min_ca_rate; else { rate_required = (uint8_t) (p_mcm_rec->rate & 0x3F); rate = rate_required; switch (rate_sel) { case 0: /* Greater than RATE specified */ if (ib_path_compare_rates(rate_required, port_rate) >= 0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Requested RATE %x >= the port\'s rate:%x\n", rate_required, port_rate); return FALSE; } /* we provide the largest RATE possible if we can */ if (port_rate) rate = port_rate; else if (ib_path_compare_rates(rate_required, sa->p_subn->min_ca_rate) < 0) rate = sa->p_subn->min_ca_rate; else rate = ib_path_rate_get_next(rate); break; case 1: /* Less than RATE specified */ /* use the smaller of the two: a. one lower then the required b. the rate of the requesting port (if exists) */ if (ib_path_compare_rates(rate_required, port_rate) > 0) rate = port_rate; else rate = ib_path_rate_get_prev(rate); break; case 2: /* Exactly RATE specified */ default: break; } /* make sure it still is in the range */ if (rate < IB_MIN_RATE || rate > IB_MAX_RATE) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Calculated RATE %x is out of range\n", rate); return FALSE; } } p_mcm_rec->rate = (rate_sel << 6) | rate; OSM_LOG_EXIT(sa->p_log); return TRUE; } static unsigned build_new_mgid(osm_sa_t * sa, ib_net64_t comp_mask, ib_member_rec_t * mcmr) { static uint32_t uniq_count; ib_gid_t *mgid = &mcmr->mgid; uint8_t scope; unsigned i; /* use the given scope state only if requested! */ if (comp_mask & IB_MCR_COMPMASK_SCOPE) ib_member_get_scope_state(mcmr->scope_state, &scope, NULL); else /* to guarantee no collision with other subnets use local scope! */ scope = IB_MC_SCOPE_LINK_LOCAL; mgid->raw[0] = 0xff; mgid->raw[1] = 0x10 | scope; mgid->raw[2] = 0xa0; mgid->raw[3] = 0x1b; memcpy(&mgid->raw[4], &sa->p_subn->opt.subnet_prefix, sizeof(uint64_t)); for (i = 0; i < 1000; i++) { memcpy(&mgid->raw[10], &uniq_count, 4); uniq_count++; if (!osm_get_mgrp_by_mgid(sa->p_subn, mgid)) return 1; } return 0; } /********************************************************************** Call this function to create a new mgrp. **********************************************************************/ static ib_api_status_t mcmr_rcv_create_new_mgrp(IN osm_sa_t * sa, IN ib_net64_t comp_mask, IN const ib_member_rec_t * p_recvd_mcmember_rec, IN const osm_physp_t * p_physp, OUT osm_mgrp_t ** pp_mgrp) { ib_net16_t mlid; uint16_t signature; ib_api_status_t status = IB_SUCCESS; osm_mgrp_t *bcast_mgrp; ib_gid_t bcast_mgid; ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec; /* copy for modifications */ char gid_str[INET6_ADDRSTRLEN]; OSM_LOG_ENTER(sa->p_log); /* we need to create the new MGID if it was not defined */ if (!ib_gid_is_notzero(&p_recvd_mcmember_rec->mgid)) { /* create a new MGID */ if (!build_new_mgid(sa, comp_mask, &mcm_rec)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B23: " "cannot allocate unique MGID value\n"); status = IB_SA_MAD_STATUS_NO_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Allocated new MGID:%s\n", inet_ntop(AF_INET6, mcm_rec.mgid.raw, gid_str, sizeof gid_str)); } else if (sa->p_subn->opt.ipoib_mcgroup_creation_validation) { /* a specific MGID was requested so validate the resulting MGID */ if (validate_requested_mgid(sa, &mcm_rec)) { memcpy(&signature, &(mcm_rec.mgid.multicast.raw_group_id), sizeof(signature)); signature = cl_ntoh16(signature); /* Check for IPoIB signature in MGID */ if (signature == 0x401B || signature == 0x601B) { /* Derive IPoIB broadcast MGID */ bcast_mgid.unicast.prefix = IPV4_BCAST_MGID_PREFIX; bcast_mgid.unicast.interface_id = IPV4_BCAST_MGID_INT_ID; /* Set scope in IPoIB broadcast MGID */ bcast_mgid.multicast.header[1] = (bcast_mgid.multicast.header[1] & 0xF0) | (mcm_rec.mgid.multicast.header[1] & 0x0F); /* Set P_Key in IPoIB broadcast MGID */ bcast_mgid.multicast.raw_group_id[2] = mcm_rec.mgid.multicast.raw_group_id[2]; bcast_mgid.multicast.raw_group_id[3] = mcm_rec.mgid.multicast.raw_group_id[3]; /* Check MC group for the IPoIB broadcast group */ if (signature != 0x401B || memcmp(&bcast_mgid, &(mcm_rec.mgid), sizeof(ib_gid_t))) { bcast_mgrp = osm_get_mgrp_by_mgid(sa->p_subn, &bcast_mgid); if (!bcast_mgrp) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B1B: Broadcast group %s not found, sending IB_SA_MAD_STATUS_REQ_INVALID\n", inet_ntop(AF_INET6, bcast_mgid.raw, gid_str, sizeof gid_str)); status = IB_SA_MAD_STATUS_REQ_INVALID; goto Exit; } if (!validate_other_comp_fields(sa->p_log, comp_mask, p_recvd_mcmember_rec, bcast_mgrp, OSM_LOG_ERROR)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B1C: validate_other_comp_fields failed for MGID: %s, sending IB_SA_MAD_STATUS_REQ_INVALID\n", inet_ntop(AF_INET6, &p_recvd_mcmember_rec->mgid, gid_str, sizeof gid_str)); status = IB_SA_MAD_STATUS_REQ_INVALID; goto Exit; } } } } else { status = IB_SA_MAD_STATUS_REQ_INVALID; goto Exit; } } /* check the requested parameters are realizable */ if (mgrp_request_is_realizable(sa, comp_mask, &mcm_rec, p_physp) == FALSE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B26: " "Requested MGRP parameters are not realizable\n"); status = IB_SA_MAD_STATUS_REQ_INVALID; goto Exit; } mlid = get_new_mlid(sa, &mcm_rec); if (mlid == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B19: " "get_new_mlid failed request mlid 0x%04x\n", cl_ntoh16(mcm_rec.mlid)); status = IB_SA_MAD_STATUS_NO_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Obtained new mlid 0x%X\n", cl_ntoh16(mlid)); mcm_rec.mlid = mlid; /* create a new MC Group */ *pp_mgrp = osm_mgrp_new(sa->p_subn, mlid, &mcm_rec); if (*pp_mgrp == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B08: " "osm_mgrp_new failed\n"); free_mlid(sa, mlid); status = IB_SA_MAD_STATUS_NO_RESOURCES; goto Exit; } /* the mcmember_record should have mtu_sel, rate_sel, and pkt_lifetime_sel = 2 */ (*pp_mgrp)->mcmember_rec.mtu &= 0x3f; (*pp_mgrp)->mcmember_rec.mtu |= IB_PATH_SELECTOR_EXACTLY << 6; (*pp_mgrp)->mcmember_rec.rate &= 0x3f; (*pp_mgrp)->mcmember_rec.rate |= IB_PATH_SELECTOR_EXACTLY << 6; (*pp_mgrp)->mcmember_rec.pkt_life &= 0x3f; (*pp_mgrp)->mcmember_rec.pkt_life |= IB_PATH_SELECTOR_EXACTLY << 6; Exit: OSM_LOG_EXIT(sa->p_log); return status; } /********************************************************************** Call this function to find or create a new mgrp. **********************************************************************/ osm_mgrp_t *osm_mcmr_rcv_find_or_create_new_mgrp(IN osm_sa_t * sa, IN ib_net64_t comp_mask, IN ib_member_rec_t * p_recvd_mcmember_rec) { osm_mgrp_t *mgrp; if ((mgrp = osm_get_mgrp_by_mgid(sa->p_subn, &p_recvd_mcmember_rec->mgid))) return mgrp; if (mcmr_rcv_create_new_mgrp(sa, comp_mask, p_recvd_mcmember_rec, NULL, &mgrp) == IB_SUCCESS) return mgrp; return NULL; } /********************************************************************* Process a request for leaving the group **********************************************************************/ static void mcmr_rcv_leave_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw) { osm_mgrp_t *p_mgrp; ib_sa_mad_t *p_sa_mad; ib_member_rec_t *p_recvd_mcmember_rec; ib_member_rec_t mcmember_rec; osm_mcm_alias_guid_t *p_mcm_alias_guid; OSM_LOG_ENTER(sa->p_log); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_mcmember_rec = (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); mcmember_rec = *p_recvd_mcmember_rec; /* Validate the subnet prefix in the PortGID */ if (p_recvd_mcmember_rec->port_gid.unicast.prefix != sa->p_subn->opt.subnet_prefix) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "PortGID subnet prefix 0x%" PRIx64 " does not match configured prefix 0x%" PRIx64 "\n", cl_ntoh64(p_recvd_mcmember_rec->port_gid.unicast.prefix), cl_ntoh64(sa->p_subn->opt.subnet_prefix)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INVALID_GID); goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sa->p_lock); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { osm_physp_t *p_req_physp; p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr(p_madw)); if (p_req_physp == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B02: " "Cannot find requester physical port\n"); } else { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of record\n"); osm_dump_mc_record_v2(sa->p_log, &mcmember_rec, FILE_ID, OSM_LOG_DEBUG); } p_mgrp = osm_get_mgrp_by_mgid(sa->p_subn, &p_recvd_mcmember_rec->mgid); if (!p_mgrp) { char gid_str[INET6_ADDRSTRLEN]; CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Failed since multicast group %s not present\n", inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw, gid_str, sizeof gid_str)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* check validity of the delete request o15-0.1.14 */ if (!validate_delete(sa, p_mgrp, osm_madw_get_mad_addr_ptr(p_madw), p_recvd_mcmember_rec, &p_mcm_alias_guid)) { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B25: " "Received an invalid delete request for " "MGID: %s for PortGID: %s\n", inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_recvd_mcmember_rec->port_gid.raw, gid_str2, sizeof gid_str2)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* remove port and/or update join state */ osm_mgrp_remove_port(sa->p_subn, sa->p_log, p_mgrp, p_mcm_alias_guid, &mcmember_rec); CL_PLOCK_RELEASE(sa->p_lock); mcmr_rcv_respond(sa, p_madw, &mcmember_rec); Exit: OSM_LOG_EXIT(sa->p_log); } static int validate_other_comp_fields(osm_log_t * p_log, ib_net64_t comp_mask, const ib_member_rec_t * p_mcmr, osm_mgrp_t * p_mgrp, osm_log_level_t log_level) { int ret = 0; if ((IB_MCR_COMPMASK_QKEY & comp_mask) && p_mcmr->qkey != p_mgrp->mcmember_rec.qkey) { OSM_LOG(p_log, log_level, "ERR 1B30: " "Q_Key mismatch: query 0x%x group 0x%x\n", cl_ntoh32(p_mcmr->qkey), cl_ntoh32(p_mgrp->mcmember_rec.qkey)); goto Exit; } if (IB_MCR_COMPMASK_PKEY & comp_mask) { if (!(ib_pkey_is_full_member(p_mcmr->pkey) || ib_pkey_is_full_member(p_mgrp->mcmember_rec.pkey))) { OSM_LOG(p_log, log_level, "ERR 1B31: " "Both limited P_Keys: query 0x%x group 0x%x\n", cl_ntoh16(p_mcmr->pkey), cl_ntoh16(p_mgrp->mcmember_rec.pkey)); goto Exit; } if (ib_pkey_get_base(p_mcmr->pkey) != ib_pkey_get_base(p_mgrp->mcmember_rec.pkey)) { OSM_LOG(p_log, log_level, "ERR 1B32: " "P_Key base mismatch: query 0x%x group 0x%x\n", cl_ntoh16(p_mcmr->pkey), cl_ntoh16(p_mgrp->mcmember_rec.pkey)); goto Exit; } } if ((IB_MCR_COMPMASK_TCLASS & comp_mask) && p_mcmr->tclass != p_mgrp->mcmember_rec.tclass) { OSM_LOG(p_log, log_level, "ERR 1B33: " "TClass mismatch: query %d group %d\n", p_mcmr->tclass, p_mgrp->mcmember_rec.tclass); goto Exit; } /* check SL, Flow, and Hop limit */ { uint32_t mgrp_flow, query_flow; uint8_t mgrp_sl, query_sl; uint8_t mgrp_hop, query_hop; ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &query_sl, &query_flow, &query_hop); ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop, &mgrp_sl, &mgrp_flow, &mgrp_hop); if ((IB_MCR_COMPMASK_SL & comp_mask) && query_sl != mgrp_sl) { OSM_LOG(p_log, log_level, "ERR 1B34: " "SL mismatch: query %d group %d\n", query_sl, mgrp_sl); goto Exit; } if ((IB_MCR_COMPMASK_FLOW & comp_mask) && query_flow != mgrp_flow) { OSM_LOG(p_log, log_level, "ERR 1B35: " "FlowLabel mismatch: query 0x%x group 0x%x\n", query_flow, mgrp_flow); goto Exit; } if ((IB_MCR_COMPMASK_HOP & comp_mask) && query_hop != mgrp_hop) { OSM_LOG(p_log, log_level, "ERR 1B36: " "Hop mismatch: query %d group %d\n", query_hop, mgrp_hop); goto Exit; } } ret = 1; Exit: return ret; } /********************************************************************** Handle a join (or create) request **********************************************************************/ static void mcmr_rcv_join_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw) { osm_mgrp_t *p_mgrp = NULL; ib_api_status_t status; ib_sa_mad_t *p_sa_mad; ib_member_rec_t *p_recvd_mcmember_rec; ib_member_rec_t mcmember_rec; osm_mcm_port_t *p_mcmr_port; osm_mcm_alias_guid_t *p_mcm_alias_guid; ib_net64_t portguid; osm_port_t *p_port; osm_physp_t *p_physp; osm_physp_t *p_request_physp; uint8_t is_new_group; /* TRUE = there is a need to create a group */ uint8_t join_state; boolean_t proxy; OSM_LOG_ENTER(sa->p_log); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_mcmember_rec = ib_sa_mad_get_payload_ptr(p_sa_mad); portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id; mcmember_rec = *p_recvd_mcmember_rec; /* Validate the subnet prefix in the PortGID */ if (p_recvd_mcmember_rec->port_gid.unicast.prefix != sa->p_subn->opt.subnet_prefix) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "PortGID subnet prefix 0x%" PRIx64 " does not match configured prefix 0x%" PRIx64 "\n", cl_ntoh64(p_recvd_mcmember_rec->port_gid.unicast.prefix), cl_ntoh64(sa->p_subn->opt.subnet_prefix)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INVALID_GID); goto Exit; } CL_PLOCK_EXCL_ACQUIRE(sa->p_lock); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { osm_physp_t *p_req_physp; p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr(p_madw)); if (p_req_physp == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B03: " "Cannot find requester physical port\n"); } else { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of incoming record\n"); osm_dump_mc_record_v2(sa->p_log, &mcmember_rec, FILE_ID, OSM_LOG_DEBUG); } /* make sure the requested port guid is known to the SM */ p_port = osm_get_port_by_alias_guid(sa->p_subn, portguid); if (!p_port) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unknown port GUID 0x%016" PRIx64 "\n", cl_ntoh64(portguid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } p_physp = p_port->p_physp; /* Check that the p_physp and the requester physp are in the same partition. */ p_request_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr(p_madw)); if (p_request_physp == NULL) { CL_PLOCK_RELEASE(sa->p_lock); goto Exit; } proxy = (p_physp != p_request_physp); if (proxy && !osm_physp_share_pkey(sa->p_log, p_physp, p_request_physp, sa->p_subn->opt.allow_both_pkeys)) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Port and requester don't share PKey\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } if ((p_sa_mad->comp_mask & IB_MCR_COMPMASK_PKEY) && ib_pkey_is_invalid(p_recvd_mcmember_rec->pkey)) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Invalid PKey supplied in request\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } ib_member_get_scope_state(p_recvd_mcmember_rec->scope_state, NULL, &join_state); /* do we need to create a new group? */ p_mgrp = osm_get_mgrp_by_mgid(sa->p_subn, &p_recvd_mcmember_rec->mgid); if (!p_mgrp) { /* check for JoinState.FullMember = 1 o15.0.1.9 */ if ((join_state & 0x01) != 0x01) { char gid_str[INET6_ADDRSTRLEN]; CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B10: " "Failed to create multicast group " "because Join State != FullMember, " "MGID: %s from port 0x%016" PRIx64 " (%s)\n", inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw, gid_str, sizeof gid_str), cl_ntoh64(portguid), p_port->p_node->print_desc); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* check the comp_mask */ if (!check_create_comp_mask(p_sa_mad->comp_mask, p_recvd_mcmember_rec)) { char gid_str[INET6_ADDRSTRLEN]; CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B11: " "Port 0x%016" PRIx64 " (%s) failed to join " "non-existing multicast group with MGID %s, " "insufficient components specified for " "implicit create (comp_mask 0x%" PRIx64 ")\n", cl_ntoh64(portguid), p_port->p_node->print_desc, inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw, gid_str, sizeof gid_str), cl_ntoh64(p_sa_mad->comp_mask)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } status = mcmr_rcv_create_new_mgrp(sa, p_sa_mad->comp_mask, p_recvd_mcmember_rec, p_physp, &p_mgrp); if (status != IB_SUCCESS) { CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, status); goto Exit; } /* copy the MGID to the result */ mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid; is_new_group = 1; } else { /* no need for a new group */ is_new_group = 0; if (sa->p_subn->opt.mcgroup_join_validation && !validate_other_comp_fields(sa->p_log, p_sa_mad->comp_mask, p_recvd_mcmember_rec, p_mgrp, OSM_LOG_ERROR)) { char gid_str[INET6_ADDRSTRLEN]; CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B1A: " "validate_other_comp_fields failed for " "MGID: %s port 0x%016" PRIx64 " (%s), sending IB_SA_MAD_STATUS_REQ_INVALID\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), cl_ntoh64(portguid), p_port->p_node->print_desc); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } } CL_ASSERT(p_mgrp); /* * o15-0.2.4: If SA supports UD multicast, then SA shall cause an * endport to join an existing multicast group if: * 1. It receives a SubnAdmSet() method for a MCMemberRecord, and * - WE KNOW THAT ALREADY * 2. The MGID is specified and matches an existing multicast * group, and * - WE KNOW THAT ALREADY * 3. The MCMemberRecord:JoinState is not all 0s, and * 4. PortGID is specified and * - WE KNOW THAT ALREADY (as it matched a real one) * 5. All other components match that existing group, either by * being wildcarded or by having values identical to those specified * by the component mask and in use by the group with the exception * of components such as ProxyJoin and Reserved, which are ignored * by SA. * * We need to check #3 and #5 here: */ if (!validate_more_comp_fields(sa->p_log, p_mgrp, p_recvd_mcmember_rec, p_sa_mad->comp_mask) || !validate_port_caps(sa->p_log, p_mgrp, p_physp) || !(join_state != 0)) { char gid_str[INET6_ADDRSTRLEN]; /* since we might have created the new group we need to cleanup */ if (is_new_group) osm_mgrp_cleanup(sa->p_subn, p_mgrp); CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B12: " "validate_more_comp_fields, validate_port_caps, " "or JoinState = 0 failed for MGID: %s port 0x%016" PRIx64 " (%s), sending IB_SA_MAD_STATUS_REQ_INVALID\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), cl_ntoh64(portguid), p_port->p_node->print_desc); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* verify that the joining port is in the partition of the group */ if (!osm_physp_has_pkey(sa->p_log, p_mgrp->mcmember_rec.pkey, p_physp)) { char gid_str[INET6_ADDRSTRLEN]; if (is_new_group) osm_mgrp_cleanup(sa->p_subn, p_mgrp); CL_PLOCK_RELEASE(sa->p_lock); memset(gid_str, 0, sizeof(gid_str)); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B14: " "Cannot join port 0x%016" PRIx64 " to MGID %s - " "Port is not in partition of this MC group\n", cl_ntoh64(portguid), inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof(gid_str))); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * o15-0.2.1 requires validation of the requesting port * in the case of modification: */ if (!is_new_group && !validate_modify(sa, p_mgrp, osm_madw_get_mad_addr_ptr(p_madw), p_recvd_mcmember_rec, &p_mcm_alias_guid)) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B13: " "validate_modify failed from port 0x%016" PRIx64 " (%s), sending IB_SA_MAD_STATUS_REQ_INVALID\n", cl_ntoh64(portguid), p_port->p_node->print_desc); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* copy qkey mlid tclass pkey sl_flow_hop mtu rate pkt_life */ copy_from_create_mc_rec(&mcmember_rec, &p_mgrp->mcmember_rec); /* create or update existing port (join-state will be updated) */ p_mcmr_port = osm_mgrp_add_port(sa->p_subn, sa->p_log, p_mgrp, p_port, &mcmember_rec, proxy); if (!p_mcmr_port) { /* we fail to add the port so we might need to delete the group */ if (is_new_group) osm_mgrp_cleanup(sa->p_subn, p_mgrp); CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B06: " "osm_mgrp_add_port failed\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } /* Release the lock as we don't need it. */ CL_PLOCK_RELEASE(sa->p_lock); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_mc_record_v2(sa->p_log, &mcmember_rec, FILE_ID, OSM_LOG_DEBUG); mcmr_rcv_respond(sa, p_madw, &mcmember_rec); Exit: OSM_LOG_EXIT(sa->p_log); } /********************************************************************** Add a patched multicast group to the results list **********************************************************************/ static ib_api_status_t mcmr_rcv_new_mcmr(IN osm_sa_t * sa, IN const ib_member_rec_t * p_rcvd_rec, IN cl_qlist_t * p_list) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_MCM_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B15: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } memset(p_rec_item, 0, sizeof(cl_list_item_t)); /* HACK: Untrusted requesters should result with 0 Join State, Port Guid, and Proxy */ p_rec_item->resp.mc_rec = *p_rcvd_rec; cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } /********************************************************************** Match the given mgrp to the requested mcmr **********************************************************************/ static void mcmr_by_comp_mask(osm_sa_t * sa, const ib_member_rec_t * p_rcvd_rec, ib_net64_t comp_mask, osm_mgrp_t * p_mgrp, const osm_physp_t * p_req_physp, boolean_t trusted_req, cl_qlist_t * list) { /* since we might change scope_state */ ib_member_rec_t match_rec; osm_mcm_alias_guid_t *p_mcm_alias_guid; ib_net64_t portguid = p_rcvd_rec->port_gid.unicast.interface_id; /* will be used for group or port info */ uint8_t scope_state; uint8_t scope_state_mask = 0; cl_map_item_t *p_item; ib_gid_t port_gid; boolean_t proxy_join = FALSE; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Checking mlid:0x%X\n", cl_ntoh16(p_mgrp->mlid)); /* first try to eliminate the group by MGID, MLID, or P_Key */ if ((IB_MCR_COMPMASK_MGID & comp_mask) && memcmp(&p_rcvd_rec->mgid, &p_mgrp->mcmember_rec.mgid, sizeof(ib_gid_t))) goto Exit; if ((IB_MCR_COMPMASK_MLID & comp_mask) && memcmp(&p_rcvd_rec->mlid, &p_mgrp->mcmember_rec.mlid, sizeof(uint16_t))) goto Exit; /* if the requester physical port doesn't have the pkey that is defined for the group - exit. */ if (!osm_physp_has_pkey(sa->p_log, p_mgrp->mcmember_rec.pkey, p_req_physp)) goto Exit; /* now do the rest of the match */ if (!validate_other_comp_fields(sa->p_log, comp_mask, p_rcvd_rec, p_mgrp, OSM_LOG_NONE)) goto Exit; if ((IB_MCR_COMPMASK_PROXY & comp_mask) && p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join) goto Exit; /* need to validate mtu, rate, and pkt_lifetime fields */ if (validate_more_comp_fields(sa->p_log, p_mgrp, p_rcvd_rec, comp_mask) == FALSE) goto Exit; /* Port specific fields */ /* so did we get the PortGUID mask */ if (IB_MCR_COMPMASK_PORT_GID & comp_mask) { /* try to find this port */ p_mcm_alias_guid = osm_mgrp_get_mcm_alias_guid(p_mgrp, portguid); if (!p_mcm_alias_guid) /* port not in group */ goto Exit; scope_state = p_mcm_alias_guid->scope_state; memcpy(&port_gid, &(p_mcm_alias_guid->port_gid), sizeof(ib_gid_t)); proxy_join = p_mcm_alias_guid->proxy_join; } else /* point to the group information */ scope_state = p_mgrp->mcmember_rec.scope_state; if (IB_MCR_COMPMASK_SCOPE & comp_mask) scope_state_mask = 0xF0; if (IB_MCR_COMPMASK_JOIN_STATE & comp_mask) scope_state_mask = scope_state_mask | 0x0F; /* Many MC records returned */ if (trusted_req == TRUE && !(IB_MCR_COMPMASK_PORT_GID & comp_mask)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Trusted req is TRUE and no specific port defined\n"); /* return all the ports that match in this MC group */ p_item = cl_qmap_head(&(p_mgrp->mcm_alias_port_tbl)); while (p_item != cl_qmap_end(&(p_mgrp->mcm_alias_port_tbl))) { p_mcm_alias_guid = (osm_mcm_alias_guid_t *) p_item; if ((scope_state_mask & p_rcvd_rec->scope_state) == (scope_state_mask & p_mcm_alias_guid->scope_state)) { /* add to the list */ match_rec = p_mgrp->mcmember_rec; match_rec.scope_state = p_mcm_alias_guid->scope_state; memcpy(&match_rec.port_gid, &p_mcm_alias_guid->port_gid, sizeof(ib_gid_t)); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Record of port_gid: %s" " in multicast_lid: 0x%X is returned\n", inet_ntop(AF_INET6, match_rec.port_gid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mgrp->mlid)); match_rec.proxy_join = (uint8_t) (p_mcm_alias_guid->proxy_join); mcmr_rcv_new_mcmr(sa, &match_rec, list); } p_item = cl_qmap_next(p_item); } } else { /* One MC record returned */ if ((scope_state_mask & p_rcvd_rec->scope_state) != (scope_state_mask & scope_state)) goto Exit; /* add to the list */ match_rec = p_mgrp->mcmember_rec; match_rec.scope_state = scope_state; memcpy(&(match_rec.port_gid), &port_gid, sizeof(ib_gid_t)); match_rec.proxy_join = (uint8_t) proxy_join; mcmr_rcv_new_mcmr(sa, &match_rec, list); } Exit: OSM_LOG_EXIT(sa->p_log); } /********************************************************************** Handle a query request **********************************************************************/ static void mcmr_query_mgrp(IN osm_sa_t * sa, IN osm_madw_t * p_madw) { const ib_sa_mad_t *p_rcvd_mad; const ib_member_rec_t *p_rcvd_rec; cl_qlist_t rec_list; ib_net64_t comp_mask; osm_physp_t *p_req_physp; boolean_t trusted_req; osm_mgrp_t *p_mgrp; OSM_LOG_ENTER(sa->p_log); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); comp_mask = p_rcvd_mad->comp_mask; /* if sm_key is not zero and does not match we never get here see main SA receiver */ trusted_req = (p_rcvd_mad->sm_key != 0); CL_PLOCK_ACQUIRE(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B04: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of record\n"); osm_dump_mc_record(sa->p_log, p_rcvd_rec, OSM_LOG_DEBUG); } cl_qlist_init(&rec_list); /* simply go over all MCGs and match */ for (p_mgrp = (osm_mgrp_t *) cl_fmap_head(&sa->p_subn->mgrp_mgid_tbl); p_mgrp != (osm_mgrp_t *) cl_fmap_end(&sa->p_subn->mgrp_mgid_tbl); p_mgrp = (osm_mgrp_t *) cl_fmap_next(&p_mgrp->map_item)) mcmr_by_comp_mask(sa, p_rcvd_rec, comp_mask, p_mgrp, p_req_physp, trusted_req, &rec_list); CL_PLOCK_RELEASE(sa->p_lock); /* p923 - The PortGID, JoinState and ProxyJoin shall be zero, except in the case of a trusted request. Note: In the mad controller we check that the SM_Key received on the mad is valid. Meaning - is either zero or equal to the local sm_key. */ if (!p_rcvd_mad->sm_key) { osm_sa_item_t *item; for (item = (osm_sa_item_t *) cl_qlist_head(&rec_list); item != (osm_sa_item_t *) cl_qlist_end(&rec_list); item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) { memset(&item->resp.mc_rec.port_gid, 0, sizeof(ib_gid_t)); ib_member_set_join_state(&item->resp.mc_rec, 0); item->resp.mc_rec.proxy_join = 0; } } osm_sa_respond(sa, p_madw, sizeof(ib_member_rec_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } static uint8_t rate_is_valid(IN const ib_sa_mad_t *p_sa_mad, IN const ib_member_rec_t *p_recvd_mcmember_rec) { uint8_t rate; /* Validate rate if supplied */ if ((p_sa_mad->comp_mask & IB_MCR_COMPMASK_RATE_SEL) && (p_sa_mad->comp_mask & IB_MCR_COMPMASK_RATE)) { rate = (uint8_t) (p_recvd_mcmember_rec->rate & 0x3F); return ib_rate_is_valid(rate); } return 1; } static int mtu_is_valid(IN const ib_sa_mad_t *p_sa_mad, IN const ib_member_rec_t *p_recvd_mcmember_rec) { uint8_t mtu; /* Validate MTU if supplied */ if ((p_sa_mad->comp_mask & IB_MCR_COMPMASK_MTU_SEL) && (p_sa_mad->comp_mask & IB_MCR_COMPMASK_MTU)) { mtu = (uint8_t) (p_recvd_mcmember_rec->mtu & 0x3F); return ib_mtu_is_valid(mtu); } return 1; } void osm_mcmr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; ib_sa_mad_t *p_sa_mad; ib_member_rec_t *p_recvd_mcmember_rec; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_mcmember_rec = (ib_member_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_MCMEMBER_RECORD); switch (p_sa_mad->method) { case IB_MAD_METHOD_SET: if (!check_join_comp_mask(p_sa_mad->comp_mask)) { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B18: " "component mask = 0x%016" PRIx64 ", " "expected comp mask = 0x%016" PRIx64 ", " "MGID: %s for PortGID: %s\n", cl_ntoh64(p_sa_mad->comp_mask), CL_NTOH64(JOIN_MC_COMP_MASK), inet_ntop(AF_INET6, p_recvd_mcmember_rec->mgid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, p_recvd_mcmember_rec->port_gid.raw, gid_str2, sizeof gid_str2)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } if (!rate_is_valid(p_sa_mad, p_recvd_mcmember_rec) || !mtu_is_valid(p_sa_mad, p_recvd_mcmember_rec)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * Join or Create Multicast Group */ mcmr_rcv_join_mgrp(sa, p_madw); break; case IB_MAD_METHOD_DELETE: if (!check_join_comp_mask(p_sa_mad->comp_mask)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B20: " "component mask = 0x%016" PRIx64 ", " "expected comp mask = 0x%016" PRIx64 "\n", cl_ntoh64(p_sa_mad->comp_mask), CL_NTOH64(JOIN_MC_COMP_MASK)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } if (!rate_is_valid(p_sa_mad, p_recvd_mcmember_rec) || !mtu_is_valid(p_sa_mad, p_recvd_mcmember_rec)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * Leave Multicast Group */ mcmr_rcv_leave_mgrp(sa, p_madw); break; case IB_MAD_METHOD_GET: case IB_MAD_METHOD_GETTABLE: if (!rate_is_valid(p_sa_mad, p_recvd_mcmember_rec) || !mtu_is_valid(p_sa_mad, p_recvd_mcmember_rec)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* * Querying a Multicast Group */ mcmr_query_mgrp(sa, p_madw); break; default: OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1B21: " "Unsupported Method (%s) for MCMemberRecord request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); break; } Exit: OSM_LOG_EXIT(sa->p_log); return; } opensm-3.3.20/opensm/osm_sa_node_record.c0000644000205000001450000002476412314616647015330 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_nr_rcv_t. * This object represents the NodeInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SA_NODE_RECORD_C #include #include #include #include #include #define SA_NR_RESP_SIZE SA_ITEM_RESP_SIZE(node_rec) typedef struct osm_nr_search_ctxt { const ib_node_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_nr_search_ctxt_t; static ib_api_status_t nr_rcv_new_nr(osm_sa_t * sa, IN const osm_node_t * p_node, IN cl_qlist_t * p_list, IN ib_net64_t port_guid, IN ib_net16_t lid, IN unsigned int port_num) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_NR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D02: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New NodeRecord: node 0x%016" PRIx64 ", port 0x%016" PRIx64 ", lid %u\n", cl_ntoh64(osm_node_get_node_guid(p_node)), cl_ntoh64(port_guid), cl_ntoh16(lid)); memset(p_rec_item, 0, SA_NR_RESP_SIZE); p_rec_item->resp.node_rec.lid = lid; p_rec_item->resp.node_rec.node_info = p_node->node_info; p_rec_item->resp.node_rec.node_info.port_guid = port_guid; p_rec_item->resp.node_rec.node_info.port_num_vendor_id = (p_rec_item->resp.node_rec.node_info.port_num_vendor_id & IB_NODE_INFO_VEND_ID_MASK) | ((port_num << IB_NODE_INFO_PORT_NUM_SHIFT) & IB_NODE_INFO_PORT_NUM_MASK); memcpy(&(p_rec_item->resp.node_rec.node_desc), &(p_node->node_desc), IB_NODE_DESCRIPTION_SIZE); cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void nr_rcv_create_nr(IN osm_sa_t * sa, IN osm_node_t * p_node, IN cl_qlist_t * p_list, IN ib_net64_t const match_port_guid, IN ib_net16_t const match_lid, IN unsigned int const match_port_num, IN const osm_physp_t * p_req_physp, IN const ib_net64_t comp_mask) { const osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; uint16_t match_lid_ho; ib_net16_t base_lid; ib_net16_t base_lid_ho; ib_net16_t max_lid_ho; uint8_t lmc; ib_net64_t port_guid; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Looking for NodeRecord with LID: %u GUID: 0x%016" PRIx64 "\n", cl_ntoh16(match_lid), cl_ntoh64(match_port_guid)); /* For switches, do not return the NodeInfo record for each port on the switch, just for port 0. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) num_ports = 1; else num_ports = osm_node_get_num_physp(p_node); for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; /* Check to see if the found p_physp and the requester physp share a pkey. If not - continue */ if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp, sa->p_subn->opt.allow_both_pkeys)) continue; port_guid = osm_physp_get_port_guid(p_physp); if ((comp_mask & IB_NR_COMPMASK_PORTGUID) && (port_guid != match_port_guid)) continue; base_lid = osm_physp_get_base_lid(p_physp); if (comp_mask & IB_NR_COMPMASK_LID) { base_lid_ho = cl_ntoh16(base_lid); lmc = osm_physp_get_lmc(p_physp); max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1); match_lid_ho = cl_ntoh16(match_lid); /* We validate that the lid belongs to this node. */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing LID: %u <= %u <= %u\n", base_lid_ho, match_lid_ho, max_lid_ho); if (match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho) continue; } if ((comp_mask & IB_NR_COMPMASK_PORTNUM) && (port_num != match_port_num)) continue; nr_rcv_new_nr(sa, p_node, p_list, port_guid, base_lid, port_num); } OSM_LOG_EXIT(sa->p_log); } static void nr_rcv_by_comp_mask(IN cl_map_item_t * p_map_item, IN void *context) { const osm_nr_search_ctxt_t *p_ctxt = context; osm_node_t *p_node = (osm_node_t *) p_map_item; const ib_node_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; osm_sa_t *sa = p_ctxt->sa; ib_net64_t comp_mask = p_ctxt->comp_mask; ib_net64_t match_port_guid = 0; ib_net16_t match_lid = 0; unsigned int match_port_num = 0; OSM_LOG_ENTER(p_ctxt->sa->p_log); osm_dump_node_info_v2(p_ctxt->sa->p_log, &p_node->node_info, FILE_ID, OSM_LOG_DEBUG); if (comp_mask & IB_NR_COMPMASK_LID) match_lid = p_rcvd_rec->lid; if (comp_mask & IB_NR_COMPMASK_NODEGUID) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Looking for node 0x%016" PRIx64 ", found 0x%016" PRIx64 "\n", cl_ntoh64(p_rcvd_rec->node_info.node_guid), cl_ntoh64(osm_node_get_node_guid(p_node))); if (p_node->node_info.node_guid != p_rcvd_rec->node_info.node_guid) goto Exit; } if (comp_mask & IB_NR_COMPMASK_PORTGUID) match_port_guid = p_rcvd_rec->node_info.port_guid; if ((comp_mask & IB_NR_COMPMASK_SYSIMAGEGUID) && p_node->node_info.sys_guid != p_rcvd_rec->node_info.sys_guid) goto Exit; if ((comp_mask & IB_NR_COMPMASK_BASEVERSION) && p_node->node_info.base_version != p_rcvd_rec->node_info.base_version) goto Exit; if ((comp_mask & IB_NR_COMPMASK_CLASSVERSION) && p_node->node_info.class_version != p_rcvd_rec->node_info.class_version) goto Exit; if ((comp_mask & IB_NR_COMPMASK_NODETYPE) && p_node->node_info.node_type != p_rcvd_rec->node_info.node_type) goto Exit; if ((comp_mask & IB_NR_COMPMASK_NUMPORTS) && p_node->node_info.num_ports != p_rcvd_rec->node_info.num_ports) goto Exit; if ((comp_mask & IB_NR_COMPMASK_PARTCAP) && p_node->node_info.partition_cap != p_rcvd_rec->node_info.partition_cap) goto Exit; if ((comp_mask & IB_NR_COMPMASK_DEVID) && p_node->node_info.device_id != p_rcvd_rec->node_info.device_id) goto Exit; if ((comp_mask & IB_NR_COMPMASK_REV) && p_node->node_info.revision != p_rcvd_rec->node_info.revision) goto Exit; if (comp_mask & IB_NR_COMPMASK_PORTNUM) match_port_num = ib_node_info_get_local_port_num(&p_rcvd_rec->node_info); if ((comp_mask & IB_NR_COMPMASK_VENDID) && ib_node_info_get_vendor_id(&p_node->node_info) != ib_node_info_get_vendor_id(&p_rcvd_rec->node_info)) goto Exit; if ((comp_mask & IB_NR_COMPMASK_NODEDESC) && strncmp((char *)&p_node->node_desc, (char *)&p_rcvd_rec->node_desc, sizeof(ib_node_desc_t))) goto Exit; nr_rcv_create_nr(sa, p_node, p_ctxt->p_list, match_port_guid, match_lid, match_port_num, p_req_physp, comp_mask); Exit: OSM_LOG_EXIT(p_ctxt->sa->p_log); } void osm_nr_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_node_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_nr_search_ctxt_t context; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_node_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_NODE_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D05: " "Unsupported Method (%s) for NodeRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1D04: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_node_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; cl_qmap_apply_func(&sa->p_subn->node_guid_tbl, nr_rcv_by_comp_mask, &context); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_node_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_path_record.c0000644000205000001450000016557312726322746015344 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2010 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_pr_rcv_t. * This object represents the PathRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_PATH_RECORD_C #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SA_PR_RESP_SIZE SA_ITEM_RESP_SIZE(path_rec) #define MAX_HOPS 64 static inline boolean_t sa_path_rec_is_tavor_port(IN const osm_port_t * p_port) { osm_node_t const *p_node; ib_net32_t vend_id; p_node = p_port->p_node; vend_id = ib_node_info_get_vendor_id(&p_node->node_info); return ((p_node->node_info.device_id == CL_HTON16(23108)) && ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE)))); } static boolean_t sa_path_rec_apply_tavor_mtu_limit(IN const ib_path_rec_t * p_pr, IN const osm_port_t * p_src_port, IN const osm_port_t * p_dest_port, IN const ib_net64_t comp_mask) { uint8_t required_mtu; /* only if at least one of the ports is a Tavor device */ if (!sa_path_rec_is_tavor_port(p_src_port) && !sa_path_rec_is_tavor_port(p_dest_port)) return FALSE; /* we can apply the patch if either: 1. No MTU required 2. Required MTU < 3. Required MTU = 1K or 512 or 256 4. Required MTU > 256 or 512 */ required_mtu = ib_path_rec_mtu(p_pr); if ((comp_mask & IB_PR_COMPMASK_MTUSELEC) && (comp_mask & IB_PR_COMPMASK_MTU)) { switch (ib_path_rec_mtu_sel(p_pr)) { case 0: /* must be greater than */ case 2: /* exact match */ if (IB_MTU_LEN_1024 < required_mtu) return FALSE; break; case 1: /* must be less than */ /* can't be disqualified by this one */ break; case 3: /* largest available */ /* the ULP intentionally requested */ /* the largest MTU possible */ return FALSE; default: /* if we're here, there's a bug in ib_path_rec_mtu_sel() */ CL_ASSERT(FALSE); break; } } return TRUE; } static ib_api_status_t pr_rcv_get_path_parms(IN osm_sa_t * sa, IN const ib_path_rec_t * p_pr, IN const osm_alias_guid_t * p_src_alias_guid, IN const uint16_t src_lid_ho, IN const osm_alias_guid_t * p_dest_alias_guid, IN const uint16_t dest_lid_ho, IN const ib_net64_t comp_mask, OUT osm_path_parms_t * p_parms) { const osm_node_t *p_node; const osm_physp_t *p_physp, *p_physp0; const osm_physp_t *p_src_physp; const osm_physp_t *p_dest_physp; const osm_prtn_t *p_prtn = NULL; osm_opensm_t *p_osm; struct osm_routing_engine *p_re; const ib_port_info_t *p_pi, *p_pi0; ib_api_status_t status = IB_SUCCESS; ib_net16_t pkey; uint8_t mtu; uint8_t rate, p0_extended_rate, dest_rate; uint8_t pkt_life; uint8_t required_mtu; uint8_t required_rate; uint8_t required_pkt_life; uint8_t sl; uint8_t in_port_num; ib_net16_t dest_lid; uint8_t i; ib_slvl_table_t *p_slvl_tbl = NULL; osm_qos_level_t *p_qos_level = NULL; uint16_t valid_sl_mask = 0xffff; int hops = 0; int extended, p0_extended; OSM_LOG_ENTER(sa->p_log); dest_lid = cl_hton16(dest_lid_ho); p_dest_physp = p_dest_alias_guid->p_base_port->p_physp; p_physp = p_src_alias_guid->p_base_port->p_physp; p_src_physp = p_physp; p_pi = &p_physp->port_info; p_osm = sa->p_subn->p_osm; p_re = p_osm->routing_engine_used; mtu = ib_port_info_get_mtu_cap(p_pi); extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; rate = ib_port_info_compute_rate(p_pi, extended); /* Mellanox Tavor device performance is better using 1K MTU. If required MTU and MTU selector are such that 1K is OK and at least one end of the path is Tavor we override the port MTU with 1K. */ if (sa->p_subn->opt.enable_quirks && sa_path_rec_apply_tavor_mtu_limit(p_pr, p_src_alias_guid->p_base_port, p_dest_alias_guid->p_base_port, comp_mask)) if (mtu > IB_MTU_LEN_1024) { mtu = IB_MTU_LEN_1024; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Optimized Path MTU to 1K for Mellanox Tavor device\n"); } /* Walk the subnet object from source to destination, tracking the most restrictive rate and mtu values along the way... If source port node is a switch, then p_physp should point to the port that routes the destination lid */ p_node = osm_physp_get_node_ptr(p_physp); if (p_node->sw) { /* * Source node is a switch. * Make sure that p_physp points to the out port of the * switch that routes to the destination lid (dest_lid_ho) */ p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F02: " "Cannot find routing from LID %u to LID %u on " "switch %s (GUID: 0x%016" PRIx64 ")\n", src_lid_ho, dest_lid_ho, p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node))); status = IB_NOT_FOUND; goto Exit; } } if (sa->p_subn->opt.qos) { /* * Whether this node is switch or CA, the IN port for * the sl2vl table is 0, because this is a source node. */ p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0); /* update valid SLs that still exist on this route */ for (i = 0; i < IB_MAX_NUM_VLS; i++) { if (valid_sl_mask & (1 << i) && ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL) valid_sl_mask &= ~(1 << i); } if (!valid_sl_mask) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "All the SLs lead to VL15 on this path\n"); status = IB_NOT_FOUND; goto Exit; } } /* * Same as above */ p_node = osm_physp_get_node_ptr(p_dest_physp); if (p_node->sw) { /* * if destination is switch, we want p_dest_physp to point to port 0 */ p_dest_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_dest_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F03: " "Can't find routing from LID %u to LID %u on " "switch %s (GUID: 0x%016" PRIx64 ")\n", src_lid_ho, dest_lid_ho, p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node))); status = IB_NOT_FOUND; goto Exit; } } /* * Now go through the path step by step */ while (p_physp != p_dest_physp) { int tmp_pnum = p_physp->port_num; p_node = osm_physp_get_node_ptr(p_physp); p_physp = osm_physp_get_remote(p_physp); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F05: " "Can't find remote phys port of %s (GUID: " "0x%016"PRIx64") port %d " "while routing from LID %u to LID %u\n", p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node)), tmp_pnum, src_lid_ho, dest_lid_ho); status = IB_ERROR; goto Exit; } in_port_num = osm_physp_get_port_num(p_physp); /* This is point to point case (no switch in between) */ if (p_physp == p_dest_physp) break; p_node = osm_physp_get_node_ptr(p_physp); if (!p_node->sw) { /* There is some sort of problem in the subnet object! If this isn't a switch, we should have reached the destination by now! */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F06: " "Internal error, bad path while routing " "%s (GUID: 0x%016"PRIx64") port %d to " "%s (GUID: 0x%016"PRIx64") port %d; " "ended at %s port %d\n", p_src_alias_guid->p_base_port->p_node->print_desc, cl_ntoh64(p_src_alias_guid->p_base_port->p_node->node_info.node_guid), p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, cl_ntoh64(p_dest_alias_guid->p_base_port->p_node->node_info.node_guid), p_dest_alias_guid->p_base_port->p_physp->port_num, p_node->print_desc, p_physp->port_num); status = IB_ERROR; goto Exit; } /* Check parameters for the ingress port in this switch. */ p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0); p_pi0 = &p_physp0->port_info; p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended); if (ib_path_compare_rates(rate, p0_extended_rate) > 0) rate = p0_extended_rate; /* Continue with the egress port on this switch. */ p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F07: " "Dead end path on switch " "%s (GUID: 0x%016"PRIx64") to LID %u\n", p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node)), dest_lid_ho); status = IB_ERROR; goto Exit; } p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0); p_pi0 = &p_physp0->port_info; p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended); if (ib_path_compare_rates(rate, p0_extended_rate) > 0) rate = p0_extended_rate; if (sa->p_subn->opt.qos) { /* * Check SL2VL table of the switch and update valid SLs */ p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, in_port_num); for (i = 0; i < IB_MAX_NUM_VLS; i++) { if (valid_sl_mask & (1 << i) && ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL) valid_sl_mask &= ~(1 << i); } if (!valid_sl_mask) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "All the SLs " "lead to VL15 on this path\n"); status = IB_NOT_FOUND; goto Exit; } } /* update number of hops traversed */ hops++; if (hops > MAX_HOPS) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F25: " "Path from GUID 0x%016" PRIx64 " (%s port %d) " "to lid %u GUID 0x%016" PRIx64 " (%s port %d) " "needs more than %d hops, max %d hops allowed\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, dest_lid_ho, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num, hops, MAX_HOPS); status = IB_NOT_FOUND; goto Exit; } } /* p_physp now points to the destination */ p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; dest_rate = ib_port_info_compute_rate(p_pi, extended); if (ib_path_compare_rates(rate, dest_rate) > 0) rate = dest_rate; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Path min MTU = %u, min rate = %u\n", mtu, rate); /* * Get QoS Level object according to the path request * and adjust path parameters according to QoS settings */ if (sa->p_subn->opt.qos && sa->p_subn->p_qos_policy && (p_qos_level = osm_qos_policy_get_qos_level_by_pr(sa->p_subn->p_qos_policy, p_pr, p_src_physp, p_dest_physp, comp_mask))) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "PathRecord request matches QoS Level '%s' (%s)\n", p_qos_level->name, p_qos_level->use ? p_qos_level->use : "no description"); if (p_qos_level->mtu_limit_set && (mtu > p_qos_level->mtu_limit)) mtu = p_qos_level->mtu_limit; if (p_qos_level->rate_limit_set && (ib_path_compare_rates(rate, p_qos_level->rate_limit) > 0)) rate = p_qos_level->rate_limit; if (p_qos_level->sl_set) { sl = p_qos_level->sl; if (!(valid_sl_mask & (1 << sl))) { status = IB_NOT_FOUND; goto Exit; } } } /* * Set packet lifetime. * According to spec definition IBA 1.2 Table 205 * PacketLifeTime description, for loopback paths, * packetLifeTime shall be zero. */ if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port) pkt_life = 0; else if (p_qos_level && p_qos_level->pkt_life_set) pkt_life = p_qos_level->pkt_life; else pkt_life = sa->p_subn->opt.subnet_timeout; /* Determine if these values meet the user criteria and adjust appropriately */ /* we silently ignore cases where only the MTU selector is defined */ if ((comp_mask & IB_PR_COMPMASK_MTUSELEC) && (comp_mask & IB_PR_COMPMASK_MTU)) { required_mtu = ib_path_rec_mtu(p_pr); switch (ib_path_rec_mtu_sel(p_pr)) { case 0: /* must be greater than */ if (mtu <= required_mtu) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (mtu >= required_mtu) { /* adjust to use the highest mtu lower than the required one */ if (required_mtu > 1) mtu = required_mtu - 1; else status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (mtu < required_mtu) status = IB_NOT_FOUND; else mtu = required_mtu; break; case 3: /* largest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_path_rec_mtu_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* we silently ignore cases where only the Rate selector is defined */ if ((comp_mask & IB_PR_COMPMASK_RATESELEC) && (comp_mask & IB_PR_COMPMASK_RATE)) { required_rate = ib_path_rec_rate(p_pr); switch (ib_path_rec_rate_sel(p_pr)) { case 0: /* must be greater than */ if (ib_path_compare_rates(rate, required_rate) <= 0) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (ib_path_compare_rates(rate, required_rate) >= 0) { /* adjust the rate to use the highest rate lower than the required one */ rate = ib_path_rate_get_prev(required_rate); if (!rate) status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (ib_path_compare_rates(rate, required_rate)) status = IB_NOT_FOUND; else rate = required_rate; break; case 3: /* largest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_path_rec_mtu_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* we silently ignore cases where only the PktLife selector is defined */ if ((comp_mask & IB_PR_COMPMASK_PKTLIFETIMESELEC) && (comp_mask & IB_PR_COMPMASK_PKTLIFETIME)) { required_pkt_life = ib_path_rec_pkt_life(p_pr); switch (ib_path_rec_pkt_life_sel(p_pr)) { case 0: /* must be greater than */ if (pkt_life <= required_pkt_life) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (pkt_life >= required_pkt_life) { /* adjust the lifetime to use the highest possible lower than the required one */ if (required_pkt_life > 1) pkt_life = required_pkt_life - 1; else status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (pkt_life < required_pkt_life) status = IB_NOT_FOUND; else pkt_life = required_pkt_life; break; case 3: /* smallest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* * set Pkey for this path record request */ if ((comp_mask & IB_PR_COMPMASK_RAWTRAFFIC) && (cl_ntoh32(p_pr->hop_flow_raw) & (1 << 31))) pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); else if (comp_mask & IB_PR_COMPMASK_PKEY) { /* * PR request has a specific pkey: * Check that source and destination share this pkey. * If QoS level has pkeys, check that this pkey exists * in the QoS level pkeys. * PR returned pkey is the requested pkey. */ pkey = p_pr->pkey; if (!osm_physp_share_this_pkey(p_src_physp, p_dest_physp, pkey, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1A: " "Ports 0x%016" PRIx64 " (%s port %d) and " "0x%016" PRIx64 " (%s port %d) " "do not share specified PKey 0x%04x\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num, cl_ntoh16(pkey)); status = IB_NOT_FOUND; goto Exit; } if (p_qos_level && p_qos_level->pkey_range_len && !osm_qos_level_has_pkey(p_qos_level, pkey)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1D: " "QoS level \"%s\" doesn't define specified PKey 0x%04x " "for ports 0x%016" PRIx64 " (%s port %d) and " "0x%016"PRIx64" (%s port %d)\n", p_qos_level->name, cl_ntoh16(pkey), cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } else if (p_qos_level && p_qos_level->pkey_range_len) { /* * PR request doesn't have a specific pkey, but QoS level * has pkeys - get shared pkey from QoS level pkeys */ pkey = osm_qos_level_get_shared_pkey(p_qos_level, p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); if (!pkey) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1E: " "Ports 0x%016" PRIx64 " (%s) and " "0x%016" PRIx64 " (%s) do not share " "PKeys defined by QoS level \"%s\"\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_qos_level->name); status = IB_NOT_FOUND; goto Exit; } } else { /* * Neither PR request nor QoS level have pkey. * Just get any shared pkey. */ pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); if (!pkey) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1B: " "Ports src 0x%016"PRIx64" (%s port %d) and " "dst 0x%016"PRIx64" (%s port %d) do not have " "any shared PKeys\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } if (pkey) { p_prtn = (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl, pkey & cl_hton16((uint16_t) ~ 0x8000)); if (p_prtn == (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl)) p_prtn = NULL; } /* * Set PathRecord SL */ if (comp_mask & IB_PR_COMPMASK_SL) { /* * Specific SL was requested */ sl = ib_path_rec_sl(p_pr); if (p_qos_level && p_qos_level->sl_set && (p_qos_level->sl != sl)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1F: " "QoS constraints: required PathRecord SL (%u) " "doesn't match QoS policy \"%s\" SL (%u) " "[%s port %d <-> %s port %d]\n", sl, p_qos_level->name, p_qos_level->sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } else if (p_qos_level && p_qos_level->sl_set) { /* * No specific SL was requested, but there is an SL in * QoS level. */ sl = p_qos_level->sl; if (pkey && p_prtn && p_prtn->sl != p_qos_level->sl) OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "QoS level SL (%u) overrides partition SL (%u)\n", p_qos_level->sl, p_prtn->sl); } else if (pkey) { /* * No specific SL in request or in QoS level - use partition SL */ if (!p_prtn) { sl = OSM_DEFAULT_SL; /* this may be possible when pkey tables are created somehow in previous runs or things are going wrong here */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F1C: " "No partition found for PKey 0x%04x - " "using default SL %d " "[%s port %d <-> %s port %d]\n", cl_ntoh16(pkey), sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); } else sl = p_prtn->sl; } else if (sa->p_subn->opt.qos) { if (valid_sl_mask & (1 << OSM_DEFAULT_SL)) sl = OSM_DEFAULT_SL; else { for (i = 0; i < IB_MAX_NUM_VLS; i++) if (valid_sl_mask & (1 << i)) break; sl = i; } } else sl = OSM_DEFAULT_SL; if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << sl))) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F24: " "Selected SL (%u) leads to VL15 " "[%s port %d <-> %s port %d]\n", sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } /* * If the routing engine wants to have a say in path SL selection, * send the currently computed SL value as a hint and let the routing * engine override it. */ if (p_re && p_re->path_sl) { uint8_t pr_sl; pr_sl = sl; sl = p_re->path_sl(p_re->context, sl, cl_hton16(src_lid_ho), cl_hton16(dest_lid_ho)); if ((comp_mask & IB_PR_COMPMASK_SL) && (sl != pr_sl)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F2A: " "Requested SL (%u) doesn't match SL calculated" "by routing engine (%u) " "[%s port %d <-> %s port %d]\n", pr_sl, sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } /* reset pkey when raw traffic */ if (comp_mask & IB_PR_COMPMASK_RAWTRAFFIC && cl_ntoh32(p_pr->hop_flow_raw) & (1 << 31)) pkey = 0; p_parms->mtu = mtu; p_parms->rate = rate; p_parms->pkt_life = pkt_life; p_parms->pkey = pkey; p_parms->sl = sl; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Path params: mtu = %u, rate = %u," " packet lifetime = %u, pkey = 0x%04X, sl = %u\n", mtu, rate, pkt_life, cl_ntoh16(pkey), sl); Exit: OSM_LOG_EXIT(sa->p_log); return status; } ib_api_status_t osm_get_path_params(IN osm_sa_t * sa, IN const osm_port_t * p_src_port, IN const uint16_t slid_ho, IN const osm_port_t * p_dest_port, IN const uint16_t dlid_ho, OUT osm_path_parms_t * p_parms) { osm_alias_guid_t *p_src_alias_guid, *p_dest_alias_guid; ib_path_rec_t pr; memset(&pr, 0, sizeof(ib_path_rec_t)); p_src_alias_guid = osm_get_alias_guid_by_guid(sa->p_subn, osm_port_get_guid(p_src_port)); p_dest_alias_guid = osm_get_alias_guid_by_guid(sa->p_subn, osm_port_get_guid(p_dest_port)); return pr_rcv_get_path_parms(sa, &pr, p_src_alias_guid, slid_ho, p_dest_alias_guid, dlid_ho, 0, p_parms); } static void pr_rcv_build_pr(IN osm_sa_t * sa, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN const uint16_t src_lid_ho, IN const uint16_t dest_lid_ho, IN const uint8_t preference, IN const osm_path_parms_t * p_parms, OUT ib_path_rec_t * p_pr) { const osm_physp_t *p_src_physp, *p_dest_physp; OSM_LOG_ENTER(sa->p_log); if (p_dgid) p_pr->dgid = *p_dgid; else { p_dest_physp = p_dest_alias_guid->p_base_port->p_physp; p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix(p_dest_physp); p_pr->dgid.unicast.interface_id = p_dest_alias_guid->alias_guid; } if (p_sgid) p_pr->sgid = *p_sgid; else { p_src_physp = p_src_alias_guid->p_base_port->p_physp; p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix(p_src_physp); p_pr->sgid.unicast.interface_id = p_src_alias_guid->alias_guid; } p_pr->dlid = cl_hton16(dest_lid_ho); p_pr->slid = cl_hton16(src_lid_ho); p_pr->hop_flow_raw &= cl_hton32(1 << 31); /* Only set HopLimit if going through a router */ if (p_dgid) p_pr->hop_flow_raw |= cl_hton32(IB_HOPLIMIT_MAX); p_pr->pkey = p_parms->pkey; ib_path_rec_set_sl(p_pr, p_parms->sl); ib_path_rec_set_qos_class(p_pr, 0); p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80); p_pr->rate = (uint8_t) (p_parms->rate | 0x80); /* According to 1.2 spec definition Table 205 PacketLifeTime description, for loopback paths, packetLifeTime shall be zero. */ if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port) p_pr->pkt_life = 0x80; /* loopback */ else p_pr->pkt_life = (uint8_t) (p_parms->pkt_life | 0x80); p_pr->preference = preference; /* always return num_path = 0 so this is only the reversible component */ if (p_parms->reversible) p_pr->num_path = 0x80; OSM_LOG_EXIT(sa->p_log); } static osm_sa_item_t *pr_rcv_get_lid_pair_path(IN osm_sa_t * sa, IN const ib_path_rec_t * p_pr, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN const uint16_t src_lid_ho, IN const uint16_t dest_lid_ho, IN const ib_net64_t comp_mask, IN const uint8_t preference) { osm_path_parms_t path_parms; osm_path_parms_t rev_path_parms; osm_sa_item_t *p_pr_item; ib_api_status_t status, rev_path_status; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID %u, Dest LID %u\n", src_lid_ho, dest_lid_ho); p_pr_item = malloc(SA_PR_RESP_SIZE); if (p_pr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F01: " "Unable to allocate path record\n"); goto Exit; } memset(p_pr_item, 0, SA_PR_RESP_SIZE); status = pr_rcv_get_path_parms(sa, p_pr, p_src_alias_guid, src_lid_ho, p_dest_alias_guid, dest_lid_ho, comp_mask, &path_parms); if (status != IB_SUCCESS) { free(p_pr_item); p_pr_item = NULL; goto Exit; } /* now try the reversible path */ rev_path_status = pr_rcv_get_path_parms(sa, p_pr, p_dest_alias_guid, dest_lid_ho, p_src_alias_guid, src_lid_ho, comp_mask, &rev_path_parms); path_parms.reversible = (rev_path_status == IB_SUCCESS); /* did we get a Reversible Path compmask ? */ /* NOTE that if the reversible component = 0, it is a don't care rather than requiring non-reversible paths ... see Vol1 Ver1.2 p900 l16 */ if ((comp_mask & IB_PR_COMPMASK_REVERSIBLE) && !path_parms.reversible && (p_pr->num_path & 0x80)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requested reversible path but failed to get one\n"); free(p_pr_item); p_pr_item = NULL; goto Exit; } pr_rcv_build_pr(sa, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, src_lid_ho, dest_lid_ho, preference, &path_parms, &p_pr_item->resp.path_rec); Exit: OSM_LOG_EXIT(sa->p_log); return p_pr_item; } static void pr_rcv_get_port_pair_paths(IN osm_sa_t * sa, IN const ib_sa_mad_t *sa_mad, IN const osm_port_t * p_req_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list) { const ib_path_rec_t *p_pr = ib_sa_mad_get_payload_ptr(sa_mad); ib_net64_t comp_mask = sa_mad->comp_mask; osm_sa_item_t *p_pr_item; uint16_t src_lid_min_ho; uint16_t src_lid_max_ho; uint16_t dest_lid_min_ho; uint16_t dest_lid_max_ho; uint16_t src_lid_ho; uint16_t dest_lid_ho; uint32_t path_num; uint8_t preference; unsigned iterations, src_offset, dest_offset; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src port 0x%016" PRIx64 ", Dst port 0x%016" PRIx64 "\n", cl_ntoh64(p_src_alias_guid->alias_guid), cl_ntoh64(p_dest_alias_guid->alias_guid)); /* Check that the req_port, src_port and dest_port all share a pkey. The check is done on the default physical port of the ports. */ if (osm_port_share_pkey(sa->p_log, p_req_port, p_src_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE || osm_port_share_pkey(sa->p_log, p_req_port, p_dest_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE || osm_port_share_pkey(sa->p_log, p_src_alias_guid->p_base_port, p_dest_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE) /* One of the pairs doesn't share a pkey so the path is disqualified. */ goto Exit; /* We shouldn't be here if the paths are disqualified in some way... Thus, we assume every possible connection is valid. We desire to return high-quality paths first. In OpenSM, higher quality means least overlap with other paths. This is acheived in practice by returning paths with different LID value on each end, which means these paths are more redundant that paths with the same LID repeated on one side. For example, in OpenSM the paths between two endpoints with LMC = 1 might be as follows: Port A, LID 1 <-> Port B, LID 3 Port A, LID 1 <-> Port B, LID 4 Port A, LID 2 <-> Port B, LID 3 Port A, LID 2 <-> Port B, LID 4 The OpenSM unicast routing algorithms attempt to disperse each path to as varied a physical path as is reasonable. 1<->3 and 1<->4 have more physical overlap (hence less redundancy) than 1<->3 and 2<->4. OpenSM ranks paths in three preference groups: Preference Value Description ---------------- ------------------------------------------- 0 Redundant in both directions with other pref value = 0 paths 1 Redundant in one direction with other pref value = 0 and pref value = 1 paths 2 Not redundant in either direction with other paths 3-FF Unused SA clients don't need to know these details, only that the lower preference paths are preferred, as stated in the spec. The paths may not actually be physically redundant depending on the topology of the subnet, but the point of LMC > 0 is to offer redundancy, so it is assumed that the subnet is physically appropriate for the specified LMC value. A more advanced implementation would inspect for physical redundancy, but I'm not going to bother with that now. */ /* Refine our search if the client specified end-point LIDs */ if (comp_mask & IB_PR_COMPMASK_DLID) dest_lid_max_ho = dest_lid_min_ho = cl_ntoh16(p_pr->dlid); else osm_port_get_lid_range_ho(p_dest_alias_guid->p_base_port, &dest_lid_min_ho, &dest_lid_max_ho); if (comp_mask & IB_PR_COMPMASK_SLID) src_lid_max_ho = src_lid_min_ho = cl_ntoh16(p_pr->slid); else osm_port_get_lid_range_ho(p_src_alias_guid->p_base_port, &src_lid_min_ho, &src_lid_max_ho); if (src_lid_min_ho == 0) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Obtained source LID of 0. No such LID possible " "(%s port %d)\n", p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num); goto Exit; } if (dest_lid_min_ho == 0) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Obtained destination LID of 0. No such LID possible " "(%s port %d)\n", p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LIDs [%u-%u], Dest LIDs [%u-%u]\n", src_lid_min_ho, src_lid_max_ho, dest_lid_min_ho, dest_lid_max_ho); src_lid_ho = src_lid_min_ho; dest_lid_ho = dest_lid_min_ho; /* Preferred paths come first in OpenSM */ preference = 0; path_num = 0; /* If SubnAdmGet, assume NumbPaths 1 (1.2 erratum) */ if (sa_mad->method == IB_MAD_METHOD_GET) iterations = 1; else if (comp_mask & IB_PR_COMPMASK_NUMBPATH) iterations = ib_path_rec_num_path(p_pr); else iterations = (unsigned) (-1); while (path_num < iterations) { /* These paths are "fully redundant" */ p_pr_item = pr_rcv_get_lid_pair_path(sa, p_pr, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, src_lid_ho, dest_lid_ho, comp_mask, preference); if (p_pr_item) { cl_qlist_insert_tail(p_list, &p_pr_item->list_item); ++path_num; } if (++src_lid_ho > src_lid_max_ho) break; if (++dest_lid_ho > dest_lid_max_ho) break; } /* Check if we've accumulated all the paths that the user cares to see */ if (path_num == iterations) goto Exit; /* Don't bother reporting preference 1 paths for now. It's more trouble than it's worth and can only occur if ports have different LMC values, which isn't supported by OpenSM right now anyway. */ preference = 2; src_lid_ho = src_lid_min_ho; dest_lid_ho = dest_lid_min_ho; src_offset = 0; dest_offset = 0; /* Iterate over the remaining paths */ while (path_num < iterations) { dest_offset++; dest_lid_ho++; if (dest_lid_ho > dest_lid_max_ho) { src_offset++; src_lid_ho++; if (src_lid_ho > src_lid_max_ho) break; /* done */ dest_offset = 0; dest_lid_ho = dest_lid_min_ho; } /* These paths are "fully non-redundant" with paths already identified above and consequently not of much value. Don't return paths we already identified above, as indicated by the offset values being equal. */ if (src_offset == dest_offset) continue; /* already reported */ p_pr_item = pr_rcv_get_lid_pair_path(sa, p_pr, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, src_lid_ho, dest_lid_ho, comp_mask, preference); if (p_pr_item) { cl_qlist_insert_tail(p_list, &p_pr_item->list_item); ++path_num; } } Exit: OSM_LOG_EXIT(sa->p_log); } /* Find the router port that is configured to handle this prefix, if any */ static ib_net64_t find_router(const osm_sa_t *sa, ib_net64_t prefix) { osm_prefix_route_t *route = NULL; osm_router_t *rtr; cl_qlist_t *l = &sa->p_subn->prefix_routes_list; cl_list_item_t *i; OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Non local DGID subnet prefix " "0x%016" PRIx64 "\n", cl_ntoh64(prefix)); for (i = cl_qlist_head(l); i != cl_qlist_end(l); i = cl_qlist_next(i)) { osm_prefix_route_t *r = (osm_prefix_route_t *)i; if (!r->prefix || r->prefix == prefix) { route = r; break; } } if (!route) return 0; if (route->guid == 0) /* first router */ rtr = (osm_router_t *) cl_qmap_head(&sa->p_subn->rtr_guid_tbl); else rtr = (osm_router_t *) cl_qmap_get(&sa->p_subn->rtr_guid_tbl, route->guid); if (rtr == (osm_router_t *) cl_qmap_end(&sa->p_subn->rtr_guid_tbl)) return 0; return osm_port_get_guid(osm_router_get_port_ptr(rtr)); } ib_net16_t osm_pr_get_end_points(IN osm_sa_t * sa, IN const ib_sa_mad_t *sa_mad, OUT const osm_alias_guid_t ** pp_src_alias_guid, OUT const osm_alias_guid_t ** pp_dest_alias_guid, OUT const osm_port_t ** pp_src_port, OUT const osm_port_t ** pp_dest_port, OUT const ib_gid_t ** pp_sgid, OUT const ib_gid_t ** pp_dgid) { const ib_path_rec_t *p_pr = ib_sa_mad_get_payload_ptr(sa_mad); ib_net64_t comp_mask = sa_mad->comp_mask; ib_net64_t dest_guid; ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; OSM_LOG_ENTER(sa->p_log); /* Determine what fields are valid and then get a pointer to the source and destination port objects, if possible. */ /* Check a few easy disqualifying cases up front before getting into the endpoints. */ *pp_src_alias_guid = NULL; *pp_src_port = NULL; if (comp_mask & IB_PR_COMPMASK_SGID) { if (!ib_gid_is_link_local(&p_pr->sgid)) { if (ib_gid_get_subnet_prefix(&p_pr->sgid) != sa->p_subn->opt.subnet_prefix) { /* This 'error' is the client's fault (bad gid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Non local SGID subnet prefix 0x%016" PRIx64 "\n", cl_ntoh64(p_pr->sgid.unicast.prefix)); sa_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } } *pp_src_alias_guid = osm_get_alias_guid_by_guid(sa->p_subn, p_pr->sgid.unicast.interface_id); if (!*pp_src_alias_guid) { /* This 'error' is the client's fault (bad gid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No source port with GUID 0x%016" PRIx64 "\n", cl_ntoh64(p_pr->sgid.unicast.interface_id)); sa_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } if (pp_sgid) *pp_sgid = &p_pr->sgid; } if (comp_mask & IB_PR_COMPMASK_SLID) { *pp_src_port = osm_get_port_by_lid(sa->p_subn, p_pr->slid); if (!*pp_src_port) { /* This 'error' is the client's fault (bad lid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No source port " "with LID %u\n", cl_ntoh16(p_pr->slid)); sa_status = IB_SA_MAD_STATUS_NO_RECORDS; goto Exit; } } *pp_dest_alias_guid = NULL; *pp_dest_port = NULL; if (comp_mask & IB_PR_COMPMASK_DGID) { if (!ib_gid_is_link_local(&p_pr->dgid) && !ib_gid_is_multicast(&p_pr->dgid) && ib_gid_get_subnet_prefix(&p_pr->dgid) != sa->p_subn->opt.subnet_prefix) { dest_guid = find_router(sa, p_pr->dgid.unicast.prefix); if (!dest_guid) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Off subnet DGID %s, but router not " "found\n", inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof(gid_str))); sa_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } if (pp_dgid) *pp_dgid = &p_pr->dgid; } else dest_guid = p_pr->dgid.unicast.interface_id; *pp_dest_alias_guid = osm_get_alias_guid_by_guid(sa->p_subn, dest_guid); if (!*pp_dest_alias_guid) { /* This 'error' is the client's fault (bad gid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No dest port with GUID 0x%016" PRIx64 "\n", cl_ntoh64(dest_guid)); sa_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } } if (comp_mask & IB_PR_COMPMASK_DLID) { *pp_dest_port = osm_get_port_by_lid(sa->p_subn, p_pr->dlid); if (!*pp_dest_port) { /* This 'error' is the client's fault (bad lid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "No dest port " "with LID %u\n", cl_ntoh16(p_pr->dlid)); sa_status = IB_SA_MAD_STATUS_NO_RECORDS; goto Exit; } } Exit: OSM_LOG_EXIT(sa->p_log); return sa_status; } static void pr_rcv_process_world(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_port_t * requester_port, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list) { const cl_qmap_t *p_tbl; const osm_alias_guid_t *p_dest_alias_guid, *p_src_alias_guid; OSM_LOG_ENTER(sa->p_log); /* Iterate the entire port space over itself. A path record from a port to itself is legit, so no need for a special case there. We compute both A -> B and B -> A, since we don't have any check to determine the reversability of the paths. */ p_tbl = &sa->p_subn->alias_port_guid_tbl; p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_tbl); while (p_dest_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_tbl)) { p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_tbl); while (p_src_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_tbl)) { pr_rcv_get_port_pair_paths(sa, sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, p_list); if (sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(p_list) > 0) goto Exit; p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_src_alias_guid->map_item); } p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_dest_alias_guid->map_item); } Exit: OSM_LOG_EXIT(sa->p_log); } void osm_pr_process_half(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_port_t * requester_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list) { const cl_qmap_t *p_tbl; const osm_alias_guid_t *p_alias_guid; OSM_LOG_ENTER(sa->p_log); /* Iterate over every port, looking for matches... A path record from a port to itself is legit, so no need to special case that one. */ p_tbl = &sa->p_subn->alias_port_guid_tbl; if (p_src_alias_guid) { /* The src port if fixed, so iterate over destination ports. */ p_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_tbl); while (p_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_tbl)) { pr_rcv_get_port_pair_paths(sa, sa_mad, requester_port, p_src_alias_guid, p_alias_guid, p_sgid, p_dgid, p_list); if (sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(p_list) > 0) break; p_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid->map_item); } } else { /* The dest port if fixed, so iterate over source ports. */ p_alias_guid = (osm_alias_guid_t *) cl_qmap_head(p_tbl); while (p_alias_guid != (osm_alias_guid_t *) cl_qmap_end(p_tbl)) { pr_rcv_get_port_pair_paths(sa, sa_mad, requester_port, p_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, p_list); if (sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(p_list) > 0) break; p_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid->map_item); } } OSM_LOG_EXIT(sa->p_log); } void osm_pr_process_pair(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_port_t * requester_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const ib_gid_t * p_sgid, IN const ib_gid_t * p_dgid, IN cl_qlist_t * p_list) { OSM_LOG_ENTER(sa->p_log); pr_rcv_get_port_pair_paths(sa, sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, p_list); OSM_LOG_EXIT(sa->p_log); } static ib_api_status_t pr_match_mgrp_attributes(IN osm_sa_t * sa, IN const ib_sa_mad_t * sa_mad, IN const osm_mgrp_t * p_mgrp) { const ib_path_rec_t *p_pr = ib_sa_mad_get_payload_ptr(sa_mad); ib_net64_t comp_mask = sa_mad->comp_mask; const osm_port_t *port; ib_api_status_t status = IB_ERROR; uint32_t flow_label; uint8_t sl, hop_limit; OSM_LOG_ENTER(sa->p_log); /* check that MLID of the MC group matches the PathRecord DLID */ if ((comp_mask & IB_PR_COMPMASK_DLID) && p_mgrp->mlid != p_pr->dlid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "DLID 0x%x is not MLID 0x%x for MC group\n", cl_ntoh16(p_pr->dlid), cl_ntoh16(p_mgrp->mlid)); goto Exit; } /* If SGID and/or SLID specified, should validate as member of MC group */ if (comp_mask & IB_PR_COMPMASK_SGID) { if (!osm_mgrp_get_mcm_alias_guid(p_mgrp, p_pr->sgid.unicast.interface_id)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "SGID %s is not a member of MC group\n", inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str, sizeof gid_str)); goto Exit; } } if (comp_mask & IB_PR_COMPMASK_SLID) { port = osm_get_port_by_lid(sa->p_subn, p_pr->slid); if (!port || !osm_mgrp_get_mcm_port(p_mgrp, port->guid)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Either no port with SLID %u found or " "SLID not a member of MC group\n", cl_ntoh16(p_pr->slid)); goto Exit; } } /* Also, MTU, rate, packet lifetime, and raw traffic requested are not currently checked */ if ((comp_mask & IB_PR_COMPMASK_PKEY) && p_pr->pkey != p_mgrp->mcmember_rec.pkey) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Pkey 0x%x doesn't match MC group Pkey 0x%x\n", cl_ntoh16(p_pr->pkey), cl_ntoh16(p_mgrp->mcmember_rec.pkey)); goto Exit; } ib_member_get_sl_flow_hop(p_mgrp->mcmember_rec.sl_flow_hop, &sl, &flow_label, &hop_limit); if ((comp_mask & IB_PR_COMPMASK_SL) && ib_path_rec_sl(p_pr) != sl) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "SL %d doesn't match MC group SL %d\n", ib_path_rec_sl(p_pr), sl); goto Exit; } /* If SubnAdmGet, assume NumbPaths of 1 (1.2 erratum) */ if ((comp_mask & IB_PR_COMPMASK_NUMBPATH) && sa_mad->method != IB_MAD_METHOD_GET && ib_path_rec_num_path(p_pr) == 0) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Number of paths requested is 0\n"); goto Exit; } if ((comp_mask & IB_PR_COMPMASK_FLOWLABEL) && ib_path_rec_flow_lbl(p_pr) != flow_label) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Flow label 0x%x doesn't match MC group " " flow label 0x%x\n", ib_path_rec_flow_lbl(p_pr), flow_label); goto Exit; } if ((comp_mask & IB_PR_COMPMASK_HOPLIMIT) && ib_path_rec_hop_limit(p_pr) != hop_limit) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Hop limit %u doesn't match MC group hop limit %u\n", ib_path_rec_hop_limit(p_pr), hop_limit); goto Exit; } if ((comp_mask & IB_PR_COMPMASK_TCLASS) && p_pr->tclass != p_mgrp->mcmember_rec.tclass) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "TClass 0x%02x doesn't match MC group TClass 0x%02x\n", p_pr->tclass, p_mgrp->mcmember_rec.tclass); goto Exit; } status = IB_SUCCESS; Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void pr_process_multicast(osm_sa_t * sa, const ib_sa_mad_t *sa_mad, cl_qlist_t *list) { ib_path_rec_t *pr = ib_sa_mad_get_payload_ptr(sa_mad); osm_mgrp_t *mgrp; ib_api_status_t status; osm_sa_item_t *pr_item; uint32_t flow_label; uint8_t sl, hop_limit; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Multicast destination requested\n"); mgrp = osm_get_mgrp_by_mgid(sa->p_subn, &pr->dgid); if (!mgrp) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F09: " "No MC group found for PathRecord destination GID %s\n", inet_ntop(AF_INET6, pr->dgid.raw, gid_str, sizeof gid_str)); return; } /* Make sure the rest of the PathRecord matches the MC group attributes */ status = pr_match_mgrp_attributes(sa, sa_mad, mgrp); if (status != IB_SUCCESS) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F19: " "MC group attributes don't match PathRecord request\n"); return; } pr_item = malloc(SA_PR_RESP_SIZE); if (pr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F18: " "Unable to allocate path record for MC group\n"); return; } memset(pr_item, 0, sizeof(cl_list_item_t)); /* Copy PathRecord request into response */ pr_item->resp.path_rec = *pr; /* Now, use the MC info to cruft up the PathRecord response */ pr_item->resp.path_rec.dgid = mgrp->mcmember_rec.mgid; pr_item->resp.path_rec.dlid = mgrp->mcmember_rec.mlid; pr_item->resp.path_rec.tclass = mgrp->mcmember_rec.tclass; pr_item->resp.path_rec.num_path = 1; pr_item->resp.path_rec.pkey = mgrp->mcmember_rec.pkey; /* MTU, rate, and packet lifetime should be exactly */ pr_item->resp.path_rec.mtu = (IB_PATH_SELECTOR_EXACTLY << 6) | mgrp->mcmember_rec.mtu; pr_item->resp.path_rec.rate = (IB_PATH_SELECTOR_EXACTLY << 6) | mgrp->mcmember_rec.rate; pr_item->resp.path_rec.pkt_life = (IB_PATH_SELECTOR_EXACTLY << 6) | mgrp->mcmember_rec.pkt_life; /* SL, Hop Limit, and Flow Label */ ib_member_get_sl_flow_hop(mgrp->mcmember_rec.sl_flow_hop, &sl, &flow_label, &hop_limit); ib_path_rec_set_sl(&pr_item->resp.path_rec, sl); ib_path_rec_set_qos_class(&pr_item->resp.path_rec, 0); /* HopLimit is not yet set in non link local MC groups */ /* If it were, this would not be needed */ if (ib_mgid_get_scope(&mgrp->mcmember_rec.mgid) != IB_MC_SCOPE_LINK_LOCAL) hop_limit = IB_HOPLIMIT_MAX; pr_item->resp.path_rec.hop_flow_raw = cl_hton32(hop_limit) | (flow_label << 8); cl_qlist_insert_tail(list, &pr_item->list_item); } void osm_pr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); ib_path_rec_t *p_pr = ib_sa_mad_get_payload_ptr(p_sa_mad); cl_qlist_t pr_list; const ib_gid_t *p_sgid = NULL, *p_dgid = NULL; const osm_alias_guid_t *p_src_alias_guid, *p_dest_alias_guid; const osm_port_t *p_src_port, *p_dest_port; osm_port_t *requester_port; uint8_t rate, mtu; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_sa_mad->method != IB_MAD_METHOD_GET && p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F17: " "Unsupported Method (%s) for PathRecord request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } /* Validate rate if supplied */ if ((p_sa_mad->comp_mask & IB_PR_COMPMASK_RATESELEC) && (p_sa_mad->comp_mask & IB_PR_COMPMASK_RATE)) { rate = ib_path_rec_rate(p_pr); if (!ib_rate_is_valid(rate)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } } /* Validate MTU if supplied */ if ((p_sa_mad->comp_mask & IB_PR_COMPMASK_MTUSELEC) && (p_sa_mad->comp_mask & IB_PR_COMPMASK_MTU)) { mtu = ib_path_rec_mtu(p_pr); if (!ib_mtu_is_valid(mtu)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } } /* Make sure either none or both ServiceID parameters are supplied */ if ((p_sa_mad->comp_mask & IB_PR_COMPMASK_SERVICEID) != 0 && (p_sa_mad->comp_mask & IB_PR_COMPMASK_SERVICEID) != IB_PR_COMPMASK_SERVICEID) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } cl_qlist_init(&pr_list); /* Most SA functions (including this one) are read-only on the subnet object, so we grab the lock non-exclusively. */ cl_plock_acquire(sa->p_lock); /* update the requester physical port */ requester_port = osm_get_port_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (requester_port == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1F16: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_port_get_guid(requester_port))); osm_dump_path_record_v2(sa->p_log, p_pr, FILE_ID, OSM_LOG_DEBUG); } /* Handle multicast destinations separately */ if ((p_sa_mad->comp_mask & IB_PR_COMPMASK_DGID) && ib_gid_is_multicast(&p_pr->dgid)) { pr_process_multicast(sa, p_sa_mad, &pr_list); goto Unlock; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unicast destination requested\n"); if (osm_pr_get_end_points(sa, p_sa_mad, &p_src_alias_guid, &p_dest_alias_guid, &p_src_port, &p_dest_port, &p_sgid, &p_dgid) != IB_SA_MAD_STATUS_SUCCESS) goto Unlock; if (p_src_alias_guid && p_src_port && p_src_alias_guid->p_base_port != p_src_port) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Requester port GUID 0x%" PRIx64 ": Port for SGUID " "0x%" PRIx64 " not same as port for SLID %u\n", cl_ntoh64(osm_port_get_guid(requester_port)), cl_ntoh64(p_pr->sgid.unicast.interface_id), cl_ntoh16(p_pr->slid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } if (p_dest_alias_guid && p_dest_port && p_dest_alias_guid->p_base_port != p_dest_port) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Requester port GUID 0x%" PRIx64 ": Port for DGUID " "0x%" PRIx64 " not same as port for DLID %u\n", cl_ntoh64(osm_port_get_guid(requester_port)), cl_ntoh64(p_pr->dgid.unicast.interface_id), cl_ntoh16(p_pr->dlid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* What happens next depends on the type of endpoint information that was specified.... */ if (p_src_alias_guid) { if (p_dest_alias_guid) osm_pr_process_pair(sa, p_sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); else if (!p_dest_port) osm_pr_process_half(sa, p_sa_mad, requester_port, p_src_alias_guid, NULL, p_sgid, p_dgid, &pr_list); else { /* Get all alias GUIDs for the dest port */ p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_dest_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_dest_alias_guid->alias_guid) == p_dest_port) osm_pr_process_pair(sa, p_sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); if (p_sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(&pr_list) > 0) break; p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_dest_alias_guid->map_item); } } } else { if (p_dest_alias_guid && !p_src_port) osm_pr_process_half(sa, p_sa_mad, requester_port, NULL, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); else if (!p_src_port && !p_dest_port) /* Katie, bar the door! */ pr_rcv_process_world(sa, p_sa_mad, requester_port, p_sgid, p_dgid, &pr_list); else if (p_dest_alias_guid && p_src_port) { /* Get all alias GUIDs for the src port */ p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_src_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_src_alias_guid->alias_guid) == p_src_port) osm_pr_process_pair(sa, p_sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); if (p_sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(&pr_list) > 0) break; p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_src_alias_guid->map_item); } } else if (p_src_port && !p_dest_port) { /* Get all alias GUIDs for the src port */ p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_src_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_src_alias_guid->alias_guid) == p_src_port) osm_pr_process_half(sa, p_sa_mad, requester_port, p_src_alias_guid, NULL, p_sgid, p_dgid, &pr_list); p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_src_alias_guid->map_item); } } else if (p_dest_port && !p_src_port) { /* Get all alias GUIDs for the dest port */ p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_dest_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_dest_alias_guid->alias_guid) == p_dest_port) osm_pr_process_half(sa, p_sa_mad, requester_port, NULL, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_dest_alias_guid->map_item); } } else { /* Get all alias GUIDs for the src port */ p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_src_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_src_alias_guid->alias_guid) == p_src_port) { /* Get all alias GUIDs for the dest port */ p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&sa->p_subn->alias_port_guid_tbl); while (p_dest_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) { if (osm_get_port_by_alias_guid(sa->p_subn, p_dest_alias_guid->alias_guid) == p_dest_port) osm_pr_process_pair(sa, p_sa_mad, requester_port, p_src_alias_guid, p_dest_alias_guid, p_sgid, p_dgid, &pr_list); if (p_sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(&pr_list) > 0) break; p_dest_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_dest_alias_guid->map_item); } } if (p_sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(&pr_list) > 0) break; p_src_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_src_alias_guid->map_item); } } } Unlock: cl_plock_release(sa->p_lock); /* Now, (finally) respond to the PathRecord request */ osm_sa_respond(sa, p_madw, sizeof(ib_path_rec_t), &pr_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_pkey_record.c0000644000205000001450000002354012314616647015342 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_PKEY_RECORD_C #include #include #include #include #include #include #define SA_PKEY_RESP_SIZE SA_ITEM_RESP_SIZE(pkey_rec) typedef struct osm_pkey_search_ctxt { const ib_pkey_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; uint16_t block_num; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_pkey_search_ctxt_t; static void sa_pkey_create(IN osm_sa_t * sa, IN osm_physp_t * p_physp, IN osm_pkey_search_ctxt_t * p_ctxt, IN uint16_t block) { osm_sa_item_t *p_rec_item; uint16_t lid; ib_pkey_table_t *tbl; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_PKEY_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4602: " "rec_item alloc failed\n"); goto Exit; } if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) lid = p_physp->port_info.base_lid; else lid = osm_node_get_base_lid(p_physp->p_node, 0); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New P_Key table for: port 0x%016" PRIx64 ", lid %u, port %u Block:%u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block); memset(p_rec_item, 0, SA_PKEY_RESP_SIZE); p_rec_item->resp.pkey_rec.lid = lid; p_rec_item->resp.pkey_rec.block_num = block; p_rec_item->resp.pkey_rec.port_num = osm_physp_get_port_num(p_physp); /* FIXME: There are ninf.PartitionCap or swinf.PartitionEnforcementCap pkey entries so everything in that range is a valid block number even if opensm is not using it. Return 0. However things outside that range should return no entries. Not sure how to figure that here? The range of pkey_tbl can be less than the cap, so this falsely triggers. */ tbl = osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block); if (tbl) p_rec_item->resp.pkey_rec.pkey_tbl = *tbl; cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_pkey_check_physp(IN osm_sa_t * sa, IN osm_physp_t * p_physp, osm_pkey_search_ctxt_t * p_ctxt) { ib_net64_t comp_mask = p_ctxt->comp_mask; uint16_t block, num_blocks; OSM_LOG_ENTER(sa->p_log); /* we got here with the phys port - all is left is to get the right block */ if (comp_mask & IB_PKEY_COMPMASK_BLOCK) { sa_pkey_create(sa, p_physp, p_ctxt, p_ctxt->block_num); } else { num_blocks = osm_pkey_tbl_get_num_blocks(osm_physp_get_pkey_tbl (p_physp)); for (block = 0; block < num_blocks; block++) sa_pkey_create(sa, p_physp, p_ctxt, block); } OSM_LOG_EXIT(sa->p_log); } static void sa_pkey_by_comp_mask(IN osm_sa_t * sa, IN const osm_port_t * p_port, osm_pkey_search_ctxt_t * p_ctxt) { const ib_pkey_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; port_num = p_rcvd_rec->port_num; p_req_physp = p_ctxt->p_req_physp; /* if this is a switch port we can search all ports otherwise we must be looking on port 0 */ if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) { /* we put it in the comp mask and port num */ port_num = p_port->p_physp->port_num; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Using Physical Default Port Number: 0x%X (for End Node)\n", port_num); comp_mask |= IB_PKEY_COMPMASK_PORT; } if (comp_mask & IB_PKEY_COMPMASK_PORT) { if (port_num < osm_node_get_num_physp(p_port->p_node)) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); /* Check that the p_physp is valid, and that is shares a pkey with the p_req_physp. */ if (p_physp && osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) sa_pkey_check_physp(sa, p_physp, p_ctxt); } else { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4603: " "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n", port_num, osm_node_get_num_physp(p_port->p_node)); goto Exit; } } else { num_ports = osm_node_get_num_physp(p_port->p_node); for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); if (!p_physp) continue; /* if the requester and the p_physp don't share a pkey - continue */ if (!osm_physp_share_pkey (sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) continue; sa_pkey_check_physp(sa, p_physp, p_ctxt); } } Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_pkey_by_comp_mask_cb(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_port_t *p_port = (osm_port_t *) p_map_item; osm_pkey_search_ctxt_t *p_ctxt = cxt; sa_pkey_by_comp_mask(p_ctxt->sa, p_port, p_ctxt); } void osm_pkey_rec_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_pkey_table_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; cl_qlist_t rec_list; osm_pkey_search_ctxt_t context; ib_net64_t comp_mask; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_pkey_table_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); comp_mask = p_rcvd_mad->comp_mask; CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_PKEY_TBL_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4605: " "Unsupported Method (%s) for PKeyRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } /* p922 - P_KeyTableRecords shall only be provided in response to trusted requests. Check that the requester is a trusted one. */ if (p_rcvd_mad->sm_key != sa->p_subn->opt.sa_key) { /* This is not a trusted requester! */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4608: " "Ignoring PKeyRecord request from non-trusted requester" " with SM_Key 0x%016" PRIx64 "\n", cl_ntoh64(p_rcvd_mad->sm_key)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4604: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.block_num = cl_ntoh16(p_rcvd_rec->block_num); context.p_req_physp = p_req_physp; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Got Query Lid:%u(%02X), Block:0x%02X(%02X), Port:0x%02X(%02X)\n", cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_PKEY_COMPMASK_LID) != 0, p_rcvd_rec->port_num, (comp_mask & IB_PKEY_COMPMASK_PORT) != 0, context.block_num, (comp_mask & IB_PKEY_COMPMASK_BLOCK) != 0); /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & IB_PKEY_COMPMASK_LID) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 460B: " "No port found with LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); else sa_pkey_by_comp_mask(sa, p_port, &context); } else cl_qmap_apply_func(&sa->p_subn->port_guid_tbl, sa_pkey_by_comp_mask_cb, &context); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_pkey_table_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_portinfo_record.c0000644000205000001450000004537112314616647016240 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_pir_rcv_t. * This object represents the PortInfoRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_PORTINFO_RECORD_C #include #include #include #include #include #include #include #define SA_PIR_RESP_SIZE SA_ITEM_RESP_SIZE(port_rec) typedef struct osm_pir_search_ctxt { const ib_portinfo_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; boolean_t is_enhanced_comp_mask; } osm_pir_search_ctxt_t; static ib_api_status_t pir_rcv_new_pir(IN osm_sa_t * sa, IN const osm_physp_t * p_physp, IN osm_pir_search_ctxt_t * p_ctxt, IN ib_net16_t const lid) { osm_sa_item_t *p_rec_item; ib_port_info_t *p_pi; osm_physp_t *p_physp0; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_PIR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2102: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New PortInfoRecord: port 0x%016" PRIx64 ", lid %u, port %u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), cl_ntoh16(lid), osm_physp_get_port_num(p_physp)); memset(p_rec_item, 0, SA_PIR_RESP_SIZE); p_rec_item->resp.port_rec.lid = lid; p_rec_item->resp.port_rec.port_info = p_physp->port_info; if (p_ctxt->comp_mask & IB_PIR_COMPMASK_OPTIONS) p_rec_item->resp.port_rec.options = p_ctxt->p_rcvd_rec->options; if ((p_ctxt->comp_mask & IB_PIR_COMPMASK_OPTIONS) == 0 || (p_ctxt->p_rcvd_rec->options & 0x80) == 0) { /* Does requested port have an extended link speed active ? */ if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) { p_physp0 = osm_node_get_physp_ptr(p_physp->p_node, 0); p_pi = &p_physp0->port_info; } else p_pi = (ib_port_info_t *) &p_physp->port_info; if ((p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) > 0) { if (ib_port_info_get_link_speed_ext_active(&p_physp->port_info)) { /* Add QDR bits to original link speed components */ p_pi = &p_rec_item->resp.port_rec.port_info; ib_port_info_set_link_speed_enabled(p_pi, ib_port_info_get_link_speed_enabled(p_pi) | IB_LINK_SPEED_ACTIVE_10); p_pi->state_info1 = (uint8_t) ((p_pi->state_info1 & IB_PORT_STATE_MASK) | (ib_port_info_get_link_speed_sup(p_pi) | IB_LINK_SPEED_ACTIVE_10) << IB_PORT_LINK_SPEED_SHIFT); p_pi->link_speed = (uint8_t) ((p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK) | (ib_port_info_get_link_speed_active(p_pi) | IB_LINK_SPEED_ACTIVE_10) << IB_PORT_LINK_SPEED_SHIFT); } } } p_rec_item->resp.port_rec.port_num = osm_physp_get_port_num(p_physp); cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void sa_pir_create(IN osm_sa_t * sa, IN const osm_physp_t * p_physp, IN osm_pir_search_ctxt_t * p_ctxt) { uint8_t lmc; uint16_t max_lid_ho; uint16_t base_lid_ho; uint16_t match_lid_ho; osm_physp_t *p_node_physp; OSM_LOG_ENTER(sa->p_log); if (p_physp->p_node->sw) { p_node_physp = osm_node_get_physp_ptr(p_physp->p_node, 0); base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_node_physp)); lmc = osm_switch_sp0_is_lmc_capable(p_physp->p_node->sw, sa->p_subn) ? osm_physp_get_lmc(p_node_physp) : 0; } else { lmc = osm_physp_get_lmc(p_physp); base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp)); } max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1); if (p_ctxt->comp_mask & IB_PIR_COMPMASK_LID) { match_lid_ho = cl_ntoh16(p_ctxt->p_rcvd_rec->lid); /* We validate that the lid belongs to this node. */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing LID: %u <= %u <= %u\n", base_lid_ho, match_lid_ho, max_lid_ho); if (match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho) goto Exit; } pir_rcv_new_pir(sa, p_physp, p_ctxt, cl_hton16(base_lid_ho)); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_pir_check_physp(IN osm_sa_t * sa, IN const osm_physp_t * p_physp, osm_pir_search_ctxt_t * p_ctxt) { const ib_portinfo_record_t *p_rcvd_rec; ib_net64_t comp_mask; const ib_port_info_t *p_comp_pi; const ib_port_info_t *p_pi; const osm_physp_t * p_physp0; ib_net32_t cap_mask; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; p_comp_pi = &p_rcvd_rec->port_info; p_pi = &p_physp->port_info; osm_dump_port_info_v2(sa->p_log, osm_node_get_node_guid(p_physp->p_node), p_physp->port_guid, p_physp->port_num, &p_physp->port_info, FILE_ID, OSM_LOG_DEBUG); /* We have to re-check the base_lid, since if the given base_lid in p_pi is zero - we are comparing on all ports. */ if (comp_mask & IB_PIR_COMPMASK_BASELID) { if (p_comp_pi->base_lid != p_pi->base_lid) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MKEY) { if (p_comp_pi->m_key != p_pi->m_key) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_GIDPRE) { if (p_comp_pi->subnet_prefix != p_pi->subnet_prefix) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_SMLID) { if (p_comp_pi->master_sm_base_lid != p_pi->master_sm_base_lid) goto Exit; } /* IBTA 1.2 errata provides support for bitwise compare if the bit 31 of the attribute modifier of the Get/GetTable is set */ if (comp_mask & IB_PIR_COMPMASK_CAPMASK) { if (p_ctxt->is_enhanced_comp_mask) { if ((p_comp_pi->capability_mask & p_pi-> capability_mask) != p_comp_pi->capability_mask) goto Exit; } else { if (p_comp_pi->capability_mask != p_pi->capability_mask) goto Exit; } } if (comp_mask & IB_PIR_COMPMASK_DIAGCODE) { if (p_comp_pi->diag_code != p_pi->diag_code) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MKEYLEASEPRD) { if (p_comp_pi->m_key_lease_period != p_pi->m_key_lease_period) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LOCALPORTNUM) { if (p_comp_pi->local_port_num != p_pi->local_port_num) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LNKWIDTHSUPPORT) { if (p_comp_pi->link_width_supported != p_pi->link_width_supported) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LNKWIDTHACTIVE) { if (p_comp_pi->link_width_active != p_pi->link_width_active) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKWIDTHENABLED) { if (p_comp_pi->link_width_enabled != p_pi->link_width_enabled) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LNKSPEEDSUPPORT) { if (ib_port_info_get_link_speed_sup(p_comp_pi) != ib_port_info_get_link_speed_sup(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_PORTSTATE) { if (ib_port_info_get_port_state(p_comp_pi) != ib_port_info_get_port_state(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_PORTPHYSTATE) { if (ib_port_info_get_port_phys_state(p_comp_pi) != ib_port_info_get_port_phys_state(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKDWNDFLTSTATE) { if (ib_port_info_get_link_down_def_state(p_comp_pi) != ib_port_info_get_link_down_def_state(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MKEYPROTBITS) { if (ib_port_info_get_mpb(p_comp_pi) != ib_port_info_get_mpb(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LMC) { if (ib_port_info_get_lmc(p_comp_pi) != ib_port_info_get_lmc(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKSPEEDACTIVE) { if (ib_port_info_get_link_speed_active(p_comp_pi) != ib_port_info_get_link_speed_active(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKSPEEDENABLE) { if (ib_port_info_get_link_speed_enabled(p_comp_pi) != ib_port_info_get_link_speed_enabled(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_NEIGHBORMTU) { if (ib_port_info_get_neighbor_mtu(p_comp_pi) != ib_port_info_get_neighbor_mtu(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MASTERSMSL) { if (ib_port_info_get_master_smsl(p_comp_pi) != ib_port_info_get_master_smsl(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_VLCAP) { if (ib_port_info_get_vl_cap(p_comp_pi) != ib_port_info_get_vl_cap(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_INITTYPE) { if (ib_port_info_get_init_type(p_comp_pi) != ib_port_info_get_init_type(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_VLHIGHLIMIT) { if (p_comp_pi->vl_high_limit != p_pi->vl_high_limit) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_VLARBHIGHCAP) { if (p_comp_pi->vl_arb_high_cap != p_pi->vl_arb_high_cap) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_VLARBLOWCAP) { if (p_comp_pi->vl_arb_low_cap != p_pi->vl_arb_low_cap) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MTUCAP) { if (ib_port_info_get_mtu_cap(p_comp_pi) != ib_port_info_get_mtu_cap(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_VLSTALLCNT) { if (ib_port_info_get_vl_stall_count(p_comp_pi) != ib_port_info_get_vl_stall_count(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_HOQLIFE) { if ((p_comp_pi->vl_stall_life & 0x1F) != (p_pi->vl_stall_life & 0x1F)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_OPVLS) { if ((p_comp_pi->vl_enforce & 0xF0) != (p_pi->vl_enforce & 0xF0)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_PARENFIN) { if ((p_comp_pi->vl_enforce & 0x08) != (p_pi->vl_enforce & 0x08)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_PARENFOUT) { if ((p_comp_pi->vl_enforce & 0x04) != (p_pi->vl_enforce & 0x04)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_FILTERRAWIN) { if ((p_comp_pi->vl_enforce & 0x02) != (p_pi->vl_enforce & 0x02)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_FILTERRAWOUT) { if ((p_comp_pi->vl_enforce & 0x01) != (p_pi->vl_enforce & 0x01)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_MKEYVIO) { if (p_comp_pi->m_key_violations != p_pi->m_key_violations) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_PKEYVIO) { if (p_comp_pi->p_key_violations != p_pi->p_key_violations) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_QKEYVIO) { if (p_comp_pi->q_key_violations != p_pi->q_key_violations) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_GUIDCAP) { if (p_comp_pi->guid_cap != p_pi->guid_cap) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_SUBNTO) { if (ib_port_info_get_timeout(p_comp_pi) != ib_port_info_get_timeout(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_RESPTIME) { if ((p_comp_pi->resp_time_value & 0x1F) != (p_pi->resp_time_value & 0x1F)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LOCALPHYERR) { if (ib_port_info_get_local_phy_err_thd(p_comp_pi) != ib_port_info_get_local_phy_err_thd(p_pi)) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_OVERRUNERR) { if (ib_port_info_get_overrun_err_thd(p_comp_pi) != ib_port_info_get_overrun_err_thd(p_pi)) goto Exit; } /* IBTA 1.2 errata provides support for bitwise compare if the bit 31 of the attribute modifier of the Get/GetTable is set */ if (comp_mask & IB_PIR_COMPMASK_CAPMASK2) { if (p_ctxt->is_enhanced_comp_mask) { if ((cl_ntoh16(p_comp_pi->capability_mask2) & cl_ntoh16(p_pi->capability_mask2)) != cl_ntoh16(p_comp_pi->capability_mask2)) goto Exit; } else { if (cl_ntoh16(p_comp_pi->capability_mask2) != cl_ntoh16(p_pi->capability_mask2)) goto Exit; } } if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) { p_physp0 = osm_node_get_physp_ptr(p_physp->p_node, 0); cap_mask = p_physp0->port_info.capability_mask; } else cap_mask = p_pi->capability_mask; if (comp_mask & IB_PIR_COMPMASK_LINKSPDEXTACT) { if (((cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) > 0) && (ib_port_info_get_link_speed_ext_active(p_comp_pi) != ib_port_info_get_link_speed_ext_active(p_pi))) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKSPDEXTSUPP) { if (((cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) > 0) && (ib_port_info_get_link_speed_ext_sup(p_comp_pi) != ib_port_info_get_link_speed_ext_sup(p_pi))) goto Exit; } if (comp_mask & IB_PIR_COMPMASK_LINKSPDEXTENAB) { if (((cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) > 0) && (ib_port_info_get_link_speed_ext_enabled(p_comp_pi) != ib_port_info_get_link_speed_ext_enabled(p_pi))) goto Exit; } sa_pir_create(sa, p_physp, p_ctxt); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_pir_by_comp_mask(IN osm_sa_t * sa, IN osm_node_t * p_node, osm_pir_search_ctxt_t * p_ctxt) { const ib_portinfo_record_t *p_rcvd_rec; ib_net64_t comp_mask; const osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; p_req_physp = p_ctxt->p_req_physp; num_ports = osm_node_get_num_physp(p_node); if (comp_mask & IB_PIR_COMPMASK_PORTNUM) { if (p_rcvd_rec->port_num < num_ports) { p_physp = osm_node_get_physp_ptr(p_node, p_rcvd_rec->port_num); /* Check that the p_physp is valid, and that the p_physp and the p_req_physp share a pkey. */ if (p_physp && osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) sa_pir_check_physp(sa, p_physp, p_ctxt); } } else { for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; /* if the requester and the p_physp don't share a pkey - continue */ if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) continue; sa_pir_check_physp(sa, p_physp, p_ctxt); } } OSM_LOG_EXIT(sa->p_log); } static void sa_pir_by_comp_mask_cb(IN cl_map_item_t * p_map_item, IN void *cxt) { osm_node_t *p_node = (osm_node_t *) p_map_item; osm_pir_search_ctxt_t *p_ctxt = cxt; sa_pir_by_comp_mask(p_ctxt->sa, p_node, p_ctxt); } void osm_pir_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_portinfo_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; cl_qlist_t rec_list; osm_pir_search_ctxt_t context; ib_net64_t comp_mask; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_portinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); comp_mask = p_rcvd_mad->comp_mask; CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_PORTINFO_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2105: " "Unsupported Method (%s) for PortInfoRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2104: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_portinfo_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; context.is_enhanced_comp_mask = cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31); /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & (IB_PIR_COMPMASK_LID | IB_PIR_COMPMASK_BASELID)) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (p_port) sa_pir_by_comp_mask(sa, p_port->p_node, &context); else OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2109: " "No port found with requested LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); } else cl_qmap_apply_func(&sa->p_subn->node_guid_tbl, sa_pir_by_comp_mask_cb, &context); cl_plock_release(sa->p_lock); /* p922 - The M_Key returned shall be zero, except in the case of a trusted request. Note: In the mad controller we check that the SM_Key received on the mad is valid. Meaning - is either zero or equal to the local sm_key. */ if (!p_rcvd_mad->sm_key) { osm_sa_item_t *item; for (item = (osm_sa_item_t *) cl_qlist_head(&rec_list); item != (osm_sa_item_t *) cl_qlist_end(&rec_list); item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) item->resp.port_rec.port_info.m_key = 0; } osm_sa_respond(sa, p_madw, sizeof(ib_portinfo_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_guidinfo_record.c0000644000205000001450000006261312615731344016176 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_gir_rcv_t. * This object represents the GUIDInfoRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_GUIDINFO_RECORD_C #include #include #include #include #include #include #include #define SA_GIR_RESP_SIZE SA_ITEM_RESP_SIZE(guid_rec) #define MOD_GIR_COMP_MASK (IB_GIR_COMPMASK_LID | IB_GIR_COMPMASK_BLOCKNUM) typedef struct osm_gir_item { cl_list_item_t list_item; ib_guidinfo_record_t rec; } osm_gir_item_t; typedef struct osm_gir_search_ctxt { const ib_guidinfo_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_gir_search_ctxt_t; static ib_api_status_t gir_rcv_new_gir(IN osm_sa_t * sa, IN const osm_node_t * p_node, IN cl_qlist_t * p_list, IN ib_net64_t const match_port_guid, IN ib_net16_t const match_lid, IN const osm_physp_t * p_physp, IN uint8_t const block_num) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_GIR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5102: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New GUIDInfoRecord: lid %u, block num %d\n", cl_ntoh16(match_lid), block_num); memset(p_rec_item, 0, SA_GIR_RESP_SIZE); p_rec_item->resp.guid_rec.lid = match_lid; p_rec_item->resp.guid_rec.block_num = block_num; if (p_physp->p_guids) memcpy(&p_rec_item->resp.guid_rec.guid_info, *p_physp->p_guids + block_num * GUID_TABLE_MAX_ENTRIES, sizeof(ib_guid_info_t)); else if (!block_num) p_rec_item->resp.guid_rec.guid_info.guid[0] = osm_physp_get_port_guid(p_physp); cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void sa_gir_create_gir(IN osm_sa_t * sa, IN osm_node_t * p_node, IN cl_qlist_t * p_list, IN ib_net64_t const match_port_guid, IN ib_net16_t const match_lid, IN const osm_physp_t * p_req_physp, IN uint8_t const match_block_num) { const osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; uint16_t match_lid_ho; ib_net16_t base_lid_ho; ib_net16_t max_lid_ho; uint8_t lmc; ib_net64_t port_guid; uint8_t block_num, start_block_num, end_block_num, num_blocks; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Looking for GUIDRecord with LID: %u GUID:0x%016" PRIx64 "\n", cl_ntoh16(match_lid), cl_ntoh64(match_port_guid)); /* For switches, do not return the GUIDInfo record(s) for each port on the switch, just for port 0. */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) num_ports = 1; else num_ports = osm_node_get_num_physp(p_node); for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; /* Check to see if the found p_physp and the requester physp share a pkey. If not, continue */ if (!osm_physp_share_pkey(sa->p_log, p_physp, p_req_physp, sa->p_subn->opt.allow_both_pkeys)) continue; port_guid = osm_physp_get_port_guid(p_physp); if (match_port_guid && (port_guid != match_port_guid)) continue; /* Note: the following check is a temporary workaround Since 1. GUIDCap should never be 0 on ports where this applies and 2. GUIDCap should not be used on ports where it doesn't apply So this should really be a check for whether the port is a switch external port or not! */ if (p_physp->port_info.guid_cap == 0) continue; num_blocks = p_physp->port_info.guid_cap / 8; if (p_physp->port_info.guid_cap % 8) num_blocks++; if (match_block_num == 255) { start_block_num = 0; end_block_num = num_blocks - 1; } else { if (match_block_num >= num_blocks) continue; end_block_num = start_block_num = match_block_num; } base_lid_ho = cl_ntoh16(osm_physp_get_base_lid(p_physp)); match_lid_ho = cl_ntoh16(match_lid); if (match_lid_ho) { lmc = osm_physp_get_lmc(p_physp); max_lid_ho = (uint16_t) (base_lid_ho + (1 << lmc) - 1); /* We validate that the lid belongs to this node. */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing LID: %u <= %u <= %u\n", base_lid_ho, match_lid_ho, max_lid_ho); if (match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho) continue; } for (block_num = start_block_num; block_num <= end_block_num; block_num++) gir_rcv_new_gir(sa, p_node, p_list, port_guid, cl_ntoh16(base_lid_ho), p_physp, block_num); } OSM_LOG_EXIT(sa->p_log); } static void sa_gir_by_comp_mask_cb(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_gir_search_ctxt_t *p_ctxt = cxt; osm_node_t *const p_node = (osm_node_t *) p_map_item; const ib_guidinfo_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; osm_sa_t *sa = p_ctxt->sa; const ib_guid_info_t *p_comp_gi; ib_net64_t const comp_mask = p_ctxt->comp_mask; ib_net64_t match_port_guid = 0; ib_net16_t match_lid = 0; uint8_t match_block_num = 255; OSM_LOG_ENTER(p_ctxt->sa->p_log); if (comp_mask & IB_GIR_COMPMASK_LID) match_lid = p_rcvd_rec->lid; if (comp_mask & IB_GIR_COMPMASK_BLOCKNUM) match_block_num = p_rcvd_rec->block_num; p_comp_gi = &p_rcvd_rec->guid_info; /* Different rule for block 0 v. other blocks */ if (comp_mask & IB_GIR_COMPMASK_GID0) { if (!p_rcvd_rec->block_num) match_port_guid = osm_physp_get_port_guid(p_req_physp); if (p_comp_gi->guid[0] != match_port_guid) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID1) { if (p_comp_gi->guid[1] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID2) { if (p_comp_gi->guid[2] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID3) { if (p_comp_gi->guid[3] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID4) { if (p_comp_gi->guid[4] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID5) { if (p_comp_gi->guid[5] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID6) { if (p_comp_gi->guid[6] != 0) goto Exit; } if (comp_mask & IB_GIR_COMPMASK_GID7) { if (p_comp_gi->guid[7] != 0) goto Exit; } sa_gir_create_gir(sa, p_node, p_ctxt->p_list, match_port_guid, match_lid, p_req_physp, match_block_num); Exit: OSM_LOG_EXIT(p_ctxt->sa->p_log); } static inline boolean_t check_mod_comp_mask(ib_net64_t comp_mask) { return ((comp_mask & MOD_GIR_COMP_MASK) == MOD_GIR_COMP_MASK); } static uint8_t coalesce_comp_mask(IN osm_madw_t *p_madw) { uint8_t comp_mask = 0; ib_sa_mad_t *p_sa_mad; p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID0) comp_mask |= 1<<0; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID1) comp_mask |= 1<<1; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID2) comp_mask |= 1<<2; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID3) comp_mask |= 1<<3; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID4) comp_mask |= 1<<4; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID5) comp_mask |= 1<<5; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID6) comp_mask |= 1<<6; if (p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID7) comp_mask |= 1<<7; return comp_mask; } static void guidinfo_respond(IN osm_sa_t *sa, IN osm_madw_t *p_madw, IN ib_guidinfo_record_t * p_guidinfo_rec) { cl_qlist_t rec_list; osm_sa_item_t *item; OSM_LOG_ENTER(sa->p_log); item = malloc(SA_GIR_RESP_SIZE); if (!item) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5101: " "rec_item alloc failed\n"); goto Exit; } item->resp.guid_rec = *p_guidinfo_rec; cl_qlist_init(&rec_list); cl_qlist_insert_tail(&rec_list, &item->list_item); osm_sa_respond(sa, p_madw, sizeof(ib_guidinfo_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } static void gir_respond(IN osm_sa_t *sa, IN osm_madw_t *p_madw) { ib_sa_mad_t *p_sa_mad; ib_guidinfo_record_t *p_rcvd_rec; ib_guidinfo_record_t guidinfo_rec; p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_guidinfo_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); guidinfo_rec = *p_rcvd_rec; guidinfo_respond(sa, p_madw, &guidinfo_rec); } static ib_net64_t sm_assigned_guid(uint8_t assigned_byte) { static uint32_t uniq_count; if (++uniq_count == 0) { uniq_count--; return 0; } return cl_hton64(((uint64_t) uniq_count) | (((uint64_t) assigned_byte) << 32) | (((uint64_t) OSM_VENDOR_ID_OPENIB) << 40)); } static void del_guidinfo(IN osm_sa_t *sa, IN osm_madw_t *p_madw, IN osm_port_t *p_port, IN uint8_t block_num) { int i; uint32_t max_block; ib_sa_mad_t *p_sa_mad; ib_guidinfo_record_t *p_rcvd_rec; ib_net64_t del_alias_guid; osm_alias_guid_t *p_alias_guid; cl_list_item_t *p_list_item; osm_mcm_port_t *p_mcm_port; osm_mcm_alias_guid_t *p_mcm_alias_guid; uint8_t del_mask; int dirty = 0; if (!p_port->p_physp->p_guids) goto Exit; max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) / GUID_TABLE_MAX_ENTRIES; if (block_num >= max_block) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5116: " "block_num %d is higher than Max GUID Cap block %d " "for port GUID 0x%" PRIx64 "\n", block_num, max_block, cl_ntoh64(p_port->p_physp->port_guid)); CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); return; } p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); del_mask = coalesce_comp_mask(p_madw); for (i = block_num * GUID_TABLE_MAX_ENTRIES; (block_num + 1) * GUID_TABLE_MAX_ENTRIES < p_port->p_physp->port_info.guid_cap ? i < (block_num + 1) * GUID_TABLE_MAX_ENTRIES : i < p_port->p_physp->port_info.guid_cap; i++) { /* can't delete block 0 index 0 (base guid is RO) for alias guid table */ if (i == 0 && p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID0) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Not allowed to delete RO GID 0\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); return; } if (!(del_mask & 1<<(i % 8))) continue; del_alias_guid = (*p_port->p_physp->p_guids)[i]; if (del_alias_guid) { /* Search all of port's multicast groups for alias */ p_list_item = cl_qlist_head(&p_port->mcm_list); while (p_list_item != cl_qlist_end(&p_port->mcm_list)) { p_mcm_port = cl_item_obj(p_list_item, p_mcm_port, list_item); p_list_item = cl_qlist_next(p_list_item); p_mcm_alias_guid = osm_mgrp_get_mcm_alias_guid(p_mcm_port->mgrp, del_alias_guid); if (p_mcm_alias_guid) { CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_DENIED); return; } } } } for (i = block_num * GUID_TABLE_MAX_ENTRIES; (block_num + 1) * GUID_TABLE_MAX_ENTRIES < p_port->p_physp->port_info.guid_cap ? i < (block_num + 1) * GUID_TABLE_MAX_ENTRIES : i < p_port->p_physp->port_info.guid_cap; i++) { if (!(del_mask & 1<<(i % 8))) continue; del_alias_guid = (*p_port->p_physp->p_guids)[i]; if (del_alias_guid) { /* remove original from alias guid table */ p_alias_guid = (osm_alias_guid_t *) cl_qmap_remove(&sa->p_subn->alias_port_guid_tbl, del_alias_guid); if (p_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&sa->p_subn->alias_port_guid_tbl)) osm_alias_guid_delete(&p_alias_guid); else OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510B: " "Original alias GUID 0x%" PRIx64 " at index %u not found\n", cl_ntoh64(del_alias_guid), i); /* clear guid at index */ (*p_port->p_physp->p_guids)[i] = 0; dirty = 1; } } if (dirty) { if (osm_queue_guidinfo(sa, p_port, block_num)) osm_sm_signal(sa->sm, OSM_SIGNAL_GUID_PROCESS_REQUEST); sa->dirty = TRUE; } memcpy(&p_rcvd_rec->guid_info, &((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES]), sizeof(ib_guid_info_t)); Exit: CL_PLOCK_RELEASE(sa->p_lock); gir_respond(sa, p_madw); } static void set_guidinfo(IN osm_sa_t *sa, IN osm_madw_t *p_madw, IN osm_port_t *p_port, IN uint8_t block_num) { uint32_t max_block; int i, j, dirty = 0; ib_sa_mad_t *p_sa_mad; ib_guidinfo_record_t *p_rcvd_rec; osm_assigned_guids_t *p_assigned_guids = 0; osm_alias_guid_t *p_alias_guid, *p_alias_guid_check; cl_map_item_t *p_item; ib_net64_t set_alias_guid, del_alias_guid, assigned_guid; uint8_t set_mask; max_block = (p_port->p_physp->port_info.guid_cap + GUID_TABLE_MAX_ENTRIES - 1) / GUID_TABLE_MAX_ENTRIES; if (block_num >= max_block) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5118: " "block_num %d is higher than Max GUID Cap block %d " "for port GUID 0x%" PRIx64 "\n", block_num, max_block, cl_ntoh64(p_port->p_physp->port_guid)); CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); return; } if (!p_port->p_physp->p_guids) { p_port->p_physp->p_guids = calloc(max_block * GUID_TABLE_MAX_ENTRIES, sizeof(ib_net64_t)); if (!p_port->p_physp->p_guids) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5103: " "GUID table memory allocation failed for port " "GUID 0x%" PRIx64 "\n", cl_ntoh64(p_port->p_physp->port_guid)); CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); return; } /* setup base port guid in index 0 */ (*p_port->p_physp->p_guids)[0] = p_port->p_physp->port_guid; } p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Dump of incoming record\n"); osm_dump_guidinfo_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } set_mask = coalesce_comp_mask(p_madw); for (i = block_num * GUID_TABLE_MAX_ENTRIES; (block_num + 1) * GUID_TABLE_MAX_ENTRIES < p_port->p_physp->port_info.guid_cap ? i < (block_num + 1) * GUID_TABLE_MAX_ENTRIES : i < p_port->p_physp->port_info.guid_cap; i++) { /* can't set block 0 index 0 (base guid is RO) for alias guid table */ if (i == 0 && p_sa_mad->comp_mask & IB_GIR_COMPMASK_GID0) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Not allowed to set RO GID 0\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); return; } if (!(set_mask & 1<<(i % 8))) continue; set_alias_guid = p_rcvd_rec->guid_info.guid[i % 8]; if (!set_alias_guid) { /* was a GUID previously assigned for this index ? */ set_alias_guid = (*p_port->p_physp->p_guids)[i]; if (set_alias_guid) { p_rcvd_rec->guid_info.guid[i % 8] = set_alias_guid; continue; } /* Is there a persistent SA assigned guid for this index ? */ if (!p_assigned_guids) p_assigned_guids = osm_get_assigned_guids_by_guid(sa->p_subn, p_port->p_physp->port_guid); if (p_assigned_guids) { set_alias_guid = p_assigned_guids->assigned_guid[i]; if (set_alias_guid) { p_rcvd_rec->guid_info.guid[i % 8] = set_alias_guid; p_item = cl_qmap_get(&sa->sm->p_subn->alias_port_guid_tbl, set_alias_guid); if (p_item == cl_qmap_end(&sa->sm->p_subn->alias_port_guid_tbl)) goto add_alias_guid; else { p_alias_guid = (osm_alias_guid_t *) p_item; if (p_alias_guid->p_base_port != p_port) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5110: " " Assigned alias port GUID 0x%" PRIx64 " index %d base port GUID 0x%" PRIx64 " now attempted on port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_alias_guid->alias_guid), i, cl_ntoh64(p_alias_guid->p_base_port->guid), cl_ntoh64(p_port->guid)); /* clear response guid at index to indicate duplicate */ p_rcvd_rec->guid_info.guid[i % 8] = 0; } continue; } } } } if (!set_alias_guid) { for (j = 0; j < 1000; j++) { assigned_guid = sm_assigned_guid(sa->p_subn->opt.sm_assigned_guid); if (!assigned_guid) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510E: No more assigned guids available\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); return; } p_item = cl_qmap_get(&sa->sm->p_subn->alias_port_guid_tbl, assigned_guid); if (p_item == cl_qmap_end(&sa->sm->p_subn->alias_port_guid_tbl)) { set_alias_guid = assigned_guid; p_rcvd_rec->guid_info.guid[i % 8] = assigned_guid; if (!p_assigned_guids) { p_assigned_guids = osm_assigned_guids_new(p_port->p_physp->port_guid, max_block * GUID_TABLE_MAX_ENTRIES); if (p_assigned_guids) { cl_qmap_insert(&(sa->p_subn->assigned_guids_tbl), p_assigned_guids->port_guid, &p_assigned_guids->map_item); } else { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510D: osm_assigned_guids_new failed port GUID 0x%" PRIx64 " index %d\n", cl_ntoh64(p_port->p_physp->port_guid), i); CL_PLOCK_RELEASE(sa->p_lock); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); return; } } if (p_assigned_guids) p_assigned_guids->assigned_guid[i] = assigned_guid; break; } } if (!set_alias_guid) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510A: " "SA assigned GUID %d failed for " "port GUID 0x%" PRIx64 "\n", i, cl_ntoh64(p_port->p_physp->port_guid)); continue; } } add_alias_guid: /* allocate alias guid and add to alias guid table */ p_alias_guid = osm_alias_guid_new(set_alias_guid, p_port); if (!p_alias_guid) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5107: " "Alias guid %d memory allocation failed" " for port GUID 0x%" PRIx64 "\n", i, cl_ntoh64(p_port->p_physp->port_guid)); CL_PLOCK_RELEASE(sa->p_lock); return; } p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_insert(&sa->sm->p_subn->alias_port_guid_tbl, p_alias_guid->alias_guid, &p_alias_guid->map_item); if (p_alias_guid_check != p_alias_guid) { /* alias GUID is a duplicate if it exists on another port or on the same port but at another index */ if (p_alias_guid_check->p_base_port != p_port || (*p_port->p_physp->p_guids)[i] != set_alias_guid) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5108: " "Duplicate alias port GUID 0x%" PRIx64 " index %d base port GUID 0x%" PRIx64 ", alias GUID already assigned to " "base port GUID 0x%" PRIx64 "\n", cl_ntoh64(p_alias_guid->alias_guid), i, cl_ntoh64(p_alias_guid->p_base_port->guid), cl_ntoh64(p_alias_guid_check->p_base_port->guid)); /* clear response guid at index to indicate duplicate */ p_rcvd_rec->guid_info.guid[i % 8] = 0; } osm_alias_guid_delete(&p_alias_guid); } else { del_alias_guid = (*p_port->p_physp->p_guids)[i]; if (del_alias_guid) { /* remove original from alias guid table */ p_alias_guid_check = (osm_alias_guid_t *) cl_qmap_remove(&sa->p_subn->alias_port_guid_tbl, del_alias_guid); if (p_alias_guid_check) osm_alias_guid_delete(&p_alias_guid_check); else OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 510C: Original alias GUID " "0x%" PRIx64 "at index %u " "not found\n", cl_ntoh64(del_alias_guid), i); } /* insert or replace guid at index */ (*p_port->p_physp->p_guids)[i] = set_alias_guid; dirty = 1; } } if (dirty) { if (osm_queue_guidinfo(sa, p_port, block_num)) osm_sm_signal(sa->sm, OSM_SIGNAL_GUID_PROCESS_REQUEST); sa->dirty = TRUE; } memcpy(&p_rcvd_rec->guid_info, &((*p_port->p_physp->p_guids)[block_num * GUID_TABLE_MAX_ENTRIES]), sizeof(ib_guid_info_t)); CL_PLOCK_RELEASE(sa->p_lock); gir_respond(sa, p_madw); } static void get_guidinfo(IN osm_sa_t *sa, IN osm_madw_t *p_madw, IN osm_physp_t *p_req_physp) { const ib_sa_mad_t *p_rcvd_mad; const ib_guidinfo_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_gir_search_ctxt_t context; p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; cl_qmap_apply_func(&sa->p_subn->node_guid_tbl, sa_gir_by_comp_mask_cb, &context); CL_PLOCK_RELEASE(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_guidinfo_record_t), &rec_list); } void osm_gir_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; osm_physp_t *p_req_physp; osm_port_t *p_port; const ib_guidinfo_record_t *p_rcvd_rec; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_GUIDINFO_RECORD); switch(p_rcvd_mad->method) { case IB_MAD_METHOD_GET: case IB_MAD_METHOD_GETTABLE: /* update the requester physical port */ CL_PLOCK_ACQUIRE(sa->p_lock); p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr(p_madw)); if (p_req_physp == NULL) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5104: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); get_guidinfo(sa, p_madw, p_req_physp); goto Exit; case IB_MAD_METHOD_SET: case IB_MAD_METHOD_DELETE: if (!check_mod_comp_mask(p_rcvd_mad->comp_mask)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5106: " "component mask = 0x%016" PRIx64 ", " "expected comp mask = 0x%016" PRIx64 "\n", cl_ntoh64(p_rcvd_mad->comp_mask), CL_NTOH64(MOD_GIR_COMP_MASK)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } p_rcvd_rec = (ib_guidinfo_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); /* update the requester physical port */ CL_PLOCK_EXCL_ACQUIRE(sa->p_lock); p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr(p_madw)); if (p_req_physp == NULL) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5104: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) { CL_PLOCK_RELEASE(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5117: " "Port with LID %u not found\n", cl_ntoh16(p_rcvd_rec->lid)); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_port->p_physp, sa->p_subn->opt.allow_both_pkeys)) { CL_PLOCK_RELEASE(sa->p_lock); goto Exit; } if (p_rcvd_mad->method == IB_MAD_METHOD_SET) set_guidinfo(sa, p_madw, p_port, p_rcvd_rec->block_num); else del_guidinfo(sa, p_madw, p_port, p_rcvd_rec->block_num); break; default: OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5105: " "Unsupported Method (%s) for GUIDInfoRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); break; } Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_multipath_record.c0000644000205000001450000014335412367522715016407 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_mpr_rcv_t. * This object represents the MultiPath Record Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_MULTIPATH_RECORD_C #include #include #include #include #include #include #include #include #define OSM_SA_MPR_MAX_NUM_PATH 127 #define MAX_HOPS 64 #define SA_MPR_RESP_SIZE SA_ITEM_RESP_SIZE(mpr_rec) static boolean_t sa_multipath_rec_is_tavor_port(IN const osm_port_t * p_port) { osm_node_t const *p_node; ib_net32_t vend_id; p_node = p_port->p_node; vend_id = ib_node_info_get_vendor_id(&p_node->node_info); return ((p_node->node_info.device_id == CL_HTON16(23108)) && ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE)))); } static boolean_t sa_multipath_rec_apply_tavor_mtu_limit(IN const ib_multipath_rec_t * p_mpr, IN const osm_port_t * p_src_port, IN const osm_port_t * p_dest_port, IN const ib_net64_t comp_mask) { uint8_t required_mtu; /* only if at least one of the ports is a Tavor device */ if (!sa_multipath_rec_is_tavor_port(p_src_port) && !sa_multipath_rec_is_tavor_port(p_dest_port)) return FALSE; /* we can apply the patch if either: 1. No MTU required 2. Required MTU < 3. Required MTU = 1K or 512 or 256 4. Required MTU > 256 or 512 */ required_mtu = ib_multipath_rec_mtu(p_mpr); if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) && (comp_mask & IB_MPR_COMPMASK_MTU)) { switch (ib_multipath_rec_mtu_sel(p_mpr)) { case 0: /* must be greater than */ case 2: /* exact match */ if (IB_MTU_LEN_1024 < required_mtu) return FALSE; break; case 1: /* must be less than */ /* can't be disqualified by this one */ break; case 3: /* largest available */ /* the ULP intentionally requested */ /* the largest MTU possible */ return FALSE; break; default: /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ CL_ASSERT(FALSE); break; } } return TRUE; } static ib_api_status_t mpr_rcv_get_path_parms(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const uint16_t src_lid_ho, IN const uint16_t dest_lid_ho, IN const ib_net64_t comp_mask, OUT osm_path_parms_t * p_parms) { const osm_node_t *p_node; const osm_physp_t *p_physp, *p_physp0; const osm_physp_t *p_src_physp; const osm_physp_t *p_dest_physp; const osm_prtn_t *p_prtn = NULL; const ib_port_info_t *p_pi, *p_pi0; ib_slvl_table_t *p_slvl_tbl; ib_api_status_t status = IB_SUCCESS; uint8_t mtu; uint8_t rate, p0_extended_rate, dest_rate; uint8_t pkt_life; uint8_t required_mtu; uint8_t required_rate; ib_net16_t required_pkey; uint8_t required_sl; uint8_t required_pkt_life; ib_net16_t dest_lid; int hops = 0; int in_port_num = 0; uint8_t i; osm_qos_level_t *p_qos_level = NULL; uint16_t valid_sl_mask = 0xffff; int extended, p0_extended; OSM_LOG_ENTER(sa->p_log); dest_lid = cl_hton16(dest_lid_ho); p_dest_physp = p_dest_alias_guid->p_base_port->p_physp; p_physp = p_src_alias_guid->p_base_port->p_physp; p_src_physp = p_physp; p_pi = &p_physp->port_info; mtu = ib_port_info_get_mtu_cap(p_pi); extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; rate = ib_port_info_compute_rate(p_pi, extended); /* Mellanox Tavor device performance is better using 1K MTU. If required MTU and MTU selector are such that 1K is OK and at least one end of the path is Tavor we override the port MTU with 1K. */ if (sa->p_subn->opt.enable_quirks && sa_multipath_rec_apply_tavor_mtu_limit(p_mpr, p_src_alias_guid->p_base_port, p_dest_alias_guid->p_base_port, comp_mask)) if (mtu > IB_MTU_LEN_1024) { mtu = IB_MTU_LEN_1024; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Optimized Path MTU to 1K for Mellanox Tavor device\n"); } /* Walk the subnet object from source to destination, tracking the most restrictive rate and mtu values along the way... If source port node is a switch, then p_physp should point to the port that routes the destination lid */ p_node = osm_physp_get_node_ptr(p_physp); if (p_node->sw) { /* * Source node is a switch. * Make sure that p_physp points to the out port of the * switch that routes to the destination lid (dest_lid_ho) */ p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4514: " "Can't find routing from LID %u to LID %u on " "switch %s (GUID 0x%016" PRIx64 ")\n", src_lid_ho, dest_lid_ho, p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node))); status = IB_NOT_FOUND; goto Exit; } } if (sa->p_subn->opt.qos) { /* * Whether this node is switch or CA, the IN port for * the sl2vl table is 0, because this is a source node. */ p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0); /* update valid SLs that still exist on this route */ for (i = 0; i < IB_MAX_NUM_VLS; i++) { if (valid_sl_mask & (1 << i) && ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL) valid_sl_mask &= ~(1 << i); } if (!valid_sl_mask) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "All the SLs lead to VL15 on this path\n"); status = IB_NOT_FOUND; goto Exit; } } /* * Same as above */ p_node = osm_physp_get_node_ptr(p_dest_physp); if (p_node->sw) { /* * if destination is switch, we want p_dest_physp to point to port 0 */ p_dest_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_dest_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4515: " "Can't find routing from LID %u to LID %u on " "switch %s (GUID 0x%016" PRIx64 ")\n", src_lid_ho, dest_lid_ho, p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node))); status = IB_NOT_FOUND; goto Exit; } } /* * Now go through the path step by step */ while (p_physp != p_dest_physp) { int tmp_pnum = p_physp->port_num; p_node = osm_physp_get_node_ptr(p_physp); p_physp = osm_physp_get_remote(p_physp); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4505: " "Can't find remote phys port of %s (GUID " "0x%016" PRIx64 ") port %d " "while routing from LID %u to LID %u", p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node)), tmp_pnum, src_lid_ho, dest_lid_ho); status = IB_ERROR; goto Exit; } /* update number of hops traversed */ hops++; if (hops > MAX_HOPS) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4520: " "Path from GUID 0x%016" PRIx64 " (%s) to" " lid %u GUID 0x%016" PRIx64 " (%s) needs" " more than %d hops, max %d hops allowed\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, dest_lid_ho, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, hops, MAX_HOPS); status = IB_NOT_FOUND; goto Exit; } in_port_num = osm_physp_get_port_num(p_physp); /* This is point to point case (no switch in between) */ if (p_physp == p_dest_physp) break; p_node = osm_physp_get_node_ptr(p_physp); if (!p_node->sw) { /* There is some sort of problem in the subnet object! If this isn't a switch, we should have reached the destination by now! */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4503: " "Internal error, bad path while routing " "from %s (GUID: 0x%016"PRIx64") port %d " "to %s (GUID: 0x%016"PRIx64") port %d; " "ended at %s port %d\n", p_src_alias_guid->p_base_port->p_node->print_desc, cl_ntoh64(p_src_alias_guid->p_base_port->p_node->node_info.node_guid), p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, cl_ntoh64(p_dest_alias_guid->p_base_port->p_node->node_info.node_guid), p_dest_alias_guid->p_base_port->p_physp->port_num, p_node->print_desc, p_physp->port_num); status = IB_ERROR; goto Exit; } /* Check parameters for the ingress port in this switch. */ p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0); p_pi0 = &p_physp0->port_info; p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended); if (ib_path_compare_rates(rate, p0_extended_rate) > 0) rate = p0_extended_rate; /* Continue with the egress port on this switch. */ p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid); if (p_physp == 0) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4516: " "Dead end path on switch " "%s (GUID: 0x%016"PRIx64") to LID %u\n", p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(p_node)), dest_lid_ho); status = IB_ERROR; goto Exit; } p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0); p_pi0 = &p_physp0->port_info; p0_extended = p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; p0_extended_rate = ib_port_info_compute_rate(p_pi, p0_extended); if (ib_path_compare_rates(rate, p0_extended_rate) > 0) rate = p0_extended_rate; if (sa->p_subn->opt.qos) { /* * Check SL2VL table of the switch and update valid SLs */ p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, in_port_num); for (i = 0; i < IB_MAX_NUM_VLS; i++) { if (valid_sl_mask & (1 << i) && ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL) valid_sl_mask &= ~(1 << i); } if (!valid_sl_mask) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "All the SLs lead to VL15 " "on this path\n"); status = IB_NOT_FOUND; goto Exit; } } } /* p_physp now points to the destination */ p_pi = &p_physp->port_info; if (mtu > ib_port_info_get_mtu_cap(p_pi)) mtu = ib_port_info_get_mtu_cap(p_pi); extended = p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS; dest_rate = ib_port_info_compute_rate(p_pi, extended); if (ib_path_compare_rates(rate, dest_rate) > 0) rate = dest_rate; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Path min MTU = %u, min rate = %u\n", mtu, rate); /* * Get QoS Level object according to the MultiPath request * and adjust MultiPath parameters according to QoS settings */ if (sa->p_subn->opt.qos && sa->p_subn->p_qos_policy && (p_qos_level = osm_qos_policy_get_qos_level_by_mpr(sa->p_subn->p_qos_policy, p_mpr, p_src_physp, p_dest_physp, comp_mask))) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MultiPathRecord request matches QoS Level '%s' (%s)\n", p_qos_level->name, p_qos_level->use ? p_qos_level->use : "no description"); if (p_qos_level->mtu_limit_set && (mtu > p_qos_level->mtu_limit)) mtu = p_qos_level->mtu_limit; if (p_qos_level->rate_limit_set && (ib_path_compare_rates(rate, p_qos_level->rate_limit) > 0)) rate = p_qos_level->rate_limit; if (p_qos_level->sl_set) { required_sl = p_qos_level->sl; if (!(valid_sl_mask & (1 << required_sl))) { status = IB_NOT_FOUND; goto Exit; } } } /* Determine if these values meet the user criteria */ /* we silently ignore cases where only the MTU selector is defined */ if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) && (comp_mask & IB_MPR_COMPMASK_MTU)) { required_mtu = ib_multipath_rec_mtu(p_mpr); switch (ib_multipath_rec_mtu_sel(p_mpr)) { case 0: /* must be greater than */ if (mtu <= required_mtu) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (mtu >= required_mtu) { /* adjust to use the highest mtu lower then the required one */ if (required_mtu > 1) mtu = required_mtu - 1; else status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (mtu < required_mtu) status = IB_NOT_FOUND; else mtu = required_mtu; break; case 3: /* largest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* we silently ignore cases where only the Rate selector is defined */ if ((comp_mask & IB_MPR_COMPMASK_RATESELEC) && (comp_mask & IB_MPR_COMPMASK_RATE)) { required_rate = ib_multipath_rec_rate(p_mpr); switch (ib_multipath_rec_rate_sel(p_mpr)) { case 0: /* must be greater than */ if (ib_path_compare_rates(rate, required_rate) <= 0) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (ib_path_compare_rates(rate, required_rate) >= 0) { /* adjust the rate to use the highest rate lower then the required one */ rate = ib_path_rate_get_prev(required_rate); if (!rate) status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (ib_path_compare_rates(rate, required_rate)) status = IB_NOT_FOUND; else rate = required_rate; break; case 3: /* largest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* Verify the pkt_life_time */ /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description, for loopback paths, packetLifeTime shall be zero. */ if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port) pkt_life = 0; /* loopback */ else if (p_qos_level && p_qos_level->pkt_life_set) pkt_life = p_qos_level->pkt_life; else pkt_life = sa->p_subn->opt.subnet_timeout; /* we silently ignore cases where only the PktLife selector is defined */ if ((comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC) && (comp_mask & IB_MPR_COMPMASK_PKTLIFETIME)) { required_pkt_life = ib_multipath_rec_pkt_life(p_mpr); switch (ib_multipath_rec_pkt_life_sel(p_mpr)) { case 0: /* must be greater than */ if (pkt_life <= required_pkt_life) status = IB_NOT_FOUND; break; case 1: /* must be less than */ if (pkt_life >= required_pkt_life) { /* adjust the lifetime to use the highest possible lower then the required one */ if (required_pkt_life > 1) pkt_life = required_pkt_life - 1; else status = IB_NOT_FOUND; } break; case 2: /* exact match */ if (pkt_life < required_pkt_life) status = IB_NOT_FOUND; else pkt_life = required_pkt_life; break; case 3: /* smallest available */ /* can't be disqualified by this one */ break; default: /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */ CL_ASSERT(FALSE); status = IB_ERROR; break; } } if (status != IB_SUCCESS) goto Exit; /* * set Pkey for this MultiPath record request */ if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC && cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31)) required_pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); else if (comp_mask & IB_MPR_COMPMASK_PKEY) { /* * MPR request has a specific pkey: * Check that source and destination share this pkey. * If QoS level has pkeys, check that this pkey exists * in the QoS level pkeys. * MPR returned pkey is the requested pkey. */ required_pkey = p_mpr->pkey; if (!osm_physp_share_this_pkey (p_src_physp, p_dest_physp, required_pkey, sa->p_subn->opt.allow_both_pkeys)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4518: " "Ports src 0x%016"PRIx64" (%s port %d) " "and dst 0x%016"PRIx64" (%s port %d) " "do not share the specified PKey 0x%04x\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num, cl_ntoh16(required_pkey)); status = IB_NOT_FOUND; goto Exit; } if (p_qos_level && p_qos_level->pkey_range_len && !osm_qos_level_has_pkey(p_qos_level, required_pkey)) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451C: " "Ports src 0x%016"PRIx64" (%s port %d) " "and dst 0x%016"PRIx64" (%s port %d) " "do not share specified PKey (0x%04x) as " "defined by QoS level \"%s\"\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num, cl_ntoh16(required_pkey), p_qos_level->name); status = IB_NOT_FOUND; goto Exit; } } else if (p_qos_level && p_qos_level->pkey_range_len) { /* * MPR request doesn't have a specific pkey, but QoS level * has pkeys - get shared pkey from QoS level pkeys */ required_pkey = osm_qos_level_get_shared_pkey(p_qos_level, p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); if (!required_pkey) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451D: " "Ports src 0x%016"PRIx64" (%s port %d) " "and dst 0x%016"PRIx64" (%s port %d) " "do not share a PKey as defined by QoS " "level \"%s\"\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num, p_qos_level->name); status = IB_NOT_FOUND; goto Exit; } } else { /* * Neither MPR request nor QoS level have pkey. * Just get any shared pkey. */ required_pkey = osm_physp_find_common_pkey(p_src_physp, p_dest_physp, sa->p_subn->opt.allow_both_pkeys); if (!required_pkey) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4519: " "Ports src 0x%016"PRIx64" (%s port %d) " "and dst 0x%016"PRIx64" (%s port %d) " "do not have any shared PKeys\n", cl_ntoh64(osm_physp_get_port_guid(p_src_physp)), p_src_physp->p_node->print_desc, p_src_physp->port_num, cl_ntoh64(osm_physp_get_port_guid (p_dest_physp)), p_dest_physp->p_node->print_desc, p_dest_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } if (required_pkey) { p_prtn = (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl, required_pkey & cl_ntoh16((uint16_t) ~ 0x8000)); if (p_prtn == (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl)) p_prtn = NULL; } /* * Set MultiPathRecord SL. */ if (comp_mask & IB_MPR_COMPMASK_SL) { /* * Specific SL was requested */ required_sl = ib_multipath_rec_sl(p_mpr); if (p_qos_level && p_qos_level->sl_set && p_qos_level->sl != required_sl) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451E: " "QoS constraints: required MultiPathRecord SL " "(%u) doesn't match QoS policy \"%s\" SL (%u) " "[%s port %d <-> %s port %d]\n", required_sl, p_qos_level->name, p_qos_level->sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } } else if (p_qos_level && p_qos_level->sl_set) { /* * No specific SL was requested, * but there is an SL in QoS level. */ required_sl = p_qos_level->sl; if (required_pkey && p_prtn && p_prtn->sl != p_qos_level->sl) OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "QoS level SL (%u) overrides partition SL (%u)\n", p_qos_level->sl, p_prtn->sl); } else if (required_pkey) { /* * No specific SL in request or in QoS level - use partition SL */ p_prtn = (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl, required_pkey & cl_ntoh16((uint16_t) ~ 0x8000)); if (!p_prtn) { required_sl = OSM_DEFAULT_SL; /* this may be possible when pkey tables are created somehow in previous runs or things are going wrong here */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451A: " "No partition found for PKey 0x%04x - " "using default SL %d " "[%s port %d <-> %s port %d]\n", cl_ntoh16(required_pkey), required_sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); } else required_sl = p_prtn->sl; } else if (sa->p_subn->opt.qos) { if (valid_sl_mask & (1 << OSM_DEFAULT_SL)) required_sl = OSM_DEFAULT_SL; else { for (i = 0; i < IB_MAX_NUM_VLS; i++) if (valid_sl_mask & (1 << i)) break; required_sl = i; } } else required_sl = OSM_DEFAULT_SL; if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << required_sl))) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451F: " "Selected SL (%u) leads to VL15 " "[%s port %d <-> %s port %d]\n", required_sl, p_src_alias_guid->p_base_port->p_node->print_desc, p_src_alias_guid->p_base_port->p_physp->port_num, p_dest_alias_guid->p_base_port->p_node->print_desc, p_dest_alias_guid->p_base_port->p_physp->port_num); status = IB_NOT_FOUND; goto Exit; } /* reset pkey when raw traffic */ if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC && cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31)) required_pkey = 0; p_parms->mtu = mtu; p_parms->rate = rate; p_parms->pkey = required_pkey; p_parms->pkt_life = pkt_life; p_parms->sl = required_sl; p_parms->hops = hops; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MultiPath params:" " mtu = %u, rate = %u, packet lifetime = %u," " pkey = 0x%04X, sl = %u, hops = %u\n", mtu, rate, pkt_life, cl_ntoh16(required_pkey), required_sl, hops); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void mpr_rcv_build_pr(IN osm_sa_t * sa, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN uint16_t src_lid_ho, IN uint16_t dest_lid_ho, IN uint8_t preference, IN const osm_path_parms_t * p_parms, OUT ib_path_rec_t * p_pr) { const osm_physp_t *p_src_physp, *p_dest_physp; OSM_LOG_ENTER(sa->p_log); p_src_physp = p_src_alias_guid->p_base_port->p_physp; p_dest_physp = p_dest_alias_guid->p_base_port->p_physp; p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix(p_dest_physp); p_pr->dgid.unicast.interface_id = p_dest_alias_guid->alias_guid; p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix(p_src_physp); p_pr->sgid.unicast.interface_id = p_src_alias_guid->alias_guid; p_pr->dlid = cl_hton16(dest_lid_ho); p_pr->slid = cl_hton16(src_lid_ho); p_pr->hop_flow_raw &= cl_hton32(1 << 31); p_pr->pkey = p_parms->pkey; ib_path_rec_set_qos_class(p_pr, 0); ib_path_rec_set_sl(p_pr, p_parms->sl); p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80); p_pr->rate = (uint8_t) (p_parms->rate | 0x80); /* According to 1.2 spec definition Table 205 PacketLifeTime description, for loopback paths, packetLifeTime shall be zero. */ if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port) p_pr->pkt_life = 0x80; /* loopback */ else p_pr->pkt_life = (uint8_t) (p_parms->pkt_life | 0x80); p_pr->preference = preference; /* always return num_path = 0 so this is only the reversible component */ if (p_parms->reversible) p_pr->num_path = 0x80; OSM_LOG_EXIT(sa->p_log); } static osm_sa_item_t *mpr_rcv_get_lid_pair_path(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const uint16_t src_lid_ho, IN const uint16_t dest_lid_ho, IN const ib_net64_t comp_mask, IN const uint8_t preference) { osm_path_parms_t path_parms; osm_path_parms_t rev_path_parms; osm_sa_item_t *p_pr_item; ib_api_status_t status, rev_path_status; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID %u, Dest LID %u\n", src_lid_ho, dest_lid_ho); p_pr_item = malloc(SA_MPR_RESP_SIZE); if (p_pr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4501: " "Unable to allocate path record\n"); goto Exit; } memset(p_pr_item, 0, SA_MPR_RESP_SIZE); status = mpr_rcv_get_path_parms(sa, p_mpr, p_src_alias_guid, p_dest_alias_guid, src_lid_ho, dest_lid_ho, comp_mask, &path_parms); if (status != IB_SUCCESS) { free(p_pr_item); p_pr_item = NULL; goto Exit; } /* now try the reversible path */ rev_path_status = mpr_rcv_get_path_parms(sa, p_mpr, p_dest_alias_guid, p_src_alias_guid, dest_lid_ho, src_lid_ho, comp_mask, &rev_path_parms); path_parms.reversible = (rev_path_status == IB_SUCCESS); /* did we get a Reversible Path compmask ? */ /* NOTE that if the reversible component = 0, it is a don't care rather then requiring non-reversible paths ... see Vol1 Ver1.2 p900 l16 */ if (comp_mask & IB_MPR_COMPMASK_REVERSIBLE) { if ((!path_parms.reversible && (p_mpr->num_path & 0x80))) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requested reversible path but failed to get one\n"); free(p_pr_item); p_pr_item = NULL; goto Exit; } } p_pr_item->resp.mpr_rec.p_src_port = p_src_alias_guid->p_base_port; p_pr_item->resp.mpr_rec.p_dest_port = p_dest_alias_guid->p_base_port; p_pr_item->resp.mpr_rec.hops = path_parms.hops; mpr_rcv_build_pr(sa, p_src_alias_guid, p_dest_alias_guid, src_lid_ho, dest_lid_ho, preference, &path_parms, &p_pr_item->resp.mpr_rec.path_rec); Exit: OSM_LOG_EXIT(sa->p_log); return p_pr_item; } static uint32_t mpr_rcv_get_port_pair_paths(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN const osm_port_t * p_req_port, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN const uint32_t rem_paths, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list) { osm_sa_item_t *p_pr_item; uint16_t src_lid_min_ho; uint16_t src_lid_max_ho; uint16_t dest_lid_min_ho; uint16_t dest_lid_max_ho; uint16_t src_lid_ho; uint16_t dest_lid_ho; uint32_t path_num = 0; uint8_t preference; unsigned src_offset, dest_offset; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src port 0x%016" PRIx64 ", Dst port 0x%016" PRIx64 "\n", cl_ntoh64(p_src_alias_guid->alias_guid), cl_ntoh64(p_dest_alias_guid->alias_guid)); /* Check that the req_port, src_port and dest_port all share a pkey. The check is done on the default physical port of the ports. */ if (osm_port_share_pkey(sa->p_log, p_req_port, p_src_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE || osm_port_share_pkey(sa->p_log, p_req_port, p_dest_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE || osm_port_share_pkey(sa->p_log, p_src_alias_guid->p_base_port, p_dest_alias_guid->p_base_port, sa->p_subn->opt.allow_both_pkeys) == FALSE) /* One of the pairs doesn't share a pkey so the path is disqualified. */ goto Exit; /* We shouldn't be here if the paths are disqualified in some way... Thus, we assume every possible connection is valid. We desire to return high-quality paths first. In OpenSM, higher quality mean least overlap with other paths. This is acheived in practice by returning paths with different LID value on each end, which means these paths are more redundant that paths with the same LID repeated on one side. For example, in OpenSM the paths between two endpoints with LMC = 1 might be as follows: Port A, LID 1 <-> Port B, LID 3 Port A, LID 1 <-> Port B, LID 4 Port A, LID 2 <-> Port B, LID 3 Port A, LID 2 <-> Port B, LID 4 The OpenSM unicast routing algorithms attempt to disperse each path to as varied a physical path as is reasonable. 1<->3 and 1<->4 have more physical overlap (hence less redundancy) than 1<->3 and 2<->4. OpenSM ranks paths in three preference groups: Preference Value Description ---------------- ------------------------------------------- 0 Redundant in both directions with other pref value = 0 paths 1 Redundant in one direction with other pref value = 0 and pref value = 1 paths 2 Not redundant in either direction with other paths 3-FF Unused SA clients don't need to know these details, only that the lower preference paths are preferred, as stated in the spec. The paths may not actually be physically redundant depending on the topology of the subnet, but the point of LMC > 0 is to offer redundancy, so I assume the subnet is physically appropriate for the specified LMC value. A more advanced implementation could inspect for physical redundancy, but I'm not going to bother with that now. */ osm_port_get_lid_range_ho(p_src_alias_guid->p_base_port, &src_lid_min_ho, &src_lid_max_ho); osm_port_get_lid_range_ho(p_dest_alias_guid->p_base_port, &dest_lid_min_ho, &dest_lid_max_ho); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LID [%u-%u], Dest LID [%u-%u]\n", src_lid_min_ho, src_lid_max_ho, dest_lid_min_ho, dest_lid_max_ho); src_lid_ho = src_lid_min_ho; dest_lid_ho = dest_lid_min_ho; /* Preferred paths come first in OpenSM */ preference = 0; while (path_num < rem_paths) { /* These paths are "fully redundant" */ p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr, p_src_alias_guid, p_dest_alias_guid, src_lid_ho, dest_lid_ho, comp_mask, preference); if (p_pr_item) { cl_qlist_insert_tail(p_list, &p_pr_item->list_item); ++path_num; } if (++src_lid_ho > src_lid_max_ho) break; if (++dest_lid_ho > dest_lid_max_ho) break; } /* Check if we've accumulated all the paths that the user cares to see */ if (path_num == rem_paths) goto Exit; /* Don't bother reporting preference 1 paths for now. It's more trouble than it's worth and can only occur if ports have different LMC values, which isn't supported by OpenSM right now anyway. */ preference = 2; src_lid_ho = src_lid_min_ho; dest_lid_ho = dest_lid_min_ho; src_offset = 0; dest_offset = 0; /* Iterate over the remaining paths */ while (path_num < rem_paths) { dest_offset++; dest_lid_ho++; if (dest_lid_ho > dest_lid_max_ho) { src_offset++; src_lid_ho++; if (src_lid_ho > src_lid_max_ho) break; /* done */ dest_offset = 0; dest_lid_ho = dest_lid_min_ho; } /* These paths are "fully non-redundant" with paths already identified above and consequently not of much value. Don't return paths we already identified above, as indicated by the offset values being equal. */ if (src_offset == dest_offset) continue; /* already reported */ p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr, p_src_alias_guid, p_dest_alias_guid, src_lid_ho, dest_lid_ho, comp_mask, preference); if (p_pr_item) { cl_qlist_insert_tail(p_list, &p_pr_item->list_item); ++path_num; } } Exit: OSM_LOG_EXIT(sa->p_log); return path_num; } #undef min #define min(x,y) (((x) < (y)) ? (x) : (y)) static osm_sa_item_t *mpr_rcv_get_apm_port_pair_paths(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN const osm_alias_guid_t * p_src_alias_guid, IN const osm_alias_guid_t * p_dest_alias_guid, IN int base_offs, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list) { osm_sa_item_t *p_pr_item = 0; uint16_t src_lid_min_ho; uint16_t src_lid_max_ho; uint16_t dest_lid_min_ho; uint16_t dest_lid_max_ho; uint16_t src_lid_ho; uint16_t dest_lid_ho; unsigned iterations; int src_lids, dest_lids; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src port 0x%016" PRIx64 ", " "Dst port 0x%016" PRIx64 ", base offs %d\n", cl_ntoh64(p_src_alias_guid->alias_guid), cl_ntoh64(p_dest_alias_guid->alias_guid), base_offs); osm_port_get_lid_range_ho(p_src_alias_guid->p_base_port, &src_lid_min_ho, &src_lid_max_ho); osm_port_get_lid_range_ho(p_dest_alias_guid->p_base_port, &dest_lid_min_ho, &dest_lid_max_ho); src_lid_ho = src_lid_min_ho; dest_lid_ho = dest_lid_min_ho; src_lids = src_lid_max_ho - src_lid_min_ho + 1; dest_lids = dest_lid_max_ho - dest_lid_min_ho + 1; src_lid_ho += base_offs % src_lids; dest_lid_ho += base_offs % dest_lids; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Src LIDs [%u-%u] hashed %u, " "Dest LIDs [%u-%u] hashed %u\n", src_lid_min_ho, src_lid_max_ho, src_lid_ho, dest_lid_min_ho, dest_lid_max_ho, dest_lid_ho); iterations = min(src_lids, dest_lids); while (iterations--) { /* These paths are "fully redundant" */ p_pr_item = mpr_rcv_get_lid_pair_path(sa, p_mpr, p_src_alias_guid, p_dest_alias_guid, src_lid_ho, dest_lid_ho, comp_mask, 0); if (p_pr_item) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Found matching path from Src LID %u to Dest LID %u with %d hops\n", src_lid_ho, dest_lid_ho, p_pr_item->resp.mpr_rec.hops); break; } if (++src_lid_ho > src_lid_max_ho) src_lid_ho = src_lid_min_ho; if (++dest_lid_ho > dest_lid_max_ho) dest_lid_ho = dest_lid_min_ho; } OSM_LOG_EXIT(sa->p_log); return p_pr_item; } static ib_net16_t mpr_rcv_get_gids(IN osm_sa_t * sa, IN const ib_gid_t * gids, IN int ngids, IN int is_sgid, OUT osm_alias_guid_t ** pp_alias_guid) { osm_alias_guid_t *p_alias_guid; ib_net16_t ib_status = IB_SUCCESS; int i; OSM_LOG_ENTER(sa->p_log); for (i = 0; i < ngids; i++, gids++) { if (!ib_gid_is_link_local(gids)) { if ((is_sgid && ib_gid_is_multicast(gids)) || (ib_gid_get_subnet_prefix(gids) != sa->p_subn->opt.subnet_prefix)) { /* This 'error' is the client's fault (bad gid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "ERR 451B: " "%sGID 0x%016" PRIx64 " is multicast or non local subnet prefix\n", is_sgid ? "S" : "D", cl_ntoh64(gids->unicast.prefix)); ib_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } } p_alias_guid = osm_get_alias_guid_by_guid(sa->p_subn, gids->unicast.interface_id); if (!p_alias_guid) { /* This 'error' is the client's fault (bad gid) so don't enter it as an error in our own log. Return an error response to the client. */ OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4506: " "No port with GUID 0x%016" PRIx64 "\n", cl_ntoh64(gids->unicast.interface_id)); ib_status = IB_SA_MAD_STATUS_INVALID_GID; goto Exit; } pp_alias_guid[i] = p_alias_guid; } Exit: OSM_LOG_EXIT(sa->p_log); return ib_status; } static ib_net16_t mpr_rcv_get_end_points(IN osm_sa_t * sa, IN const osm_madw_t * p_madw, OUT osm_alias_guid_t ** pp_alias_guids, OUT int *nsrc, OUT int *ndest) { const ib_multipath_rec_t *p_mpr; const ib_sa_mad_t *p_sa_mad; ib_net64_t comp_mask; ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS; ib_gid_t *gids; OSM_LOG_ENTER(sa->p_log); /* Determine what fields are valid and then get a pointer to the source and destination port objects, if possible. */ p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); gids = (ib_gid_t *) p_mpr->gids; comp_mask = p_sa_mad->comp_mask; /* Check a few easy disqualifying cases up front before getting into the endpoints. */ *nsrc = *ndest = 0; if (comp_mask & IB_MPR_COMPMASK_SGIDCOUNT) { *nsrc = p_mpr->sgid_count; if (*nsrc > IB_MULTIPATH_MAX_GIDS) *nsrc = IB_MULTIPATH_MAX_GIDS; sa_status = mpr_rcv_get_gids(sa, gids, *nsrc, 1, pp_alias_guids); if (sa_status != IB_SUCCESS) goto Exit; } if (comp_mask & IB_MPR_COMPMASK_DGIDCOUNT) { *ndest = p_mpr->dgid_count; if (*ndest + *nsrc > IB_MULTIPATH_MAX_GIDS) *ndest = IB_MULTIPATH_MAX_GIDS - *nsrc; sa_status = mpr_rcv_get_gids(sa, gids + *nsrc, *ndest, 0, pp_alias_guids + *nsrc); } Exit: OSM_LOG_EXIT(sa->p_log); return sa_status; } #define hash_lids(a, b, lmc) \ (((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103) static void mpr_rcv_get_apm_paths(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN const osm_port_t * p_req_port, IN osm_alias_guid_t ** _pp_alias_guids, IN const ib_net64_t comp_mask, IN cl_qlist_t * p_list) { osm_alias_guid_t *pp_alias_guids[4]; osm_sa_item_t *matrix[2][2]; int base_offs, src_lid_ho, dest_lid_ho; int sumA, sumB, minA, minB; OSM_LOG_ENTER(sa->p_log); /* * We want to: * 1. use different lid offsets (from base) for the resultant paths * to increase the probability of redundant paths or in case * of Clos - to ensure it (different offset => different spine!) * 2. keep consistent paths no matter of direction and order of ports * 3. distibute the lid offsets to balance the load * So, we sort the ports (within the srcs, and within the dests), * hash the lids of S0, D0 (after the sort), and call mpr_rcv_get_apm_port_pair_paths * with base_lid for S0, D0 and base_lid + 1 for S1, D1. This way we will get * always the same offsets - order independent, and make sure different spines are used. * Note that the diagonals on a Clos have the same number of hops, so it doesn't * really matter which diagonal we use. */ if (_pp_alias_guids[0]->p_base_port->guid < _pp_alias_guids[1]->p_base_port->guid) { pp_alias_guids[0] = _pp_alias_guids[0]; pp_alias_guids[1] = _pp_alias_guids[1]; } else { pp_alias_guids[0] = _pp_alias_guids[1]; pp_alias_guids[1] = _pp_alias_guids[0]; } if (_pp_alias_guids[2]->p_base_port->guid < _pp_alias_guids[3]->p_base_port->guid) { pp_alias_guids[2] = _pp_alias_guids[2]; pp_alias_guids[3] = _pp_alias_guids[3]; } else { pp_alias_guids[2] = _pp_alias_guids[3]; pp_alias_guids[3] = _pp_alias_guids[2]; } src_lid_ho = osm_port_get_base_lid(pp_alias_guids[0]->p_base_port); dest_lid_ho = osm_port_get_base_lid(pp_alias_guids[2]->p_base_port); base_offs = src_lid_ho < dest_lid_ho ? hash_lids(src_lid_ho, dest_lid_ho, sa->p_subn->opt.lmc) : hash_lids(dest_lid_ho, src_lid_ho, sa->p_subn->opt.lmc); matrix[0][0] = mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0], pp_alias_guids[2], base_offs, comp_mask, p_list); matrix[0][1] = mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[0], pp_alias_guids[3], base_offs, comp_mask, p_list); matrix[1][0] = mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1], pp_alias_guids[2], base_offs + 1, comp_mask, p_list); matrix[1][1] = mpr_rcv_get_apm_port_pair_paths(sa, p_mpr, pp_alias_guids[1], pp_alias_guids[3], base_offs + 1, comp_mask, p_list); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "APM matrix:\n" "\t{0,0} 0x%X->0x%X (%d)\t| {0,1} 0x%X->0x%X (%d)\n" "\t{1,0} 0x%X->0x%X (%d)\t| {1,1} 0x%X->0x%X (%d)\n", matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.slid : 0, matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.dlid : 0, matrix[0][0] ? matrix[0][0]->resp.mpr_rec.hops : 0, matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.slid : 0, matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.dlid : 0, matrix[0][1] ? matrix[0][1]->resp.mpr_rec.hops : 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.slid : 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.dlid : 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.hops : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.slid : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.dlid : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.hops : 0); sumA = minA = sumB = minB = 0; /* check diagonal A {(0,0), (1,1)} */ if (matrix[0][0]) { sumA += matrix[0][0]->resp.mpr_rec.hops; minA = matrix[0][0]->resp.mpr_rec.hops; } if (matrix[1][1]) { sumA += matrix[1][1]->resp.mpr_rec.hops; if (minA) minA = min(minA, matrix[1][1]->resp.mpr_rec.hops); else minA = matrix[1][1]->resp.mpr_rec.hops; } /* check diagonal B {(0,1), (1,0)} */ if (matrix[0][1]) { sumB += matrix[0][1]->resp.mpr_rec.hops; minB = matrix[0][1]->resp.mpr_rec.hops; } if (matrix[1][0]) { sumB += matrix[1][0]->resp.mpr_rec.hops; if (minB) minB = min(minB, matrix[1][0]->resp.mpr_rec.hops); else minB = matrix[1][0]->resp.mpr_rec.hops; } /* and the winner is... */ if (minA <= minB || (minA == minB && sumA < sumB)) { /* Diag A */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Diag {0,0} & {1,1} is the best:\n" "\t{0,0} 0x%X->0x%X (%d)\t & {1,1} 0x%X->0x%X (%d)\n", matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.slid : 0, matrix[0][0] ? matrix[0][0]->resp.mpr_rec.path_rec.dlid : 0, matrix[0][0] ? matrix[0][0]->resp.mpr_rec.hops : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.slid : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.path_rec.dlid : 0, matrix[1][1] ? matrix[1][1]->resp.mpr_rec.hops : 0); if (matrix[0][0]) cl_qlist_insert_tail(p_list, &matrix[0][0]->list_item); if (matrix[1][1]) cl_qlist_insert_tail(p_list, &matrix[1][1]->list_item); free(matrix[0][1]); free(matrix[1][0]); } else { /* Diag B */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Diag {0,1} & {1,0} is the best:\n" "\t{0,1} 0x%X->0x%X (%d)\t & {1,0} 0x%X->0x%X (%d)\n", matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.slid : 0, matrix[0][1] ? matrix[0][1]->resp.mpr_rec.path_rec.dlid : 0, matrix[0][1] ? matrix[0][1]->resp.mpr_rec.hops : 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.slid : 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.path_rec.dlid: 0, matrix[1][0] ? matrix[1][0]->resp.mpr_rec.hops : 0); if (matrix[0][1]) cl_qlist_insert_tail(p_list, &matrix[0][1]->list_item); if (matrix[1][0]) cl_qlist_insert_tail(p_list, &matrix[1][0]->list_item); free(matrix[0][0]); free(matrix[1][1]); } OSM_LOG_EXIT(sa->p_log); } static void mpr_rcv_process_pairs(IN osm_sa_t * sa, IN const ib_multipath_rec_t * p_mpr, IN osm_port_t * p_req_port, IN osm_alias_guid_t ** pp_alias_guids, IN const int nsrc, IN int ndest, IN ib_net64_t comp_mask, IN cl_qlist_t * p_list) { osm_alias_guid_t **pp_src_alias_guid, **pp_es; osm_alias_guid_t **pp_dest_alias_guid, **pp_ed; uint32_t max_paths, num_paths, total_paths = 0; OSM_LOG_ENTER(sa->p_log); if (comp_mask & IB_MPR_COMPMASK_NUMBPATH) max_paths = p_mpr->num_path & 0x7F; else max_paths = OSM_SA_MPR_MAX_NUM_PATH; for (pp_src_alias_guid = pp_alias_guids, pp_es = pp_alias_guids + nsrc; pp_src_alias_guid < pp_es; pp_src_alias_guid++) { for (pp_dest_alias_guid = pp_es, pp_ed = pp_es + ndest; pp_dest_alias_guid < pp_ed; pp_dest_alias_guid++) { num_paths = mpr_rcv_get_port_pair_paths(sa, p_mpr, p_req_port, *pp_src_alias_guid, *pp_dest_alias_guid, max_paths - total_paths, comp_mask, p_list); total_paths += num_paths; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "%d paths %d total paths %d max paths\n", num_paths, total_paths, max_paths); /* Just take first NumbPaths found */ if (total_paths >= max_paths) goto Exit; } } Exit: OSM_LOG_EXIT(sa->p_log); } void osm_mpr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; const ib_multipath_rec_t *p_mpr; ib_sa_mad_t *p_sa_mad; osm_port_t *requester_port; osm_alias_guid_t *pp_alias_guids[IB_MULTIPATH_MAX_GIDS]; cl_qlist_t pr_list; ib_net16_t sa_status; int nsrc, ndest; uint8_t rate, mtu; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_mpr = (ib_multipath_rec_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD); if ((p_sa_mad->rmpp_flags & IB_RMPP_FLAG_ACTIVE) != IB_RMPP_FLAG_ACTIVE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4510: " "Invalid request since RMPP_FLAG_ACTIVE is not set\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* we only support SubnAdmGetMulti method */ if (p_sa_mad->method != IB_MAD_METHOD_GETMULTI) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4513: " "Unsupported Method (%s) for MultiPathRecord request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_multipath_record_v2(sa->p_log, p_mpr, FILE_ID, OSM_LOG_DEBUG); /* Make sure required components (S/DGIDCount) are supplied */ if (!(p_sa_mad->comp_mask & IB_MPR_COMPMASK_SGIDCOUNT) || !(p_sa_mad->comp_mask & IB_MPR_COMPMASK_DGIDCOUNT)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } /* Validate rate if supplied */ if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_RATESELEC) && (p_sa_mad->comp_mask & IB_MPR_COMPMASK_RATE)) { rate = ib_multipath_rec_rate(p_mpr); if (!ib_rate_is_valid(rate)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } } /* Validate MTU if supplied */ if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_MTUSELEC) && (p_sa_mad->comp_mask & IB_MPR_COMPMASK_MTU)) { mtu = ib_multipath_rec_mtu(p_mpr); if (!ib_mtu_is_valid(mtu)) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } } /* Make sure either none or both ServiceID parameters are supplied */ if ((p_sa_mad->comp_mask & IB_MPR_COMPMASK_SERVICEID) != 0 && (p_sa_mad->comp_mask & IB_MPR_COMPMASK_SERVICEID) != IB_MPR_COMPMASK_SERVICEID) { osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_INSUF_COMPS); goto Exit; } cl_qlist_init(&pr_list); /* Most SA functions (including this one) are read-only on the subnet object, so we grab the lock non-exclusively. */ cl_plock_acquire(sa->p_lock); /* update the requester physical port */ requester_port = osm_get_port_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (requester_port == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4517: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_port_get_guid(requester_port))); sa_status = mpr_rcv_get_end_points(sa, p_madw, pp_alias_guids, &nsrc, &ndest); if (sa_status != IB_SA_MAD_STATUS_SUCCESS || !nsrc || !ndest) { cl_plock_release(sa->p_lock); if (sa_status == IB_SA_MAD_STATUS_SUCCESS && (!nsrc || !ndest)) OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4512: " "mpr_rcv_get_end_points failed, # GIDs found; " "src %d; dest %d)\n", nsrc, ndest); if (sa_status == IB_SA_MAD_STATUS_SUCCESS) osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); else osm_sa_send_error(sa, p_madw, sa_status); goto Exit; } /* APM request */ if (nsrc == 2 && ndest == 2 && (p_mpr->num_path & 0x7F) == 2) mpr_rcv_get_apm_paths(sa, p_mpr, requester_port, pp_alias_guids, p_sa_mad->comp_mask, &pr_list); else mpr_rcv_process_pairs(sa, p_mpr, requester_port, pp_alias_guids, nsrc, ndest, p_sa_mad->comp_mask, &pr_list); cl_plock_release(sa->p_lock); /* o15-0.2.7: If MultiPath is supported, then SA shall respond to a SubnAdmGetMulti() containing a valid MultiPathRecord attribute with a set of zero or more PathRecords satisfying the constraints indicated in the MultiPathRecord received. The PathRecord Attribute ID shall be used in the response. */ p_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD; osm_sa_respond(sa, p_madw, sizeof(ib_path_rec_t), &pr_list); Exit: OSM_LOG_EXIT(sa->p_log); } #endif opensm-3.3.20/opensm/osm_sa_service_record.c0000644000205000001450000005543112315015362016022 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_sr_rcv_t. * This object represents the ServiceRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_SERVICE_RECORD_C #include #include #include #include #include #include #include #include #define SA_SR_RESP_SIZE SA_ITEM_RESP_SIZE(service_rec) typedef struct osm_sr_match_item { cl_qlist_t sr_list; ib_service_record_t *p_service_rec; ib_net64_t comp_mask; osm_sa_t *sa; } osm_sr_match_item_t; typedef struct osm_sr_search_ctxt { osm_sr_match_item_t *p_sr_item; const osm_physp_t *p_req_physp; } osm_sr_search_ctxt_t; static boolean_t match_service_pkey_with_ports_pkey(IN osm_sa_t * sa, IN const osm_madw_t * p_madw, ib_service_record_t * p_service_rec, ib_net64_t const comp_mask) { boolean_t valid = TRUE; osm_physp_t *p_req_physp; ib_net64_t service_guid; osm_port_t *service_port; /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2404: " "Cannot find requester physical port\n"); valid = FALSE; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); if ((comp_mask & IB_SR_COMPMASK_SPKEY) == IB_SR_COMPMASK_SPKEY) { /* We have a ServiceP_Key - check matching on requester port, and ServiceGid port (if such exists) */ /* Make sure it matches the p_req_physp */ if (!osm_physp_has_pkey (sa->p_log, p_service_rec->service_pkey, p_req_physp)) { valid = FALSE; goto Exit; } /* If unicast, make sure it matches the port of the ServiceGid */ if (comp_mask & IB_SR_COMPMASK_SGID && !ib_gid_is_multicast(&p_service_rec->service_gid)) { service_guid = p_service_rec->service_gid.unicast.interface_id; service_port = osm_get_port_by_alias_guid(sa->p_subn, service_guid); if (!service_port) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2405: " "No port object for port 0x%016" PRIx64 "\n", cl_ntoh64(service_guid)); valid = FALSE; goto Exit; } /* check on the table of the default physical port of the service port */ if (!osm_physp_has_pkey(sa->p_log, p_service_rec->service_pkey, service_port->p_physp)) { valid = FALSE; goto Exit; } } } Exit: return valid; } static boolean_t match_name_to_key_association(IN osm_sa_t * sa, ib_service_record_t * p_service_rec, ib_net64_t comp_mask) { UNUSED_PARAM(p_service_rec); UNUSED_PARAM(sa); if ((comp_mask & (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) == (IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME)) { /* For now, we are not maintaining the ServiceAssociation record * so just return TRUE */ return TRUE; } return TRUE; } static boolean_t validate_sr(IN osm_sa_t * sa, IN const osm_madw_t * p_madw) { boolean_t valid = TRUE; ib_sa_mad_t *p_sa_mad; ib_service_record_t *p_recvd_service_rec; OSM_LOG_ENTER(sa->p_log); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_service_rec = (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); valid = match_service_pkey_with_ports_pkey(sa, p_madw, p_recvd_service_rec, p_sa_mad->comp_mask); if (!valid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "No Match for Service Pkey\n"); valid = FALSE; goto Exit; } valid = match_name_to_key_association(sa, p_recvd_service_rec, p_sa_mad->comp_mask); if (!valid) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Service Record Name to key matching failed\n"); valid = FALSE; goto Exit; } Exit: OSM_LOG_EXIT(sa->p_log); return valid; } static void sr_rcv_respond(IN osm_sa_t * sa, IN osm_madw_t * p_madw, IN cl_qlist_t * p_list) { /* p923 - The ServiceKey shall be set to 0, except in the case of a trusted request. Note: In the mad controller we check that the SM_Key received on the mad is valid. Meaning - is either zero or equal to the local sm_key. */ if (!osm_madw_get_sa_mad_ptr(p_madw)->sm_key) { osm_sa_item_t *item; for (item = (osm_sa_item_t *) cl_qlist_head(p_list); item != (osm_sa_item_t *) cl_qlist_end(p_list); item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) memset(item->resp.service_rec.service_key, 0, sizeof(item->resp.service_rec.service_key)); } osm_sa_respond(sa, p_madw, sizeof(ib_service_record_t), p_list); } static void get_matching_sr(IN cl_list_item_t * p_list_item, IN void *context) { osm_sr_search_ctxt_t *p_ctxt = context; osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; osm_sa_item_t *p_sr_pool_item; osm_sr_match_item_t *p_sr_item = p_ctxt->p_sr_item; ib_net64_t comp_mask = p_sr_item->comp_mask; const osm_physp_t *p_req_physp = p_ctxt->p_req_physp; if (comp_mask & IB_SR_COMPMASK_SID) { if (p_sr_item->p_service_rec->service_id != p_svcr->service_record.service_id) return; } if (comp_mask & IB_SR_COMPMASK_SGID) { if (memcmp(&p_sr_item->p_service_rec->service_gid, &p_svcr->service_record.service_gid, sizeof(p_svcr->service_record.service_gid)) != 0) return; } if (comp_mask & IB_SR_COMPMASK_SPKEY) { if (p_sr_item->p_service_rec->service_pkey != p_svcr->service_record.service_pkey) return; } if (comp_mask & IB_SR_COMPMASK_SKEY) { if (memcmp(p_sr_item->p_service_rec->service_key, p_svcr->service_record.service_key, 16 * sizeof(uint8_t))) return; } if (comp_mask & IB_SR_COMPMASK_SNAME) { if (memcmp(p_sr_item->p_service_rec->service_name, p_svcr->service_record.service_name, sizeof(p_svcr->service_record.service_name)) != 0) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_0) { if (p_sr_item->p_service_rec->service_data8[0] != p_svcr->service_record.service_data8[0]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_1) { if (p_sr_item->p_service_rec->service_data8[1] != p_svcr->service_record.service_data8[1]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_2) { if (p_sr_item->p_service_rec->service_data8[2] != p_svcr->service_record.service_data8[2]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_3) { if (p_sr_item->p_service_rec->service_data8[3] != p_svcr->service_record.service_data8[3]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_4) { if (p_sr_item->p_service_rec->service_data8[4] != p_svcr->service_record.service_data8[4]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_5) { if (p_sr_item->p_service_rec->service_data8[5] != p_svcr->service_record.service_data8[5]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_6) { if (p_sr_item->p_service_rec->service_data8[6] != p_svcr->service_record.service_data8[6]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_7) { if (p_sr_item->p_service_rec->service_data8[7] != p_svcr->service_record.service_data8[7]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_8) { if (p_sr_item->p_service_rec->service_data8[8] != p_svcr->service_record.service_data8[8]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_9) { if (p_sr_item->p_service_rec->service_data8[9] != p_svcr->service_record.service_data8[9]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_10) { if (p_sr_item->p_service_rec->service_data8[10] != p_svcr->service_record.service_data8[10]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_11) { if (p_sr_item->p_service_rec->service_data8[11] != p_svcr->service_record.service_data8[11]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_12) { if (p_sr_item->p_service_rec->service_data8[12] != p_svcr->service_record.service_data8[12]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_13) { if (p_sr_item->p_service_rec->service_data8[13] != p_svcr->service_record.service_data8[13]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_14) { if (p_sr_item->p_service_rec->service_data8[14] != p_svcr->service_record.service_data8[14]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA8_15) { if (p_sr_item->p_service_rec->service_data8[15] != p_svcr->service_record.service_data8[15]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_0) { if (p_sr_item->p_service_rec->service_data16[0] != p_svcr->service_record.service_data16[0]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_1) { if (p_sr_item->p_service_rec->service_data16[1] != p_svcr->service_record.service_data16[1]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_2) { if (p_sr_item->p_service_rec->service_data16[2] != p_svcr->service_record.service_data16[2]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_3) { if (p_sr_item->p_service_rec->service_data16[3] != p_svcr->service_record.service_data16[3]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_4) { if (p_sr_item->p_service_rec->service_data16[4] != p_svcr->service_record.service_data16[4]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_5) { if (p_sr_item->p_service_rec->service_data16[5] != p_svcr->service_record.service_data16[5]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_6) { if (p_sr_item->p_service_rec->service_data16[6] != p_svcr->service_record.service_data16[6]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA16_7) { if (p_sr_item->p_service_rec->service_data16[7] != p_svcr->service_record.service_data16[7]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA32_0) { if (p_sr_item->p_service_rec->service_data32[0] != p_svcr->service_record.service_data32[0]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA32_1) { if (p_sr_item->p_service_rec->service_data32[1] != p_svcr->service_record.service_data32[1]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA32_2) { if (p_sr_item->p_service_rec->service_data32[2] != p_svcr->service_record.service_data32[2]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA32_3) { if (p_sr_item->p_service_rec->service_data32[3] != p_svcr->service_record.service_data32[3]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA64_0) { if (p_sr_item->p_service_rec->service_data64[0] != p_svcr->service_record.service_data64[0]) return; } if (comp_mask & IB_SR_COMPMASK_SDATA64_1) { if (p_sr_item->p_service_rec->service_data64[1] != p_svcr->service_record.service_data64[1]) return; } /* Check that the requester port has the pkey which is the service_pkey. If not - then it cannot receive this ServiceRecord. */ /* The check is relevant only if the service_pkey is valid */ if (!ib_pkey_is_invalid(p_svcr->service_record.service_pkey)) { if (!osm_physp_has_pkey(p_sr_item->sa->p_log, p_svcr->service_record.service_pkey, p_req_physp)) { OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_VERBOSE, "requester port doesn't have the service_pkey: 0x%X\n", cl_ntoh16(p_svcr->service_record.service_pkey)); return; } } p_sr_pool_item = malloc(SA_SR_RESP_SIZE); if (p_sr_pool_item == NULL) { OSM_LOG(p_sr_item->sa->p_log, OSM_LOG_ERROR, "ERR 2408: " "Unable to acquire Service Record from pool\n"); goto Exit; } p_sr_pool_item->resp.service_rec = p_svcr->service_record; cl_qlist_insert_tail(&p_sr_item->sr_list, &p_sr_pool_item->list_item); Exit: return; } static void sr_rcv_process_get_method(osm_sa_t * sa, IN osm_madw_t * p_madw) { ib_sa_mad_t *p_sa_mad; ib_service_record_t *p_recvd_service_rec; osm_sr_match_item_t sr_match_item; osm_sr_search_ctxt_t context; osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); /* Grab the lock */ cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2409: " "Cannot find requester physical port\n"); goto Exit; } p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_service_rec = (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&sr_match_item.sr_list); sr_match_item.p_service_rec = p_recvd_service_rec; sr_match_item.comp_mask = p_sa_mad->comp_mask; sr_match_item.sa = sa; context.p_sr_item = &sr_match_item; context.p_req_physp = p_req_physp; cl_qlist_apply_func(&sa->p_subn->sa_sr_list, get_matching_sr, &context); cl_plock_release(sa->p_lock); if (p_sa_mad->method == IB_MAD_METHOD_GET && cl_qlist_count(&sr_match_item.sr_list) == 0) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "No records matched the Service Record query\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); goto Exit; } sr_rcv_respond(sa, p_madw, &sr_match_item.sr_list); Exit: OSM_LOG_EXIT(sa->p_log); return; } static void sr_rcv_process_set_method(osm_sa_t * sa, IN osm_madw_t * p_madw) { ib_sa_mad_t *p_sa_mad; ib_service_record_t *p_recvd_service_rec; ib_net64_t comp_mask; osm_svcr_t *p_svcr; osm_sa_item_t *p_sr_item; cl_qlist_t sr_list; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_service_rec = (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); comp_mask = p_sa_mad->comp_mask; if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, FILE_ID, OSM_LOG_DEBUG); if ((comp_mask & (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) != (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID)) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Component Mask RID check failed for METHOD_SET\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } /* if we were not provided with a service lease make it infinite */ if (!(comp_mask & IB_SR_COMPMASK_SLEASE)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "ServiceLease Component Mask not set - using infinite lease\n"); p_recvd_service_rec->service_lease = 0xFFFFFFFF; } /* If Record exists with matching RID */ p_svcr = osm_svcr_get_by_rid(sa->p_subn, sa->p_log, p_recvd_service_rec); if (p_svcr == NULL) { /* Create the instance of the osm_svcr_t object */ p_svcr = osm_svcr_new(p_recvd_service_rec); if (p_svcr == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2411: " "Failed to create new service record\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } /* Add this new osm_svcr_t object to subnet object */ osm_svcr_insert_to_db(sa->p_subn, sa->p_log, p_svcr); } else /* Update the old instance of the osm_svcr_t object */ osm_svcr_init(p_svcr, p_recvd_service_rec); cl_plock_release(sa->p_lock); if (p_recvd_service_rec->service_lease != 0xFFFFFFFF) { #if 0 cl_timer_trim(&sa->sr_timer, p_recvd_service_rec->service_lease * 1000); #endif /* This was a bug since no check was made to see if too long */ /* just make sure the timer works - get a call back within a second */ cl_timer_trim(&sa->sr_timer, 1000); p_svcr->modified_time = cl_get_time_stamp_sec(); } p_sr_item = malloc(SA_SR_RESP_SIZE); if (p_sr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2412: " "Unable to acquire Service record\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); goto Exit; } if ((comp_mask & IB_SR_COMPMASK_SPKEY) != IB_SR_COMPMASK_SPKEY) /* Set the Default Service P_Key in the response */ p_recvd_service_rec->service_pkey = IB_DEFAULT_PKEY; p_sr_item->resp.service_rec = *p_recvd_service_rec; cl_qlist_init(&sr_list); cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); sr_rcv_respond(sa, p_madw, &sr_list); Exit: OSM_LOG_EXIT(sa->p_log); } static void sr_rcv_process_delete_method(osm_sa_t * sa, IN osm_madw_t * p_madw) { ib_sa_mad_t *p_sa_mad; ib_service_record_t *p_recvd_service_rec; osm_svcr_t *p_svcr; osm_sa_item_t *p_sr_item; cl_qlist_t sr_list; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); p_recvd_service_rec = (ib_service_record_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) osm_dump_service_record_v2(sa->p_log, p_recvd_service_rec, FILE_ID, OSM_LOG_DEBUG); /* If Record exists with matching RID */ p_svcr = osm_svcr_get_by_rid(sa->p_subn, sa->p_log, p_recvd_service_rec); if (p_svcr == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "No records matched the RID\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RECORDS); goto Exit; } osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr); cl_plock_release(sa->p_lock); p_sr_item = malloc(SA_SR_RESP_SIZE); if (p_sr_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2413: " "Unable to acquire Service record\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES); osm_svcr_delete(p_svcr); goto Exit; } /* provide back the copy of the record */ p_sr_item->resp.service_rec = p_svcr->service_record; cl_qlist_init(&sr_list); cl_qlist_insert_tail(&sr_list, &p_sr_item->list_item); osm_svcr_delete(p_svcr); sr_rcv_respond(sa, p_madw, &sr_list); Exit: OSM_LOG_EXIT(sa->p_log); return; } void osm_sr_rcv_process(IN void *context, IN void *data) { osm_sa_t *sa = context; osm_madw_t *p_madw = data; ib_sa_mad_t *p_sa_mad; boolean_t valid; OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_SERVICE_RECORD); switch (p_sa_mad->method) { case IB_MAD_METHOD_SET: cl_plock_excl_acquire(sa->p_lock); valid = validate_sr(sa, p_madw); if (!valid) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, "Component Mask check failed for set request\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } sr_rcv_process_set_method(sa, p_madw); break; case IB_MAD_METHOD_DELETE: cl_plock_excl_acquire(sa->p_lock); valid = validate_sr(sa, p_madw); if (!valid) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Component Mask check failed for delete request\n"); osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); goto Exit; } sr_rcv_process_delete_method(sa, p_madw); break; case IB_MAD_METHOD_GET: case IB_MAD_METHOD_GETTABLE: sr_rcv_process_get_method(sa, p_madw); break; default: OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s) for ServiceRecord request\n", ib_get_sa_method_str(p_sa_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); break; } Exit: OSM_LOG_EXIT(sa->p_log); } void osm_sr_rcv_lease_cb(IN void *context) { osm_sa_t *sa = context; cl_list_item_t *p_list_item; cl_list_item_t *p_next_list_item; osm_svcr_t *p_svcr; uint32_t curr_time; uint32_t elapsed_time; uint32_t trim_time = 20; /* maxiaml timer refresh is 20 seconds */ OSM_LOG_ENTER(sa->p_log); cl_plock_excl_acquire(sa->p_lock); p_list_item = cl_qlist_head(&sa->p_subn->sa_sr_list); while (p_list_item != cl_qlist_end(&sa->p_subn->sa_sr_list)) { p_svcr = (osm_svcr_t *) p_list_item; if (p_svcr->service_record.service_lease == 0xFFFFFFFF) { p_list_item = cl_qlist_next(p_list_item); continue; } /* current time in seconds */ curr_time = cl_get_time_stamp_sec(); /* elapsed time from last modify */ elapsed_time = curr_time - p_svcr->modified_time; /* but it can not be less then 1 */ if (elapsed_time < 1) elapsed_time = 1; if (elapsed_time < p_svcr->lease_period) { /* Just update the service lease period note: for simplicity we work with a uint32_t field external to the network order lease_period of the MAD */ p_svcr->lease_period -= elapsed_time; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Remaining time for Service Name:%s is:0x%X\n", p_svcr->service_record.service_name, p_svcr->lease_period); p_svcr->modified_time = curr_time; /* Update the trim timer */ if (trim_time > p_svcr->lease_period) { trim_time = p_svcr->lease_period; if (trim_time < 1) trim_time = 1; } p_list_item = cl_qlist_next(p_list_item); continue; } else { p_next_list_item = cl_qlist_next(p_list_item); /* Remove the service Record */ osm_svcr_remove_from_db(sa->p_subn, sa->p_log, p_svcr); osm_svcr_delete(p_svcr); p_list_item = p_next_list_item; continue; } } /* Release the Lock */ cl_plock_release(sa->p_lock); if (trim_time != 0xFFFFFFFF) { cl_timer_trim(&sa->sr_timer, trim_time * 1000); /* Convert to milli seconds */ } OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_slvl_record.c0000644000205000001450000002205712314616647015354 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_slvl_rec_rcv_t. * This object represents the SLtoVL Mapping Query Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_SLVL_RECORD_C #include #include #include #include #include #include #define SA_SLVL_RESP_SIZE SA_ITEM_RESP_SIZE(slvl_rec) typedef struct osm_slvl_search_ctxt { const ib_slvl_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; uint8_t in_port_num; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_slvl_search_ctxt_t; static void sa_slvl_create(IN osm_sa_t * sa, IN const osm_physp_t * p_physp, IN osm_slvl_search_ctxt_t * p_ctxt, IN uint8_t in_port_idx) { osm_sa_item_t *p_rec_item; uint16_t lid; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_SLVL_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2602: " "rec_item alloc failed\n"); goto Exit; } if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) lid = p_physp->port_info.base_lid; else lid = osm_node_get_base_lid(p_physp->p_node, 0); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New SLtoVL Map for: OUT port 0x%016" PRIx64 ", lid 0x%X, port %u to In Port:%u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), cl_ntoh16(lid), osm_physp_get_port_num(p_physp), in_port_idx); memset(p_rec_item, 0, SA_SLVL_RESP_SIZE); p_rec_item->resp.slvl_rec.lid = lid; if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) { p_rec_item->resp.slvl_rec.out_port_num = osm_physp_get_port_num(p_physp); p_rec_item->resp.slvl_rec.in_port_num = in_port_idx; } p_rec_item->resp.slvl_rec.slvl_tbl = *(osm_physp_get_slvl_tbl(p_physp, in_port_idx)); cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_slvl_by_comp_mask(IN osm_sa_t * sa, IN const osm_port_t * p_port, osm_slvl_search_ctxt_t * p_ctxt) { const ib_slvl_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; const osm_physp_t *p_out_physp, *p_in_physp; uint8_t in_port_num, out_port_num; uint8_t num_ports; uint8_t in_port_start, in_port_end; uint8_t out_port_start, out_port_end; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; num_ports = osm_node_get_num_physp(p_port->p_node); in_port_start = 0; in_port_end = num_ports - 1; out_port_start = 0; out_port_end = num_ports - 1; p_req_physp = p_ctxt->p_req_physp; if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Using Physical Default Port Number: 0x%X (for End Node)\n", p_port->p_physp->port_num); p_out_physp = p_port->p_physp; /* check that the p_out_physp and the p_req_physp share a pkey */ if (osm_physp_share_pkey(sa->p_log, p_req_physp, p_out_physp, sa->p_subn->opt.allow_both_pkeys)) sa_slvl_create(sa, p_out_physp, p_ctxt, 0); } else { if (comp_mask & IB_SLVL_COMPMASK_OUT_PORT) out_port_start = out_port_end = p_rcvd_rec->out_port_num; if (comp_mask & IB_SLVL_COMPMASK_IN_PORT) in_port_start = in_port_end = p_rcvd_rec->in_port_num; for (out_port_num = out_port_start; out_port_num <= out_port_end; out_port_num++) { p_out_physp = osm_node_get_physp_ptr(p_port->p_node, out_port_num); if (!p_out_physp) continue; for (in_port_num = in_port_start; in_port_num <= in_port_end; in_port_num++) { #if 0 if (out_port_num && out_port_num == in_port_num) continue; #endif p_in_physp = osm_node_get_physp_ptr(p_port->p_node, in_port_num); if (!p_in_physp) continue; /* if the requester and the p_out_physp don't share a pkey - continue */ if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_out_physp, sa->p_subn->opt.allow_both_pkeys)) continue; sa_slvl_create(sa, p_out_physp, p_ctxt, in_port_num); } } } OSM_LOG_EXIT(sa->p_log); } static void sa_slvl_by_comp_mask_cb(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_port_t *p_port = (osm_port_t *) p_map_item; osm_slvl_search_ctxt_t *p_ctxt = cxt; sa_slvl_by_comp_mask(p_ctxt->sa, p_port, p_ctxt); } void osm_slvl_rec_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *p_rcvd_mad; const ib_slvl_table_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; cl_qlist_t rec_list; osm_slvl_search_ctxt_t context; ib_api_status_t status = IB_SUCCESS; ib_net64_t comp_mask; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_slvl_table_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); comp_mask = p_rcvd_mad->comp_mask; CL_ASSERT(p_rcvd_mad->attr_id == IB_MAD_ATTR_SLVL_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (p_rcvd_mad->method != IB_MAD_METHOD_GET && p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2604: " "Unsupported Method (%s) for SL2VLRecord request\n", ib_get_sa_method_str(p_rcvd_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2603: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = p_rcvd_mad->comp_mask; context.sa = sa; context.in_port_num = p_rcvd_rec->in_port_num; context.p_req_physp = p_req_physp; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Got Query Lid:%u(%02X), In-Port:0x%02X(%02X), Out-Port:0x%02X(%02X)\n", cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_SLVL_COMPMASK_LID) != 0, p_rcvd_rec->in_port_num, (comp_mask & IB_SLVL_COMPMASK_IN_PORT) != 0, p_rcvd_rec->out_port_num, (comp_mask & IB_SLVL_COMPMASK_OUT_PORT) != 0); /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & IB_SLVL_COMPMASK_LID) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) { status = IB_NOT_FOUND; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2608: " "No port found with LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); } } if (status == IB_SUCCESS) { /* if we have a unique port - no need for a port search */ if (p_port) /* this does the loop on all the port phys ports */ sa_slvl_by_comp_mask(sa, p_port, &context); else cl_qmap_apply_func(&sa->p_subn->port_guid_tbl, sa_slvl_by_comp_mask_cb, &context); } cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_slvl_table_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_sminfo_record.c0000644000205000001450000002351512314616647015667 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_smir_rcv_t. * This object represents the SMInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_SMINFO_RECORD_C #include #include #include #include #include #include #include #include #include #include #include #include #define SA_SMIR_RESP_SIZE SA_ITEM_RESP_SIZE(sminfo_rec) typedef struct osm_smir_search_ctxt { const ib_sminfo_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_smir_search_ctxt_t; static ib_api_status_t smir_rcv_new_smir(IN osm_sa_t * sa, IN const osm_port_t * p_port, IN cl_qlist_t * p_list, IN ib_net64_t const guid, IN ib_net32_t const act_count, IN uint8_t const pri_state, IN const osm_physp_t * p_req_physp) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_SMIR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2801: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New SMInfo: GUID 0x%016" PRIx64 "\n", cl_ntoh64(guid)); memset(p_rec_item, 0, SA_SMIR_RESP_SIZE); p_rec_item->resp.sminfo_rec.lid = osm_port_get_base_lid(p_port); p_rec_item->resp.sminfo_rec.sm_info.guid = guid; p_rec_item->resp.sminfo_rec.sm_info.act_count = act_count; p_rec_item->resp.sminfo_rec.sm_info.pri_state = pri_state; cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void sa_smir_by_comp_mask(IN osm_sa_t * sa, IN const osm_remote_sm_t * p_rem_sm, osm_smir_search_ctxt_t * p_ctxt) { const ib_sminfo_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; ib_net64_t const comp_mask = p_ctxt->comp_mask; osm_port_t *p_port; OSM_LOG_ENTER(sa->p_log); if (comp_mask & IB_SMIR_COMPMASK_GUID) { if (p_rem_sm->smi.guid != p_rcvd_rec->sm_info.guid) goto Exit; } if (comp_mask & IB_SMIR_COMPMASK_PRIORITY) { if (ib_sminfo_get_priority(&p_rem_sm->smi) != ib_sminfo_get_priority(&p_rcvd_rec->sm_info)) goto Exit; } if (comp_mask & IB_SMIR_COMPMASK_SMSTATE) { if (ib_sminfo_get_state(&p_rem_sm->smi) != ib_sminfo_get_state(&p_rcvd_rec->sm_info)) goto Exit; } /* Implement any other needed search cases */ p_port = osm_get_port_by_guid(sa->p_subn, p_rem_sm->smi.guid); if (p_port == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2810: " "No port for remote sm\n"); goto Exit; } smir_rcv_new_smir(sa, p_port, p_ctxt->p_list, p_rem_sm->smi.guid, p_rem_sm->smi.act_count, p_rem_sm->smi.pri_state, p_req_physp); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_smir_by_comp_mask_cb(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_remote_sm_t *p_rem_sm = (osm_remote_sm_t *) p_map_item; osm_smir_search_ctxt_t *p_ctxt = cxt; sa_smir_by_comp_mask(p_ctxt->sa, p_rem_sm, p_ctxt); } void osm_smir_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *sad_mad; const ib_sminfo_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; const ib_sm_info_t *p_smi; cl_qlist_t rec_list; osm_smir_search_ctxt_t context; ib_api_status_t status = IB_SUCCESS; ib_net64_t comp_mask; ib_net64_t port_guid; osm_physp_t *p_req_physp; osm_port_t *local_port; osm_remote_sm_t *p_rem_sm; cl_qmap_t *p_sm_guid_tbl; uint8_t pri_state; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); sad_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_sminfo_record_t *) ib_sa_mad_get_payload_ptr(sad_mad); comp_mask = sad_mad->comp_mask; CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (sad_mad->method != IB_MAD_METHOD_GET && sad_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2804: " "Unsupported Method (%s) for SMInfoRecord request\n", ib_get_sa_method_str(sad_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2803: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_sm_info_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } p_smi = &p_rcvd_rec->sm_info; cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = sad_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & IB_SMIR_COMPMASK_LID) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) { status = IB_NOT_FOUND; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2806: " "No port found with LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); } } if (status == IB_SUCCESS) { /* Handle our own SM first */ local_port = osm_get_port_by_guid(sa->p_subn, sa->p_subn->sm_port_guid); if (!local_port) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2809: " "No port found with GUID 0x%016" PRIx64 "\n", cl_ntoh64(sa->p_subn->sm_port_guid)); goto Exit; } if (!p_port || local_port == p_port) { if (FALSE == osm_physp_share_pkey(sa->p_log, p_req_physp, local_port->p_physp, sa->p_subn->opt.allow_both_pkeys)) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2805: " "Cannot get SMInfo record due to pkey violation\n"); goto Exit; } /* Check that other search components specified match */ if ((comp_mask & IB_SMIR_COMPMASK_GUID) && sa->p_subn->sm_port_guid != p_smi->guid) goto Remotes; if ((comp_mask & IB_SMIR_COMPMASK_PRIORITY) && sa->p_subn->opt.sm_priority != ib_sminfo_get_priority(p_smi)) goto Remotes; if ((comp_mask & IB_SMIR_COMPMASK_SMSTATE) && sa->p_subn->sm_state != ib_sminfo_get_state(p_smi)) goto Remotes; /* Now, add local SMInfo to list */ pri_state = sa->p_subn->sm_state & 0x0F; pri_state |= (sa->p_subn->opt.sm_priority & 0x0F) << 4; smir_rcv_new_smir(sa, local_port, context.p_list, sa->p_subn->sm_port_guid, cl_ntoh32(sa->p_subn->p_osm->stats. qp0_mads_sent), pri_state, p_req_physp); } Remotes: if (p_port && p_port != local_port) { /* Find remote SM corresponding to p_port */ port_guid = osm_port_get_guid(p_port); p_sm_guid_tbl = &sa->p_subn->sm_guid_tbl; p_rem_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_guid_tbl, port_guid); if (p_rem_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl)) sa_smir_by_comp_mask(sa, p_rem_sm, &context); else OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 280A: " "No remote SM for GUID 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); } else if (!p_port) { /* Go over all other known (remote) SMs */ cl_qmap_apply_func(&sa->p_subn->sm_guid_tbl, sa_smir_by_comp_mask_cb, &context); } } cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_sminfo_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_vlarb_record.c0000644000205000001450000002235512314616650015475 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_vlarb_rec_rcv_t. * This object represents the VLArbitrationRecord Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SA_VLARB_RECORD_C #include #include #include #include #include #include #define SA_VLA_RESP_SIZE SA_ITEM_RESP_SIZE(vlarb_rec) typedef struct osm_vl_arb_search_ctxt { const ib_vl_arb_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; uint8_t block_num; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_vl_arb_search_ctxt_t; static void sa_vl_arb_create(IN osm_sa_t * sa, IN osm_physp_t * p_physp, IN osm_vl_arb_search_ctxt_t * p_ctxt, IN uint8_t block) { osm_sa_item_t *p_rec_item; uint16_t lid; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_VLA_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A02: " "rec_item alloc failed\n"); goto Exit; } if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) lid = p_physp->port_info.base_lid; else lid = osm_node_get_base_lid(p_physp->p_node, 0); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New VLArbitration for: port 0x%016" PRIx64 ", lid %u, port %u Block:%u\n", cl_ntoh64(osm_physp_get_port_guid(p_physp)), cl_ntoh16(lid), osm_physp_get_port_num(p_physp), block); memset(p_rec_item, 0, SA_VLA_RESP_SIZE); p_rec_item->resp.vlarb_rec.lid = lid; p_rec_item->resp.vlarb_rec.port_num = osm_physp_get_port_num(p_physp); p_rec_item->resp.vlarb_rec.block_num = block; p_rec_item->resp.vlarb_rec.vl_arb_tbl = *(osm_physp_get_vla_tbl(p_physp, block)); cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_vl_arb_check_physp(IN osm_sa_t * sa, IN osm_physp_t * p_physp, osm_vl_arb_search_ctxt_t * p_ctxt) { ib_net64_t comp_mask = p_ctxt->comp_mask; uint8_t block; OSM_LOG_ENTER(sa->p_log); /* we got here with the phys port - all that's left is to get the right block */ for (block = 1; block <= 4; block++) { if (!(comp_mask & IB_VLA_COMPMASK_BLOCK) || block == p_ctxt->block_num) sa_vl_arb_create(sa, p_physp, p_ctxt, block); } OSM_LOG_EXIT(sa->p_log); } static void sa_vl_arb_by_comp_mask(osm_sa_t * sa, IN const osm_port_t * p_port, osm_vl_arb_search_ctxt_t * p_ctxt) { const ib_vl_arb_table_record_t *p_rcvd_rec; ib_net64_t comp_mask; osm_physp_t *p_physp; uint8_t port_num; uint8_t num_ports; const osm_physp_t *p_req_physp; OSM_LOG_ENTER(sa->p_log); p_rcvd_rec = p_ctxt->p_rcvd_rec; comp_mask = p_ctxt->comp_mask; port_num = p_rcvd_rec->port_num; p_req_physp = p_ctxt->p_req_physp; /* if this is a switch port we can search all ports otherwise we must be looking on port 0 */ if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) { /* we put it in the comp mask and port num */ port_num = p_port->p_physp->port_num; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Using Physical Default Port Number: 0x%X (for End Node)\n", port_num); comp_mask |= IB_VLA_COMPMASK_OUT_PORT; } if (comp_mask & IB_VLA_COMPMASK_OUT_PORT) { if (port_num < osm_node_get_num_physp(p_port->p_node)) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); /* check that the p_physp is valid, and that the requester and the p_physp share a pkey. */ if (p_physp && osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) sa_vl_arb_check_physp(sa, p_physp, p_ctxt); } else { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A03: " "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n", port_num, osm_node_get_num_physp(p_port->p_node)); goto Exit; } } else { num_ports = osm_node_get_num_physp(p_port->p_node); for (port_num = 0; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_port->p_node, port_num); if (!p_physp) continue; /* if the requester and the p_physp don't share a pkey - continue */ if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) continue; sa_vl_arb_check_physp(sa, p_physp, p_ctxt); } } Exit: OSM_LOG_EXIT(sa->p_log); } static void sa_vl_arb_by_comp_mask_cb(IN cl_map_item_t * p_map_item, void *cxt) { const osm_port_t *p_port = (osm_port_t *) p_map_item; osm_vl_arb_search_ctxt_t *p_ctxt = cxt; sa_vl_arb_by_comp_mask(p_ctxt->sa, p_port, p_ctxt); } void osm_vlarb_rec_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *sad_mad; const ib_vl_arb_table_record_t *p_rcvd_rec; const osm_port_t *p_port = NULL; cl_qlist_t rec_list; osm_vl_arb_search_ctxt_t context; ib_api_status_t status = IB_SUCCESS; ib_net64_t comp_mask; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); sad_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_vl_arb_table_record_t *) ib_sa_mad_get_payload_ptr(sad_mad); comp_mask = sad_mad->comp_mask; CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_VLARB_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (sad_mad->method != IB_MAD_METHOD_GET && sad_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A05: " "Unsupported Method (%s) for a VLArbRecord request\n", ib_get_sa_method_str(sad_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A04: " "Cannot find requester physical port\n"); goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = sad_mad->comp_mask; context.sa = sa; context.block_num = p_rcvd_rec->block_num; context.p_req_physp = p_req_physp; OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Got Query Lid:%u(%02X), Port:0x%02X(%02X), Block:0x%02X(%02X)\n", cl_ntoh16(p_rcvd_rec->lid), (comp_mask & IB_VLA_COMPMASK_LID) != 0, p_rcvd_rec->port_num, (comp_mask & IB_VLA_COMPMASK_OUT_PORT) != 0, p_rcvd_rec->block_num, (comp_mask & IB_VLA_COMPMASK_BLOCK) != 0); /* If the user specified a LID, it obviously narrows our work load, since we don't have to search every port */ if (comp_mask & IB_VLA_COMPMASK_LID) { p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid); if (!p_port) { status = IB_NOT_FOUND; OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2A09: " "No port found with LID %u\n", cl_ntoh16(p_rcvd_rec->lid)); } } if (status == IB_SUCCESS) { /* if we got a unique port - no need for a port search */ if (p_port) /* this does the loop on all the port phys ports */ sa_vl_arb_by_comp_mask(sa, p_port, &context); else cl_qmap_apply_func(&sa->p_subn->port_guid_tbl, sa_vl_arb_by_comp_mask_cb, &context); } cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_vl_arb_table_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_sa_sw_info_record.c0000644000205000001450000001717712314616650016041 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_sir_rcv_t. * This object represents the SwitchInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SA_SW_INFO_RECORD_C #include #include #include #include #include #define SA_SIR_RESP_SIZE SA_ITEM_RESP_SIZE(swinfo_rec) typedef struct osm_sir_search_ctxt { const ib_switch_info_record_t *p_rcvd_rec; ib_net64_t comp_mask; cl_qlist_t *p_list; osm_sa_t *sa; const osm_physp_t *p_req_physp; } osm_sir_search_ctxt_t; static ib_api_status_t sir_rcv_new_sir(IN osm_sa_t * sa, IN const osm_switch_t * p_sw, IN cl_qlist_t * p_list, IN ib_net16_t lid) { osm_sa_item_t *p_rec_item; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sa->p_log); p_rec_item = malloc(SA_SIR_RESP_SIZE); if (p_rec_item == NULL) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5308: " "rec_item alloc failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "New SwitchInfoRecord: lid %u\n", cl_ntoh16(lid)); memset(p_rec_item, 0, SA_SIR_RESP_SIZE); p_rec_item->resp.swinfo_rec.lid = lid; p_rec_item->resp.swinfo_rec.switch_info = p_sw->switch_info; cl_qlist_insert_tail(p_list, &p_rec_item->list_item); Exit: OSM_LOG_EXIT(sa->p_log); return status; } static void sir_rcv_create_sir(IN osm_sa_t * sa, IN const osm_switch_t * p_sw, IN cl_qlist_t * p_list, IN ib_net16_t match_lid, IN const osm_physp_t * p_req_physp) { osm_port_t *p_port; const osm_physp_t *p_physp; uint16_t match_lid_ho; ib_net16_t min_lid_ho; ib_net16_t max_lid_ho; OSM_LOG_ENTER(sa->p_log); OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Looking for SwitchInfoRecord with LID: %u\n", cl_ntoh16(match_lid)); /* In switches, the port guid is the node guid. */ p_port = osm_get_port_by_guid(sa->p_subn, p_sw->p_node->node_info.port_guid); if (!p_port) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530A: " "Failed to find Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); goto Exit; } /* check that the requester physp and the current physp are under the same partition. */ p_physp = p_port->p_physp; if (!p_physp) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 530B: " "Failed to find default physical Port by Node Guid:0x%016" PRIx64 "\n", cl_ntoh64(p_sw->p_node->node_info.node_guid)); goto Exit; } if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_physp, sa->p_subn->opt.allow_both_pkeys)) goto Exit; /* get the port 0 of the switch */ osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); match_lid_ho = cl_ntoh16(match_lid); if (match_lid_ho) { /* We validate that the lid belongs to this switch. */ OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Comparing LID: %u <= %u <= %u\n", min_lid_ho, match_lid_ho, max_lid_ho); if (match_lid_ho < min_lid_ho || match_lid_ho > max_lid_ho) goto Exit; } sir_rcv_new_sir(sa, p_sw, p_list, osm_port_get_base_lid(p_port)); Exit: OSM_LOG_EXIT(sa->p_log); } static void sir_rcv_by_comp_mask(IN cl_map_item_t * p_map_item, IN void *cxt) { const osm_sir_search_ctxt_t *p_ctxt = cxt; const osm_switch_t *p_sw = (osm_switch_t *) p_map_item; const ib_switch_info_record_t *const p_rcvd_rec = p_ctxt->p_rcvd_rec; const osm_physp_t *const p_req_physp = p_ctxt->p_req_physp; osm_sa_t *sa = p_ctxt->sa; ib_net64_t const comp_mask = p_ctxt->comp_mask; ib_net16_t match_lid = 0; OSM_LOG_ENTER(p_ctxt->sa->p_log); osm_dump_switch_info_v2(p_ctxt->sa->p_log, &p_sw->switch_info, FILE_ID, OSM_LOG_VERBOSE); if (comp_mask & IB_SWIR_COMPMASK_LID) { match_lid = p_rcvd_rec->lid; if (!match_lid) goto Exit; } sir_rcv_create_sir(sa, p_sw, p_ctxt->p_list, match_lid, p_req_physp); Exit: OSM_LOG_EXIT(p_ctxt->sa->p_log); } void osm_sir_rcv_process(IN void *ctx, IN void *data) { osm_sa_t *sa = ctx; osm_madw_t *p_madw = data; const ib_sa_mad_t *sad_mad; const ib_switch_info_record_t *p_rcvd_rec; cl_qlist_t rec_list; osm_sir_search_ctxt_t context; osm_physp_t *p_req_physp; CL_ASSERT(sa); OSM_LOG_ENTER(sa->p_log); CL_ASSERT(p_madw); sad_mad = osm_madw_get_sa_mad_ptr(p_madw); p_rcvd_rec = (ib_switch_info_record_t *) ib_sa_mad_get_payload_ptr(sad_mad); CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_RECORD); /* we only support SubnAdmGet and SubnAdmGetTable methods */ if (sad_mad->method != IB_MAD_METHOD_GET && sad_mad->method != IB_MAD_METHOD_GETTABLE) { OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5305: " "Unsupported Method (%s) for SwitchInfoRecord request\n", ib_get_sa_method_str(sad_mad->method)); osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); goto Exit; } cl_plock_acquire(sa->p_lock); /* update the requester physical port */ p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, osm_madw_get_mad_addr_ptr (p_madw)); if (p_req_physp == NULL) { cl_plock_release(sa->p_lock); OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 5304: " "Cannot find requester physical port\n"); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Requester port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); osm_dump_switch_info_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG); } cl_qlist_init(&rec_list); context.p_rcvd_rec = p_rcvd_rec; context.p_list = &rec_list; context.comp_mask = sad_mad->comp_mask; context.sa = sa; context.p_req_physp = p_req_physp; /* Go over all switches */ cl_qmap_apply_func(&sa->p_subn->sw_guid_tbl, sir_rcv_by_comp_mask, &context); cl_plock_release(sa->p_lock); osm_sa_respond(sa, p_madw, sizeof(ib_switch_info_record_t), &rec_list); Exit: OSM_LOG_EXIT(sa->p_log); } opensm-3.3.20/opensm/osm_service.c0000644000205000001450000001035212725515146014004 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 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 service record functions. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_SERVICE_C #include #include void osm_svcr_delete(IN osm_svcr_t * p_svcr) { free(p_svcr); } void osm_svcr_init(IN osm_svcr_t * p_svcr, IN const ib_service_record_t * p_svc_rec) { CL_ASSERT(p_svcr); p_svcr->modified_time = cl_get_time_stamp_sec(); /* We track the time left for this service in an external field to avoid extra cl_ntoh/hton required for working with the MAD field */ p_svcr->lease_period = cl_ntoh32(p_svc_rec->service_lease); p_svcr->service_record = *p_svc_rec; } osm_svcr_t *osm_svcr_new(IN const ib_service_record_t * p_svc_rec) { osm_svcr_t *p_svcr; CL_ASSERT(p_svc_rec); p_svcr = (osm_svcr_t *) malloc(sizeof(*p_svcr)); if (p_svcr) { memset(p_svcr, 0, sizeof(*p_svcr)); osm_svcr_init(p_svcr, p_svc_rec); } return p_svcr; } static cl_status_t match_rid_of_svc_rec(IN const cl_list_item_t * p_list_item, IN void *context) { ib_service_record_t *p_svc_rec = (ib_service_record_t *) context; osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; if (memcmp(&p_svcr->service_record, p_svc_rec, sizeof(p_svc_rec->service_id) + sizeof(p_svc_rec->service_gid) + sizeof(p_svc_rec->service_pkey))) return CL_NOT_FOUND; else return CL_SUCCESS; } osm_svcr_t *osm_svcr_get_by_rid(IN osm_subn_t const *p_subn, IN osm_log_t * p_log, IN ib_service_record_t * p_svc_rec) { cl_list_item_t *p_list_item; OSM_LOG_ENTER(p_log); p_list_item = cl_qlist_find_from_head(&p_subn->sa_sr_list, match_rid_of_svc_rec, p_svc_rec); if (p_list_item == cl_qlist_end(&p_subn->sa_sr_list)) p_list_item = NULL; OSM_LOG_EXIT(p_log); return (osm_svcr_t *) p_list_item; } void osm_svcr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_svcr_t * p_svcr) { OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Inserting new Service Record into Database\n"); cl_qlist_insert_head(&p_subn->sa_sr_list, &p_svcr->list_item); p_subn->p_osm->sa.dirty = TRUE; OSM_LOG_EXIT(p_log); } void osm_svcr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, IN osm_svcr_t * p_svcr) { OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing Service Record Name:%s ID:0x%016" PRIx64 " from Database\n", p_svcr->service_record.service_name, cl_ntoh64(p_svcr->service_record.service_id)); cl_qlist_remove_item(&p_subn->sa_sr_list, &p_svcr->list_item); p_subn->p_osm->sa.dirty = TRUE; OSM_LOG_EXIT(p_log); } opensm-3.3.20/opensm/osm_slvl_map_rcv.c0000644000205000001450000001275312273221507015033 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_slvl_rcv_t. * This object represents the SLtoVL Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SLVL_MAP_RCV_C #include #include #include #include #include #include /* * WE ONLY RECEIVE GET or SET responses */ void osm_slvl_rcv_process(IN void *context, IN void *p_data) { osm_sm_t *sm = context; osm_madw_t *p_madw = p_data; ib_slvl_table_t *p_slvl_tbl; ib_smp_t *p_smp; osm_port_t *p_port; osm_physp_t *p_physp; osm_node_t *p_node; osm_slvl_context_t *p_context; ib_net64_t port_guid; ib_net64_t node_guid; uint32_t attr_mod; uint8_t startinport, endinport, startoutport, endoutport; uint8_t in_port, out_port; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_slvl_context_ptr(p_madw); p_slvl_tbl = ib_smp_get_payload_ptr(p_smp); port_guid = p_context->port_guid; node_guid = p_context->node_guid; CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SLVL_TABLE); if (!sm->p_subn->opt.suppress_sl2vl_mad_status_errors && ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit2; } cl_plock_excl_acquire(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2C06: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); /* in case of a non switch node the attr modifier should be ignored */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { unsigned num_ports = osm_node_get_num_physp(p_node) - 1; attr_mod = cl_ntoh32(p_smp->attr_mod); if (attr_mod & 0x10000) { startoutport = ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) ? 0 : 1; endoutport = osm_node_get_num_physp(p_node) - 1; } else startoutport = endoutport = attr_mod & 0xff; if (attr_mod & 0x20000) { startinport = ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) ? 0 : 1; endinport = osm_node_get_num_physp(p_node) - 1; } else startinport = endinport = (attr_mod >> 8) & 0xff; if (startinport > num_ports || startoutport > num_ports) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2C07" "Invalid attribute modifier 0x%x received in" " response from switch 0x%" PRIx64 "\n", cl_ntoh32(attr_mod), cl_ntoh64(node_guid)); goto Exit; } } else { startoutport = endoutport = p_port->p_physp->port_num; startinport = endinport = 0; } OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received SLtoVL GetResp" " in_port_num %u out_port_num %u with GUID 0x%" PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", startinport == endinport ? startinport : 0xff, startoutport == endoutport ? startoutport : 0xff, cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); osm_dump_slvl_map_table_v2(sm->p_log, port_guid, startinport == endinport ? startinport : 0xff, startoutport == endoutport ? startoutport : 0xff, p_slvl_tbl, FILE_ID, OSM_LOG_DEBUG); for (out_port = startoutport; out_port <= endoutport; out_port++) { p_physp = osm_node_get_physp_ptr(p_node, out_port); for (in_port = startinport; in_port <= endinport; in_port++) osm_physp_set_slvl_tbl(p_physp, p_slvl_tbl, in_port); } Exit: cl_plock_release(sm->p_lock); Exit2: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_sm.c0000644000205000001450000003336412336645226012774 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. 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 osm_sm_t. * This object represents the SM Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SM_C #include #include #include #include #include #include #include #define OSM_SM_INITIAL_TID_VALUE 0x1233 extern void osm_lft_rcv_process(IN void *context, IN void *data); extern void osm_mft_rcv_process(IN void *context, IN void *data); extern void osm_nd_rcv_process(IN void *context, IN void *data); extern void osm_ni_rcv_process(IN void *context, IN void *data); extern void osm_pkey_rcv_process(IN void *context, IN void *data); extern void osm_pi_rcv_process(IN void *context, IN void *data); extern void osm_gi_rcv_process(IN void *context, IN void *data); extern void osm_slvl_rcv_process(IN void *context, IN void *p_data); extern void osm_sminfo_rcv_process(IN void *context, IN void *data); extern void osm_si_rcv_process(IN void *context, IN void *data); extern void osm_trap_rcv_process(IN void *context, IN void *data); extern void osm_vla_rcv_process(IN void *context, IN void *data); extern void osm_mlnx_epi_rcv_process(IN void *context, IN void *data); extern void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal); extern void osm_sm_state_mgr_polling_callback(IN void *context); static void sm_process(osm_sm_t * sm, osm_signal_t signal) { #ifdef ENABLE_OSM_PERF_MGR if (signal == OSM_SIGNAL_PERFMGR_SWEEP) osm_perfmgr_process(&sm->p_subn->p_osm->perfmgr); else #endif osm_state_mgr_process(sm, signal); } static void sm_sweeper(IN void *p_ptr) { ib_api_status_t status; osm_sm_t * p_sm = p_ptr; unsigned signals, i; OSM_LOG_ENTER(p_sm->p_log); while (p_sm->thread_state == OSM_THREAD_STATE_RUN) { /* * Wait on the event with a timeout. * Sweeps may be initiated "off schedule" by simply * signaling the event. */ status = cl_event_wait_on(&p_sm->signal_event, EVENT_NO_TIMEOUT, TRUE); if (status == CL_SUCCESS) OSM_LOG(p_sm->p_log, OSM_LOG_DEBUG, "Off schedule sweep signalled\n"); else { OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E01: " "Event wait failed (%s)\n", CL_STATUS_MSG(status)); continue; } if (osm_exit_flag) break; cl_spinlock_acquire(&p_sm->signal_lock); signals = p_sm->signal_mask; p_sm->signal_mask = 0; cl_spinlock_release(&p_sm->signal_lock); for (i = 0; signals; signals >>= 1, i++) if (signals & 1) sm_process(p_sm, i); } OSM_LOG_EXIT(p_sm->p_log); } static void sm_sweep(void *arg) { osm_sm_t *sm = arg; /* do the sweep only if we are in MASTER state */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER || sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING) osm_sm_signal(sm, OSM_SIGNAL_SWEEP); cl_timer_start(&sm->sweep_timer, sm->p_subn->opt.sweep_interval * 1000); } static void sweep_fail_process(IN void *context, IN void *p_data) { osm_sm_t *sm = context; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "light sweep failed\n"); sm->p_subn->force_heavy_sweep = TRUE; } void osm_sm_construct(IN osm_sm_t * p_sm) { memset(p_sm, 0, sizeof(*p_sm)); p_sm->thread_state = OSM_THREAD_STATE_NONE; p_sm->sm_trans_id = OSM_SM_INITIAL_TID_VALUE; cl_spinlock_construct(&p_sm->signal_lock); cl_spinlock_construct(&p_sm->state_lock); cl_timer_construct(&p_sm->polling_timer); cl_event_construct(&p_sm->signal_event); cl_event_construct(&p_sm->subnet_up_event); cl_event_wheel_construct(&p_sm->trap_aging_tracker); cl_thread_construct(&p_sm->sweeper); osm_sm_mad_ctrl_construct(&p_sm->mad_ctrl); osm_lid_mgr_construct(&p_sm->lid_mgr); osm_ucast_mgr_construct(&p_sm->ucast_mgr); } void osm_sm_shutdown(IN osm_sm_t * p_sm) { boolean_t signal_event = FALSE; OSM_LOG_ENTER(p_sm->p_log); /* * Signal our threads that we're leaving. */ if (p_sm->thread_state != OSM_THREAD_STATE_NONE) signal_event = TRUE; p_sm->thread_state = OSM_THREAD_STATE_EXIT; /* * Don't trigger unless event has been initialized. * Destroy the thread before we tear down the other objects. */ if (signal_event) cl_event_signal(&p_sm->signal_event); cl_timer_stop(&p_sm->polling_timer); cl_timer_stop(&p_sm->sweep_timer); cl_thread_destroy(&p_sm->sweeper); /* * Always destroy controllers before the corresponding * receiver to guarantee that all callbacks from the * dispatcher are complete. */ osm_sm_mad_ctrl_destroy(&p_sm->mad_ctrl); cl_disp_unregister(p_sm->ni_disp_h); cl_disp_unregister(p_sm->pi_disp_h); cl_disp_unregister(p_sm->gi_disp_h); cl_disp_unregister(p_sm->si_disp_h); cl_disp_unregister(p_sm->nd_disp_h); cl_disp_unregister(p_sm->lft_disp_h); cl_disp_unregister(p_sm->mft_disp_h); cl_disp_unregister(p_sm->sm_info_disp_h); cl_disp_unregister(p_sm->trap_disp_h); cl_disp_unregister(p_sm->slvl_disp_h); cl_disp_unregister(p_sm->vla_disp_h); cl_disp_unregister(p_sm->pkey_disp_h); cl_disp_unregister(p_sm->mlnx_epi_disp_h); cl_disp_unregister(p_sm->sweep_fail_disp_h); OSM_LOG_EXIT(p_sm->p_log); } void osm_sm_destroy(IN osm_sm_t * p_sm) { OSM_LOG_ENTER(p_sm->p_log); osm_lid_mgr_destroy(&p_sm->lid_mgr); osm_ucast_mgr_destroy(&p_sm->ucast_mgr); cl_event_wheel_destroy(&p_sm->trap_aging_tracker); cl_timer_destroy(&p_sm->sweep_timer); cl_timer_destroy(&p_sm->polling_timer); cl_event_destroy(&p_sm->signal_event); cl_event_destroy(&p_sm->subnet_up_event); cl_spinlock_destroy(&p_sm->signal_lock); cl_spinlock_destroy(&p_sm->state_lock); free(p_sm->mlids_req); osm_log_v2(p_sm->p_log, OSM_LOG_SYS, FILE_ID, "Exiting SM\n"); /* Format Waived */ OSM_LOG_EXIT(p_sm->p_log); } ib_api_status_t osm_sm_init(IN osm_sm_t * p_sm, IN osm_subn_t * p_subn, IN osm_db_t * p_db, IN osm_vendor_t * p_vendor, IN osm_mad_pool_t * p_mad_pool, IN osm_vl15_t * p_vl15, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_dispatcher_t * p_disp, IN cl_plock_t * p_lock) { ib_api_status_t status; OSM_LOG_ENTER(p_log); p_sm->p_subn = p_subn; p_sm->p_db = p_db; p_sm->p_vendor = p_vendor; p_sm->p_mad_pool = p_mad_pool; p_sm->p_vl15 = p_vl15; p_sm->p_log = p_log; p_sm->p_disp = p_disp; p_sm->p_lock = p_lock; status = cl_spinlock_init(&p_sm->signal_lock); if (status != CL_SUCCESS) goto Exit; status = cl_spinlock_init(&p_sm->state_lock); if (status != CL_SUCCESS) goto Exit; status = cl_event_init(&p_sm->signal_event, FALSE); if (status != CL_SUCCESS) goto Exit; status = cl_event_init(&p_sm->subnet_up_event, FALSE); if (status != CL_SUCCESS) goto Exit; status = cl_timer_init(&p_sm->sweep_timer, sm_sweep, p_sm); if (status != CL_SUCCESS) goto Exit; status = cl_timer_init(&p_sm->polling_timer, osm_sm_state_mgr_polling_callback, p_sm); if (status != CL_SUCCESS) goto Exit; p_sm->mlids_req_max = 0; p_sm->mlids_req = malloc((IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1) * sizeof(p_sm->mlids_req[0])); if (!p_sm->mlids_req) goto Exit; memset(p_sm->mlids_req, 0, (IB_LID_MCAST_END_HO - IB_LID_MCAST_START_HO + 1) * sizeof(p_sm->mlids_req[0])); status = osm_sm_mad_ctrl_init(&p_sm->mad_ctrl, p_sm->p_subn, p_sm->p_mad_pool, p_sm->p_vl15, p_sm->p_vendor, p_log, p_stats, p_lock, p_disp); if (status != IB_SUCCESS) goto Exit; status = cl_event_wheel_init(&p_sm->trap_aging_tracker); if (status != IB_SUCCESS) goto Exit; status = osm_lid_mgr_init(&p_sm->lid_mgr, p_sm); if (status != IB_SUCCESS) goto Exit; status = osm_ucast_mgr_init(&p_sm->ucast_mgr, p_sm); if (status != IB_SUCCESS) goto Exit; status = IB_INSUFFICIENT_RESOURCES; p_sm->sweep_fail_disp_h = cl_disp_register(p_disp, OSM_MSG_LIGHT_SWEEP_FAIL, sweep_fail_process, p_sm); if (p_sm->sweep_fail_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->ni_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_INFO, osm_ni_rcv_process, p_sm); if (p_sm->ni_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->pi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORT_INFO, osm_pi_rcv_process, p_sm); if (p_sm->pi_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->gi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUID_INFO, osm_gi_rcv_process, p_sm); if (p_sm->gi_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->si_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO, osm_si_rcv_process, p_sm); if (p_sm->si_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->nd_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_DESC, osm_nd_rcv_process, p_sm); if (p_sm->nd_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT, osm_lft_rcv_process, p_sm); if (p_sm->lft_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT, osm_mft_rcv_process, p_sm); if (p_sm->mft_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->sm_info_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SM_INFO, osm_sminfo_rcv_process, p_sm); if (p_sm->sm_info_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->trap_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NOTICE, osm_trap_rcv_process, p_sm); if (p_sm->trap_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->slvl_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SLVL, osm_slvl_rcv_process, p_sm); if (p_sm->slvl_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->vla_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB, osm_vla_rcv_process, p_sm); if (p_sm->vla_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->pkey_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PKEY, osm_pkey_rcv_process, p_sm); if (p_sm->pkey_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_sm->mlnx_epi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MLNX_EXT_PORT_INFO, osm_mlnx_epi_rcv_process, p_sm); if (p_sm->mlnx_epi_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; p_subn->sm_state = p_subn->opt.sm_inactive ? IB_SMINFO_STATE_NOTACTIVE : IB_SMINFO_STATE_DISCOVERING; osm_report_sm_state(p_sm); /* * Now that the component objects are initialized, start * the sweeper thread if the user wants sweeping. */ p_sm->thread_state = OSM_THREAD_STATE_RUN; status = cl_thread_init(&p_sm->sweeper, sm_sweeper, p_sm, "opensm sweeper"); if (status != IB_SUCCESS) goto Exit; if (p_sm->p_subn->opt.sweep_interval) cl_timer_start(&p_sm->sweep_timer, p_sm->p_subn->opt.sweep_interval * 1000); Exit: OSM_LOG_EXIT(p_log); return status; } void osm_sm_signal(osm_sm_t * p_sm, osm_signal_t signal) { cl_spinlock_acquire(&p_sm->signal_lock); p_sm->signal_mask |= 1 << signal; cl_event_signal(&p_sm->signal_event); cl_spinlock_release(&p_sm->signal_lock); } void osm_sm_sweep(IN osm_sm_t * p_sm) { OSM_LOG_ENTER(p_sm->p_log); osm_sm_signal(p_sm, OSM_SIGNAL_SWEEP); OSM_LOG_EXIT(p_sm->p_log); } ib_api_status_t osm_sm_bind(IN osm_sm_t * p_sm, IN ib_net64_t port_guid) { ib_api_status_t status; OSM_LOG_ENTER(p_sm->p_log); status = osm_sm_mad_ctrl_bind(&p_sm->mad_ctrl, port_guid); if (status != IB_SUCCESS) { OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR 2E10: " "SM MAD Controller bind failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_sm->p_log); return status; } void osm_sm_reroute_mlid(osm_sm_t * sm, ib_net16_t mlid) { mlid = cl_ntoh16(mlid) - IB_LID_MCAST_START_HO; sm->mlids_req[mlid] = 1; if (sm->mlids_req_max < mlid) sm->mlids_req_max = mlid; osm_sm_signal(sm, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "rerouting requested for MLID 0x%x\n", mlid + IB_LID_MCAST_START_HO); } void osm_set_sm_priority(osm_sm_t * sm, uint8_t priority) { uint8_t old_pri = sm->p_subn->opt.sm_priority; sm->p_subn->opt.sm_priority = priority; if (old_pri < priority && sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY) osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); } opensm-3.3.20/opensm/osm_sminfo_rcv.c0000644000205000001450000004654312306357062014520 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_sminfo_rcv_t. * This object represents the SMInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SMINFO_RCV_C #include #include #include #include #include #include #include /********************************************************************** Return TRUE if the remote sm given (by ib_sm_info_t) is higher, return FALSE otherwise. By higher - we mean: SM with higher priority or with same priority and lower GUID. **********************************************************************/ static boolean_t smi_rcv_remote_sm_is_higher(IN osm_sm_t * sm, IN const ib_sm_info_t * p_rem_smi) { return osm_sm_is_greater_than(ib_sminfo_get_priority(p_rem_smi), p_rem_smi->guid, sm->p_subn->opt.sm_priority, sm->p_subn->sm_port_guid); } static void smi_rcv_process_get_request(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { uint8_t payload[IB_SMP_DATA_SIZE]; ib_sm_info_t *p_smi = (ib_sm_info_t *) payload; ib_api_status_t status; ib_sm_info_t *p_remote_smi; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); /* No real need to grab the lock for this function. */ memset(payload, 0, sizeof(payload)); CL_ASSERT(osm_madw_get_smp_ptr(p_madw)->method == IB_MAD_METHOD_GET); p_smi->guid = sm->p_subn->sm_port_guid; p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent); p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state | sm->p_subn->opt.sm_priority << 4); /* p.840 line 20 - Return 0 for the SM key unless we authenticate the requester as the master SM. */ p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw)); if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to master SM with real sm_key\n"); p_smi->sm_key = sm->p_subn->opt.sm_key; } else { /* The requester is not authenticated as master - set sm_key to zero. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to SM not master with zero sm_key\n"); p_smi->sm_key = 0; } status = osm_resp_send(sm, p_madw, 0, payload); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F02: " "Error sending SMInfo response (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** * Check if the p_smp received is legal. * Current checks: * MADHeader:AttributeModifier of ACKNOWLEDGE that was not sent by a * Standby SM. * MADHeader:AttributeModifiers of HANDOVER/DISABLE/STANDBY/DISCOVER * that was not sent by a Master SM. * FUTURE - TO DO: * Check that the SM_Key matches. **********************************************************************/ static ib_api_status_t smi_rcv_check_set_req_legality(IN const ib_smp_t * p_smp) { ib_sm_info_t *p_smi; p_smi = ib_smp_get_payload_ptr(p_smp); if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_ACKNOWLEDGE) { if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_STANDBY) return IB_SUCCESS; } else if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_HANDOVER || p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISABLE || p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY || p_smp->attr_mod == IB_SMINFO_ATTR_MOD_DISCOVER) { if (ib_sminfo_get_state(p_smi) == IB_SMINFO_STATE_MASTER) return IB_SUCCESS; } return IB_INVALID_PARAMETER; } static void smi_rcv_process_set_request(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { uint8_t payload[IB_SMP_DATA_SIZE]; ib_smp_t *p_smp; ib_sm_info_t *p_smi = (ib_sm_info_t *) payload; ib_sm_info_t *sm_smi; ib_api_status_t status; osm_sm_signal_t sm_signal; ib_sm_info_t *p_remote_smi; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); memset(payload, 0, sizeof(payload)); p_smp = osm_madw_get_smp_ptr(p_madw); sm_smi = ib_smp_get_payload_ptr(p_smp); if (p_smp->method != IB_MAD_METHOD_SET) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F03: " "Unsupported set method 0x%X\n", p_smp->method); goto Exit; } CL_PLOCK_ACQUIRE(sm->p_lock); p_smi->guid = sm->p_subn->sm_port_guid; p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent); p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state | sm->p_subn->opt.sm_priority << 4); /* p.840 line 20 - Return 0 for the SM key unless we authenticate the requester as the master SM. */ p_remote_smi = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(p_madw)); if (ib_sminfo_get_state(p_remote_smi) == IB_SMINFO_STATE_MASTER) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to master SM with real sm_key\n"); p_smi->sm_key = sm->p_subn->opt.sm_key; } else { /* The requester is not authenticated as master - set sm_key to zero. */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to SM not master with zero sm_key\n"); p_smi->sm_key = 0; } /* Check the legality of the packet */ status = smi_rcv_check_set_req_legality(p_smp); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F04: " "Check legality failed. AttributeModifier:0x%X RemoteState:%s\n", p_smp->attr_mod, osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi))); status = osm_resp_send(sm, p_madw, 7, payload); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F05: " "Error sending SMInfo response (%s)\n", ib_get_err_str(status)); CL_PLOCK_RELEASE(sm->p_lock); goto Exit; } /* translate from IB_SMINFO_ATTR to OSM_SM_SIGNAL */ switch (p_smp->attr_mod) { case IB_SMINFO_ATTR_MOD_HANDOVER: sm_signal = OSM_SM_SIGNAL_HANDOVER; break; case IB_SMINFO_ATTR_MOD_ACKNOWLEDGE: sm_signal = OSM_SM_SIGNAL_ACKNOWLEDGE; break; case IB_SMINFO_ATTR_MOD_DISABLE: sm_signal = OSM_SM_SIGNAL_DISABLE; break; case IB_SMINFO_ATTR_MOD_STANDBY: sm_signal = OSM_SM_SIGNAL_STANDBY; break; case IB_SMINFO_ATTR_MOD_DISCOVER: sm_signal = OSM_SM_SIGNAL_DISCOVER; break; default: /* This code shouldn't be reached - checked in the check legality */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F06: " "THIS CODE SHOULD NOT BE REACHED!!\n"); CL_PLOCK_RELEASE(sm->p_lock); goto Exit; } CL_PLOCK_RELEASE(sm->p_lock); /* check legality of the needed transition in the SM state machine */ status = osm_sm_state_mgr_check_legality(sm, sm_signal); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F07: " "Failed check of legality of needed SM transition. " "AttributeModifier:0x%X RemoteState:%s\n", p_smp->attr_mod, osm_get_sm_mgr_state_str(ib_sminfo_get_state(sm_smi))); status = osm_resp_send(sm, p_madw, 7, payload); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F08: " "Error sending SMInfo response (%s)\n", ib_get_err_str(status)); goto Exit; } /* the SubnSet(SMInfo) command is ok. Send a response. */ status = osm_resp_send(sm, p_madw, 0, payload); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F09: " "Error sending SMInfo response (%s)\n", ib_get_err_str(status)); /* it is a legal packet - act according to it */ /* if the AttributeModifier is STANDBY - need to save on the sm in */ /* the master_sm_guid variable - the guid of the current master. */ if (p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Received a STANDBY signal. Updating " "sm_state_mgr master_guid: 0x%016" PRIx64 "\n", cl_ntoh64(sm_smi->guid)); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->master_sm_guid = sm_smi->guid; CL_PLOCK_RELEASE(sm->p_lock); } status = osm_sm_state_mgr_process(sm, sm_signal); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F10: " "Error in SM state transition (%s)\n", ib_get_err_str(status)); Exit: OSM_LOG_EXIT(sm->p_log); } static void smi_rcv_process_get_sm(IN osm_sm_t * sm, IN const osm_remote_sm_t * p_sm, boolean_t light_sweep) { const ib_sm_info_t *p_smi; OSM_LOG_ENTER(sm->p_log); p_smi = &p_sm->smi; OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Detected SM 0x%016" PRIx64 " in state %u (%s)\n", cl_ntoh64(p_smi->guid), ib_sminfo_get_state(p_smi), osm_get_sm_mgr_state_str(ib_sminfo_get_state(p_smi))); /* Check the state of this SM vs. our own. */ switch (sm->p_subn->sm_state) { case IB_SMINFO_STATE_NOTACTIVE: break; case IB_SMINFO_STATE_DISCOVERING: switch (ib_sminfo_get_state(p_smi)) { case IB_SMINFO_STATE_NOTACTIVE: break; case IB_SMINFO_STATE_MASTER: sm->master_sm_found = 1; /* save on the sm the guid of the current master. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Found master SM. Updating sm_state_mgr master_guid: 0x%016" PRIx64 "\n", cl_ntoh64(p_smi->guid)); sm->master_sm_guid = p_smi->guid; break; case IB_SMINFO_STATE_DISCOVERING: case IB_SMINFO_STATE_STANDBY: if (smi_rcv_remote_sm_is_higher(sm, p_smi)) { /* the remote is a higher sm - need to stop sweeping */ sm->master_sm_found = 1; /* save on the sm the guid of the higher SM we found - */ /* we will poll it - as long as it lives - we should be in Standby. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Found higher SM. Updating sm_state_mgr master_guid:" " 0x%016" PRIx64 "\n", cl_ntoh64(p_smi->guid)); sm->master_sm_guid = p_smi->guid; } break; default: break; } break; case IB_SMINFO_STATE_STANDBY: /* if the guid of the SM that sent us this response is equal to the */ /* p_sm_mgr->master_guid - then this is a signal that the polling */ switch (ib_sminfo_get_state(p_smi)) { case IB_SMINFO_STATE_MASTER: /* This means the master is alive */ /* Signal that to the SM state mgr */ osm_sm_state_mgr_signal_master_is_alive(sm); if (!smi_rcv_remote_sm_is_higher(sm, p_smi)) osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); break; case IB_SMINFO_STATE_STANDBY: /* This should be the response from the sm we are polling. */ /* If it is - then signal master is alive */ if (sm->master_sm_guid == p_sm->smi.guid) { /* Make sure that it is an SM with higher priority than us. If we started polling it when it was master, and it moved to standby - then it might be with a lower priority than us - and then we don't want to continue polling it. */ if (smi_rcv_remote_sm_is_higher(sm, p_smi)) osm_sm_state_mgr_signal_master_is_alive (sm); } break; default: /* any other state - do nothing */ break; } break; case IB_SMINFO_STATE_MASTER: switch (ib_sminfo_get_state(p_smi)) { case IB_SMINFO_STATE_MASTER: /* If this is a response due to our polling, this means that we are * waiting for a handover from this SM, and it is still alive - * signal that. If we detected the remote SM with higher priority * we should init a heavy sweep in order to go STANDBY. If we * detected a remote SM with lower priority, we should resend trap144 * as it might not get it and we don't want to wait for a HANDOVER * forever. */ if (sm->polling_sm_guid) { if (smi_rcv_remote_sm_is_higher(sm, p_smi)) sm->p_subn->force_heavy_sweep = TRUE; else { /* Update master_sm_guid to the GUID of the newly * found MASTER SM and send trap 144 to it. */ sm->master_sm_guid = sm->polling_sm_guid; osm_send_trap144(sm, TRAP_144_MASK_SM_PRIORITY_CHANGE); } osm_sm_state_mgr_signal_master_is_alive(sm); } else { /* This is a response we got while sweeping the subnet. * * If this is during a heavy sweep, we will handle a case of * handover needed later on, when the sweep is done and all * SMs are recognized. * * If this is during a light sweep, initiate a heavy sweep * to initiate handover scenarios. * * Note that it does not matter if the remote SM is lower * or higher priority. If it is lower priority, we must * wait for it HANDOVER. If it is higher priority, we need * to HANDOVER to it. Both cases are handled after doing * a heavy sweep. */ if (light_sweep) sm->p_subn->force_heavy_sweep = TRUE; } break; case IB_SMINFO_STATE_STANDBY: if (light_sweep && smi_rcv_remote_sm_is_higher(sm, p_smi)) sm->p_subn->force_heavy_sweep = TRUE; break; default: /* any other state - do nothing */ break; } break; default: break; } OSM_LOG_EXIT(sm->p_log); } static void smi_rcv_process_get_response(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { const ib_smp_t *p_smp; const ib_sm_info_t *p_smi; cl_qmap_t *p_sm_tbl; osm_port_t *p_port; ib_net64_t port_guid; osm_remote_sm_t *p_sm; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); if (p_smp->method != IB_MAD_METHOD_GET_RESP) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F11: " "Unsupported response method 0x%X\n", p_smp->method); goto Exit; } p_smi = ib_smp_get_payload_ptr(p_smp); p_sm_tbl = &sm->p_subn->sm_guid_tbl; port_guid = p_smi->guid; osm_dump_sm_info_v2(sm->p_log, p_smi, FILE_ID, OSM_LOG_DEBUG); /* Check that the sm_key of the found SM is the same as ours, or is zero. If not - OpenSM cannot continue with configuration!. */ if (p_smi->sm_key != 0 && p_smi->sm_key != sm->p_subn->opt.sm_key) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F18: " "Got SM with sm_key that doesn't match our " "local key. Exiting\n"); osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "Found remote SM with non-matching sm_key. Exiting\n"); osm_exit_flag = TRUE; goto Exit; } /* Determine if we already have another SM object for this SM. */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F12: " "No port object for this SM\n"); goto _unlock_and_exit; } if (osm_port_get_guid(p_port) != p_smi->guid) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F13: " "Bogus SM port GUID, Expected 0x%016" PRIx64 ", Received 0x%016" PRIx64 "\n", cl_ntoh64(osm_port_get_guid(p_port)), cl_ntoh64(p_smi->guid)); goto _unlock_and_exit; } if (port_guid == sm->p_subn->sm_port_guid) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Self query response received - SM port 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); goto _unlock_and_exit; } p_sm = (osm_remote_sm_t *) cl_qmap_get(p_sm_tbl, port_guid); if (p_sm == (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl)) { p_sm = malloc(sizeof(*p_sm)); if (p_sm == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F14: " "Unable to allocate SM object\n"); goto _unlock_and_exit; } osm_remote_sm_init(p_sm, p_smi); cl_qmap_insert(p_sm_tbl, port_guid, &p_sm->map_item); } else /* We already know this SM. Update the SMInfo attribute. */ p_sm->smi = *p_smi; smi_rcv_process_get_sm(sm, p_sm, osm_madw_get_smi_context_ptr(p_madw)-> light_sweep); _unlock_and_exit: CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); } static void smi_rcv_process_set_response(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { const ib_smp_t *p_smp; const ib_sm_info_t *p_smi; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } if (p_smp->method != IB_MAD_METHOD_GET_RESP) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F16: " "Unsupported response method 0x%X\n", p_smp->method); goto Exit; } p_smi = ib_smp_get_payload_ptr(p_smp); osm_dump_sm_info_v2(sm->p_log, p_smi, FILE_ID, OSM_LOG_DEBUG); /* Check the AttributeModifier */ if (p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F17: " "Unsupported attribute modifier 0x%X, " "expected ATTR_MOD_HANDOVER\n", p_smp->attr_mod); goto Exit; } /* This is a response on a HANDOVER request - Nothing to do. */ Exit: OSM_LOG_EXIT(sm->p_log); } void osm_sminfo_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_smp_t *p_smp; osm_smi_context_t *p_smi_context; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit; } /* Determine if this is a request for our own SMInfo or if this is a response to our request for another SM's SMInfo. */ if (ib_smp_is_response(p_smp)) { const ib_sm_info_t *p_smi = ib_smp_get_payload_ptr(p_smp); /* Get the context - to see if this is a response to a Get or Set method */ p_smi_context = osm_madw_get_smi_context_ptr(p_madw); /* Verify that response is from expected port and there is no port moving issue. */ if (p_smi_context->port_guid != p_smi->guid) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 2F19: " "Unexpected SM port GUID in response" ", Expected 0x%016" PRIx64 ", Received 0x%016" PRIx64 "\n", cl_ntoh64(p_smi_context->port_guid), cl_ntoh64(p_smi->guid)); goto Exit; } if (p_smi_context->set_method == FALSE) /* this is a response to a Get method */ smi_rcv_process_get_response(sm, p_madw); else /* this is a response to a Set method */ smi_rcv_process_set_response(sm, p_madw); } else if (p_smp->method == IB_MAD_METHOD_GET) /* This is a SubnGet request */ smi_rcv_process_get_request(sm, p_madw); else /* This should be a SubnSet request */ smi_rcv_process_set_request(sm, p_madw); Exit: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_sm_mad_ctrl.c0000644000205000001450000006025612713102205014621 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. 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 osm_sm_mad_ctrl_t. * This object represents the SM MAD request controller object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_SM_MAD_CTRL_C #include #include #include #include #include #include /****f* opensm: SM/sm_mad_ctrl_retire_trans_mad * NAME * sm_mad_ctrl_retire_trans_mad * * DESCRIPTION * This function handles clean-up of MADs associated with the SM's * outstanding transactions on the wire. * * SYNOPSIS */ static void sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw) { uint32_t outstanding; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); /* Return the MAD & wrapper to the pool. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Retiring MAD with TID 0x%" PRIx64 "\n", cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id)); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats); OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n", p_ctrl->p_stats->qp0_mads_outstanding, outstanding ? "" : ": wire is clean."); OSM_LOG_EXIT(p_ctrl->p_log); } /************/ /****f* opensm: SM/sm_mad_ctrl_disp_done_callback * NAME * sm_mad_ctrl_disp_done_callback * * DESCRIPTION * This function is the Dispatcher callback that indicates * a received MAD has been processed by the recipient. * * SYNOPSIS */ static void sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data) { osm_sm_mad_ctrl_t *p_ctrl = context; osm_madw_t *p_madw = p_data; ib_smp_t *p_smp; OSM_LOG_ENTER(p_ctrl->p_log); /* If the MAD that just finished processing was a response, then retire the transaction, since we must have generated the request. Otherwise, retire the transaction if a response was expected, as in the case of a send failure. If a response was not expected, just put the MAD back in the pool, because the MAD was a query from some outside agent, e.g. Get(SMInfo) from another SM. */ p_smp = osm_madw_get_smp_ptr(p_madw); if (ib_smp_is_response(p_smp)) { CL_ASSERT(p_madw->resp_expected == FALSE); sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); } else if (p_madw->resp_expected == TRUE) sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); else osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); OSM_LOG_EXIT(p_ctrl->p_log); } /************/ /****f* opensm: SM/sm_mad_ctrl_update_wire_stats * NAME * sm_mad_ctrl_update_wire_stats * * DESCRIPTION * Updates wire stats for outstanding MADs and calls the VL15 poller. * * SYNOPSIS */ static void sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * p_ctrl) { uint32_t mads_on_wire; OSM_LOG_ENTER(p_ctrl->p_log); mads_on_wire = cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire); OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u SMPs on the wire, %u outstanding\n", mads_on_wire, p_ctrl->p_stats->qp0_mads_outstanding); /* We can signal the VL15 controller to send another MAD if any are waiting for transmission. */ osm_vl15_poll(p_ctrl->p_vl15); OSM_LOG_EXIT(p_ctrl->p_log); } /****f* opensm: SM/sm_mad_ctrl_process_get_resp * NAME * sm_mad_ctrl_process_get_resp * * DESCRIPTION * This function handles method GetResp() for received MADs. * This is the most common path for QP0 MADs. * * SYNOPSIS */ static void sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw, IN void *transaction_context) { ib_smp_t *p_smp; cl_status_t status; osm_madw_t *p_old_madw; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); CL_ASSERT(transaction_context); p_smp = osm_madw_get_smp_ptr(p_madw); if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: " "'D' bit not set in returned SMP\n"); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); } p_old_madw = transaction_context; sm_mad_ctrl_update_wire_stats(p_ctrl); /* Copy the MAD Wrapper context from the requesting MAD to the new MAD. This mechanism allows the recipient controller to recover its own context regarding this MAD transaction. Once we've copied the context, we can return the original MAD to the pool. */ osm_madw_copy_context(p_madw, p_old_madw); osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_NODE_DESC: msg_id = OSM_MSG_MAD_NODE_DESC; break; case IB_MAD_ATTR_NODE_INFO: msg_id = OSM_MSG_MAD_NODE_INFO; break; case IB_MAD_ATTR_GUID_INFO: msg_id = OSM_MSG_MAD_GUID_INFO; break; case IB_MAD_ATTR_SWITCH_INFO: msg_id = OSM_MSG_MAD_SWITCH_INFO; break; case IB_MAD_ATTR_PORT_INFO: msg_id = OSM_MSG_MAD_PORT_INFO; break; case IB_MAD_ATTR_LIN_FWD_TBL: msg_id = OSM_MSG_MAD_LFT; break; case IB_MAD_ATTR_MCAST_FWD_TBL: msg_id = OSM_MSG_MAD_MFT; break; case IB_MAD_ATTR_SM_INFO: msg_id = OSM_MSG_MAD_SM_INFO; break; case IB_MAD_ATTR_SLVL_TABLE: msg_id = OSM_MSG_MAD_SLVL; break; case IB_MAD_ATTR_VL_ARBITRATION: msg_id = OSM_MSG_MAD_VL_ARB; break; case IB_MAD_ATTR_P_KEY_TABLE: msg_id = OSM_MSG_MAD_PKEY; break; case IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO: msg_id = OSM_MSG_MAD_MLNX_EXT_PORT_INFO; break; case IB_MAD_ATTR_CLASS_PORT_INFO: case IB_MAD_ATTR_NOTICE: case IB_MAD_ATTR_INFORM_INFO: default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: " "Unsupported attribute 0x%X (%s)\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } /* Post this MAD to the dispatcher for asynchronous processing by the appropriate controller. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(msg_id)); status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, sm_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: " "Dispatcher post message failed (%s) for attribute 0x%X (%s)\n", CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /****f* opensm: SM/sm_mad_ctrl_process_get * NAME * sm_mad_ctrl_process_get * * DESCRIPTION * This function handles method Get() for received MADs. * * SYNOPSIS */ static void sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw) { ib_smp_t *p_smp; cl_status_t status; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; OSM_LOG_ENTER(p_ctrl->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_SM_INFO: msg_id = OSM_MSG_MAD_SM_INFO; break; default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, "Ignoring SubnGet MAD - unsupported attribute 0x%X\n", cl_ntoh16(p_smp->attr_id)); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } /* Post this MAD to the dispatcher for asynchronous processing by the appropriate controller. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(msg_id)); status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, sm_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: " "Dispatcher post message failed (%s)\n", CL_STATUS_MSG(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SM/sm_mad_ctrl_process_set * NAME * sm_mad_ctrl_process_set * * DESCRIPTION * This function handles method Set() for received MADs. * * SYNOPSIS */ static void sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw) { ib_smp_t *p_smp; cl_status_t status; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; OSM_LOG_ENTER(p_ctrl->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_SM_INFO: msg_id = OSM_MSG_MAD_SM_INFO; break; default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: " "Unsupported attribute 0x%X (%s)\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } /* Post this MAD to the dispatcher for asynchronous processing by the appropriate controller. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(msg_id)); status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, sm_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: " "Dispatcher post message failed (%s)\n", CL_STATUS_MSG(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SM/sm_mad_ctrl_process_trap * NAME * sm_mad_ctrl_process_trap * * DESCRIPTION * This function handles method Trap() for received MADs. * * SYNOPSIS */ static void sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw) { ib_smp_t *p_smp; cl_status_t status; cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; OSM_LOG_ENTER(p_ctrl->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); /* Make sure OpenSM is master. If not - then we should not process the trap */ if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) { OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Received trap but OpenSM is not in MASTER state. " "Dropping mad\n"); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_NOTICE: msg_id = OSM_MSG_MAD_NOTICE; break; default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: " "Unsupported attribute 0x%X (%s)\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } /* Post this MAD to the dispatcher for asynchronous processing by the appropriate controller. */ OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(msg_id)); status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, sm_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: " "Dispatcher post message failed (%s)\n", CL_STATUS_MSG(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SM/sm_mad_ctrl_process_trap_repress * NAME * sm_mad_ctrl_process_trap_repress * * DESCRIPTION * This function handles method TrapRepress() for received MADs. * * SYNOPSIS */ static void sm_mad_ctrl_process_trap_repress(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_madw_t * p_madw) { ib_smp_t *p_smp; OSM_LOG_ENTER(p_ctrl->p_log); p_smp = osm_madw_get_smp_ptr(p_madw); /* Note that attr_id (like the rest of the MAD) is in network byte order. */ switch (p_smp->attr_id) { case IB_MAD_ATTR_NOTICE: sm_mad_ctrl_update_wire_stats(p_ctrl); sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); break; default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3105: " "Unsupported attribute 0x%X (%s)\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); break; } OSM_LOG_EXIT(p_ctrl->p_log); } static void log_rcv_cb_error(osm_log_t *p_log, ib_smp_t *p_smp, ib_net16_t status) { char buf[BUF_SIZE]; uint32_t i; if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) { char ipath[BUF_SIZE], rpath[BUF_SIZE]; int ni = sprintf(ipath, "%d", p_smp->initial_path[0]); int nr = sprintf(rpath, "%d", p_smp->return_path[0]); for (i = 1; i <= p_smp->hop_count; i++) { ni += sprintf(ipath + ni, ",%d", p_smp->initial_path[i]); nr += sprintf(rpath + nr, ",%d", p_smp->return_path[i]); } snprintf(buf, sizeof(buf), "\n\t\t\tInitial path: %s Return path: %s", ipath, rpath); } OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3111: " "Received MAD with error status = 0x%X\n" "\t\t\t%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "%s\n", cl_ntoh16(status), ib_get_sm_method_str(p_smp->method), ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->trans_id), p_smp->mgmt_class == IB_MCLASS_SUBN_DIR ? buf : ""); osm_dump_dr_smp_v2(p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SM/sm_mad_ctrl_rcv_callback * NAME * sm_mad_ctrl_rcv_callback * * DESCRIPTION * This is the callback from the transport layer for received MADs. * * SYNOPSIS */ static void sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, IN void *bind_context, IN osm_madw_t * p_req_madw) { osm_sm_mad_ctrl_t *p_ctrl = bind_context; ib_smp_t *p_smp; ib_net16_t status; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); /* A MAD was received from the wire, possibly in response to a request. */ cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd); OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n", p_ctrl->p_stats->qp0_mads_rcvd); p_smp = osm_madw_get_smp_ptr(p_madw); /* if we are closing down simply do nothing */ if (osm_exit_flag) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "Ignoring received mad - since we are exiting\n"); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_DEBUG); /* retire the mad or put it back */ if (ib_smp_is_response(p_smp)) { CL_ASSERT(p_madw->resp_expected == FALSE); sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); } else if (p_madw->resp_expected == TRUE) sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); else osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } if (OSM_LOG_IS_ACTIVE_V2(p_ctrl->p_log, OSM_LOG_FRAMES)) osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_FRAMES); if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) status = ib_smp_get_status(p_smp); else status = p_smp->status; if (status != 0) log_rcv_cb_error(p_ctrl->p_log, p_smp, status); switch (p_smp->method) { case IB_MAD_METHOD_GET_RESP: CL_ASSERT(p_req_madw != NULL); sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw); break; case IB_MAD_METHOD_GET: CL_ASSERT(p_req_madw == NULL); sm_mad_ctrl_process_get(p_ctrl, p_madw); break; case IB_MAD_METHOD_TRAP: CL_ASSERT(p_req_madw == NULL); sm_mad_ctrl_process_trap(p_ctrl, p_madw); break; case IB_MAD_METHOD_SET: CL_ASSERT(p_req_madw == NULL); sm_mad_ctrl_process_set(p_ctrl, p_madw); break; case IB_MAD_METHOD_TRAP_REPRESS: CL_ASSERT(p_req_madw != NULL); sm_mad_ctrl_process_trap_repress(p_ctrl, p_madw); break; case IB_MAD_METHOD_SEND: case IB_MAD_METHOD_REPORT: case IB_MAD_METHOD_REPORT_RESP: default: cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: " "Unsupported method = 0x%X\n", p_smp->method); osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_ERROR); osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ /****f* opensm: SM/sm_mad_ctrl_send_err_cb * NAME * sm_mad_ctrl_send_err_cb * * DESCRIPTION * This is the callback from the transport layer for send errors * on MADs that were expecting a response. * * SYNOPSIS */ static void sm_mad_ctrl_send_err_cb(IN void *context, IN osm_madw_t * p_madw) { osm_sm_mad_ctrl_t *p_ctrl = context; ib_api_status_t status; ib_smp_t *p_smp; OSM_LOG_ENTER(p_ctrl->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: " "MAD completed in error (%s): " "%s(%s), attr_mod 0x%x, TID 0x%" PRIx64 "\n", ib_get_err_str(p_madw->status), ib_get_sm_method_str(p_smp->method), ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->trans_id)); /* If this was a SubnSet MAD, then this error might indicate a problem in configuring the subnet. In this case - need to mark that there was such a problem. The subnet will not be up, and the next sweep should be a heavy sweep as well. */ if (p_smp->method == IB_MAD_METHOD_SET && (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO || p_smp->attr_id == IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO || p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL || p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO || p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL || p_smp->attr_id == IB_MAD_ATTR_P_KEY_TABLE)) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: " "Set method failed for attribute 0x%X (%s)\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); p_ctrl->p_subn->subnet_initialization_error = TRUE; } else if (p_madw->status == IB_TIMEOUT && p_smp->method == IB_MAD_METHOD_GET) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3120: " "Timeout while getting attribute 0x%X (%s); " "Possible mis-set mkey?\n", cl_ntoh16(p_smp->attr_id), ib_get_sm_attr_str(p_smp->attr_id)); } osm_dump_dr_smp_v2(p_ctrl->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE); /* Since we did not get any response we suspect the DR path used for the target port. Find it and replace it with an alternate path. This is true only if the destination lid is not 0xFFFF, since then we are aiming for a specific path and not specific destination lid. */ /* For now - do not add the alternate dr path to the release */ #if 0 if (p_madw->mad_addr.dest_lid != 0xFFFF) { osm_physp_t *p_physp = osm_get_physp_by_mad_addr(p_ctrl->p_log, p_ctrl->p_subn, &(p_madw-> mad_addr)); if (!p_physp) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: " "Failed to find the corresponding phys port\n"); } else { osm_physp_replace_dr_path_with_alternate_dr_path (p_ctrl->p_log, p_ctrl->p_subn, p_physp, p_madw->h_bind); } } #endif /* An error occurred. No response was received to a request MAD. Retire the original request MAD. */ sm_mad_ctrl_update_wire_stats(p_ctrl); if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) { OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw))); status = cl_disp_post(p_ctrl->h_disp, osm_madw_get_err_msg(p_madw), p_madw, sm_mad_ctrl_disp_done_callback, p_ctrl); if (status != CL_SUCCESS) OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: " "Dispatcher post message failed (%s)\n", CL_STATUS_MSG(status)); } else /* No error message was provided, just retire the MAD. */ sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); OSM_LOG_EXIT(p_ctrl->p_log); } /* * PARAMETERS * * RETURN VALUES * * NOTES * * SEE ALSO *********/ void osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * p_ctrl) { CL_ASSERT(p_ctrl); memset(p_ctrl, 0, sizeof(*p_ctrl)); p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; } void osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * p_ctrl) { CL_ASSERT(p_ctrl); if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE) osm_vendor_unbind(p_ctrl->h_bind); cl_disp_unregister(p_ctrl->h_disp); } ib_api_status_t osm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * p_ctrl, IN osm_subn_t * p_subn, IN osm_mad_pool_t * p_mad_pool, IN osm_vl15_t * p_vl15, IN osm_vendor_t * p_vendor, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN cl_plock_t * p_lock, IN cl_dispatcher_t * p_disp) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); osm_sm_mad_ctrl_construct(p_ctrl); p_ctrl->p_subn = p_subn; p_ctrl->p_log = p_log; p_ctrl->p_disp = p_disp; p_ctrl->p_mad_pool = p_mad_pool; p_ctrl->p_vendor = p_vendor; p_ctrl->p_stats = p_stats; p_ctrl->p_lock = p_lock; p_ctrl->p_vl15 = p_vl15; p_ctrl->h_disp = cl_disp_register(p_disp, CL_DISP_MSGID_NONE, NULL, NULL); if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: " "Dispatcher registration failed\n"); status = IB_INSUFFICIENT_RESOURCES; goto Exit; } Exit: OSM_LOG_EXIT(p_log); return status; } ib_api_status_t osm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * p_ctrl, IN ib_net64_t port_guid) { osm_bind_info_t bind_info; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_ctrl->p_log); if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) { OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: " "Multiple binds not allowed\n"); status = IB_ERROR; goto Exit; } bind_info.class_version = 1; bind_info.is_report_processor = FALSE; bind_info.is_responder = TRUE; bind_info.is_trap_processor = TRUE; bind_info.mad_class = IB_MCLASS_SUBN_DIR; bind_info.port_guid = port_guid; bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE; bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE; bind_info.timeout = p_ctrl->p_subn->opt.transaction_timeout; bind_info.retries = p_ctrl->p_subn->opt.transaction_retries; OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, &bind_info, p_ctrl->p_mad_pool, sm_mad_ctrl_rcv_callback, sm_mad_ctrl_send_err_cb, p_ctrl); if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { status = IB_ERROR; OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: " "Vendor specific bind failed\n"); goto Exit; } Exit: OSM_LOG_EXIT(p_ctrl->p_log); return status; } opensm-3.3.20/opensm/osm_sm_state_mgr.c0000644000205000001450000004074212417743476015045 00000000000000/* * Copyright (c) 2002-2013 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2013, Oracle and/or its affiliates. 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 osm_sm_state_mgr_t. * This file implements the SM State Manager object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_SM_STATE_MGR_C #include #include #include #include #include #include #include #include #include #include #include #include void osm_report_sm_state(osm_sm_t * sm) { char buf[64]; const char *state_str = osm_get_sm_mgr_state_str(sm->p_subn->sm_state); osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "Entering %s state\n", state_str); snprintf(buf, sizeof(buf), "ENTERING SM %s STATE", state_str); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, buf); } static boolean_t sm_state_mgr_send_master_sm_info_req(osm_sm_t * sm, uint8_t sm_state) { osm_madw_context_t context; const osm_port_t *p_port; ib_api_status_t status; osm_dr_path_t dr_path; ib_net64_t guid; boolean_t sent_req = FALSE; OSM_LOG_ENTER(sm->p_log); memset(&context, 0, sizeof(context)); if (sm_state == IB_SMINFO_STATE_STANDBY) { /* * We are in STANDBY state - this means we need to poll the * master SM (according to master_guid). * Send a query of SubnGet(SMInfo) to the subn * master_sm_base_lid object. */ guid = sm->master_sm_guid; } else { /* * We are not in STANDBY - this means we are in MASTER state - * so we need to poll the SM that is saved in polling_sm_guid * under sm. * Send a query of SubnGet(SMInfo) to that SM. */ guid = sm->polling_sm_guid; } /* Verify that SM is not polling itself */ if (guid == sm->p_subn->sm_port_guid) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "OpenSM doesn't poll itself\n"); goto Exit; } p_port = osm_get_port_by_guid(sm->p_subn, guid); if (p_port == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3203: " "No port object for GUID 0x%016" PRIx64 "\n", cl_ntoh64(guid)); goto Exit; } context.smi_context.port_guid = guid; context.smi_context.set_method = FALSE; memcpy(&dr_path, osm_physp_get_dr_path_ptr(p_port->p_physp), sizeof(osm_dr_path_t)); status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_SM_INFO, 0, FALSE, ib_port_info_get_m_key(&p_port->p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3204: " "Failure requesting SMInfo (%s)\n", ib_get_err_str(status)); else sent_req = TRUE; Exit: OSM_LOG_EXIT(sm->p_log); return (sent_req); } static void sm_state_mgr_start_polling(osm_sm_t * sm) { uint32_t timeout; cl_status_t cl_status; OSM_LOG_ENTER(sm->p_log); /* * Init the retry_number back to zero - need to restart counting */ sm->retry_number = 0; /* * Send a SubnGet(SMInfo) query to the current (or new) master found. */ CL_PLOCK_ACQUIRE(sm->p_lock); timeout = sm->p_subn->opt.sminfo_polling_timeout; sm_state_mgr_send_master_sm_info_req(sm, sm->p_subn->sm_state); CL_PLOCK_RELEASE(sm->p_lock); /* * Start a timer that will wake up every sminfo_polling_timeout milliseconds. * The callback of the timer will send a SubnGet(SMInfo) to the Master SM * and restart the timer */ cl_status = cl_timer_start(&sm->polling_timer, timeout); if (cl_status != CL_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3210: " "Failed to start polling timer\n"); OSM_LOG_EXIT(sm->p_log); } void osm_sm_state_mgr_polling_callback(IN void *context) { osm_sm_t *sm = context; uint32_t timeout; cl_status_t cl_status; uint8_t sm_state; OSM_LOG_ENTER(sm->p_log); cl_spinlock_acquire(&sm->state_lock); sm_state = sm->p_subn->sm_state; cl_spinlock_release(&sm->state_lock); CL_PLOCK_ACQUIRE(sm->p_lock); timeout = sm->p_subn->opt.sminfo_polling_timeout; /* * We can be here in one of two cases: * 1. We are a STANDBY sm polling on the master SM. * 2. We are a MASTER sm, waiting for a handover from a remote master sm. * If we are not in one of these cases - don't need to restart the poller. */ if (!((sm_state == IB_SMINFO_STATE_MASTER && sm->polling_sm_guid != 0) || sm_state == IB_SMINFO_STATE_STANDBY)) { CL_PLOCK_RELEASE(sm->p_lock); goto Exit; } /* * If we are a STANDBY sm and the osm_exit_flag is set, then let's * signal the subnet_up. This is relevant for the case of running only * once. In that case - the program is stuck until this signal is * received. In other cases - it is not relevant whether or not the * signal is on - since we are currently in exit flow */ if (sm_state == IB_SMINFO_STATE_STANDBY && osm_exit_flag) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Signalling subnet_up_event\n"); cl_event_signal(&sm->subnet_up_event); goto Exit; } /* * If retry number reached the max_retry_number in the subnet opt - call * osm_sm_state_mgr_process with signal OSM_SM_SIGNAL_POLLING_TIMEOUT */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "SM State %d (%s), Retry number:%d\n", sm->p_subn->sm_state, osm_get_sm_mgr_state_str(sm->p_subn->sm_state), sm->retry_number); if (sm->retry_number > sm->p_subn->opt.polling_retry_number) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Reached polling_retry_number value in retry_number. " "Go to DISCOVERY state\n"); osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_POLLING_TIMEOUT); goto Exit; } /* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */ if (sm_state_mgr_send_master_sm_info_req(sm, sm_state)) { /* Request sent, increment the retry number */ sm->retry_number++; } CL_PLOCK_RELEASE(sm->p_lock); /* restart the timer */ cl_status = cl_timer_start(&sm->polling_timer, timeout); if (cl_status != CL_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3211: " "Failed to restart polling timer\n"); Exit: OSM_LOG_EXIT(sm->p_log); } static void sm_state_mgr_signal_error(osm_sm_t * sm, IN osm_sm_signal_t signal) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3207: " "Invalid signal %s in state %s\n", osm_get_sm_mgr_signal_str(signal), osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); } void osm_sm_state_mgr_signal_master_is_alive(osm_sm_t * sm) { OSM_LOG_ENTER(sm->p_log); sm->retry_number = 0; OSM_LOG_EXIT(sm->p_log); } ib_api_status_t osm_sm_state_mgr_process(osm_sm_t * sm, IN osm_sm_signal_t signal) { ib_api_status_t status = IB_SUCCESS; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); /* * The state lock prevents many race conditions from screwing * up the state transition process. */ cl_spinlock_acquire(&sm->state_lock); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received signal %s in state %s\n", osm_get_sm_mgr_signal_str(signal), osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); switch (sm->p_subn->sm_state) { case IB_SMINFO_STATE_DISCOVERING: switch (signal) { case OSM_SM_SIGNAL_DISCOVERY_COMPLETED: /* * Update the state of the SM to MASTER */ /* Turn on the first_time_master_sweep flag */ sm->p_subn->sm_state = IB_SMINFO_STATE_MASTER; osm_report_sm_state(sm); /* * Make sure to set the subnet master_sm_base_lid * to the sm_base_lid value */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->p_subn->first_time_master_sweep = TRUE; sm->p_subn->master_sm_base_lid = sm->p_subn->sm_base_lid; CL_PLOCK_RELEASE(sm->p_lock); break; case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: /* * Finished all discovery actions - move to STANDBY * start the polling */ sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; osm_report_sm_state(sm); /* * Since another SM is doing the LFT config - we should not * ignore the results of it */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->p_subn->ignore_existing_lfts = FALSE; CL_PLOCK_RELEASE(sm->p_lock); sm_state_mgr_start_polling(sm); break; case OSM_SM_SIGNAL_HANDOVER: /* * Signal for a new sweep. We need to discover the other SM. * If we already discovered this SM, and got the * HANDOVER - this means the remote SM is of lower priority. * In this case we will stop polling it (since it is a lower * priority SM in STANDBY state). */ osm_sm_signal(sm, OSM_SIGNAL_SWEEP); break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_STANDBY: switch (signal) { case OSM_SM_SIGNAL_POLLING_TIMEOUT: case OSM_SM_SIGNAL_DISCOVER: /* * case 1: Polling timeout occured - this means that the Master SM * is no longer alive. * case 2: Got a signal to move to DISCOVERING * Move to DISCOVERING state and start sweeping */ sm->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING; osm_report_sm_state(sm); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->p_subn->coming_out_of_standby = TRUE; CL_PLOCK_RELEASE(sm->p_lock); osm_sm_signal(sm, OSM_SIGNAL_SWEEP); break; case OSM_SM_SIGNAL_DISABLE: /* * Update the state to NOT_ACTIVE */ sm->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE; osm_report_sm_state(sm); break; case OSM_SM_SIGNAL_HANDOVER: /* * Update the state to MASTER, and start sweeping * OPTIONAL: send ACKNOWLEDGE */ /* Turn on the force_first_time_master_sweep flag */ /* We want full reconfiguration to occur on the first */ /* master sweep of this SM */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); /* * Make sure to set the subnet master_sm_base_lid * to the sm_base_lid value */ sm->p_subn->master_sm_base_lid = sm->p_subn->sm_base_lid; sm->p_subn->force_first_time_master_sweep = TRUE; CL_PLOCK_RELEASE(sm->p_lock); sm->p_subn->sm_state = IB_SMINFO_STATE_MASTER; osm_report_sm_state(sm); osm_sm_signal(sm, OSM_SIGNAL_SWEEP); break; case OSM_SM_SIGNAL_ACKNOWLEDGE: /* * Do nothing - already moved to STANDBY */ break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_NOTACTIVE: switch (signal) { case OSM_SM_SIGNAL_STANDBY: /* * Update the state to STANDBY * start the polling */ sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; osm_report_sm_state(sm); sm_state_mgr_start_polling(sm); break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_MASTER: switch (signal) { case OSM_SM_SIGNAL_POLLING_TIMEOUT: /* * We received a polling timeout - this means that we * waited for a remote master sm to send us a handover, * but didn't get it, and didn't get a response from * that remote sm. * We want to force a heavy sweep - hopefully this * occurred because the remote sm died, and we'll find * this out and configure the subnet after a heavy sweep. * We also want to clear the polling_sm_guid - since * we are done polling on that remote sm - we are * sweeping again. */ case OSM_SM_SIGNAL_HANDOVER: /* * If we received a handover in a master state - then we * want to force a heavy sweep. This means that either * we are in a sweep currently - in this case - no * change, or we are in idle state - since we * recognized a master SM before - so we want to make a * heavy sweep and reconfigure the new subnet. * We also want to clear the polling_sm_guid - since * we are done polling on that remote sm - we got a * handover from it. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Forcing heavy sweep. Received signal %s\n", osm_get_sm_mgr_signal_str(signal)); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->polling_sm_guid = 0; sm->p_subn->force_first_time_master_sweep = TRUE; CL_PLOCK_RELEASE(sm->p_lock); osm_sm_signal(sm, OSM_SIGNAL_SWEEP); break; case OSM_SM_SIGNAL_HANDOVER_SENT: /* * Just sent a HANDOVER signal - move to STANDBY * start the polling */ sm->p_subn->sm_state = IB_SMINFO_STATE_STANDBY; osm_report_sm_state(sm); sm_state_mgr_start_polling(sm); break; case OSM_SM_SIGNAL_WAIT_FOR_HANDOVER: /* * We found a remote master SM, and we are waiting for * it to handover the mastership to us. Need to start * polling that SM, to make sure it is alive, if it * isn't - then we should move back to discovering, * since something must have happened to it. */ sm_state_mgr_start_polling(sm); break; case OSM_SM_SIGNAL_DISCOVER: sm->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING; osm_report_sm_state(sm); break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3208: " "Invalid state %s\n", osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); } cl_spinlock_release(&sm->state_lock); OSM_LOG_EXIT(sm->p_log); return status; } ib_api_status_t osm_sm_state_mgr_check_legality(osm_sm_t * sm, IN osm_sm_signal_t signal) { ib_api_status_t status = IB_SUCCESS; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); /* * The state lock prevents many race conditions from screwing * up the state transition process. */ cl_spinlock_acquire(&sm->state_lock); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received signal %s in state %s\n", osm_get_sm_mgr_signal_str(signal), osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); switch (sm->p_subn->sm_state) { case IB_SMINFO_STATE_DISCOVERING: switch (signal) { case OSM_SM_SIGNAL_DISCOVERY_COMPLETED: case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED: case OSM_SM_SIGNAL_HANDOVER: status = IB_SUCCESS; break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_STANDBY: switch (signal) { case OSM_SM_SIGNAL_POLLING_TIMEOUT: case OSM_SM_SIGNAL_DISCOVER: case OSM_SM_SIGNAL_DISABLE: case OSM_SM_SIGNAL_HANDOVER: case OSM_SM_SIGNAL_ACKNOWLEDGE: status = IB_SUCCESS; break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_NOTACTIVE: switch (signal) { case OSM_SM_SIGNAL_STANDBY: status = IB_SUCCESS; break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; case IB_SMINFO_STATE_MASTER: switch (signal) { case OSM_SM_SIGNAL_HANDOVER: case OSM_SM_SIGNAL_HANDOVER_SENT: status = IB_SUCCESS; break; default: sm_state_mgr_signal_error(sm, signal); status = IB_INVALID_PARAMETER; break; } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3209: " "Invalid state %s\n", osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); status = IB_INVALID_PARAMETER; } cl_spinlock_release(&sm->state_lock); OSM_LOG_EXIT(sm->p_log); return status; } opensm-3.3.20/opensm/osm_state_mgr.c0000644000205000001450000015445612720551023014334 00000000000000/* * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_state_mgr_t. * This file implements the State Manager object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_STATE_MGR_C #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern void osm_drop_mgr_process(IN osm_sm_t * sm); extern int osm_qos_setup(IN osm_opensm_t * p_osm); extern int osm_pkey_mgr_process(IN osm_opensm_t * p_osm); extern int osm_mcast_mgr_process(IN osm_sm_t * sm, boolean_t config_all); extern int osm_link_mgr_process(IN osm_sm_t * sm, IN uint8_t state); extern void osm_guid_mgr_process(IN osm_sm_t * sm); static void state_mgr_up_msg(IN const osm_sm_t * sm) { /* * This message should be written only once - when the * SM moves to Master state and the subnet is up for * the first time. */ osm_log_v2(sm->p_log, sm->p_subn->first_time_master_sweep ? OSM_LOG_SYS : OSM_LOG_INFO, FILE_ID, "SUBNET UP\n"); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, sm->p_subn->opt.sweep_interval ? "SUBNET UP" : "SUBNET UP (sweep disabled)"); } static void state_mgr_reset_node_count(IN cl_map_item_t * p_map_item, IN void *context) { osm_node_t *p_node = (osm_node_t *) p_map_item; p_node->discovery_count = 0; memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size); } static void state_mgr_reset_port_count(IN cl_map_item_t * p_map_item, IN void *context) { osm_port_t *p_port = (osm_port_t *) p_map_item; p_port->discovery_count = 0; } static void state_mgr_reset_switch_count(IN cl_map_item_t * p_map_item, IN void *context) { osm_switch_t *p_sw = (osm_switch_t *) p_map_item; if (p_sw->max_lid_ho != 0) p_sw->need_update = 1; } static void state_mgr_get_sw_info(IN cl_map_item_t * p_object, IN void *context) { osm_node_t *p_node; osm_physp_t *p_physp; osm_dr_path_t *p_dr_path; osm_madw_context_t mad_context; osm_switch_t *const p_sw = (osm_switch_t *) p_object; osm_sm_t *sm = context; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); p_node = p_sw->p_node; p_physp = osm_node_get_physp_ptr(p_node, 0); p_dr_path = osm_physp_get_dr_path_ptr(p_physp); memset(&mad_context, 0, sizeof(mad_context)); mad_context.si_context.node_guid = osm_node_get_node_guid(p_node); mad_context.si_context.set_method = FALSE; mad_context.si_context.light_sweep = TRUE; mad_context.si_context.lft_top_change = FALSE; status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_SWITCH_INFO, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3304: " "Request for SwitchInfo from 0x%" PRIx64 " failed (%s)\n", cl_ntoh64(osm_node_get_node_guid(p_node)), ib_get_err_str(status)); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** Initiate a remote port info request for the given physical port **********************************************************************/ static void state_mgr_get_remote_port_info(IN osm_sm_t * sm, IN osm_physp_t * p_physp) { osm_dr_path_t *p_dr_path; osm_dr_path_t rem_node_dr_path; osm_madw_context_t mad_context; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); /* generate a dr path leaving on the physp to the remote node */ p_dr_path = osm_physp_get_dr_path_ptr(p_physp); memcpy(&rem_node_dr_path, p_dr_path, sizeof(osm_dr_path_t)); if (osm_dr_path_extend(&rem_node_dr_path, osm_physp_get_port_num(p_physp))) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332D: " "DR path with hop count %d couldn't be extended " "so skipping PortInfo query\n", p_dr_path->hop_count); goto Exit; } memset(&mad_context, 0, sizeof(mad_context)); mad_context.pi_context.node_guid = osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp)); mad_context.pi_context.port_guid = p_physp->port_guid; mad_context.pi_context.set_method = FALSE; mad_context.pi_context.light_sweep = TRUE; mad_context.pi_context.active_transition = FALSE; mad_context.pi_context.client_rereg = FALSE; /* note that with some negative logic - if the query failed it means * that there is no point in going to heavy sweep */ status = osm_req_get(sm, &rem_node_dr_path, IB_MAD_ATTR_PORT_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &mad_context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332E: " "Request for remote PortInfo from 0x%" PRIx64 " failed (%s)\n", cl_ntoh64(p_physp->port_guid), ib_get_err_str(status)); Exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** Initiates a thorough sweep of the subnet. Used when there is suspicion that something on the subnet has changed. **********************************************************************/ static ib_api_status_t state_mgr_sweep_hop_0(IN osm_sm_t * sm) { ib_api_status_t status; osm_dr_path_t dr_path; osm_bind_handle_t h_bind; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; OSM_LOG_ENTER(sm->p_log); memset(path_array, 0, sizeof(path_array)); /* * First, get the bind handle. */ h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl); if (h_bind != OSM_BIND_INVALID_HANDLE) { OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING HEAVY SWEEP"); /* * Start the sweep by clearing the port counts, then * get our own NodeInfo at 0 hops. */ CL_PLOCK_ACQUIRE(sm->p_lock); cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_reset_node_count, sm); cl_qmap_apply_func(&sm->p_subn->port_guid_tbl, state_mgr_reset_port_count, sm); cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl, state_mgr_reset_switch_count, sm); /* Set the in_sweep_hop_0 flag in subn to be TRUE. * This will indicate the sweeping not to continue beyond the * the current node. * This is relevant for the case of SM on switch, since in the * switch info we need to signal somehow not to continue * the sweeping. */ sm->p_subn->in_sweep_hop_0 = TRUE; CL_PLOCK_RELEASE(sm->p_lock); osm_dr_path_init(&dr_path, 0, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, NULL); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3305: " "Request for NodeInfo failed (%s)\n", ib_get_err_str(status)); } else { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No bound ports. Deferring sweep...\n"); status = IB_INVALID_STATE; } OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** Clear out all existing port lid assignments **********************************************************************/ static ib_api_status_t state_mgr_clean_known_lids(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; cl_ptr_vector_t *p_vec = &(sm->p_subn->port_lid_tbl); uint32_t i; OSM_LOG_ENTER(sm->p_log); /* we need a lock here! */ CL_PLOCK_ACQUIRE(sm->p_lock); for (i = 0; i < cl_ptr_vector_get_size(p_vec); i++) cl_ptr_vector_set(p_vec, i, NULL); CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** Clear SA cache **********************************************************************/ static ib_api_status_t state_mgr_sa_clean(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; cl_qmap_t *p_port_guid_tbl; osm_assigned_guids_t *p_assigned_guids, *p_next_assigned_guids; osm_alias_guid_t *p_alias_guid, *p_next_alias_guid; osm_mcm_port_t *mcm_port; osm_subn_t * p_subn; osm_port_t *p_port; osm_infr_t *p_infr; osm_svcr_t *p_svcr; OSM_LOG_ENTER(sm->p_log); p_subn = sm->p_subn; /* we need a lock here! */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); if (p_subn->opt.drop_event_subscriptions) { /* Clean InformInfo records */ p_infr = (osm_infr_t *) cl_qlist_remove_head(&p_subn->sa_infr_list); while (p_infr != (osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) { osm_infr_delete(p_infr); p_infr = (osm_infr_t *) cl_qlist_remove_head(&p_subn->sa_infr_list); } /* For now, treat Service Records in same category as InformInfos */ /* Clean Service records */ p_svcr = (osm_svcr_t *) cl_qlist_remove_head(&p_subn->sa_sr_list); while (p_svcr != (osm_svcr_t *) cl_qlist_end(&p_subn->sa_sr_list)) { osm_svcr_delete(p_svcr); p_svcr = (osm_svcr_t *) cl_qlist_remove_head(&p_subn->sa_sr_list); } } /* Clean Multicast member list on each port */ p_port_guid_tbl = &p_subn->port_guid_tbl; for (p_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); p_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl); p_port = (osm_port_t *) cl_qmap_next(&p_port->map_item)) { while (!cl_is_qlist_empty(&p_port->mcm_list)) { mcm_port = cl_item_obj(cl_qlist_head(&p_port->mcm_list), mcm_port, list_item); osm_mgrp_delete_port(p_subn, sm->p_log, mcm_port->mgrp, p_port); } /* Hack - clean alias guid table from physp */ free(p_port->p_physp->p_guids); p_port->p_physp->p_guids = NULL; } /* Clean Alias Guid work objects */ while (cl_qlist_count(&p_subn->alias_guid_list)) osm_guid_work_obj_delete((osm_guidinfo_work_obj_t *) cl_qlist_remove_head(&p_subn->alias_guid_list)); /* Clean Assigned GUIDs table */ p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_head(&p_subn->assigned_guids_tbl); while (p_next_assigned_guids != (osm_assigned_guids_t *) cl_qmap_end(&p_subn->assigned_guids_tbl)) { p_assigned_guids = p_next_assigned_guids; p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_next(&p_assigned_guids->map_item); cl_qmap_remove_item(&p_subn->assigned_guids_tbl, &p_assigned_guids->map_item); osm_assigned_guids_delete(&p_assigned_guids); } /* Clean Alias GUIDs table */ p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&p_subn->alias_port_guid_tbl); while (p_next_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&p_subn->alias_port_guid_tbl)) { p_alias_guid = p_next_alias_guid; p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid->map_item); if (osm_alias_guid_get_alias_guid(p_alias_guid) != osm_alias_guid_get_base_guid(p_alias_guid)) { /* Clean if it's not base port GUID */ cl_qmap_remove_item(&p_subn->alias_port_guid_tbl, &p_alias_guid->map_item); osm_alias_guid_delete(&p_alias_guid); } } p_subn->p_osm->sa.dirty = TRUE; CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** Notifies the transport layer that the local LID has changed, which give it a chance to update address vectors, etc.. **********************************************************************/ static ib_api_status_t state_mgr_notify_lid_change(IN osm_sm_t * sm) { ib_api_status_t status; osm_bind_handle_t h_bind; OSM_LOG_ENTER(sm->p_log); /* * First, get the bind handle. */ h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl); if (h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3306: " "No bound ports\n"); status = IB_ERROR; goto Exit; } /* * Notify the transport layer that we changed the local LID. */ status = osm_vendor_local_lid_change(h_bind); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3307: " "Vendor LID update failed (%s)\n", ib_get_err_str(status)); Exit: OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** Returns true if the SM port is down. The SM's port object must exist in the port_guid table. **********************************************************************/ static boolean_t state_mgr_is_sm_port_down(IN osm_sm_t * sm) { ib_net64_t port_guid; osm_port_t *p_port; osm_physp_t *p_physp; uint8_t state; OSM_LOG_ENTER(sm->p_log); port_guid = sm->p_subn->sm_port_guid; /* * If we don't know our own port guid yet, assume the port is down. */ if (port_guid == 0) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3308: " "SM port GUID unknown\n"); state = IB_LINK_DOWN; goto Exit; } CL_ASSERT(port_guid); CL_PLOCK_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3309: " "SM port with GUID:%016" PRIx64 " is unknown\n", cl_ntoh64(port_guid)); state = IB_LINK_DOWN; CL_PLOCK_RELEASE(sm->p_lock); goto Exit; } p_physp = p_port->p_physp; CL_ASSERT(p_physp); if (p_port->p_node->sw && !ib_switch_info_is_enhanced_port0(&p_port->p_node->sw->switch_info)) state = IB_LINK_ACTIVE; /* base SP0 */ else state = osm_physp_get_port_state(p_physp); if (!p_port->discovery_count) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 330A: Failed to discover SM port\n"); state = IB_LINK_DOWN; } CL_PLOCK_RELEASE(sm->p_lock); Exit: OSM_LOG_EXIT(sm->p_log); return (state == IB_LINK_DOWN); } /********************************************************************** Sweeps the node 1 hop away. This sets off a "chain reaction" that causes discovery of the subnet. Used when there is suspicion that something on the subnet has changed. **********************************************************************/ static ib_api_status_t state_mgr_sweep_hop_1(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; osm_madw_context_t context; osm_node_t *p_node; osm_port_t *p_port; osm_dr_path_t hop_1_path; ib_net64_t port_guid; uint8_t port_num; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; uint8_t num_ports; osm_physp_t *p_ext_physp; OSM_LOG_ENTER(sm->p_log); /* * First, get our own port and node objects. */ port_guid = sm->p_subn->sm_port_guid; CL_ASSERT(port_guid); /* Set the in_sweep_hop_0 flag in subn to be FALSE. * This will indicate the sweeping to continue beyond the * the current node. * This is relevant for the case of SM on switch, since in the * switch info we need to signal that the sweeping should * continue through the switch. */ sm->p_subn->in_sweep_hop_0 = FALSE; p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: " "No SM port object\n"); status = IB_ERROR; goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); port_num = ib_node_info_get_local_port_num(&p_node->node_info); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Probing hop 1 on local port %u\n", port_num); memset(path_array, 0, sizeof(path_array)); /* the hop_1 operations depend on the type of our node. * Currently - legal nodes that can host SM are SW and CA */ switch (osm_node_get_type(p_node)) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, 1, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: " "Request for NodeInfo failed (%s)\n", ib_get_err_str(status)); break; case IB_NODE_TYPE_SWITCH: /* Need to go over all the ports of the switch, and send a * node_info from them. This doesn't include the port 0 of the * switch, which hosts the SM. * Note: We'll send another switchInfo on port 0, since if no * ports are connected, we still want to get some response, and * have the subnet come up. */ num_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < num_ports; port_num++) { /* go through the port only if the port is not DOWN */ p_ext_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_ext_physp && ib_port_info_get_port_state (&(p_ext_physp->port_info)) > IB_LINK_DOWN) { memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, 1, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3312: " "Request for NodeInfo failed (%s)\n", ib_get_err_str(status)); } } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3313: Unknown node type %d (%s)\n", osm_node_get_type(p_node), p_node->print_desc); } Exit: OSM_LOG_EXIT(sm->p_log); return status; } static void query_sm_info(cl_map_item_t * item, void *cxt) { osm_madw_context_t context; osm_remote_sm_t *r_sm = cl_item_obj(item, r_sm, map_item); osm_sm_t *sm = cxt; ib_api_status_t ret; osm_port_t *p_port; p_port= osm_get_port_by_guid(sm->p_subn, r_sm->smi.guid); if (p_port == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3340: " "No port object on given sm object\n"); return; } context.smi_context.port_guid = r_sm->smi.guid; context.smi_context.set_method = FALSE; context.smi_context.light_sweep = TRUE; ret = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_port->p_physp), IB_MAD_ATTR_SM_INFO, 0, FALSE, ib_port_info_get_m_key(&p_port->p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (ret != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3314: " "Failure requesting SMInfo (%s)\n", ib_get_err_str(ret)); } static void state_mgr_reset_state_change_bit(IN cl_map_item_t * obj, IN void *context) { osm_madw_context_t mad_context; osm_switch_t *p_sw = (osm_switch_t *) obj; osm_sm_t *sm = context; osm_node_t *p_node; osm_physp_t *p_physp; osm_dr_path_t *p_path; ib_api_status_t status; ib_switch_info_t si; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); p_node = p_sw->p_node; CL_ASSERT(p_node); p_physp = osm_node_get_physp_ptr(p_node, 0); p_path = osm_physp_get_dr_path_ptr(p_physp); if (!ib_switch_info_get_state_change(&p_sw->switch_info)) goto exit; si = p_sw->switch_info; ib_switch_info_state_change_set(&si); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Resetting PortStateChange on switch GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); mad_context.si_context.light_sweep = FALSE; mad_context.si_context.node_guid = osm_node_get_node_guid(p_node); mad_context.si_context.set_method = TRUE; mad_context.si_context.lft_top_change = FALSE; status = osm_req_set(sm, p_path, (uint8_t *) &si, sizeof(si), IB_MAD_ATTR_SWITCH_INFO, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &mad_context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332A: " "Sending SwitchInfo attribute failed (%s)\n", ib_get_err_str(status)); exit: OSM_LOG_EXIT(sm->p_log); } static void state_mgr_update_node_desc(IN cl_map_item_t * obj, IN void *context) { osm_madw_context_t mad_context; osm_node_t *p_node = (osm_node_t *) obj; osm_sm_t *sm = context; osm_physp_t *p_physp = NULL; unsigned i, num_ports; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_node); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Updating NodeDesc for 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); /* get a physp to request from. */ num_ports = osm_node_get_num_physp(p_node); for (i = 0; i < num_ports; i++) if ((p_physp = osm_node_get_physp_ptr(p_node, i))) break; if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: " "Failed to find any valid physical port object.\n"); goto exit; } mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node); status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp), IB_MAD_ATTR_NODE_DESC, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &mad_context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331B: Failure initiating NodeDescription request " "(%s) to 0x%016" PRIx64 "\n", ib_get_err_str(status), cl_ntoh64(osm_node_get_node_guid(p_node))); exit: OSM_LOG_EXIT(sm->p_log); } void osm_reset_switch_state_change_bit(IN osm_opensm_t *osm) { CL_PLOCK_ACQUIRE(&osm->lock); cl_qmap_apply_func(&osm->subn.sw_guid_tbl, state_mgr_reset_state_change_bit, &osm->sm); CL_PLOCK_RELEASE(&osm->lock); } void osm_update_node_desc(IN osm_opensm_t *osm) { CL_PLOCK_ACQUIRE(&osm->lock); cl_qmap_apply_func(&osm->subn.node_guid_tbl, state_mgr_update_node_desc, &osm->sm); CL_PLOCK_RELEASE(&osm->lock); } /********************************************************************** During a light sweep, check each node to see if the node description is valid and if not issue a ND query. **********************************************************************/ static void state_mgr_get_node_desc(IN cl_map_item_t * obj, IN void *context) { osm_node_t *p_node = (osm_node_t *) obj; osm_sm_t *sm = context; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_node); if (p_node->print_desc && strcmp(p_node->print_desc, OSM_NODE_DESC_UNKNOWN)) /* if ND is valid, do nothing */ goto exit; OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3319: Unknown node description for node GUID " "0x%016" PRIx64 ". Reissuing ND query\n", cl_ntoh64(osm_node_get_node_guid(p_node))); state_mgr_update_node_desc(obj, context); exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** Initiates a lightweight sweep of the subnet. Used during normal sweeps after the subnet is up. **********************************************************************/ static ib_api_status_t state_mgr_light_sweep_start(IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; osm_bind_handle_t h_bind; cl_qmap_t *p_sw_tbl; cl_map_item_t *p_next; osm_node_t *p_node; osm_physp_t *p_physp; uint8_t port_num; OSM_LOG_ENTER(sm->p_log); p_sw_tbl = &sm->p_subn->sw_guid_tbl; /* * First, get the bind handle. */ h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl); if (h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No bound ports. Deferring sweep...\n"); status = IB_INVALID_STATE; goto _exit; } OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP"); CL_PLOCK_ACQUIRE(sm->p_lock); cl_qmap_apply_func(p_sw_tbl, state_mgr_get_sw_info, sm); CL_PLOCK_RELEASE(sm->p_lock); CL_PLOCK_ACQUIRE(sm->p_lock); cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_get_node_desc, sm); CL_PLOCK_RELEASE(sm->p_lock); /* now scan the list of physical ports that were not down but have no remote port */ CL_PLOCK_ACQUIRE(sm->p_lock); p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl); while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) { p_node = (osm_node_t *) p_next; p_next = cl_qmap_next(p_next); for (port_num = 1; port_num < osm_node_get_num_physp(p_node); port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (p_physp && (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) && !osm_physp_get_remote(p_physp)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: " "Unknown remote side for node 0x%016" PRIx64 " (%s) port %u. Adding to light sweep sampling list\n", cl_ntoh64(osm_node_get_node_guid (p_node)), p_node->print_desc, port_num); osm_dump_dr_path_v2(sm->p_log, osm_physp_get_dr_path_ptr (p_physp), FILE_ID, OSM_LOG_ERROR); state_mgr_get_remote_port_info(sm, p_physp); } } } cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm); CL_PLOCK_RELEASE(sm->p_lock); _exit: OSM_LOG_EXIT(sm->p_log); return status; } /********************************************************************** * Go over all the remote SMs (as updated in the sm_guid_tbl). * Find if there is a remote sm that is a master SM. * If there is a remote master SM - return a pointer to it, * else - return NULL. **********************************************************************/ static osm_remote_sm_t *state_mgr_exists_other_master_sm(IN osm_sm_t * sm) { cl_qmap_t *p_sm_tbl; osm_remote_sm_t *p_sm; osm_remote_sm_t *p_sm_res = NULL; osm_node_t *p_node; OSM_LOG_ENTER(sm->p_log); p_sm_tbl = &sm->p_subn->sm_guid_tbl; /* go over all the remote SMs */ for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl); p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl); p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) { /* If the sm is in MASTER state - return a pointer to it */ p_node = osm_get_node_by_guid(sm->p_subn, p_sm->smi.guid); if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Found remote master SM with guid:0x%016" PRIx64 " (node %s)\n", cl_ntoh64(p_sm->smi.guid), p_node ? p_node->print_desc : "UNKNOWN"); p_sm_res = p_sm; goto Exit; } } Exit: OSM_LOG_EXIT(sm->p_log); return p_sm_res; } /********************************************************************** * Go over all remote SMs (as updated in the sm_guid_tbl). * Find the one with the highest priority and lowest guid. * Compare this SM to the local SM. If the local SM is higher - * return NULL, if the remote SM is higher - return a pointer to it. **********************************************************************/ static osm_remote_sm_t *state_mgr_get_highest_sm(IN osm_sm_t * sm) { cl_qmap_t *p_sm_tbl; osm_remote_sm_t *p_sm = NULL; osm_remote_sm_t *p_highest_sm; uint8_t highest_sm_priority; ib_net64_t highest_sm_guid; osm_node_t *p_node; OSM_LOG_ENTER(sm->p_log); p_sm_tbl = &sm->p_subn->sm_guid_tbl; /* Start with the local sm as the standard */ p_highest_sm = NULL; highest_sm_priority = sm->p_subn->opt.sm_priority; highest_sm_guid = sm->p_subn->sm_port_guid; /* go over all the remote SMs */ for (p_sm = (osm_remote_sm_t *) cl_qmap_head(p_sm_tbl); p_sm != (osm_remote_sm_t *) cl_qmap_end(p_sm_tbl); p_sm = (osm_remote_sm_t *) cl_qmap_next(&p_sm->map_item)) { /* If the sm is in NOTACTIVE state - continue */ if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_NOTACTIVE) continue; if (osm_sm_is_greater_than(ib_sminfo_get_priority(&p_sm->smi), p_sm->smi.guid, highest_sm_priority, highest_sm_guid)) { /* the new p_sm is with higher priority - update the highest_sm */ /* to this sm */ p_highest_sm = p_sm; highest_sm_priority = ib_sminfo_get_priority(&p_sm->smi); highest_sm_guid = p_sm->smi.guid; } } if (p_highest_sm != NULL) { p_node = osm_get_node_by_guid(sm->p_subn, p_highest_sm->smi.guid); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Found higher priority SM with guid: %016" PRIx64 " (node %s)\n", cl_ntoh64(p_highest_sm->smi.guid), p_node ? p_node->print_desc : "UNKNOWN"); } OSM_LOG_EXIT(sm->p_log); return p_highest_sm; } /********************************************************************** * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the * remote_sm indicated. **********************************************************************/ static void state_mgr_send_handover(IN osm_sm_t * sm, IN osm_remote_sm_t * p_sm) { uint8_t payload[IB_SMP_DATA_SIZE]; ib_sm_info_t *p_smi = (ib_sm_info_t *) payload; osm_madw_context_t context; const osm_port_t *p_port; ib_api_status_t status; OSM_LOG_ENTER(sm->p_log); /* * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given. */ memset(&context, 0, sizeof(context)); p_port = osm_get_port_by_guid(sm->p_subn, p_sm->smi.guid); if (p_port == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3316: " "No port object on given remote_sm object\n"); goto Exit; } /* update the master_guid in the sm_state_mgr object according to */ /* the guid of the port where the new Master SM should reside. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Handing over mastership. Updating sm_state_mgr master_guid: %016" PRIx64 " (node %s)\n", cl_ntoh64(p_port->guid), p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN"); sm->master_sm_guid = p_port->guid; context.smi_context.port_guid = p_port->guid; context.smi_context.set_method = TRUE; memset(payload, 0, sizeof(payload)); p_smi->guid = sm->p_subn->sm_port_guid; p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent); p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state | sm->p_subn->opt.sm_priority << 4); /* * Return 0 for the SM key unless we authenticate the requester * as the master SM. */ if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to master SM with real sm_key\n"); p_smi->sm_key = sm->p_subn->opt.sm_key; } else { /* The requester is not authenticated as master - set sm_key to zero */ OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to SM not master with zero sm_key\n"); p_smi->sm_key = 0; } CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_port->p_physp), payload, sizeof(payload), IB_MAD_ATTR_SM_INFO, IB_SMINFO_ATTR_MOD_HANDOVER, FALSE, ib_port_info_get_m_key(&p_port->p_physp->port_info), CL_DISP_MSGID_NONE, &context); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3317: " "Failure requesting SMInfo (%s), remote SM at 0x%" PRIx64 " (node %s)\n", ib_get_err_str(status), cl_ntoh64(p_port->guid), p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN"); Exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** * Send Trap 64 on all new ports. **********************************************************************/ static void state_mgr_report_new_ports(IN osm_sm_t * sm) { ib_gid_t port_gid; ib_mad_notice_attr_t notice; ib_api_status_t status; ib_net64_t port_guid; cl_map_item_t *p_next; osm_port_t *p_port; uint16_t min_lid_ho; uint16_t max_lid_ho; OSM_LOG_ENTER(sm->p_log); CL_PLOCK_ACQUIRE(sm->p_lock); p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl); while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) { p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); if (!p_port->is_new) continue; port_guid = osm_port_get_guid(p_port); /* issue a notice - trap 64 (SM_GID_IN_SERVICE_TRAP) */ /* details of the notice */ notice.generic_type = 0x80 | IB_NOTICE_TYPE_SUBN_MGMT; /* is generic subn mgt type */ ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */ /* endport becomes reachable */ notice.g_or_v.generic.trap_num = CL_HTON16(SM_GID_IN_SERVICE_TRAP); /* 64 */ /* The sm_base_lid is saved in network order already. */ notice.issuer_lid = sm->p_subn->sm_base_lid; /* following C14-72.1.1 and table 119 p739 */ /* we need to provide the GID */ port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; port_gid.unicast.interface_id = port_guid; memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid), sizeof(ib_gid_t)); /* According to page 653 - the issuer gid in this case of trap * is the SM gid, since the SM is the initiator of this trap. */ notice.issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; notice.issuer_gid.unicast.interface_id = sm->p_subn->sm_port_guid; status = osm_report_notice(sm->p_log, sm->p_subn, ¬ice); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: " "Error sending trap reports on GUID:0x%016" PRIx64 " (%s)\n", port_gid.unicast.interface_id, ib_get_err_str(status)); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); OSM_LOG(sm->p_log, OSM_LOG_INFO, "Discovered new port with GUID:0x%016" PRIx64 " LID range [%u,%u] of node: %s\n", cl_ntoh64(port_gid.unicast.interface_id), min_lid_ho, max_lid_ho, p_port->p_node ? p_port->p_node-> print_desc : "UNKNOWN"); p_port->is_new = 0; } CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); } /********************************************************************** * Make sure that the lid_port_tbl of the subnet has only the ports * that are recognized, and in the correct lid place. There could be * errors if we wanted to assign a certain port with lid X, but that * request didn't reach the port. In this case port_lid_tbl will have * the port under lid X, though the port isn't updated with this lid. * We will run a new heavy sweep (since there were errors in the * initialization), but here we'll clean the database from incorrect * information. **********************************************************************/ static void state_mgr_check_tbl_consistency(IN osm_sm_t * sm) { cl_qmap_t *p_port_guid_tbl; osm_port_t *p_port; osm_port_t *p_next_port; cl_ptr_vector_t *p_port_lid_tbl; size_t max_lid, ref_size, curr_size, lid; osm_port_t *p_port_ref, *p_port_stored; cl_ptr_vector_t ref_port_lid_tbl; uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; OSM_LOG_ENTER(sm->p_log); if (sm->lid_mgr.dirty == FALSE) goto Exit; sm->lid_mgr.dirty = FALSE; cl_ptr_vector_construct(&ref_port_lid_tbl); cl_ptr_vector_init(&ref_port_lid_tbl, cl_ptr_vector_get_size(&sm->p_subn->port_lid_tbl), OSM_SUBNET_VECTOR_GROW_SIZE); p_port_guid_tbl = &sm->p_subn->port_guid_tbl; /* Let's go over all the ports according to port_guid_tbl, * and add the port to a reference port_lid_tbl. */ p_next_port = (osm_port_t *) cl_qmap_head(p_port_guid_tbl); while (p_next_port != (osm_port_t *) cl_qmap_end(p_port_guid_tbl)) { p_port = p_next_port; p_next_port = (osm_port_t *) cl_qmap_next(&p_next_port->map_item); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); for (lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++) cl_ptr_vector_set(&ref_port_lid_tbl, lid_ho, p_port); } p_port_lid_tbl = &sm->p_subn->port_lid_tbl; ref_size = cl_ptr_vector_get_size(&ref_port_lid_tbl); curr_size = cl_ptr_vector_get_size(p_port_lid_tbl); /* They should be the same, but compare it anyway */ max_lid = (ref_size > curr_size) ? ref_size : curr_size; for (lid = 1; lid < max_lid; lid++) { p_port_ref = NULL; p_port_stored = NULL; cl_ptr_vector_at(p_port_lid_tbl, lid, (void *)&p_port_stored); cl_ptr_vector_at(&ref_port_lid_tbl, lid, (void *)&p_port_ref); if (p_port_stored == p_port_ref) /* This is the "good" case - both entries are the * same for this lid. Nothing to do. */ continue; if (p_port_ref == NULL) { /* There is an object in the subnet database for this * lid, but no such object exists in the reference * port_list_tbl. This can occur if we wanted to assign * a certain port with some lid (different than the one * pre-assigned to it), and the port didn't get the * PortInfo Set request. Due to this, the port is * updated with its original lid in our database * rather than the new lid we wanted to give it. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3322: " "lid %zu is wrongly assigned to port 0x%016" PRIx64 " (\'%s\' port %u) in port_lid_tbl\n", lid, cl_ntoh64(osm_port_get_guid(p_port_stored)), p_port_stored->p_node->print_desc, p_port_stored->p_physp->port_num); } else if (p_port_stored == NULL) /* There is an object in the new database, but no * object in our subnet database. This is the matching * case of the prior check - the port still has its * original lid. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3323: " "port 0x%016" PRIx64 " (\'%s\' port %u)" " exists in new port_lid_tbl under lid %zu," " but missing in subnet port_lid_tbl db\n", cl_ntoh64(osm_port_get_guid(p_port_ref)), p_port_ref->p_node->print_desc, p_port_ref->p_physp->port_num, lid); else { /* if we reached here then p_port_stored != p_port_ref. * We were trying to set a lid to p_port_stored, but * it didn't reach it, and p_port_ref also didn't get * the lid update. */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3324: " "lid %zu has port 0x%016" PRIx64 " (\'%s\' port %u) in new port_lid_tbl db, " "and port 0x%016" PRIx64 " (\'%s\' port %u)" " in subnet port_lid_tbl db\n", lid, cl_ntoh64(osm_port_get_guid(p_port_ref)), p_port_ref->p_node->print_desc, p_port_ref->p_physp->port_num, cl_ntoh64(osm_port_get_guid(p_port_stored)), p_port_stored->p_node->print_desc, p_port_stored->p_physp->port_num); } /* * Clear the lid of the port in order to ignore it * in routing phase */ if (p_port_stored) { OSM_LOG(sm->p_log, OSM_LOG_INFO, "Clearing Lid for " "port 0x%016" PRIx64 "\n", cl_ntoh64(osm_port_get_guid(p_port_stored))); osm_port_clear_base_lid(p_port_stored); cl_ptr_vector_set(p_port_lid_tbl, lid, NULL); } /* Make sure we'll do another heavy sweep. */ sm->p_subn->subnet_initialization_error = TRUE; } cl_ptr_vector_destroy(&ref_port_lid_tbl); Exit: OSM_LOG_EXIT(sm->p_log); } static void check_switch_lft(cl_map_item_t * item, void *log) { osm_switch_t *sw = (osm_switch_t *) item; if (!sw->new_lft) return; if (memcmp(sw->lft, sw->new_lft, sw->max_lid_ho + 1)) osm_log_v2(log, OSM_LOG_ERROR, FILE_ID, "ERR 331D: " "LFT of switch 0x%016" PRIx64 " (%s) is not up to date\n", cl_ntoh64(sw->p_node->node_info.node_guid), sw->p_node->print_desc); } int wait_for_pending_transactions(osm_stats_t * stats) { #ifdef HAVE_LIBPTHREAD pthread_mutex_lock(&stats->mutex); while (stats->qp0_mads_outstanding && !osm_exit_flag) pthread_cond_wait(&stats->cond, &stats->mutex); pthread_mutex_unlock(&stats->mutex); #else while (1) { unsigned count = stats->qp0_mads_outstanding; if (!count || osm_exit_flag) break; cl_event_wait_on(&stats->event, EVENT_NO_TIMEOUT, TRUE); } #endif return osm_exit_flag; } static void do_sweep(osm_sm_t * sm) { ib_api_status_t status; osm_remote_sm_t *p_remote_sm; unsigned config_parsed = 0; if (sm->p_subn->force_first_time_master_sweep) { sm->p_subn->force_heavy_sweep = TRUE; sm->p_subn->coming_out_of_standby = TRUE; sm->p_subn->first_time_master_sweep = TRUE; sm->p_subn->force_first_time_master_sweep = FALSE; } /* after subnet initialization error, run heavy sweep */ if (sm->p_subn->subnet_initialization_error) sm->p_subn->force_heavy_sweep = TRUE; if (sm->p_subn->force_heavy_sweep) { if (osm_subn_rescan_conf_files(sm->p_subn) < 0) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331A: " "osm_subn_rescan_conf_file failed\n"); else config_parsed = 1; } if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER && sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING) return; if (sm->p_subn->coming_out_of_standby) { /* * Need to force re-write of sm_base_lid to all ports * to do that we want all the ports to be considered * foreign */ state_mgr_clean_known_lids(sm); /* * Need to clean SA cache when state changes to STANDBY * after handover. */ state_mgr_sa_clean(sm); /* * Need to reconfigure LFTs, PKEYs, and QoS on all switches * when coming out of STANDBY */ sm->p_subn->need_update = 1; } sm->master_sm_found = 0; /* * If we already have switches, then try a light sweep. * Otherwise, this is probably our first discovery pass * or we are connected in loopback. In both cases do a * heavy sweep. * Note: If we are connected in loopback we want a heavy * sweep, since we will not be getting any traps if there is * a lost connection. */ /* if we are in DISCOVERING state - this means it is either in * initializing or wake up from STANDBY - run the heavy sweep */ if (cl_qmap_count(&sm->p_subn->sw_guid_tbl) && sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING && sm->p_subn->opt.force_heavy_sweep == FALSE && sm->p_subn->force_heavy_sweep == FALSE && sm->p_subn->force_reroute == FALSE && sm->p_subn->subnet_initialization_error == FALSE && (state_mgr_light_sweep_start(sm) == IB_SUCCESS)) { if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; if (!sm->p_subn->force_heavy_sweep) { if (sm->p_subn->opt.sa_db_dump && !osm_sa_db_file_dump(sm->p_subn->p_osm)) osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_SA_DB_DUMPED, NULL); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "LIGHT SWEEP COMPLETE"); return; } } /* * Unicast cache should be invalidated when subnet re-route is * requested, and when OpenSM comes out of standby state. */ if (sm->p_subn->opt.use_ucast_cache && (sm->p_subn->force_reroute || sm->p_subn->coming_out_of_standby)) osm_ucast_cache_invalidate(&sm->ucast_mgr); /* * If we don't need to do a heavy sweep and we want to do a reroute, * just reroute only. */ if (cl_qmap_count(&sm->p_subn->sw_guid_tbl) && sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING && sm->p_subn->opt.force_heavy_sweep == FALSE && sm->p_subn->force_heavy_sweep == FALSE && sm->p_subn->force_reroute == TRUE && sm->p_subn->subnet_initialization_error == FALSE) { /* Reset flag */ sm->p_subn->force_reroute = FALSE; /* Re-program the switches fully */ sm->p_subn->ignore_existing_lfts = TRUE; if (osm_ucast_mgr_process(&sm->ucast_mgr)) { OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "REROUTE FAILED"); return; } osm_qos_setup(sm->p_subn->p_osm); /* Reset flag */ sm->p_subn->ignore_existing_lfts = FALSE; if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; osm_congestion_control_setup(sm->p_subn->p_osm); if (osm_congestion_control_wait_pending_transactions(sm->p_subn->p_osm)) return; if (!sm->p_subn->subnet_initialization_error) { OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "REROUTE COMPLETE"); osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_UCAST_ROUTING_DONE, (void *) UCAST_ROUTING_REROUTE); return; } } osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_HEAVY_SWEEP_START, NULL); /* go to heavy sweep */ repeat_discovery: /* First of all - unset all flags */ sm->p_subn->force_heavy_sweep = FALSE; sm->p_subn->force_reroute = FALSE; sm->p_subn->subnet_initialization_error = FALSE; /* Reset tracking values in case limiting component got removed * from fabric. */ sm->p_subn->min_ca_mtu = IB_MAX_MTU; sm->p_subn->min_ca_rate = IB_MAX_RATE; sm->p_subn->min_data_vls = IB_MAX_NUM_VLS - 1; sm->p_subn->min_sw_data_vls = IB_MAX_NUM_VLS - 1; /* rescan configuration updates */ if (!config_parsed && osm_subn_rescan_conf_files(sm->p_subn) < 0) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331A: " "osm_subn_rescan_conf_file failed\n"); if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER) sm->p_subn->need_update = 1; status = state_mgr_sweep_hop_0(sm); if (status != IB_SUCCESS || wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; if (state_mgr_is_sm_port_down(sm) == TRUE) { if (sm->p_subn->last_sm_port_state) { sm->p_subn->last_sm_port_state = 0; state_mgr_sa_clean(sm); osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "SM port is down\n"); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SM PORT DOWN"); } /* Run the drop manager - we want to clear all records */ osm_drop_mgr_process(sm); /* Move to DISCOVERING state */ if (sm->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING) osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVER); osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_STATE_CHANGE, NULL); return; } else { if (!sm->p_subn->last_sm_port_state) { sm->p_subn->last_sm_port_state = 1; osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "SM port is up\n"); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SM PORT UP"); } } status = state_mgr_sweep_hop_1(sm); if (status != IB_SUCCESS || wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; /* discovery completed - check other sm presence */ if (sm->master_sm_found) { /* * Call the sm_state_mgr with signal * MASTER_OR_HIGHER_SM_DETECTED_DONE */ osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "ENTERING STANDBY STATE"); /* notify master SM about us */ osm_send_trap144(sm, 0); osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_STATE_CHANGE, NULL); return; } /* if new sweep requested - don't bother with the rest */ if (sm->p_subn->force_heavy_sweep) { config_parsed = 0; goto repeat_discovery; } osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_HEAVY_SWEEP_DONE, NULL); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "HEAVY SWEEP COMPLETE"); osm_drop_mgr_process(sm); /* If we are MASTER - get the highest remote_sm, and * see if it is higher than our local sm. */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER) { p_remote_sm = state_mgr_get_highest_sm(sm); if (p_remote_sm != NULL) { /* report new ports (trap 64) before leaving MASTER */ state_mgr_report_new_ports(sm); /* need to handover the mastership * to the remote sm, and move to standby */ state_mgr_send_handover(sm, p_remote_sm); osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_HANDOVER_SENT); return; } else { /* We are the highest sm - check to see if there is * a remote SM that is in master state. */ p_remote_sm = state_mgr_exists_other_master_sm(sm); if (p_remote_sm != NULL) { /* There is a remote SM that is master. * need to wait for that SM to relinquish control * of its portion of the subnet. C14-60.2.1. * Also - need to start polling on that SM. */ CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); sm->polling_sm_guid = p_remote_sm->smi.guid; CL_PLOCK_RELEASE(sm->p_lock); osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_WAIT_FOR_HANDOVER); return; } else if (sm->polling_sm_guid) { /* Stop polling SM if it's not found */ osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_POLLING_TIMEOUT); return; } } } /* * If we are not MASTER already - this means that we are * in discovery state. call osm_sm_state_mgr with signal * DISCOVERY_COMPLETED */ if (sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING) osm_sm_state_mgr_process(sm, OSM_SM_SIGNAL_DISCOVERY_COMPLETED); osm_reset_switch_state_change_bit(sm->p_subn->p_osm); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; osm_pkey_mgr_process(sm->p_subn->p_osm); /* try to restore SA DB (this should be before lid_mgr because we may want to disable clients reregistration when SA DB is restored) */ osm_sa_db_file_load(sm->p_subn->p_osm); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "PKEY setup completed - STARTING SM LID CONFIG"); osm_lid_mgr_process_sm(&sm->lid_mgr); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SM LID ASSIGNMENT COMPLETE - STARTING SUBNET LID CONFIG"); state_mgr_notify_lid_change(sm); osm_lid_mgr_process_subnet(&sm->lid_mgr); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; /* At this point we need to check the consistency of * the port_lid_tbl under the subnet. There might be * errors in it if PortInfo Set requests didn't reach * their destination. */ state_mgr_check_tbl_consistency(sm); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "LID ASSIGNMENT COMPLETE - STARTING SWITCH TABLE CONFIG"); /* * Proceed with unicast forwarding table configuration; if it fails * return early to wait for a trap or the next sweep interval. */ if (!sm->ucast_mgr.cache_valid || osm_ucast_cache_process(&sm->ucast_mgr)) { if (osm_ucast_mgr_process(&sm->ucast_mgr)) { osm_ucast_cache_invalidate(&sm->ucast_mgr); return; } } osm_qos_setup(sm->p_subn->p_osm); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; /* We are done setting all LFTs so clear the ignore existing. * From now on, as long as we are still master, we want to * take into account these lfts. */ sm->p_subn->ignore_existing_lfts = FALSE; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SWITCHES CONFIGURED FOR UNICAST"); osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_UCAST_ROUTING_DONE, (void *) UCAST_ROUTING_HEAVY_SWEEP); if (!sm->p_subn->opt.disable_multicast) { osm_mcast_mgr_process(sm, TRUE); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "SWITCHES CONFIGURED FOR MULTICAST"); } osm_guid_mgr_process(sm); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "ALIAS GUIDS CONFIGURED"); /* * The LINK_PORTS state is required since we cannot count on * the port state change MADs to succeed. This is an artifact * of the spec defining state change from state X to state X * as an error. The hardware then is not required to process * other parameters provided by the Set(PortInfo) Packet. */ osm_link_mgr_process(sm, IB_LINK_NO_CHANGE); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "LINKS PORTS CONFIGURED - SET LINKS TO ARMED STATE"); osm_link_mgr_process(sm, IB_LINK_ARMED); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "LINKS ARMED - SET LINKS TO ACTIVE STATE"); osm_link_mgr_process(sm, IB_LINK_ACTIVE); if (wait_for_pending_transactions(&sm->p_subn->p_osm->stats)) return; /* * The sweep completed! */ /* Now do GSI configuration */ osm_congestion_control_setup(sm->p_subn->p_osm); if (osm_congestion_control_wait_pending_transactions(sm->p_subn->p_osm)) return; /* * Send trap 64 on newly discovered endports */ state_mgr_report_new_ports(sm); /* check switch lft buffers assignments */ cl_qmap_apply_func(&sm->p_subn->sw_guid_tbl, check_switch_lft, sm->p_log); /* in any case we zero this flag */ sm->p_subn->coming_out_of_standby = FALSE; sm->p_subn->first_time_master_sweep = FALSE; /* If there were errors - then the subnet is not really up */ if (sm->p_subn->subnet_initialization_error == TRUE) { osm_log_v2(sm->p_log, OSM_LOG_SYS, FILE_ID, "Errors during initialization\n"); OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_ERROR, "ERRORS DURING INITIALIZATION"); } else { sm->p_subn->need_update = 0; osm_dump_all(sm->p_subn->p_osm); state_mgr_up_msg(sm); if (OSM_LOG_IS_ACTIVE_V2(sm->p_log, OSM_LOG_VERBOSE) || sm->p_subn->opt.sa_db_dump) osm_sa_db_file_dump(sm->p_subn->p_osm); } /* * Finally signal the subnet up event */ cl_event_signal(&sm->subnet_up_event); osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_SUBNET_UP, NULL); /* if we got a signal to force heavy sweep or errors * in the middle of the sweep - try another sweep. */ if (sm->p_subn->force_heavy_sweep) osm_sm_signal(sm, OSM_SIGNAL_SWEEP); /* Write a new copy of our persistent guid2mkey database */ osm_db_store(sm->p_subn->p_g2m, sm->p_subn->opt.fsync_high_avail_files); osm_db_store(sm->p_subn->p_neighbor, sm->p_subn->opt.fsync_high_avail_files); } static void do_process_mgrp_queue(osm_sm_t * sm) { if (sm->p_subn->sm_state != IB_SMINFO_STATE_MASTER) return; if (!sm->p_subn->opt.disable_multicast) { osm_mcast_mgr_process(sm, FALSE); wait_for_pending_transactions(&sm->p_subn->p_osm->stats); } } static void do_process_guid_queue(osm_sm_t *sm) { osm_guid_mgr_process(sm); wait_for_pending_transactions(&sm->p_subn->p_osm->stats); } void osm_state_mgr_process(IN osm_sm_t * sm, IN osm_signal_t signal) { CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received signal %s in state %s\n", osm_get_sm_signal_str(signal), osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); switch (signal) { case OSM_SIGNAL_SWEEP: if (!sm->p_subn->sweeping_enabled) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "sweeping disabled - " "ignoring signal %s in state %s\n", osm_get_sm_signal_str(signal), osm_get_sm_mgr_state_str(sm->p_subn->sm_state)); } else do_sweep(sm); break; case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST: do_process_mgrp_queue(sm); break; case OSM_SIGNAL_GUID_PROCESS_REQUEST: do_process_guid_queue(sm); break; default: CL_ASSERT(FALSE); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3320: " "Invalid SM signal %u\n", signal); break; } OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_subnet.c0000644000205000001450000030457712726322575013666 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (c) 2013 Oracle and/or its affiliates. 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 osm_subn_t. * This object represents an IBA subnet. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_SUBNET_C #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const char null_str[] = "(null)"; #define OPT_OFFSET(opt) offsetof(osm_subn_opt_t, opt) #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0])) typedef struct opt_rec { const char *name; unsigned long opt_offset; void (*parse_fn)(osm_subn_t *p_subn, char *p_key, char *p_val_str, void *p_val1, void *p_val2, void (*)(osm_subn_t *, void *)); void (*setup_fn)(osm_subn_t *p_subn, void *p_val); int can_update; } opt_rec_t; static const char *module_name_str[] = { "main.c", "osm_console.c", "osm_console_io.c", "osm_db_files.c", "osm_db_pack.c", "osm_drop_mgr.c", "osm_dump.c", "osm_event_plugin.c", "osm_guid_info_rcv.c", "osm_guid_mgr.c", "osm_helper.c", "osm_inform.c", "osm_lid_mgr.c", "osm_lin_fwd_rcv.c", "osm_link_mgr.c", "osm_log.c", "osm_mad_pool.c", "osm_mcast_fwd_rcv.c", "osm_mcast_mgr.c", "osm_mcast_tbl.c", "osm_mcm_port.c", "osm_mesh.c", "osm_mlnx_ext_port_info_rcv.c", "osm_mtree.c", "osm_multicast.c", "osm_node.c", "osm_node_desc_rcv.c", "osm_node_info_rcv.c", "osm_opensm.c", "osm_perfmgr.c", "osm_perfmgr_db.c", "osm_pkey.c", "osm_pkey_mgr.c", "osm_pkey_rcv.c", "osm_port.c", "osm_port_info_rcv.c", "osm_prtn.c", "osm_prtn_config.c", "osm_qos.c", "osm_qos_parser_l.c", "osm_qos_parser_y.c", "osm_qos_policy.c", "osm_remote_sm.c", "osm_req.c", "osm_resp.c", "osm_router.c", "osm_sa.c", "osm_sa_class_port_info.c", "osm_sa_guidinfo_record.c", "osm_sa_informinfo.c", "osm_sa_lft_record.c", "osm_sa_link_record.c", "osm_sa_mad_ctrl.c", "osm_sa_mcmember_record.c", "osm_sa_mft_record.c", "osm_sa_multipath_record.c", "osm_sa_node_record.c", "osm_sa_path_record.c", "osm_sa_pkey_record.c", "osm_sa_portinfo_record.c", "osm_sa_service_record.c", "osm_sa_slvl_record.c", "osm_sa_sminfo_record.c", "osm_sa_sw_info_record.c", "osm_sa_vlarb_record.c", "osm_service.c", "osm_slvl_map_rcv.c", "osm_sm.c", "osm_sminfo_rcv.c", "osm_sm_mad_ctrl.c", "osm_sm_state_mgr.c", "osm_state_mgr.c", "osm_subnet.c", "osm_sw_info_rcv.c", "osm_switch.c", "osm_torus.c", "osm_trap_rcv.c", "osm_ucast_cache.c", "osm_ucast_dnup.c", "osm_ucast_file.c", "osm_ucast_ftree.c", "osm_ucast_lash.c", "osm_ucast_mgr.c", "osm_ucast_updn.c", "osm_vendor_ibumad.c", "osm_vl15intf.c", "osm_vl_arb_rcv.c", "st.c", "osm_ucast_dfsssp.c", "osm_congestion_control.c", /* Add new module names here ... */ /* FILE_ID define in those modules must be identical to index here */ /* last FILE_ID is currently 89 */ }; #define MOD_NAME_STR_UNKNOWN_VAL (ARR_SIZE(module_name_str)) static int find_module_name(const char *name, uint8_t *file_id) { uint8_t i; for (i = 0; i < MOD_NAME_STR_UNKNOWN_VAL; i++) { if (strcmp(name, module_name_str[i]) == 0) { if (file_id) *file_id = i; return 0; } } return 1; } static void log_report(const char *fmt, ...) { char buf[128]; va_list args; va_start(args, fmt); vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); printf("%s", buf); cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0); } static void log_config_value(char *name, const char *fmt, ...) { char buf[128]; va_list args; unsigned n; va_start(args, fmt); n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name); if (n > sizeof(buf)) n = sizeof(buf); n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args); if (n > sizeof(buf) - 2) n = sizeof(buf) - 2; snprintf(buf + n, sizeof(buf) - n, "\n"); va_end(args); printf("%s", buf); cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0); } static void opts_setup_log_flags(osm_subn_t *p_subn, void *p_val) { p_subn->p_osm->log.level = *((uint8_t *) p_val); } static void opts_setup_force_log_flush(osm_subn_t *p_subn, void *p_val) { p_subn->p_osm->log.flush = *((boolean_t *) p_val); } static void opts_setup_accum_log_file(osm_subn_t *p_subn, void *p_val) { p_subn->p_osm->log.accum_log_file = *((boolean_t *) p_val); } static void opts_setup_log_max_size(osm_subn_t *p_subn, void *p_val) { uint32_t log_max_size = *((uint32_t *) p_val); p_subn->p_osm->log.max_size = (unsigned long)log_max_size << 20; /* convert from MB to bytes */ } static void opts_setup_sminfo_polling_timeout(osm_subn_t *p_subn, void *p_val) { osm_sm_t *p_sm = &p_subn->p_osm->sm; uint32_t sminfo_polling_timeout = *((uint32_t *) p_val); cl_timer_stop(&p_sm->polling_timer); cl_timer_start(&p_sm->polling_timer, sminfo_polling_timeout); } static void opts_setup_sm_priority(osm_subn_t *p_subn, void *p_val) { osm_sm_t *p_sm = &p_subn->p_osm->sm; uint8_t sm_priority = *((uint8_t *) p_val); osm_set_sm_priority(p_sm, sm_priority); } static int opts_strtoul(uint32_t *val, IN char *p_val_str, IN char *p_key, uint32_t max_value) { char *endptr; unsigned long int tmp_val; errno = 0; tmp_val = strtoul(p_val_str, &endptr, 0); *val = tmp_val; if (*p_val_str == '\0' || *endptr != '\0') { log_report("-E- Parsing error in field %s, expected " "numeric input received: %s\n", p_key, p_val_str); return -1; } if (tmp_val > max_value || ((tmp_val == ULONG_MAX) && errno == ERANGE)) { log_report("-E- Parsing error in field %s, value out of range\n", p_key); return -1; } return 0; } static int opts_strtoull(uint64_t *val, IN char *p_val_str, IN char *p_key, uint64_t max_value) { char *endptr; unsigned long long int tmp_val; errno = 0; tmp_val = strtoull(p_val_str, &endptr, 0); *val = tmp_val; if (*p_val_str == '\0' || *endptr != '\0') { log_report("-E- Parsing error in field %s, expected " "numeric input received: %s\n", p_key, p_val_str); return -1; } if (tmp_val > max_value || (tmp_val == ULLONG_MAX && errno == ERANGE)) { log_report("-E- Parsing error in field %s, value out of range", p_key); return -1; } return 0; } static void opts_parse_net64(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint64_t *p_val1 = p_v1, *p_val2 = p_v2; uint64_t val; if (opts_strtoull(&val, p_val_str, p_key, UINT64_MAX)) return; if (cl_hton64(val) != *p_val1) { log_config_value(p_key, "0x%016" PRIx64, val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = cl_ntoh64(val); } } static void opts_parse_uint32(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint32_t *p_val1 = p_v1, *p_val2 = p_v2; uint32_t val; if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX)) return; if (val != *p_val1) { log_config_value(p_key, "%u", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = val; } } static void opts_parse_net32(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint32_t *p_val1 = p_v1, *p_val2 = p_v2; uint32_t val; if (opts_strtoul(&val, p_val_str, p_key, UINT32_MAX)) return; if (cl_hton32(val) != *p_val1) { log_config_value(p_key, "%u", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = cl_hton32(val); } } static void opts_parse_int32(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { int32_t *p_val1 = p_v1, *p_val2 = p_v2; int32_t val = strtol(p_val_str, NULL, 0); if (val != *p_val1) { log_config_value(p_key, "%d", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = val; } } static void opts_parse_uint16(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint16_t *p_val1 = p_v1, *p_val2 = p_v2; uint32_t tmp_val; if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX)) return; uint16_t val = (uint16_t) tmp_val; if (val != *p_val1) { log_config_value(p_key, "%u", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = val; } } static void opts_parse_net16(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint16_t *p_val1 = p_v1, *p_val2 = p_v2; uint32_t tmp_val; if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT16_MAX)) return; uint16_t val = (uint16_t) tmp_val; if (cl_hton16(val) != *p_val1) { log_config_value(p_key, "0x%04x", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = cl_hton16(val); } } static void opts_parse_uint8(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint8_t *p_val1 = p_v1, *p_val2 = p_v2; uint32_t tmp_val; if (opts_strtoul(&tmp_val, p_val_str, p_key, UINT8_MAX)) return; uint8_t val = (uint8_t) tmp_val; if (val != *p_val1) { log_config_value(p_key, "%u", val); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = val; } } static void opts_parse_boolean(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { boolean_t *p_val1 = p_v1, *p_val2 = p_v2; boolean_t val; if (!p_val_str) return; if (strcmp("TRUE", p_val_str)) val = FALSE; else val = TRUE; if (val != *p_val1) { log_config_value(p_key, "%s", p_val_str); if (pfn) pfn(p_subn, &val); *p_val1 = *p_val2 = val; } } static void opts_parse_charp(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { char **p_val1 = p_v1, **p_val2 = p_v2; const char *current_str = *p_val1 ? *p_val1 : null_str; if (p_val_str && strcmp(p_val_str, current_str)) { char *new; log_config_value(p_key, "%s", p_val_str); /* special case the "(null)" string */ new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL; if (pfn) pfn(p_subn, new); if (*p_val1 && *p_val1 != *p_val2) free(*p_val1); if (*p_val2) free(*p_val2); *p_val1 = *p_val2 = new; } } static void opts_parse_256bit(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { uint8_t *p_val1 = p_v1, *p_val2 = p_v2; uint8_t val[IB_CC_PORT_MASK_DATA_SIZE] = { 0 }; char tmpbuf[3] = { 0 }; uint8_t tmpint; int numdigits = 0; int startindex; char *strptr = p_val_str; char *ptr; int i; /* parse like it's hypothetically a 256 bit integer code * * store "big endian" */ if (!strncmp(strptr, "0x", 2) || !strncmp(strptr, "0X", 2)) strptr+=2; for (ptr = strptr; *ptr; ptr++) { if (!isxdigit(*ptr)) { log_report("invalid hex digit in bitmask\n"); return; } numdigits++; } if (!numdigits) { log_report("invalid length bitmask\n"); return; } /* max of 2 hex chars per byte */ if (numdigits > IB_CC_PORT_MASK_DATA_SIZE * 2) numdigits = IB_CC_PORT_MASK_DATA_SIZE * 2; startindex = IB_CC_PORT_MASK_DATA_SIZE - ((numdigits - 1) / 2) - 1; if (numdigits % 2) { memcpy(tmpbuf, strptr, 1); strptr += 1; } else { memcpy(tmpbuf, strptr, 2); strptr += 2; } tmpint = strtoul(tmpbuf, NULL, 16); val[startindex] = tmpint; for (i = (startindex + 1); i < IB_CC_PORT_MASK_DATA_SIZE; i++) { memcpy(tmpbuf, strptr, 2); strptr += 2; tmpint = strtoul(tmpbuf, NULL, 16); val[i] = tmpint; } if (memcmp(val, p_val1, IB_CC_PORT_MASK_DATA_SIZE)) { log_config_value(p_key, "%s", p_val_str); if (pfn) pfn(p_subn, val); memcpy(p_val1, val, IB_CC_PORT_MASK_DATA_SIZE); memcpy(p_val2, val, IB_CC_PORT_MASK_DATA_SIZE); } } static void opts_parse_cct_entry(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cct_entry_t *p_cct1 = p_v1, *p_cct2 = p_v2; osm_cct_entry_t cct; char buf[512] = { 0 }; char *ptr; strncpy(buf, p_val_str, 511); if (!(ptr = strchr(buf, ':'))) { log_report("invalid CCT entry\n"); return; } *ptr = '\0'; ptr++; cct.shift = strtoul(buf, NULL, 0); cct.multiplier = strtoul(ptr, NULL, 0); if (cct.shift != p_cct1->shift || cct.multiplier != p_cct1->multiplier) { log_config_value(p_key, "%s", p_val_str); if (pfn) pfn(p_subn, &cct); p_cct1->shift = p_cct2->shift = cct.shift; p_cct1->multiplier = p_cct2->multiplier = cct.multiplier; } } static void opts_parse_cc_cct(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cct_t *p_val1 = p_v1, *p_val2 = p_v2; const char *current_str = p_val1->input_str ? p_val1->input_str : null_str; if (p_val_str && strcmp(p_val_str, current_str)) { osm_cct_t newcct; char *new; unsigned int len = 0; char *lasts; char *tok; char *ptr; /* special case the "(null)" string */ new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL; if (!new) { log_config_value(p_key, "%s", p_val_str); if (pfn) pfn(p_subn, NULL); memset(p_val1->entries, '\0', sizeof(p_val1->entries)); memset(p_val2->entries, '\0', sizeof(p_val2->entries)); p_val1->entries_len = p_val2->entries_len = 0; p_val1->input_str = p_val2->input_str = NULL; return; } memset(&newcct, '\0', sizeof(newcct)); tok = strtok_r(new, ",", &lasts); while (tok && len < OSM_CCT_ENTRY_MAX) { if (!(ptr = strchr(tok, ':'))) { log_report("invalid CCT entry\n"); free(new); return; } *ptr = '\0'; ptr++; newcct.entries[len].shift = strtoul(tok, NULL, 0); newcct.entries[len].multiplier = strtoul(ptr, NULL, 0); len++; tok = strtok_r(NULL, ",", &lasts); } free(new); newcct.entries_len = len; newcct.input_str = strdup(p_val_str); log_config_value(p_key, "%s", p_val_str); if (pfn) pfn(p_subn, &newcct); if (p_val1->input_str && p_val1->input_str != p_val2->input_str) free(p_val1->input_str); if (p_val2->input_str) free(p_val2->input_str); memcpy(p_val1->entries, newcct.entries, sizeof(newcct.entries)); memcpy(p_val2->entries, newcct.entries, sizeof(newcct.entries)); p_val1->entries_len = p_val2->entries_len = newcct.entries_len; p_val1->input_str = p_val2->input_str = newcct.input_str; } } static int parse_ca_cong_common(char *p_val_str, uint8_t *sl, unsigned int *val_offset) { char *new, *lasts, *sl_str, *val_str; uint8_t sltmp; new = strcmp(null_str, p_val_str) ? strdup(p_val_str) : NULL; if (!new) return -1; sl_str = strtok_r(new, " \t", &lasts); val_str = strtok_r(NULL, " \t", &lasts); if (!val_str) { log_report("value must be specified in addition to SL\n"); free(new); return -1; } sltmp = strtoul(sl_str, NULL, 0); if (sltmp >= IB_CA_CONG_ENTRY_DATA_SIZE) { log_report("invalid SL specified\n"); free(new); return -1; } *sl = sltmp; *val_offset = (unsigned int)(val_str - new); free(new); return 0; } static void opts_parse_ccti_timer(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2; unsigned int val_offset = 0; uint8_t sl = 0; if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0) return; opts_parse_net16(p_subn, p_key, p_val_str + val_offset, &p_val1[sl].ccti_timer, &p_val2[sl].ccti_timer, pfn); } static void opts_parse_ccti_increase(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2; unsigned int val_offset = 0; uint8_t sl = 0; if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0) return; opts_parse_uint8(p_subn, p_key, p_val_str + val_offset, &p_val1[sl].ccti_increase, &p_val2[sl].ccti_increase, pfn); } static void opts_parse_trigger_threshold(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2; unsigned int val_offset = 0; uint8_t sl = 0; if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0) return; opts_parse_uint8(p_subn, p_key, p_val_str + val_offset, &p_val1[sl].trigger_threshold, &p_val2[sl].trigger_threshold, pfn); } static void opts_parse_ccti_min(IN osm_subn_t *p_subn, IN char *p_key, IN char *p_val_str, void *p_v1, void *p_v2, void (*pfn)(osm_subn_t *, void *)) { osm_cacongestion_entry_t *p_val1 = p_v1, *p_val2 = p_v2; unsigned int val_offset = 0; uint8_t sl = 0; if (parse_ca_cong_common(p_val_str, &sl, &val_offset) < 0) return; opts_parse_uint8(p_subn, p_key, p_val_str + val_offset, &p_val1[sl].ccti_min, &p_val2[sl].ccti_min, pfn); } static const opt_rec_t opt_tbl[] = { { "guid", OPT_OFFSET(guid), opts_parse_net64, NULL, 0 }, { "m_key", OPT_OFFSET(m_key), opts_parse_net64, NULL, 1 }, { "sm_key", OPT_OFFSET(sm_key), opts_parse_net64, NULL, 1 }, { "sa_key", OPT_OFFSET(sa_key), opts_parse_net64, NULL, 1 }, { "subnet_prefix", OPT_OFFSET(subnet_prefix), opts_parse_net64, NULL, 1 }, { "m_key_lease_period", OPT_OFFSET(m_key_lease_period), opts_parse_net16, NULL, 1 }, { "m_key_protection_level", OPT_OFFSET(m_key_protect_bits), opts_parse_uint8, NULL, 1 }, { "m_key_lookup", OPT_OFFSET(m_key_lookup), opts_parse_boolean, NULL, 1 }, { "sweep_interval", OPT_OFFSET(sweep_interval), opts_parse_uint32, NULL, 1 }, { "max_wire_smps", OPT_OFFSET(max_wire_smps), opts_parse_uint32, NULL, 1 }, { "max_wire_smps2", OPT_OFFSET(max_wire_smps2), opts_parse_uint32, NULL, 1 }, { "max_smps_timeout", OPT_OFFSET(max_smps_timeout), opts_parse_uint32, NULL, 1 }, { "console", OPT_OFFSET(console), opts_parse_charp, NULL, 0 }, { "console_port", OPT_OFFSET(console_port), opts_parse_uint16, NULL, 0 }, { "transaction_timeout", OPT_OFFSET(transaction_timeout), opts_parse_uint32, NULL, 0 }, { "transaction_retries", OPT_OFFSET(transaction_retries), opts_parse_uint32, NULL, 0 }, { "max_msg_fifo_timeout", OPT_OFFSET(max_msg_fifo_timeout), opts_parse_uint32, NULL, 1 }, { "sm_priority", OPT_OFFSET(sm_priority), opts_parse_uint8, opts_setup_sm_priority, 1 }, { "lmc", OPT_OFFSET(lmc), opts_parse_uint8, NULL, 0 }, { "lmc_esp0", OPT_OFFSET(lmc_esp0), opts_parse_boolean, NULL, 0 }, { "max_op_vls", OPT_OFFSET(max_op_vls), opts_parse_uint8, NULL, 1 }, { "force_link_speed", OPT_OFFSET(force_link_speed), opts_parse_uint8, NULL, 1 }, { "force_link_speed_ext", OPT_OFFSET(force_link_speed_ext), opts_parse_uint8, NULL, 1 }, { "fdr10", OPT_OFFSET(fdr10), opts_parse_uint8, NULL, 1 }, { "reassign_lids", OPT_OFFSET(reassign_lids), opts_parse_boolean, NULL, 1 }, { "ignore_other_sm", OPT_OFFSET(ignore_other_sm), opts_parse_boolean, NULL, 1 }, { "single_thread", OPT_OFFSET(single_thread), opts_parse_boolean, NULL, 0 }, { "disable_multicast", OPT_OFFSET(disable_multicast), opts_parse_boolean, NULL, 1 }, { "subnet_timeout", OPT_OFFSET(subnet_timeout), opts_parse_uint8, NULL, 1 }, { "packet_life_time", OPT_OFFSET(packet_life_time), opts_parse_uint8, NULL, 1 }, { "vl_stall_count", OPT_OFFSET(vl_stall_count), opts_parse_uint8, NULL, 1 }, { "leaf_vl_stall_count", OPT_OFFSET(leaf_vl_stall_count), opts_parse_uint8, NULL, 1 }, { "head_of_queue_lifetime", OPT_OFFSET(head_of_queue_lifetime), opts_parse_uint8, NULL, 1 }, { "leaf_head_of_queue_lifetime", OPT_OFFSET(leaf_head_of_queue_lifetime), opts_parse_uint8, NULL, 1 }, { "local_phy_errors_threshold", OPT_OFFSET(local_phy_errors_threshold), opts_parse_uint8, NULL, 1 }, { "overrun_errors_threshold", OPT_OFFSET(overrun_errors_threshold), opts_parse_uint8, NULL, 1 }, { "use_mfttop", OPT_OFFSET(use_mfttop), opts_parse_boolean, NULL, 1}, { "sminfo_polling_timeout", OPT_OFFSET(sminfo_polling_timeout), opts_parse_uint32, opts_setup_sminfo_polling_timeout, 1 }, { "polling_retry_number", OPT_OFFSET(polling_retry_number), opts_parse_uint32, NULL, 1 }, { "force_heavy_sweep", OPT_OFFSET(force_heavy_sweep), opts_parse_boolean, NULL, 1 }, { "port_prof_ignore_file", OPT_OFFSET(port_prof_ignore_file), opts_parse_charp, NULL, 0 }, { "hop_weights_file", OPT_OFFSET(hop_weights_file), opts_parse_charp, NULL, 0 }, { "dimn_ports_file", OPT_OFFSET(port_search_ordering_file), opts_parse_charp, NULL, 0 }, { "port_search_ordering_file", OPT_OFFSET(port_search_ordering_file), opts_parse_charp, NULL, 0 }, { "port_profile_switch_nodes", OPT_OFFSET(port_profile_switch_nodes), opts_parse_boolean, NULL, 1 }, { "sweep_on_trap", OPT_OFFSET(sweep_on_trap), opts_parse_boolean, NULL, 1 }, { "routing_engine", OPT_OFFSET(routing_engine_names), opts_parse_charp, NULL, 0 }, { "connect_roots", OPT_OFFSET(connect_roots), opts_parse_boolean, NULL, 1 }, { "use_ucast_cache", OPT_OFFSET(use_ucast_cache), opts_parse_boolean, NULL, 0 }, { "log_file", OPT_OFFSET(log_file), opts_parse_charp, NULL, 0 }, { "log_max_size", OPT_OFFSET(log_max_size), opts_parse_uint32, opts_setup_log_max_size, 1 }, { "log_flags", OPT_OFFSET(log_flags), opts_parse_uint8, opts_setup_log_flags, 1 }, { "force_log_flush", OPT_OFFSET(force_log_flush), opts_parse_boolean, opts_setup_force_log_flush, 1 }, { "accum_log_file", OPT_OFFSET(accum_log_file), opts_parse_boolean, opts_setup_accum_log_file, 1 }, { "partition_config_file", OPT_OFFSET(partition_config_file), opts_parse_charp, NULL, 0 }, { "no_partition_enforcement", OPT_OFFSET(no_partition_enforcement), opts_parse_boolean, NULL, 1 }, { "part_enforce", OPT_OFFSET(part_enforce), opts_parse_charp, NULL, 1 }, { "allow_both_pkeys", OPT_OFFSET(allow_both_pkeys), opts_parse_boolean, NULL, 0 }, { "sm_assigned_guid", OPT_OFFSET(sm_assigned_guid), opts_parse_uint8, NULL, 1 }, { "qos", OPT_OFFSET(qos), opts_parse_boolean, NULL, 1 }, { "qos_policy_file", OPT_OFFSET(qos_policy_file), opts_parse_charp, NULL, 0 }, { "suppress_sl2vl_mad_status_errors", OPT_OFFSET(suppress_sl2vl_mad_status_errors), opts_parse_boolean, NULL, 1 }, { "dump_files_dir", OPT_OFFSET(dump_files_dir), opts_parse_charp, NULL, 0 }, { "lid_matrix_dump_file", OPT_OFFSET(lid_matrix_dump_file), opts_parse_charp, NULL, 0 }, { "lfts_file", OPT_OFFSET(lfts_file), opts_parse_charp, NULL, 0 }, { "root_guid_file", OPT_OFFSET(root_guid_file), opts_parse_charp, NULL, 0 }, { "cn_guid_file", OPT_OFFSET(cn_guid_file), opts_parse_charp, NULL, 0 }, { "io_guid_file", OPT_OFFSET(io_guid_file), opts_parse_charp, NULL, 0 }, { "port_shifting", OPT_OFFSET(port_shifting), opts_parse_boolean, NULL, 1 }, { "scatter_ports", OPT_OFFSET(scatter_ports), opts_parse_uint32, NULL, 1 }, { "max_reverse_hops", OPT_OFFSET(max_reverse_hops), opts_parse_uint16, NULL, 0 }, { "ids_guid_file", OPT_OFFSET(ids_guid_file), opts_parse_charp, NULL, 0 }, { "guid_routing_order_file", OPT_OFFSET(guid_routing_order_file), opts_parse_charp, NULL, 0 }, { "guid_routing_order_no_scatter", OPT_OFFSET(guid_routing_order_no_scatter), opts_parse_boolean, NULL, 0 }, { "sa_db_file", OPT_OFFSET(sa_db_file), opts_parse_charp, NULL, 0 }, { "sa_db_dump", OPT_OFFSET(sa_db_dump), opts_parse_boolean, NULL, 1 }, { "torus_config", OPT_OFFSET(torus_conf_file), opts_parse_charp, NULL, 1 }, { "do_mesh_analysis", OPT_OFFSET(do_mesh_analysis), opts_parse_boolean, NULL, 1 }, { "exit_on_fatal", OPT_OFFSET(exit_on_fatal), opts_parse_boolean, NULL, 1 }, { "honor_guid2lid_file", OPT_OFFSET(honor_guid2lid_file), opts_parse_boolean, NULL, 1 }, { "daemon", OPT_OFFSET(daemon), opts_parse_boolean, NULL, 0 }, { "sm_inactive", OPT_OFFSET(sm_inactive), opts_parse_boolean, NULL, 1 }, { "babbling_port_policy", OPT_OFFSET(babbling_port_policy), opts_parse_boolean, NULL, 1 }, { "drop_event_subscriptions", OPT_OFFSET(drop_event_subscriptions), opts_parse_boolean, NULL, 1 }, { "ipoib_mcgroup_creation_validation", OPT_OFFSET(ipoib_mcgroup_creation_validation), opts_parse_boolean, NULL, 1 }, { "mcgroup_join_validation", OPT_OFFSET(mcgroup_join_validation), opts_parse_boolean, NULL, 1 }, { "use_optimized_slvl", OPT_OFFSET(use_optimized_slvl), opts_parse_boolean, NULL, 1 }, { "fsync_high_avail_files", OPT_OFFSET(fsync_high_avail_files), opts_parse_boolean, NULL, 1 }, #ifdef ENABLE_OSM_PERF_MGR { "perfmgr", OPT_OFFSET(perfmgr), opts_parse_boolean, NULL, 0 }, { "perfmgr_redir", OPT_OFFSET(perfmgr_redir), opts_parse_boolean, NULL, 0 }, { "perfmgr_sweep_time_s", OPT_OFFSET(perfmgr_sweep_time_s), opts_parse_uint16, NULL, 0 }, { "perfmgr_max_outstanding_queries", OPT_OFFSET(perfmgr_max_outstanding_queries), opts_parse_uint32, NULL, 0 }, { "perfmgr_ignore_cas", OPT_OFFSET(perfmgr_ignore_cas), opts_parse_boolean, NULL, 0 }, { "event_db_dump_file", OPT_OFFSET(event_db_dump_file), opts_parse_charp, NULL, 0 }, { "perfmgr_rm_nodes", OPT_OFFSET(perfmgr_rm_nodes), opts_parse_boolean, NULL, 0 }, { "perfmgr_log_errors", OPT_OFFSET(perfmgr_log_errors), opts_parse_boolean, NULL, 0 }, { "perfmgr_query_cpi", OPT_OFFSET(perfmgr_query_cpi), opts_parse_boolean, NULL, 0 }, { "perfmgr_xmit_wait_log", OPT_OFFSET(perfmgr_xmit_wait_log), opts_parse_boolean, NULL, 0 }, { "perfmgr_xmit_wait_threshold", OPT_OFFSET(perfmgr_xmit_wait_threshold), opts_parse_uint32, NULL, 0 }, #endif /* ENABLE_OSM_PERF_MGR */ { "event_plugin_name", OPT_OFFSET(event_plugin_name), opts_parse_charp, NULL, 0 }, { "event_plugin_options", OPT_OFFSET(event_plugin_options), opts_parse_charp, NULL, 0 }, { "node_name_map_name", OPT_OFFSET(node_name_map_name), opts_parse_charp, NULL, 0 }, { "qos_max_vls", OPT_OFFSET(qos_options.max_vls), opts_parse_uint32, NULL, 1 }, { "qos_high_limit", OPT_OFFSET(qos_options.high_limit), opts_parse_int32, NULL, 1 }, { "qos_vlarb_high", OPT_OFFSET(qos_options.vlarb_high), opts_parse_charp, NULL, 1 }, { "qos_vlarb_low", OPT_OFFSET(qos_options.vlarb_low), opts_parse_charp, NULL, 1 }, { "qos_sl2vl", OPT_OFFSET(qos_options.sl2vl), opts_parse_charp, NULL, 1 }, { "qos_ca_max_vls", OPT_OFFSET(qos_ca_options.max_vls), opts_parse_uint32, NULL, 1 }, { "qos_ca_high_limit", OPT_OFFSET(qos_ca_options.high_limit), opts_parse_int32, NULL, 1 }, { "qos_ca_vlarb_high", OPT_OFFSET(qos_ca_options.vlarb_high), opts_parse_charp, NULL, 1 }, { "qos_ca_vlarb_low", OPT_OFFSET(qos_ca_options.vlarb_low), opts_parse_charp, NULL, 1 }, { "qos_ca_sl2vl", OPT_OFFSET(qos_ca_options.sl2vl), opts_parse_charp, NULL, 1 }, { "qos_sw0_max_vls", OPT_OFFSET(qos_sw0_options.max_vls), opts_parse_uint32, NULL, 1 }, { "qos_sw0_high_limit", OPT_OFFSET(qos_sw0_options.high_limit), opts_parse_int32, NULL, 1 }, { "qos_sw0_vlarb_high", OPT_OFFSET(qos_sw0_options.vlarb_high), opts_parse_charp, NULL, 1 }, { "qos_sw0_vlarb_low", OPT_OFFSET(qos_sw0_options.vlarb_low), opts_parse_charp, NULL, 1 }, { "qos_sw0_sl2vl", OPT_OFFSET(qos_sw0_options.sl2vl), opts_parse_charp, NULL, 1 }, { "qos_swe_max_vls", OPT_OFFSET(qos_swe_options.max_vls), opts_parse_uint32, NULL, 1 }, { "qos_swe_high_limit", OPT_OFFSET(qos_swe_options.high_limit), opts_parse_int32, NULL, 1 }, { "qos_swe_vlarb_high", OPT_OFFSET(qos_swe_options.vlarb_high), opts_parse_charp, NULL, 1 }, { "qos_swe_vlarb_low", OPT_OFFSET(qos_swe_options.vlarb_low), opts_parse_charp, NULL, 1 }, { "qos_swe_sl2vl", OPT_OFFSET(qos_swe_options.sl2vl), opts_parse_charp, NULL, 1 }, { "qos_rtr_max_vls", OPT_OFFSET(qos_rtr_options.max_vls), opts_parse_uint32, NULL, 1 }, { "qos_rtr_high_limit", OPT_OFFSET(qos_rtr_options.high_limit), opts_parse_int32, NULL, 1 }, { "qos_rtr_vlarb_high", OPT_OFFSET(qos_rtr_options.vlarb_high), opts_parse_charp, NULL, 1 }, { "qos_rtr_vlarb_low", OPT_OFFSET(qos_rtr_options.vlarb_low), opts_parse_charp, NULL, 1 }, { "qos_rtr_sl2vl", OPT_OFFSET(qos_rtr_options.sl2vl), opts_parse_charp, NULL, 1 }, { "congestion_control", OPT_OFFSET(congestion_control), opts_parse_boolean, NULL, 1 }, { "cc_key", OPT_OFFSET(cc_key), opts_parse_net64, NULL, 0}, { "cc_max_outstanding_mads", OPT_OFFSET(cc_max_outstanding_mads), opts_parse_uint32, NULL, 0 }, { "cc_sw_cong_setting_control_map", OPT_OFFSET(cc_sw_cong_setting_control_map), opts_parse_net32, NULL, 1}, { "cc_sw_cong_setting_victim_mask", OPT_OFFSET(cc_sw_cong_setting_victim_mask), opts_parse_256bit, NULL, 1}, { "cc_sw_cong_setting_credit_mask", OPT_OFFSET(cc_sw_cong_setting_credit_mask), opts_parse_256bit, NULL, 1}, { "cc_sw_cong_setting_threshold", OPT_OFFSET(cc_sw_cong_setting_threshold), opts_parse_uint8, NULL, 1}, { "cc_sw_cong_setting_packet_size", OPT_OFFSET(cc_sw_cong_setting_packet_size), opts_parse_uint8, NULL, 1}, { "cc_sw_cong_setting_credit_starvation_threshold", OPT_OFFSET(cc_sw_cong_setting_credit_starvation_threshold), opts_parse_uint8, NULL, 1}, { "cc_sw_cong_setting_credit_starvation_return_delay", OPT_OFFSET(cc_sw_cong_setting_credit_starvation_return_delay), opts_parse_cct_entry, NULL, 1}, { "cc_sw_cong_setting_marking_rate", OPT_OFFSET(cc_sw_cong_setting_marking_rate), opts_parse_net16, NULL, 1}, { "cc_ca_cong_setting_port_control", OPT_OFFSET(cc_ca_cong_setting_port_control), opts_parse_net16, NULL, 1}, { "cc_ca_cong_setting_control_map", OPT_OFFSET(cc_ca_cong_setting_control_map), opts_parse_net16, NULL, 1}, { "cc_ca_cong_setting_ccti_timer", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_timer, NULL, 1}, { "cc_ca_cong_setting_ccti_increase", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_increase, NULL, 1}, { "cc_ca_cong_setting_trigger_threshold", OPT_OFFSET(cc_ca_cong_entries), opts_parse_trigger_threshold, NULL, 1}, { "cc_ca_cong_setting_ccti_min", OPT_OFFSET(cc_ca_cong_entries), opts_parse_ccti_min, NULL, 1}, { "cc_cct", OPT_OFFSET(cc_cct), opts_parse_cc_cct, NULL, 1}, { "enable_quirks", OPT_OFFSET(enable_quirks), opts_parse_boolean, NULL, 1 }, { "no_clients_rereg", OPT_OFFSET(no_clients_rereg), opts_parse_boolean, NULL, 1 }, { "prefix_routes_file", OPT_OFFSET(prefix_routes_file), opts_parse_charp, NULL, 0 }, { "consolidate_ipv6_snm_req", OPT_OFFSET(consolidate_ipv6_snm_req), opts_parse_boolean, NULL, 1 }, { "lash_start_vl", OPT_OFFSET(lash_start_vl), opts_parse_uint8, NULL, 1 }, { "sm_sl", OPT_OFFSET(sm_sl), opts_parse_uint8, NULL, 1 }, { "log_prefix", OPT_OFFSET(log_prefix), opts_parse_charp, NULL, 1 }, { "per_module_logging_file", OPT_OFFSET(per_module_logging_file), opts_parse_charp, NULL, 0 }, { "quasi_ftree_indexing", OPT_OFFSET(quasi_ftree_indexing), opts_parse_boolean, NULL, 1 }, {0} }; static int compar_mgids(const void *m1, const void *m2) { return memcmp(m1, m2, sizeof(ib_gid_t)); } static void subn_validate_g2m(osm_subn_t *p_subn) { cl_qlist_t guids; osm_db_guid_elem_t *p_item; uint64_t mkey; boolean_t valid_entry; OSM_LOG_ENTER(&(p_subn->p_osm->log)); cl_qlist_init(&guids); if (osm_db_guid2mkey_guids(p_subn->p_g2m, &guids)) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7506: " "could not get mkey guid list\n"); goto Exit; } while ((p_item = (osm_db_guid_elem_t *) cl_qlist_remove_head(&guids)) != (osm_db_guid_elem_t *) cl_qlist_end(&guids)) { valid_entry = TRUE; if (p_item->guid == 0) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7507: found invalid zero guid"); valid_entry = FALSE; } else if (osm_db_guid2mkey_get(p_subn->p_g2m, p_item->guid, &mkey)) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7508: could not get mkey for guid:0x%016" PRIx64 "\n", p_item->guid); valid_entry = FALSE; } if (valid_entry == FALSE) { if (osm_db_guid2mkey_delete(p_subn->p_g2m, p_item->guid)) OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7509: failed to delete entry for " "guid:0x%016" PRIx64 "\n", p_item->guid); } free(p_item); } Exit: OSM_LOG_EXIT(&(p_subn->p_osm->log)); } static void subn_validate_neighbor(osm_subn_t *p_subn) { cl_qlist_t entries; osm_db_neighbor_elem_t *p_item; boolean_t valid_entry; uint64_t guid; uint8_t port; OSM_LOG_ENTER(&(p_subn->p_osm->log)); cl_qlist_init(&entries); if (osm_db_neighbor_guids(p_subn->p_neighbor, &entries)) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7512: " "could not get neighbor entry list\n"); goto Exit; } while ((p_item = (osm_db_neighbor_elem_t *) cl_qlist_remove_head(&entries)) != (osm_db_neighbor_elem_t *) cl_qlist_end(&entries)) { valid_entry = TRUE; OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_DEBUG, "Validating neighbor for guid:0x%016" PRIx64 ", port %d\n", p_item->guid, p_item->portnum); if (p_item->guid == 0) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7513: found invalid zero guid\n"); valid_entry = FALSE; } else if (p_item->portnum == 0) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7514: found invalid zero port for " "guid: 0x%016" PRIx64 "\n", p_item->guid); valid_entry = FALSE; } else if (osm_db_neighbor_get(p_subn->p_neighbor, p_item->guid, p_item->portnum, &guid, &port)) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7515: could not find neighbor for " "guid: 0x%016" PRIx64 ", port %d\n", p_item->guid, p_item->portnum); valid_entry = FALSE; } else if (guid == 0) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7516: found invalid neighbor " "zero guid for guid: 0x%016" PRIx64 ", port %d\n", p_item->guid, p_item->portnum); valid_entry = FALSE; } else if (port == 0) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7517: found invalid neighbor " "zero port for guid: 0x%016" PRIx64 ", port %d\n", p_item->guid, p_item->portnum); valid_entry = FALSE; } else if (osm_db_neighbor_get(p_subn->p_neighbor, guid, port, &guid, &port) || guid != p_item->guid || port != p_item->portnum) { OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7518: neighbor does not point " "back at us (guid: 0x%016" PRIx64 ", port %d)\n", p_item->guid, p_item->portnum); valid_entry = FALSE; } if (valid_entry == FALSE) { if (osm_db_neighbor_delete(p_subn->p_neighbor, p_item->guid, p_item->portnum)) OSM_LOG(&(p_subn->p_osm->log), OSM_LOG_ERROR, "ERR 7519: failed to delete entry for " "guid:0x%016" PRIx64 " port:%u\n", p_item->guid, p_item->portnum); } free(p_item); } Exit: OSM_LOG_EXIT(&(p_subn->p_osm->log)); } void osm_subn_construct(IN osm_subn_t * p_subn) { memset(p_subn, 0, sizeof(*p_subn)); cl_ptr_vector_construct(&p_subn->port_lid_tbl); cl_qmap_init(&p_subn->sw_guid_tbl); cl_qmap_init(&p_subn->node_guid_tbl); cl_qmap_init(&p_subn->port_guid_tbl); cl_qmap_init(&p_subn->alias_port_guid_tbl); cl_qmap_init(&p_subn->assigned_guids_tbl); cl_qmap_init(&p_subn->sm_guid_tbl); cl_qlist_init(&p_subn->sa_sr_list); cl_qlist_init(&p_subn->sa_infr_list); cl_qlist_init(&p_subn->alias_guid_list); cl_qlist_init(&p_subn->prefix_routes_list); cl_qmap_init(&p_subn->rtr_guid_tbl); cl_qmap_init(&p_subn->prtn_pkey_tbl); cl_fmap_init(&p_subn->mgrp_mgid_tbl, compar_mgids); } static void subn_destroy_qos_options(osm_qos_options_t *opt) { free(opt->vlarb_high); free(opt->vlarb_low); free(opt->sl2vl); } static void subn_opt_destroy(IN osm_subn_opt_t * p_opt) { free(p_opt->console); free(p_opt->port_prof_ignore_file); free(p_opt->hop_weights_file); free(p_opt->port_search_ordering_file); free(p_opt->routing_engine_names); free(p_opt->log_file); free(p_opt->partition_config_file); free(p_opt->qos_policy_file); free(p_opt->dump_files_dir); free(p_opt->part_enforce); free(p_opt->lid_matrix_dump_file); free(p_opt->lfts_file); free(p_opt->root_guid_file); free(p_opt->cn_guid_file); free(p_opt->io_guid_file); free(p_opt->ids_guid_file); free(p_opt->guid_routing_order_file); free(p_opt->sa_db_file); free(p_opt->torus_conf_file); #ifdef ENABLE_OSM_PERF_MGR free(p_opt->event_db_dump_file); #endif /* ENABLE_OSM_PERF_MGR */ free(p_opt->event_plugin_name); free(p_opt->event_plugin_options); free(p_opt->node_name_map_name); free(p_opt->prefix_routes_file); free(p_opt->log_prefix); subn_destroy_qos_options(&p_opt->qos_options); subn_destroy_qos_options(&p_opt->qos_ca_options); subn_destroy_qos_options(&p_opt->qos_sw0_options); subn_destroy_qos_options(&p_opt->qos_swe_options); subn_destroy_qos_options(&p_opt->qos_rtr_options); free(p_opt->cc_cct.input_str); } void osm_subn_destroy(IN osm_subn_t * p_subn) { int i; osm_node_t *p_node, *p_next_node; osm_assigned_guids_t *p_assigned_guids, *p_next_assigned_guids; osm_alias_guid_t *p_alias_guid, *p_next_alias_guid; osm_port_t *p_port, *p_next_port; osm_switch_t *p_sw, *p_next_sw; osm_remote_sm_t *p_rsm, *p_next_rsm; osm_prtn_t *p_prtn, *p_next_prtn; osm_infr_t *p_infr, *p_next_infr; osm_svcr_t *p_svcr, *p_next_svcr; /* it might be a good idea to de-allocate all known objects */ p_next_node = (osm_node_t *) cl_qmap_head(&p_subn->node_guid_tbl); while (p_next_node != (osm_node_t *) cl_qmap_end(&p_subn->node_guid_tbl)) { p_node = p_next_node; p_next_node = (osm_node_t *) cl_qmap_next(&p_node->map_item); osm_node_delete(&p_node); } p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_head(&p_subn->assigned_guids_tbl); while (p_next_assigned_guids != (osm_assigned_guids_t *) cl_qmap_end(&p_subn->assigned_guids_tbl)) { p_assigned_guids = p_next_assigned_guids; p_next_assigned_guids = (osm_assigned_guids_t *) cl_qmap_next(&p_assigned_guids->map_item); osm_assigned_guids_delete(&p_assigned_guids); } p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_head(&p_subn->alias_port_guid_tbl); while (p_next_alias_guid != (osm_alias_guid_t *) cl_qmap_end(&p_subn->alias_port_guid_tbl)) { p_alias_guid = p_next_alias_guid; p_next_alias_guid = (osm_alias_guid_t *) cl_qmap_next(&p_alias_guid->map_item); osm_alias_guid_delete(&p_alias_guid); } while (cl_qlist_count(&p_subn->alias_guid_list)) osm_guid_work_obj_delete((osm_guidinfo_work_obj_t *) cl_qlist_remove_head(&p_subn->alias_guid_list)); p_next_port = (osm_port_t *) cl_qmap_head(&p_subn->port_guid_tbl); while (p_next_port != (osm_port_t *) cl_qmap_end(&p_subn->port_guid_tbl)) { p_port = p_next_port; p_next_port = (osm_port_t *) cl_qmap_next(&p_port->map_item); osm_port_delete(&p_port); } p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); osm_switch_delete(&p_sw); } p_next_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl); while (p_next_rsm != (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) { p_rsm = p_next_rsm; p_next_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item); free(p_rsm); } p_next_prtn = (osm_prtn_t *) cl_qmap_head(&p_subn->prtn_pkey_tbl); while (p_next_prtn != (osm_prtn_t *) cl_qmap_end(&p_subn->prtn_pkey_tbl)) { p_prtn = p_next_prtn; p_next_prtn = (osm_prtn_t *) cl_qmap_next(&p_prtn->map_item); osm_prtn_delete(p_subn, &p_prtn); } cl_fmap_remove_all(&p_subn->mgrp_mgid_tbl); for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO; i++) if (p_subn->mboxes[i]) osm_mgrp_box_delete(p_subn->mboxes[i]); p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list); while (p_next_infr != (osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) { p_infr = p_next_infr; p_next_infr = (osm_infr_t *) cl_qlist_next(&p_infr->list_item); osm_infr_delete(p_infr); } p_next_svcr = (osm_svcr_t *) cl_qlist_head(&p_subn->sa_sr_list); while (p_next_svcr != (osm_svcr_t *) cl_qlist_end(&p_subn->sa_sr_list)) { p_svcr = p_next_svcr; p_next_svcr = (osm_svcr_t *) cl_qlist_next(&p_svcr->list_item); osm_svcr_delete(p_svcr); } cl_ptr_vector_destroy(&p_subn->port_lid_tbl); osm_qos_policy_destroy(p_subn->p_qos_policy); while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) { cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list); free(item); } subn_opt_destroy(&p_subn->opt); free(p_subn->opt.file_opts); } ib_api_status_t osm_subn_init(IN osm_subn_t * p_subn, IN osm_opensm_t * p_osm, IN const osm_subn_opt_t * p_opt) { cl_status_t status; p_subn->p_osm = p_osm; status = cl_ptr_vector_init(&p_subn->port_lid_tbl, OSM_SUBNET_VECTOR_MIN_SIZE, OSM_SUBNET_VECTOR_GROW_SIZE); if (status != CL_SUCCESS) return status; status = cl_ptr_vector_set_capacity(&p_subn->port_lid_tbl, OSM_SUBNET_VECTOR_CAPACITY); if (status != CL_SUCCESS) return status; /* LID zero is not valid. NULL out this entry for the convenience of other code. */ cl_ptr_vector_set(&p_subn->port_lid_tbl, 0, NULL); p_subn->opt = *p_opt; p_subn->max_ucast_lid_ho = IB_LID_UCAST_END_HO; p_subn->max_mcast_lid_ho = IB_LID_MCAST_END_HO; p_subn->min_ca_mtu = IB_MAX_MTU; p_subn->min_ca_rate = IB_MAX_RATE; p_subn->min_data_vls = IB_MAX_NUM_VLS - 1; p_subn->min_sw_data_vls = IB_MAX_NUM_VLS - 1; p_subn->ignore_existing_lfts = TRUE; /* we assume master by default - so we only need to set it true if STANDBY */ p_subn->coming_out_of_standby = FALSE; p_subn->sweeping_enabled = TRUE; p_subn->last_sm_port_state = 1; /* Initialize the guid2mkey database */ p_subn->p_g2m = osm_db_domain_init(&(p_osm->db), "guid2mkey"); if (!p_subn->p_g2m) { OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7510: " "Error initializing Guid-to-MKey persistent database\n"); return IB_ERROR; } if (osm_db_restore(p_subn->p_g2m)) { #ifndef __WIN__ /* * When Windows is BSODing, it might corrupt files that * were previously opened for writing, even if the files * are closed, so we might see corrupted guid2mkey file. */ if (p_subn->opt.exit_on_fatal) { osm_log(&(p_osm->log), OSM_LOG_SYS, "FATAL: Error restoring Guid-to-Mkey " "persistent database\n"); return IB_ERROR; } else #endif OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7511: Error restoring Guid-to-Mkey " "persistent database\n"); } subn_validate_g2m(p_subn); /* Initialize the neighbor database */ p_subn->p_neighbor = osm_db_domain_init(&(p_osm->db), "neighbors"); if (!p_subn->p_neighbor) { OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7520: Error " "initializing neighbor link persistent database\n"); return IB_ERROR; } if (osm_db_restore(p_subn->p_neighbor)) { #ifndef __WIN__ /* * When Windows is BSODing, it might corrupt files that * were previously opened for writing, even if the files * are closed, so we might see corrupted neighbors file. */ if (p_subn->opt.exit_on_fatal) { osm_log(&(p_osm->log), OSM_LOG_SYS, "FATAL: Error restoring neighbor link " "persistent database\n"); return IB_ERROR; } else #endif OSM_LOG(&(p_osm->log), OSM_LOG_ERROR, "ERR 7521: Error restoring neighbor link " "persistent database\n"); } subn_validate_neighbor(p_subn); return IB_SUCCESS; } osm_port_t *osm_get_port_by_mad_addr(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN osm_mad_addr_t * p_mad_addr) { osm_port_t *port = osm_get_port_by_lid(p_subn, p_mad_addr->dest_lid); if (!port) OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7504: " "Lid is out of range: %u\n", cl_ntoh16(p_mad_addr->dest_lid)); return port; } ib_api_status_t osm_get_gid_by_mad_addr(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN osm_mad_addr_t * p_mad_addr, OUT ib_gid_t * p_gid) { const osm_port_t *p_port; if (p_gid == NULL) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7505: " "Provided output GID is NULL\n"); return IB_INVALID_PARAMETER; } p_port = osm_get_port_by_mad_addr(p_log, p_subn, p_mad_addr); if (!p_port) return IB_INVALID_PARAMETER; p_gid->unicast.interface_id = p_port->p_physp->port_guid; p_gid->unicast.prefix = p_subn->opt.subnet_prefix; return IB_SUCCESS; } osm_physp_t *osm_get_physp_by_mad_addr(IN osm_log_t * p_log, IN const osm_subn_t * p_subn, IN osm_mad_addr_t * p_mad_addr) { osm_port_t *p_port; p_port = osm_get_port_by_mad_addr(p_log, p_subn, p_mad_addr); if (!p_port) return NULL; return p_port->p_physp; } osm_switch_t *osm_get_switch_by_guid(IN const osm_subn_t * p_subn, IN ib_net64_t guid) { osm_switch_t *p_switch; p_switch = (osm_switch_t *) cl_qmap_get(&(p_subn->sw_guid_tbl), guid); if (p_switch == (osm_switch_t *) cl_qmap_end(&(p_subn->sw_guid_tbl))) p_switch = NULL; return p_switch; } osm_node_t *osm_get_node_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid) { osm_node_t *p_node; p_node = (osm_node_t *) cl_qmap_get(&(p_subn->node_guid_tbl), guid); if (p_node == (osm_node_t *) cl_qmap_end(&(p_subn->node_guid_tbl))) p_node = NULL; return p_node; } osm_port_t *osm_get_port_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid) { osm_port_t *p_port; p_port = (osm_port_t *) cl_qmap_get(&(p_subn->port_guid_tbl), guid); if (p_port == (osm_port_t *) cl_qmap_end(&(p_subn->port_guid_tbl))) p_port = NULL; return p_port; } osm_alias_guid_t *osm_get_alias_guid_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid) { osm_alias_guid_t *p_alias_guid; p_alias_guid = (osm_alias_guid_t *) cl_qmap_get(&(p_subn->alias_port_guid_tbl), guid); if (p_alias_guid == (osm_alias_guid_t *) cl_qmap_end(&(p_subn->alias_port_guid_tbl))) return NULL; return p_alias_guid; } osm_port_t *osm_get_port_by_alias_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid) { osm_alias_guid_t *p_alias_guid; p_alias_guid = osm_get_alias_guid_by_guid(p_subn, guid); if (!p_alias_guid) return NULL; return p_alias_guid->p_base_port; } osm_assigned_guids_t *osm_assigned_guids_new(IN const ib_net64_t port_guid, IN const uint32_t num_guids) { osm_assigned_guids_t *p_assigned_guids; p_assigned_guids = calloc(1, sizeof(*p_assigned_guids) + sizeof(ib_net64_t) * (num_guids - 1)); if (p_assigned_guids) p_assigned_guids->port_guid = port_guid; return p_assigned_guids; } void osm_assigned_guids_delete(IN OUT osm_assigned_guids_t ** pp_assigned_guids) { free(*pp_assigned_guids); *pp_assigned_guids = NULL; } osm_assigned_guids_t *osm_get_assigned_guids_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t port_guid) { osm_assigned_guids_t *p_assigned_guids; p_assigned_guids = (osm_assigned_guids_t *) cl_qmap_get(&(p_subn->assigned_guids_tbl), port_guid); if (p_assigned_guids == (osm_assigned_guids_t *) cl_qmap_end(&(p_subn->assigned_guids_tbl))) return NULL; return p_assigned_guids; } osm_port_t *osm_get_port_by_lid_ho(IN osm_subn_t const * subn, IN uint16_t lid) { if (lid < cl_ptr_vector_get_size(&subn->port_lid_tbl)) return cl_ptr_vector_get(&subn->port_lid_tbl, lid); return NULL; } osm_mgrp_t *osm_get_mgrp_by_mgid(IN osm_subn_t * subn, IN ib_gid_t * mgid) { osm_mgrp_t *mgrp; mgrp = (osm_mgrp_t *)cl_fmap_get(&subn->mgrp_mgid_tbl, mgid); if (mgrp != (osm_mgrp_t *)cl_fmap_end(&subn->mgrp_mgid_tbl)) return mgrp; return NULL; } int is_mlnx_ext_port_info_supported(ib_net16_t devid) { uint16_t devid_ho; devid_ho = cl_ntoh16(devid); if ((devid_ho >= 0xc738 && devid_ho <= 0xc73b) || devid_ho == 0xcb20 || devid_ho == 0xcf08) return 1; if (devid_ho >= 0x1003 && devid_ho <= 0x1016) return 1; return 0; } static void subn_init_qos_options(osm_qos_options_t *opt, osm_qos_options_t *f) { opt->max_vls = 0; opt->high_limit = -1; if (opt->vlarb_high) free(opt->vlarb_high); opt->vlarb_high = NULL; if (opt->vlarb_low) free(opt->vlarb_low); opt->vlarb_low = NULL; if (opt->sl2vl) free(opt->sl2vl); opt->sl2vl = NULL; if (f) memcpy(f, opt, sizeof(*f)); } void osm_subn_set_default_opt(IN osm_subn_opt_t * p_opt) { memset(p_opt, 0, sizeof(osm_subn_opt_t)); p_opt->guid = 0; p_opt->m_key = OSM_DEFAULT_M_KEY; p_opt->sm_key = OSM_DEFAULT_SM_KEY; p_opt->sa_key = OSM_DEFAULT_SA_KEY; p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX; p_opt->m_key_lease_period = 0; p_opt->m_key_protect_bits = 0; p_opt->m_key_lookup = TRUE; p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS; p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE; p_opt->max_wire_smps2 = p_opt->max_wire_smps; p_opt->console = strdup(OSM_DEFAULT_CONSOLE); p_opt->console_port = OSM_DEFAULT_CONSOLE_PORT; p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC; p_opt->transaction_retries = OSM_DEFAULT_RETRY_COUNT; p_opt->max_smps_timeout = 1000 * p_opt->transaction_timeout * p_opt->transaction_retries; /* by default we will consider waiting for 50x transaction timeout normal */ p_opt->max_msg_fifo_timeout = 50 * OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC; p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY; p_opt->lmc = OSM_DEFAULT_LMC; p_opt->lmc_esp0 = FALSE; p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS; p_opt->force_link_speed = 15; p_opt->force_link_speed_ext = 31; p_opt->fdr10 = 1; p_opt->reassign_lids = FALSE; p_opt->ignore_other_sm = FALSE; p_opt->single_thread = FALSE; p_opt->disable_multicast = FALSE; p_opt->force_log_flush = FALSE; p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT; p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE; p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT; p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT; p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE; p_opt->leaf_head_of_queue_lifetime = OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE; p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD; p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD; p_opt->use_mfttop = TRUE; p_opt->sminfo_polling_timeout = OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS; p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER; p_opt->force_heavy_sweep = FALSE; p_opt->log_flags = OSM_LOG_DEFAULT_LEVEL; p_opt->honor_guid2lid_file = FALSE; p_opt->daemon = FALSE; p_opt->sm_inactive = FALSE; p_opt->babbling_port_policy = FALSE; p_opt->drop_event_subscriptions = FALSE; p_opt->ipoib_mcgroup_creation_validation = TRUE; p_opt->mcgroup_join_validation = TRUE; p_opt->use_optimized_slvl = FALSE; p_opt->fsync_high_avail_files = TRUE; #ifdef ENABLE_OSM_PERF_MGR p_opt->perfmgr = FALSE; p_opt->perfmgr_redir = TRUE; p_opt->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S; p_opt->perfmgr_max_outstanding_queries = OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES; p_opt->perfmgr_ignore_cas = FALSE; p_opt->event_db_dump_file = NULL; /* use default */ p_opt->perfmgr_rm_nodes = TRUE; p_opt->perfmgr_log_errors = TRUE; p_opt->perfmgr_query_cpi = TRUE; p_opt->perfmgr_xmit_wait_log = FALSE; p_opt->perfmgr_xmit_wait_threshold = OSM_PERFMGR_DEFAULT_XMIT_WAIT_THRESHOLD; #endif /* ENABLE_OSM_PERF_MGR */ p_opt->event_plugin_name = NULL; p_opt->event_plugin_options = NULL; p_opt->node_name_map_name = NULL; p_opt->dump_files_dir = getenv("OSM_TMP_DIR"); if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir)) p_opt->dump_files_dir = strdup(OSM_DEFAULT_TMP_DIR); else p_opt->dump_files_dir = strdup(p_opt->dump_files_dir); p_opt->log_file = strdup(OSM_DEFAULT_LOG_FILE); p_opt->log_max_size = 0; p_opt->partition_config_file = strdup(OSM_DEFAULT_PARTITION_CONFIG_FILE); p_opt->no_partition_enforcement = FALSE; p_opt->part_enforce = strdup(OSM_PARTITION_ENFORCE_BOTH); p_opt->allow_both_pkeys = FALSE; p_opt->sm_assigned_guid = 0; p_opt->qos = FALSE; p_opt->qos_policy_file = strdup(OSM_DEFAULT_QOS_POLICY_FILE); p_opt->suppress_sl2vl_mad_status_errors = FALSE; p_opt->accum_log_file = TRUE; p_opt->port_prof_ignore_file = NULL; p_opt->hop_weights_file = NULL; p_opt->port_search_ordering_file = NULL; p_opt->port_profile_switch_nodes = FALSE; p_opt->sweep_on_trap = TRUE; p_opt->use_ucast_cache = FALSE; p_opt->routing_engine_names = NULL; p_opt->connect_roots = FALSE; p_opt->lid_matrix_dump_file = NULL; p_opt->lfts_file = NULL; p_opt->root_guid_file = NULL; p_opt->cn_guid_file = NULL; p_opt->io_guid_file = NULL; p_opt->port_shifting = FALSE; p_opt->scatter_ports = OSM_DEFAULT_SCATTER_PORTS; p_opt->max_reverse_hops = 0; p_opt->ids_guid_file = NULL; p_opt->guid_routing_order_file = NULL; p_opt->guid_routing_order_no_scatter = FALSE; p_opt->sa_db_file = NULL; p_opt->sa_db_dump = FALSE; p_opt->torus_conf_file = strdup(OSM_DEFAULT_TORUS_CONF_FILE); p_opt->do_mesh_analysis = FALSE; p_opt->exit_on_fatal = TRUE; p_opt->congestion_control = FALSE; p_opt->cc_key = OSM_DEFAULT_CC_KEY; p_opt->cc_max_outstanding_mads = OSM_CC_DEFAULT_MAX_OUTSTANDING_QUERIES; p_opt->enable_quirks = FALSE; p_opt->no_clients_rereg = FALSE; p_opt->prefix_routes_file = strdup(OSM_DEFAULT_PREFIX_ROUTES_FILE); p_opt->consolidate_ipv6_snm_req = FALSE; p_opt->lash_start_vl = 0; p_opt->sm_sl = OSM_DEFAULT_SL; p_opt->log_prefix = NULL; p_opt->per_module_logging_file = strdup(OSM_DEFAULT_PER_MOD_LOGGING_CONF_FILE); subn_init_qos_options(&p_opt->qos_options, NULL); subn_init_qos_options(&p_opt->qos_ca_options, NULL); subn_init_qos_options(&p_opt->qos_sw0_options, NULL); subn_init_qos_options(&p_opt->qos_swe_options, NULL); subn_init_qos_options(&p_opt->qos_rtr_options, NULL); p_opt->cc_cct.entries_len = 0; p_opt->cc_cct.input_str = NULL; p_opt->quasi_ftree_indexing = FALSE; } static char *clean_val(char *val) { char *p = val; /* clean leading spaces */ while (isspace(*p)) p++; val = p; if (!*val) return val; /* clean trailing spaces */ p = val + strlen(val) - 1; while (p > val && isspace(*p)) p--; p[1] = '\0'; /* clean quotas */ if ((*val == '\"' && *p == '\"') || (*val == '\'' && *p == '\'')) { val++; *p-- = '\0'; } return val; } static int subn_dump_qos_options(FILE * file, const char *set_name, const char *prefix, osm_qos_options_t * opt) { return fprintf(file, "# %s\n" "%s_max_vls %u\n" "%s_high_limit %d\n" "%s_vlarb_high %s\n" "%s_vlarb_low %s\n" "%s_sl2vl %s\n", set_name, prefix, opt->max_vls, prefix, opt->high_limit, prefix, opt->vlarb_high, prefix, opt->vlarb_low, prefix, opt->sl2vl); } static ib_api_status_t append_prefix_route(IN osm_subn_t * p_subn, uint64_t prefix, uint64_t guid) { osm_prefix_route_t *route; route = malloc(sizeof *route); if (! route) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "out of memory"); return IB_ERROR; } route->prefix = cl_hton64(prefix); route->guid = cl_hton64(guid); cl_qlist_insert_tail(&p_subn->prefix_routes_list, &route->list_item); return IB_SUCCESS; } static ib_api_status_t parse_prefix_routes_file(IN osm_subn_t * p_subn) { osm_log_t *log = &p_subn->p_osm->log; FILE *fp; char buf[1024]; int line = 0; int errors = 0; while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) { cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list); free(item); } fp = fopen(p_subn->opt.prefix_routes_file, "r"); if (! fp) { if (errno == ENOENT) return IB_SUCCESS; OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s", p_subn->opt.prefix_routes_file, strerror(errno)); return IB_ERROR; } while (fgets(buf, sizeof buf, fp) != NULL) { char *p_prefix, *p_guid, *p_extra, *p_last, *p_end; uint64_t prefix, guid; line++; if (errors > 10) break; p_prefix = strtok_r(buf, " \t\n", &p_last); if (! p_prefix) continue; /* ignore blank lines */ if (*p_prefix == '#') continue; /* ignore comment lines */ p_guid = strtok_r(NULL, " \t\n", &p_last); if (! p_guid) { OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing GUID\n", p_subn->opt.prefix_routes_file, line); errors++; continue; } p_extra = strtok_r(NULL, " \t\n", &p_last); if (p_extra && *p_extra != '#') { OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n", p_subn->opt.prefix_routes_file, line); } if (strcmp(p_prefix, "*") == 0) prefix = 0; else { prefix = strtoull(p_prefix, &p_end, 16); if (*p_end != '\0') { OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal prefix: %s\n", p_subn->opt.prefix_routes_file, line, p_prefix); errors++; continue; } } if (strcmp(p_guid, "*") == 0) guid = 0; else { guid = strtoull(p_guid, &p_end, 16); if (*p_end != '\0' && *p_end != '#') { OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal GUID: %s\n", p_subn->opt.prefix_routes_file, line, p_guid); errors++; continue; } } if (append_prefix_route(p_subn, prefix, guid) != IB_SUCCESS) { errors++; break; } } fclose(fp); return (errors == 0) ? IB_SUCCESS : IB_ERROR; } static ib_api_status_t insert_per_module_debug(IN osm_subn_t * p_subn, char *mod_name, osm_log_level_t level) { uint8_t index; if (find_module_name(mod_name, &index)) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "Module name %s not found\n", mod_name); return IB_ERROR; } osm_set_log_per_module(&p_subn->p_osm->log, index, level); return IB_SUCCESS; } static ib_api_status_t parse_per_mod_logging_file(IN osm_subn_t * p_subn) { osm_log_t *log = &p_subn->p_osm->log; FILE *fp; char buf[1024]; int line = 0; int errors = 0; osm_reset_log_per_module(log); if (p_subn->opt.per_module_logging_file == NULL) return IB_SUCCESS; fp = fopen(p_subn->opt.per_module_logging_file, "r"); if (!fp) { if (errno == ENOENT) return IB_SUCCESS; OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s", p_subn->opt.per_module_logging_file, strerror(errno)); return IB_ERROR; } while (fgets(buf, sizeof buf, fp) != NULL) { char *p_mod_name, *p_level, *p_extra, *p_last; osm_log_level_t level; line++; if (errors > 10) break; p_mod_name = strtok_r(buf, " =,\t\n", &p_last); if (!p_mod_name) continue; /* ignore blank lines */ if (*p_mod_name == '#') continue; /* ignore comment lines */ p_level = strtok_r(NULL, " \t\n", &p_last); if (!p_level) { OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing log level\n", p_subn->opt.per_module_logging_file, line); errors++; continue; } p_extra = strtok_r(NULL, " \t\n", &p_last); if (p_extra && *p_extra != '#') { OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n", p_subn->opt.per_module_logging_file, line); } level = strtoul(p_level, NULL, 0); if (insert_per_module_debug(p_subn, p_mod_name, level) != IB_SUCCESS) { errors++; break; } } fclose(fp); return (errors == 0) ? IB_SUCCESS : IB_ERROR; } static void subn_verify_max_vls(unsigned *max_vls, const char *prefix) { if (!*max_vls || *max_vls > 15) { if (*max_vls) log_report(" Invalid Cached Option: %s_max_vls=%u: " "Using Default = %u\n", prefix, *max_vls, OSM_DEFAULT_QOS_MAX_VLS); *max_vls = 0; } } static void subn_verify_high_limit(int *high_limit, const char *prefix) { if (*high_limit < 0 || *high_limit > 255) { if (*high_limit > 255) log_report(" Invalid Cached Option: %s_high_limit=%d: " "Using Default: %d\n", prefix, *high_limit, OSM_DEFAULT_QOS_HIGH_LIMIT); *high_limit = -1; } } static void subn_verify_vlarb(char **vlarb, const char *prefix, const char *suffix) { char *str, *tok, *end, *ptr; int count = 0; if (*vlarb == NULL) return; str = strdup(*vlarb); tok = strtok_r(str, ",\n", &ptr); while (tok) { char *vl_str, *weight_str; vl_str = tok; weight_str = strchr(tok, ':'); if (weight_str) { long vl, weight; *weight_str = '\0'; weight_str++; vl = strtol(vl_str, &end, 0); if (*end) log_report(" Warning: Cached Option " "%s_vlarb_%s:vl=%s" " improperly formatted\n", prefix, suffix, vl_str); else if (vl < 0 || vl > 14) log_report(" Warning: Cached Option " "%s_vlarb_%s:vl=%ld out of range\n", prefix, suffix, vl); weight = strtol(weight_str, &end, 0); if (*end) log_report(" Warning: Cached Option " "%s_vlarb_%s:weight=%s " "improperly formatted\n", prefix, suffix, weight_str); else if (weight < 0 || weight > 255) log_report(" Warning: Cached Option " "%s_vlarb_%s:weight=%ld " "out of range\n", prefix, suffix, weight); } else log_report(" Warning: Cached Option " "%s_vlarb_%s:vl:weight=%s " "improperly formatted\n", prefix, suffix, tok); count++; tok = strtok_r(NULL, ",\n", &ptr); } if (count > 64) log_report(" Warning: Cached Option %s_vlarb_%s: > 64 listed:" " excess vl:weight pairs will be dropped\n", prefix, suffix); free(str); } static void subn_verify_sl2vl(char **sl2vl, const char *prefix) { char *str, *tok, *end, *ptr; int count = 0; if (*sl2vl == NULL) return; str = strdup(*sl2vl); tok = strtok_r(str, ",\n", &ptr); while (tok) { long vl = strtol(tok, &end, 0); if (*end) log_report(" Warning: Cached Option %s_sl2vl:vl=%s " "improperly formatted\n", prefix, tok); else if (vl < 0 || vl > 15) log_report(" Warning: Cached Option %s_sl2vl:vl=%ld " "out of range\n", prefix, vl); count++; tok = strtok_r(NULL, ",\n", &ptr); } if (count < 16) log_report(" Warning: Cached Option %s_sl2vl: < 16 VLs " "listed\n", prefix); else if (count > 16) log_report(" Warning: Cached Option %s_sl2vl: > 16 listed: " "excess VLs will be dropped\n", prefix); free(str); } static void subn_verify_qos_set(osm_qos_options_t *set, const char *prefix) { subn_verify_max_vls(&set->max_vls, prefix); subn_verify_high_limit(&set->high_limit, prefix); subn_verify_vlarb(&set->vlarb_low, prefix, "low"); subn_verify_vlarb(&set->vlarb_high, prefix, "high"); subn_verify_sl2vl(&set->sl2vl, prefix); } int osm_subn_verify_config(IN osm_subn_opt_t * p_opts) { if (p_opts->lmc > 7) { log_report(" Invalid Cached Option Value:lmc = %u:" "Using Default:%u\n", p_opts->lmc, OSM_DEFAULT_LMC); p_opts->lmc = OSM_DEFAULT_LMC; } if (15 < p_opts->sm_priority) { log_report(" Invalid Cached Option Value:sm_priority = %u:" "Using Default:%u\n", p_opts->sm_priority, OSM_DEFAULT_SM_PRIORITY); p_opts->sm_priority = OSM_DEFAULT_SM_PRIORITY; } if ((15 < p_opts->force_link_speed) || (p_opts->force_link_speed > 7 && p_opts->force_link_speed < 15)) { log_report(" Invalid Cached Option Value:force_link_speed = %u:" "Using Default:%u\n", p_opts->force_link_speed, IB_PORT_LINK_SPEED_ENABLED_MASK); p_opts->force_link_speed = IB_PORT_LINK_SPEED_ENABLED_MASK; } if ((31 < p_opts->force_link_speed_ext) || (p_opts->force_link_speed_ext > 3 && p_opts->force_link_speed_ext < 30)) { log_report(" Invalid Cached Option Value:force_link_speed_ext = %u:" "Using Default:%u\n", p_opts->force_link_speed_ext, 31); p_opts->force_link_speed_ext = 31; } if (2 < p_opts->fdr10) { log_report(" Invalid Cached Option Value:fdr10 = %u:" "Using Default:%u\n", p_opts->fdr10, 1); p_opts->fdr10 = 1; } if (p_opts->max_wire_smps == 0) p_opts->max_wire_smps = 0x7FFFFFFF; else if (p_opts->max_wire_smps > 0x7FFFFFFF) { log_report(" Invalid Cached Option Value: max_wire_smps = %u," " Using Default: %u\n", p_opts->max_wire_smps, OSM_DEFAULT_SMP_MAX_ON_WIRE); p_opts->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE; } if (p_opts->max_wire_smps2 > 0x7FFFFFFF) { log_report(" Invalid Cached Option Value: max_wire_smps2 = %u," " Using Default: %u", p_opts->max_wire_smps2, p_opts->max_wire_smps); p_opts->max_wire_smps2 = p_opts->max_wire_smps; } if (strcmp(p_opts->console, OSM_DISABLE_CONSOLE) && strcmp(p_opts->console, OSM_LOCAL_CONSOLE) #ifdef ENABLE_OSM_CONSOLE_LOOPBACK && strcmp(p_opts->console, OSM_LOOPBACK_CONSOLE) #endif #ifdef ENABLE_OSM_CONSOLE_SOCKET && strcmp(p_opts->console, OSM_REMOTE_CONSOLE) #endif ) { log_report(" Invalid Cached Option Value:console = %s" ", Using Default:%s\n", p_opts->console, OSM_DEFAULT_CONSOLE); free(p_opts->console); p_opts->console = strdup(OSM_DEFAULT_CONSOLE); } if (p_opts->no_partition_enforcement == TRUE) { strcpy(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OFF); p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF; } else { if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH) == 0) p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH; else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_IN) == 0) p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_IN; else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OUT) == 0) p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OUT; else if (strcmp(p_opts->part_enforce, OSM_PARTITION_ENFORCE_OFF) == 0) p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF; else { log_report(" Invalid Cached Option Value:part_enforce = %s" ", Using Default:%s\n", p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH); strcpy(p_opts->part_enforce, OSM_PARTITION_ENFORCE_BOTH); p_opts->part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH; } } if (p_opts->qos) { subn_verify_qos_set(&p_opts->qos_options, "qos"); subn_verify_qos_set(&p_opts->qos_ca_options, "qos_ca"); subn_verify_qos_set(&p_opts->qos_sw0_options, "qos_sw0"); subn_verify_qos_set(&p_opts->qos_swe_options, "qos_swe"); subn_verify_qos_set(&p_opts->qos_rtr_options, "qos_rtr"); } #ifdef ENABLE_OSM_PERF_MGR if (p_opts->perfmgr_sweep_time_s < 1) { log_report(" Invalid Cached Option Value:perfmgr_sweep_time_s " "= %u Using Default:%u\n", p_opts->perfmgr_sweep_time_s, OSM_PERFMGR_DEFAULT_SWEEP_TIME_S); p_opts->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S; } if (p_opts->perfmgr_max_outstanding_queries < 1) { log_report(" Invalid Cached Option Value:" "perfmgr_max_outstanding_queries = %u" " Using Default:%u\n", p_opts->perfmgr_max_outstanding_queries, OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES); p_opts->perfmgr_max_outstanding_queries = OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES; } #endif if (p_opts->m_key_protect_bits > 3) { log_report(" Invalid Cached Option Value:" "m_key_protection_level = %u Setting to %u " "instead\n", p_opts->m_key_protect_bits, 2); p_opts->m_key_protect_bits = 2; } if (p_opts->m_key_protect_bits && p_opts->m_key_lease_period) { if (!p_opts->sweep_interval) { log_report(" Sweep disabled with protected mkey " "leases in effect; re-enabling sweeping " "with interval %u\n", cl_ntoh16(p_opts->m_key_lease_period) - 1); p_opts->sweep_interval = cl_ntoh16(p_opts->m_key_lease_period) - 1; } if (p_opts->sweep_interval >= cl_ntoh16(p_opts->m_key_lease_period)) { log_report(" Sweep interval %u >= mkey lease period " "%u. Setting lease period to %u\n", p_opts->sweep_interval, cl_ntoh16(p_opts->m_key_lease_period), p_opts->sweep_interval + 1); p_opts->m_key_lease_period = cl_hton16(p_opts->sweep_interval + 1); } } return 0; } int osm_subn_parse_conf_file(const char *file_name, osm_subn_opt_t * p_opts) { char line[1024]; FILE *opts_file; char *p_key, *p_val, *pound_sign; const opt_rec_t *r; void *p_field1, *p_field2; int token_matched; opts_file = fopen(file_name, "r"); if (!opts_file) { if (errno == ENOENT) return 1; printf("cannot open file \'%s\': %s\n", file_name, strerror(errno)); return -1; } printf(" Reading Cached Option File: %s\n", file_name); p_opts->config_file = file_name; if (!p_opts->file_opts && !(p_opts->file_opts = malloc(sizeof(*p_opts)))) { fclose(opts_file); return -1; } memcpy(p_opts->file_opts, p_opts, sizeof(*p_opts)); p_opts->file_opts->file_opts = NULL; while (fgets(line, 1023, opts_file) != NULL) { pound_sign = strchr(line,'#'); token_matched = 0; /* Truncate any comments. */ if (pound_sign) *pound_sign = '\0'; /* get the first token */ p_key = strtok_r(line, " \t\n", &p_val); if (!p_key) continue; p_val = clean_val(p_val); for (r = opt_tbl; r->name; r++) { if (strcmp(r->name, p_key)) continue; token_matched = 1; p_field1 = (void *)p_opts->file_opts + r->opt_offset; p_field2 = (void *)p_opts + r->opt_offset; /* don't call setup function first time */ r->parse_fn(NULL, p_key, p_val, p_field1, p_field2, NULL); break; } if (!token_matched) log_report(" Unrecognized token: \"%s\"\n", p_key); } fclose(opts_file); osm_subn_verify_config(p_opts); return 0; } int osm_subn_rescan_conf_files(IN osm_subn_t * p_subn) { char line[1024]; osm_subn_opt_t *p_opts = &p_subn->opt; const opt_rec_t *r; FILE *opts_file; char *p_key, *p_val, *pound_sign; void *p_field1, *p_field2; int token_matched; if (!p_opts->config_file) return 0; opts_file = fopen(p_opts->config_file, "r"); if (!opts_file) { if (errno == ENOENT) return 1; OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "cannot open file \'%s\': %s\n", p_opts->config_file, strerror(errno)); return -1; } subn_init_qos_options(&p_opts->qos_options, &p_opts->file_opts->qos_options); subn_init_qos_options(&p_opts->qos_ca_options, &p_opts->file_opts->qos_ca_options); subn_init_qos_options(&p_opts->qos_sw0_options, &p_opts->file_opts->qos_sw0_options); subn_init_qos_options(&p_opts->qos_swe_options, &p_opts->file_opts->qos_swe_options); subn_init_qos_options(&p_opts->qos_rtr_options, &p_opts->file_opts->qos_rtr_options); while (fgets(line, 1023, opts_file) != NULL) { pound_sign = strchr(line,'#'); token_matched = 0; /* Truncate any comments. */ if (pound_sign) *pound_sign = '\0'; /* get the first token */ p_key = strtok_r(line, " \t\n", &p_val); if (!p_key) continue; p_val = clean_val(p_val); for (r = opt_tbl; r->name; r++) { if (strcmp(r->name, p_key)) continue; token_matched = 1; if (!r->can_update) continue; p_field1 = (void *)p_opts->file_opts + r->opt_offset; p_field2 = (void *)p_opts + r->opt_offset; r->parse_fn(p_subn, p_key, p_val, p_field1, p_field2, r->setup_fn); break; } if (!token_matched) log_report(" Unrecognized token: \"%s\"\n", p_key); } fclose(opts_file); osm_subn_verify_config(p_opts); parse_prefix_routes_file(p_subn); parse_per_mod_logging_file(p_subn); return 0; } void osm_subn_output_conf(FILE *out, IN osm_subn_opt_t * p_opts) { int cacongoutputcount = 0; int i; fprintf(out, "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n" "# The port GUID on which the OpenSM is running\n" "guid 0x%016" PRIx64 "\n\n" "# M_Key value sent to all ports qualifying all Set(PortInfo)\n" "m_key 0x%016" PRIx64 "\n\n" "# The lease period used for the M_Key on this subnet in [sec]\n" "m_key_lease_period %u\n\n" "# The protection level used for the M_Key on this subnet\n" "m_key_protection_level %u\n\n" "# If TRUE, SM tries to determine the m_key of unknown ports from guid2mkey file\n" "# If FALSE, SM won't try to determine the m_key of unknown ports.\n" "# Preconfigured m_key will be used instead\n" "m_key_lookup %s\n\n" "# SM_Key value of the SM used for SM authentication\n" "sm_key 0x%016" PRIx64 "\n\n" "# SM_Key value to qualify rcv SA queries as 'trusted'\n" "sa_key 0x%016" PRIx64 "\n\n" "# Note that for both values above (sm_key and sa_key)\n" "# OpenSM version 3.2.1 and below used the default value '1'\n" "# in a host byte order, it is fixed now but you may need to\n" "# change the values to interoperate with old OpenSM running\n" "# on a little endian machine.\n\n" "# Subnet prefix used on this subnet\n" "subnet_prefix 0x%016" PRIx64 "\n\n" "# The LMC value used on this subnet\n" "lmc %u\n\n" "# lmc_esp0 determines whether LMC value used on subnet is used for\n" "# enhanced switch port 0. If TRUE, LMC value for subnet is used for\n" "# ESP0. Otherwise, LMC value for ESP0s is 0.\n" "lmc_esp0 %s\n\n" "# sm_sl determines SMSL used for SM/SA communication\n" "sm_sl %u\n\n" "# The code of maximal time a packet can live in a switch\n" "# The actual time is 4.096usec * 2^\n" "# The value 0x14 disables this mechanism\n" "packet_life_time 0x%02x\n\n" "# The number of sequential packets dropped that cause the port\n" "# to enter the VLStalled state. The result of setting this value to\n" "# zero is undefined.\n" "vl_stall_count 0x%02x\n\n" "# The number of sequential packets dropped that cause the port\n" "# to enter the VLStalled state. This value is for switch ports\n" "# driving a CA or router port. The result of setting this value\n" "# to zero is undefined.\n" "leaf_vl_stall_count 0x%02x\n\n" "# The code of maximal time a packet can wait at the head of\n" "# transmission queue.\n" "# The actual time is 4.096usec * 2^\n" "# The value 0x14 disables this mechanism\n" "head_of_queue_lifetime 0x%02x\n\n" "# The maximal time a packet can wait at the head of queue on\n" "# switch port connected to a CA or router port\n" "leaf_head_of_queue_lifetime 0x%02x\n\n" "# Limit the maximal operational VLs\n" "max_op_vls %u\n\n" "# Force PortInfo:LinkSpeedEnabled on switch ports\n" "# If 0, don't modify PortInfo:LinkSpeedEnabled on switch port\n" "# Otherwise, use value for PortInfo:LinkSpeedEnabled on switch port\n" "# Values are (IB Spec 1.2.1, 14.2.5.6 Table 146 \"PortInfo\")\n" "# 1: 2.5 Gbps\n" "# 3: 2.5 or 5.0 Gbps\n" "# 5: 2.5 or 10.0 Gbps\n" "# 7: 2.5 or 5.0 or 10.0 Gbps\n" "# 2,4,6,8-14 Reserved\n" "# Default 15: set to PortInfo:LinkSpeedSupported\n" "force_link_speed %u\n\n" "# Force PortInfo:LinkSpeedExtEnabled on ports\n" "# If 0, don't modify PortInfo:LinkSpeedExtEnabled on port\n" "# Otherwise, use value for PortInfo:LinkSpeedExtEnabled on port\n" "# Values are (MgtWG RefID #4722)\n" "# 1: 14.0625 Gbps\n" "# 2: 25.78125 Gbps\n" "# 3: 14.0625 Gbps or 25.78125 Gbps\n" "# 30: Disable extended link speeds\n" "# Default 31: set to PortInfo:LinkSpeedExtSupported\n" "force_link_speed_ext %u\n\n" "# FDR10 on ports on devices that support FDR10\n" "# Values are:\n" "# 0: don't use fdr10 (no MLNX ExtendedPortInfo MADs)\n" "# Default 1: enable fdr10 when supported\n" "# 2: disable fdr10 when supported\n" "fdr10 %u\n\n" "# The subnet_timeout code that will be set for all the ports\n" "# The actual timeout is 4.096usec * 2^\n" "subnet_timeout %u\n\n" "# Threshold of local phy errors for sending Trap 129\n" "local_phy_errors_threshold 0x%02x\n\n" "# Threshold of credit overrun errors for sending Trap 130\n" "overrun_errors_threshold 0x%02x\n\n" "# Use SwitchInfo:MulticastFDBTop if advertised in PortInfo:CapabilityMask\n" "use_mfttop %s\n\n", cl_ntoh64(p_opts->guid), cl_ntoh64(p_opts->m_key), cl_ntoh16(p_opts->m_key_lease_period), p_opts->m_key_protect_bits, p_opts->m_key_lookup ? "TRUE" : "FALSE", cl_ntoh64(p_opts->sm_key), cl_ntoh64(p_opts->sa_key), cl_ntoh64(p_opts->subnet_prefix), p_opts->lmc, p_opts->lmc_esp0 ? "TRUE" : "FALSE", p_opts->sm_sl, p_opts->packet_life_time, p_opts->vl_stall_count, p_opts->leaf_vl_stall_count, p_opts->head_of_queue_lifetime, p_opts->leaf_head_of_queue_lifetime, p_opts->max_op_vls, p_opts->force_link_speed, p_opts->force_link_speed_ext, p_opts->fdr10, p_opts->subnet_timeout, p_opts->local_phy_errors_threshold, p_opts->overrun_errors_threshold, p_opts->use_mfttop ? "TRUE" : "FALSE"); fprintf(out, "#\n# PARTITIONING OPTIONS\n#\n" "# Partition configuration file to be used\n" "partition_config_file %s\n\n" "# Disable partition enforcement by switches (DEPRECATED)\n" "# This option is DEPRECATED. Please use part_enforce instead\n" "no_partition_enforcement %s\n\n" "# Partition enforcement type (for switches)\n" "# Values are both, out, in and off\n" "# Default is both (outbound and inbound enforcement)\n" "part_enforce %s\n\n" "# Allow both full and limited membership on the same partition\n" "allow_both_pkeys %s\n\n" "# SM assigned GUID byte where GUID is formed from OpenFabrics OUI\n" "# followed by 40 bits xy 00 ab cd ef where xy is the SM assigned GUID byte\n" "# and ab cd ef is an SM autogenerated 24 bits\n" "# SM assigned GUID byte should be configured as subnet unique\n" "sm_assigned_guid 0x%02x\n\n", p_opts->partition_config_file, p_opts->no_partition_enforcement ? "TRUE" : "FALSE", p_opts->part_enforce, p_opts->allow_both_pkeys ? "TRUE" : "FALSE", p_opts->sm_assigned_guid); fprintf(out, "#\n# SWEEP OPTIONS\n#\n" "# The number of seconds between subnet sweeps (0 disables it)\n" "sweep_interval %u\n\n" "# If TRUE cause all lids to be reassigned\n" "reassign_lids %s\n\n" "# If TRUE forces every sweep to be a heavy sweep\n" "force_heavy_sweep %s\n\n" "# If TRUE every trap 128 and 144 will cause a heavy sweep.\n" "# NOTE: successive identical traps (>10) are suppressed\n" "sweep_on_trap %s\n\n", p_opts->sweep_interval, p_opts->reassign_lids ? "TRUE" : "FALSE", p_opts->force_heavy_sweep ? "TRUE" : "FALSE", p_opts->sweep_on_trap ? "TRUE" : "FALSE"); fprintf(out, "#\n# ROUTING OPTIONS\n#\n" "# If TRUE count switches as link subscriptions\n" "port_profile_switch_nodes %s\n\n", p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE"); fprintf(out, "# Name of file with port guids to be ignored by port profiling\n" "port_prof_ignore_file %s\n\n", p_opts->port_prof_ignore_file ? p_opts->port_prof_ignore_file : null_str); fprintf(out, "# The file holding routing weighting factors per output port\n" "hop_weights_file %s\n\n", p_opts->hop_weights_file ? p_opts->hop_weights_file : null_str); fprintf(out, "# The file holding non-default port order per switch for routing\n" "port_search_ordering_file %s\n\n", p_opts->port_search_ordering_file ? p_opts->port_search_ordering_file : null_str); fprintf(out, "# Routing engine\n" "# Multiple routing engines can be specified separated by\n" "# commas so that specific ordering of routing algorithms will\n" "# be tried if earlier routing engines fail.\n" "# Supported engines: minhop, updn, dnup, file, ftree, lash,\n" "# dor, torus-2QoS, dfsssp, sssp\n" "routing_engine %s\n\n", p_opts->routing_engine_names ? p_opts->routing_engine_names : null_str); fprintf(out, "# Connect roots (use FALSE if unsure)\n" "connect_roots %s\n\n", p_opts->connect_roots ? "TRUE" : "FALSE"); fprintf(out, "# Use unicast routing cache (use FALSE if unsure)\n" "use_ucast_cache %s\n\n", p_opts->use_ucast_cache ? "TRUE" : "FALSE"); fprintf(out, "# Lid matrix dump file name\n" "lid_matrix_dump_file %s\n\n", p_opts->lid_matrix_dump_file ? p_opts->lid_matrix_dump_file : null_str); fprintf(out, "# LFTs file name\nlfts_file %s\n\n", p_opts->lfts_file ? p_opts->lfts_file : null_str); fprintf(out, "# The file holding the root node guids (for fat-tree or Up/Down)\n" "# One guid in each line\nroot_guid_file %s\n\n", p_opts->root_guid_file ? p_opts->root_guid_file : null_str); fprintf(out, "# The file holding the fat-tree compute node guids\n" "# One guid in each line\ncn_guid_file %s\n\n", p_opts->cn_guid_file ? p_opts->cn_guid_file : null_str); fprintf(out, "# The file holding the fat-tree I/O node guids\n" "# One guid in each line.\n" "# If only io_guid file is provided, the rest of nodes\n" "# are considered as compute nodes.\n" "io_guid_file %s\n\n", p_opts->io_guid_file ? p_opts->io_guid_file : null_str); fprintf(out, "# If TRUE enables alternative indexing policy for ftree routing\n" "# in quasi-ftree topologies that can improve shift-pattern support.\n" "# The switch indexing starts from root switch and leaf switches\n" "# are termination points of BFS algorithm\n" "# If FALSE, the indexing starts from leaf switch (default)\n" "quasi_ftree_indexing %s\n\n", p_opts->quasi_ftree_indexing ? "TRUE" : "FALSE"); fprintf(out, "# Number of reverse hops allowed for I/O nodes\n" "# Used for connectivity between I/O nodes connected to Top Switches\nmax_reverse_hops %d\n\n", p_opts->max_reverse_hops); fprintf(out, "# The file holding the node ids which will be used by" " Up/Down algorithm instead\n# of GUIDs (one guid and" " id in each line)\nids_guid_file %s\n\n", p_opts->ids_guid_file ? p_opts->ids_guid_file : null_str); fprintf(out, "# The file holding guid routing order guids (for MinHop and Up/Down)\n" "guid_routing_order_file %s\n\n", p_opts->guid_routing_order_file ? p_opts->guid_routing_order_file : null_str); fprintf(out, "# Do mesh topology analysis (for LASH algorithm)\n" "do_mesh_analysis %s\n\n", p_opts->do_mesh_analysis ? "TRUE" : "FALSE"); fprintf(out, "# Starting VL for LASH algorithm\n" "lash_start_vl %u\n\n", p_opts->lash_start_vl); fprintf(out, "# Port Shifting (use FALSE if unsure)\n" "port_shifting %s\n\n", p_opts->port_shifting ? "TRUE" : "FALSE"); fprintf(out, "# Assign ports in a random order instead of round-robin\n" "# If zero disable (default), otherwise use the value as a random seed\n" "scatter_ports %d\n\n", p_opts->scatter_ports); fprintf(out, "# Don't use scatter for ports defined in\n" "# guid_routing_order file\n" "guid_routing_order_no_scatter %s\n\n", p_opts->guid_routing_order_no_scatter ? "TRUE" : "FALSE"); fprintf(out, "# SA database file name\nsa_db_file %s\n\n", p_opts->sa_db_file ? p_opts->sa_db_file : null_str); fprintf(out, "# If TRUE causes OpenSM to dump SA database at the end of\n" "# every light sweep, regardless of the verbosity level\n" "sa_db_dump %s\n\n", p_opts->sa_db_dump ? "TRUE" : "FALSE"); fprintf(out, "# Torus-2QoS configuration file name\ntorus_config %s\n\n", p_opts->torus_conf_file ? p_opts->torus_conf_file : null_str); fprintf(out, "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n" "# SM priority used for deciding who is the master\n" "# Range goes from 0 (lowest priority) to 15 (highest).\n" "sm_priority %u\n\n" "# If TRUE other SMs on the subnet should be ignored\n" "ignore_other_sm %s\n\n" "# Timeout in [msec] between two polls of active master SM\n" "sminfo_polling_timeout %u\n\n" "# Number of failing polls of remote SM that declares it dead\n" "polling_retry_number %u\n\n" "# If TRUE honor the guid2lid file when coming out of standby\n" "# state, if such file exists and is valid\n" "honor_guid2lid_file %s\n\n", p_opts->sm_priority, p_opts->ignore_other_sm ? "TRUE" : "FALSE", p_opts->sminfo_polling_timeout, p_opts->polling_retry_number, p_opts->honor_guid2lid_file ? "TRUE" : "FALSE"); fprintf(out, "#\n# TIMING AND THREADING OPTIONS\n#\n" "# Maximum number of SMPs sent in parallel\n" "max_wire_smps %u\n\n" "# Maximum number of timeout based SMPs allowed to be outstanding\n" "# A value less than or equal to max_wire_smps disables this mechanism\n" "max_wire_smps2 %u\n\n" "# The timeout in [usec] used for sending SMPs above max_wire_smps limit\n" "# and below max_wire_smps2 limit\n" "max_smps_timeout %u\n\n" "# The maximum time in [msec] allowed for a transaction to complete\n" "transaction_timeout %u\n\n" "# The maximum number of retries allowed for a transaction to complete\n" "transaction_retries %u\n\n" "# Maximal time in [msec] a message can stay in the incoming message queue.\n" "# If there is more than one message in the queue and the last message\n" "# stayed in the queue more than this value, any SA request will be\n" "# immediately be dropped but BUSY status is not currently returned.\n" "max_msg_fifo_timeout %u\n\n" "# Use a single thread for handling SA queries\n" "single_thread %s\n\n", p_opts->max_wire_smps, p_opts->max_wire_smps2, p_opts->max_smps_timeout, p_opts->transaction_timeout, p_opts->transaction_retries, p_opts->max_msg_fifo_timeout, p_opts->single_thread ? "TRUE" : "FALSE"); fprintf(out, "#\n# MISC OPTIONS\n#\n" "# Daemon mode\n" "daemon %s\n\n" "# SM Inactive\n" "sm_inactive %s\n\n" "# Babbling Port Policy\n" "babbling_port_policy %s\n\n" "# Drop event subscriptions (InformInfo and ServiceRecord) on port removal and SM coming out of STANDBY\n" "drop_event_subscriptions %s\n\n" "# Validate IPoIB non-broadcast group creation parameters against\n" "# broadcast group parameters per IETF RFC 4391 (default TRUE)\n" "ipoib_mcgroup_creation_validation %s\n\n" "# Validate multicast join parameters against multicast group\n" "# parameters when MC group already exists\n" "mcgroup_join_validation %s\n\n" "# Use Optimized SLtoVLMapping programming if supported by device\n" "use_optimized_slvl %s\n\n" "# Sync in memory files used for high availability with storage\n" "fsync_high_avail_files %s\n\n", p_opts->daemon ? "TRUE" : "FALSE", p_opts->sm_inactive ? "TRUE" : "FALSE", p_opts->babbling_port_policy ? "TRUE" : "FALSE", p_opts->drop_event_subscriptions ? "TRUE" : "FALSE", p_opts->ipoib_mcgroup_creation_validation ? "TRUE" : "FALSE", p_opts->mcgroup_join_validation ? "TRUE" : "FALSE", p_opts->use_optimized_slvl ? "TRUE" : "FALSE", p_opts->fsync_high_avail_files ? "TRUE" : "FALSE"); #ifdef ENABLE_OSM_PERF_MGR fprintf(out, "#\n# Performance Manager Options\n#\n" "# perfmgr enable\n" "# PerfMgr is enabled if TRUE and disabled if FALSE (default FALSE)\n" "perfmgr %s\n\n" "# redirection enable\n" "# Redirection supported if TRUE and not supported if FALSE (default TRUE)\n" "perfmgr_redir %s\n\n" "# sweep time in seconds (default %u seconds)\n" "perfmgr_sweep_time_s %u\n\n" "# Max outstanding queries (default %u)\n" "perfmgr_max_outstanding_queries %u\n\n" "# Ignore CAs on sweep (default FALSE)\n" "perfmgr_ignore_cas %s\n\n" "# Remove missing nodes from DB (default TRUE)\n" "perfmgr_rm_nodes %s\n\n" "# Log error counters to opensm.log (default TRUE)\n" "perfmgr_log_errors %s\n\n" "# Query PerfMgt Get(ClassPortInfo) for extended capabilities\n" "# Extended capabilities include 64 bit extended counters\n" "# and transmit wait support (default TRUE)\n" "perfmgr_query_cpi %s\n\n" "# Log xmit_wait errors (default FALSE)\n" "perfmgr_xmit_wait_log %s\n\n" "# If logging xmit_wait's; set threshold (default %u)\n" "perfmgr_xmit_wait_threshold %u\n\n" , p_opts->perfmgr ? "TRUE" : "FALSE", p_opts->perfmgr_redir ? "TRUE" : "FALSE", OSM_PERFMGR_DEFAULT_SWEEP_TIME_S, p_opts->perfmgr_sweep_time_s, OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES, p_opts->perfmgr_max_outstanding_queries, p_opts->perfmgr_ignore_cas ? "TRUE" : "FALSE", p_opts->perfmgr_rm_nodes ? "TRUE" : "FALSE", p_opts->perfmgr_log_errors ? "TRUE" : "FALSE", p_opts->perfmgr_query_cpi ? "TRUE" : "FALSE", p_opts->perfmgr_xmit_wait_log ? "TRUE" : "FALSE", OSM_PERFMGR_DEFAULT_XMIT_WAIT_THRESHOLD, p_opts->perfmgr_xmit_wait_threshold); fprintf(out, "#\n# Event DB Options\n#\n" "# Dump file to dump the events to\n" "event_db_dump_file %s\n\n", p_opts->event_db_dump_file ? p_opts->event_db_dump_file : null_str); #endif /* ENABLE_OSM_PERF_MGR */ fprintf(out, "#\n# Event Plugin Options\n#\n" "# Event plugin name(s)\n" "event_plugin_name %s\n\n" "# Options string that would be passed to the plugin(s)\n" "event_plugin_options %s\n\n", p_opts->event_plugin_name ? p_opts->event_plugin_name : null_str, p_opts->event_plugin_options ? p_opts->event_plugin_options : null_str); fprintf(out, "#\n# Node name map for mapping node's to more descriptive node descriptions\n" "# (man ibnetdiscover for more information)\n#\n" "node_name_map_name %s\n\n", p_opts->node_name_map_name ? p_opts->node_name_map_name : null_str); fprintf(out, "#\n# DEBUG FEATURES\n#\n" "# The log flags used\n" "log_flags 0x%02x\n\n" "# Force flush of the log file after each log message\n" "force_log_flush %s\n\n" "# Log file to be used\n" "log_file %s\n\n" "# Limit the size of the log file in MB. If overrun, log is restarted\n" "log_max_size %u\n\n" "# If TRUE will accumulate the log over multiple OpenSM sessions\n" "accum_log_file %s\n\n" "# Per module logging configuration file\n" "# Each line in config file contains \n" "# where module_name is file name including .c\n" "# separator is either = , space, or tab\n" "# log_flags is the same flags as used in the coarse/overall logging\n" "per_module_logging_file %s\n\n" "# The directory to hold the file OpenSM dumps\n" "dump_files_dir %s\n\n" "# If TRUE enables new high risk options and hardware specific quirks\n" "enable_quirks %s\n\n" "# If TRUE disables client reregistration\n" "no_clients_rereg %s\n\n" "# If TRUE OpenSM should disable multicast support and\n" "# no multicast routing is performed if TRUE\n" "disable_multicast %s\n\n" "# If TRUE opensm will exit on fatal initialization issues\n" "exit_on_fatal %s\n\n" "# console [off|local" #ifdef ENABLE_OSM_CONSOLE_LOOPBACK "|loopback" #endif #ifdef ENABLE_OSM_CONSOLE_SOCKET "|socket]\n" #else "]\n" #endif "console %s\n\n" "# Telnet port for console (default %d)\n" "console_port %d\n\n", p_opts->log_flags, p_opts->force_log_flush ? "TRUE" : "FALSE", p_opts->log_file, p_opts->log_max_size, p_opts->accum_log_file ? "TRUE" : "FALSE", p_opts->per_module_logging_file ? p_opts->per_module_logging_file : null_str, p_opts->dump_files_dir, p_opts->enable_quirks ? "TRUE" : "FALSE", p_opts->no_clients_rereg ? "TRUE" : "FALSE", p_opts->disable_multicast ? "TRUE" : "FALSE", p_opts->exit_on_fatal ? "TRUE" : "FALSE", p_opts->console, OSM_DEFAULT_CONSOLE_PORT, p_opts->console_port); fprintf(out, "#\n# QoS OPTIONS\n#\n" "# Enable QoS setup\n" "qos %s\n\n" "# QoS policy file to be used\n" "qos_policy_file %s\n" "# Supress QoS MAD status errors\n" "suppress_sl2vl_mad_status_errors %s\n\n", p_opts->qos ? "TRUE" : "FALSE", p_opts->qos_policy_file, p_opts->suppress_sl2vl_mad_status_errors ? "TRUE" : "FALSE"); subn_dump_qos_options(out, "QoS default options", "qos", &p_opts->qos_options); fprintf(out, "\n"); subn_dump_qos_options(out, "QoS CA options", "qos_ca", &p_opts->qos_ca_options); fprintf(out, "\n"); subn_dump_qos_options(out, "QoS Switch Port 0 options", "qos_sw0", &p_opts->qos_sw0_options); fprintf(out, "\n"); subn_dump_qos_options(out, "QoS Switch external ports options", "qos_swe", &p_opts->qos_swe_options); fprintf(out, "\n"); subn_dump_qos_options(out, "QoS Router ports options", "qos_rtr", &p_opts->qos_rtr_options); fprintf(out, "\n"); fprintf(out, "#\n# Congestion Control OPTIONS (EXPERIMENTAL)\n#\n\n" "# Enable Congestion Control Configuration\n" "congestion_control %s\n\n" "# CCKey to use when configuring congestion control\n" "# note that this does not configure a new CCkey, only the CCkey to use\n" "cc_key 0x%016" PRIx64 "\n\n" "# Congestion Control Max outstanding MAD\n" "cc_max_outstanding_mads %u\n\n", p_opts->congestion_control ? "TRUE" : "FALSE", cl_ntoh64(p_opts->cc_key), p_opts->cc_max_outstanding_mads); fprintf(out, "#\n# Congestion Control SwitchCongestionSetting options\n#\n" "# Control Map - bitmask indicating which of the following are to be used\n" "# bit 0 - victim mask\n" "# bit 1 - credit mask\n" "# bit 2 - threshold + packet size\n" "# bit 3 - credit starvation threshold + return delay valid\n" "# bit 4 - marking rate valid\n" "cc_sw_cong_setting_control_map 0x%X\n\n", cl_ntoh32(p_opts->cc_sw_cong_setting_control_map)); fprintf(out, "# Victim Mask - 256 bit mask representing switch ports, mark packets with FECN\n" "# whether they are the source or victim of congestion\n" "# bit 0 - port 0 (enhanced port)\n" "# bit 1 - port 1\n" "# ...\n" "# bit 254 - port 254\n" "# bit 255 - reserved\n" "cc_sw_cong_setting_victim_mask 0x"); for (i = 0; i < IB_CC_PORT_MASK_DATA_SIZE; i++) fprintf(out, "%02X", p_opts->cc_sw_cong_setting_victim_mask[i]); fprintf(out, "\n\n"); fprintf(out, "# Credit Mask - 256 bit mask representing switch ports to apply credit starvation\n" "# bit 0 - port 0 (enhanced port)\n" "# bit 1 - port 1\n" "# ...\n" "# bit 254 - port 254\n" "# bit 255 - reserved\n" "cc_sw_cong_setting_credit_mask 0x"); for (i = 0; i < IB_CC_PORT_MASK_DATA_SIZE; i++) fprintf(out, "%02X", p_opts->cc_sw_cong_setting_credit_mask[i]); fprintf(out, "\n\n"); fprintf(out, "# Threshold - value indicating aggressiveness of congestion marking\n" "# 0x0 - none, 0x1 - loose, ..., 0xF - aggressive\n" "cc_sw_cong_setting_threshold 0x%02X\n\n" "# Packet Size - any packet less than this size will not be marked with a FECN\n" "# units are in credits\n" "cc_sw_cong_setting_packet_size %u\n\n" "# Credit Starvation Threshold - value indicating aggressiveness of credit starvation\n" "# 0x0 - none, 0x1 - loose, ..., 0xF - aggressive\n" "cc_sw_cong_setting_credit_starvation_threshold 0x%02X\n\n" "# Credit Starvation Return Delay - in CCT entry shift:multiplier format, see IB spec\n" "cc_sw_cong_setting_credit_starvation_return_delay %u:%u\n\n" "# Marking Rate - mean number of packets between markings\n" "cc_sw_cong_setting_marking_rate %u\n\n", p_opts->cc_sw_cong_setting_threshold, p_opts->cc_sw_cong_setting_packet_size, p_opts->cc_sw_cong_setting_credit_starvation_threshold, p_opts->cc_sw_cong_setting_credit_starvation_return_delay.shift, p_opts->cc_sw_cong_setting_credit_starvation_return_delay.multiplier, cl_ntoh16(p_opts->cc_sw_cong_setting_marking_rate)); fprintf(out, "#\n# Congestion Control CA Congestion Setting options\n#\n" "# Port Control\n" "# bit 0 = 0, QP based congestion control\n" "# bit 0 = 1, SL/port based congestion control\n" "cc_ca_cong_setting_port_control 0x%04X\n\n" "# Control Map - 16 bit bitmask indicating which SLs should be configured\n" "cc_ca_cong_setting_control_map 0x%04X\n\n", cl_ntoh16(p_opts->cc_ca_cong_setting_port_control), cl_ntoh16(p_opts->cc_ca_cong_setting_control_map)); fprintf(out, "#\n# CA Congestion Setting Entries\n#\n" "# Each of congestion control settings below configures the CA Congestion\n" "# Settings for an individual SL. The SL must be specified before the value.\n" "# These options may be specified multiple times to configure different values\n" "# for different SLs.\n" "#\n" "# ccti timer - when expires decrements 1 from the CCTI\n" "# ccti increase - number to be added to the table index on receipt of a BECN\n" "# trigger threshold - when the ccti is equal to this, an event is logged\n" "# ccti min - the minimum value for the ccti. This imposes a minimum rate\n" "# on the injection rate\n\n"); for (i = 0; i < IB_CA_CONG_ENTRY_DATA_SIZE; i++) { /* Don't output unless one of the settings has been set, there's no need * to output 16 chunks of this with all defaults of 0 */ if (p_opts->cc_ca_cong_entries[i].ccti_timer || p_opts->cc_ca_cong_entries[i].ccti_increase || p_opts->cc_ca_cong_entries[i].trigger_threshold || p_opts->cc_ca_cong_entries[i].ccti_min) { fprintf(out, "# SL = %u\n" "cc_ca_cong_setting_ccti_timer %u %u\n" "cc_ca_cong_setting_ccti_increase %u %u\n" "cc_ca_cong_setting_trigger_threshold %u %u\n" "cc_ca_cong_setting_ccti_min %u %u\n\n", i, i, cl_ntoh16(p_opts->cc_ca_cong_entries[i].ccti_timer), i, p_opts->cc_ca_cong_entries[i].ccti_increase, i, p_opts->cc_ca_cong_entries[i].trigger_threshold, i, p_opts->cc_ca_cong_entries[i].ccti_min); cacongoutputcount++; } } /* If by chance all the CA Cong Settings are default, output at least 1 chunk * for illustration */ if (!cacongoutputcount) fprintf(out, "# SL = 0\n" "cc_ca_cong_setting_ccti_timer 0 %u\n" "cc_ca_cong_setting_ccti_increase 0 %u\n" "cc_ca_cong_setting_trigger_threshold 0 %u\n" "cc_ca_cong_setting_ccti_min 0 %u\n\n", cl_ntoh16(p_opts->cc_ca_cong_entries[0].ccti_timer), p_opts->cc_ca_cong_entries[0].ccti_increase, p_opts->cc_ca_cong_entries[0].trigger_threshold, p_opts->cc_ca_cong_entries[0].ccti_min); fprintf(out, "#\n# Congestion Control Table\n#\n" "# Comma separated list of CCT entries representing CCT.\n" "# Format is shift:multipler,shift_multiplier,shift:multiplier,...\n" "cc_cct "); if (!p_opts->cc_cct.entries_len) { fprintf(out, "%s\n", null_str); } else { fprintf(out, "%u:%u", p_opts->cc_cct.entries[0].shift, p_opts->cc_cct.entries[0].multiplier); for (i = 1; i < p_opts->cc_cct.entries_len; i++) { fprintf(out, ",%u:%u", p_opts->cc_cct.entries[i].shift, p_opts->cc_cct.entries[i].multiplier); } fprintf(out, "\n"); } fprintf(out, "\n"); fprintf(out, "# Prefix routes file name\n" "prefix_routes_file %s\n\n", p_opts->prefix_routes_file); fprintf(out, "#\n# IPv6 Solicited Node Multicast (SNM) Options\n#\n" "consolidate_ipv6_snm_req %s\n\n", p_opts->consolidate_ipv6_snm_req ? "TRUE" : "FALSE"); fprintf(out, "# Log prefix\nlog_prefix %s\n\n", p_opts->log_prefix); /* optional string attributes ... */ } int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t * p_opts) { FILE *opts_file; opts_file = fopen(file_name, "w"); if (!opts_file) { printf("cannot open file \'%s\' for writing: %s\n", file_name, strerror(errno)); return -1; } osm_subn_output_conf(opts_file, p_opts); fclose(opts_file); return 0; } opensm-3.3.20/opensm/osm_sw_info_rcv.c0000644000205000001450000003337112472650240014662 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005,2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_si_rcv_t. * This object represents the SwitchInfo Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_SW_INFO_RCV_C #include #include #include #include #include #if 0 /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void si_rcv_get_fwd_tbl(IN osm_sm_t * sm, IN osm_switch_t * p_sw) { osm_madw_context_t context; osm_dr_path_t *p_dr_path; osm_physp_t *p_physp; osm_node_t *p_node; uint32_t block_id_ho; uint32_t max_block_id_ho; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); p_node = p_sw->p_node; CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); context.lft_context.node_guid = osm_node_get_node_guid(p_node); context.lft_context.set_method = FALSE; max_block_id_ho = osm_switch_get_max_block_id_in_use(p_sw); p_physp = osm_node_get_physp_ptr(p_node, 0); p_dr_path = osm_physp_get_dr_path_ptr(p_physp); for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Retrieving FT block %u\n", block_id_ho); status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_LIN_FWD_TBL, cl_hton32(block_id_ho), TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) /* continue the loop despite the error */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3603: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); } OSM_LOG_EXIT(sm->p_log); } /********************************************************************** The plock must be held before calling this function. **********************************************************************/ static void si_rcv_get_mcast_fwd_tbl(IN osm_sm_t * sm, IN osm_switch_t * p_sw) { osm_madw_context_t context; osm_dr_path_t *p_dr_path; osm_physp_t *p_physp; osm_node_t *p_node; osm_mcast_tbl_t *p_tbl; uint32_t block_id_ho; uint32_t max_block_id_ho; uint32_t position; uint32_t max_position; uint32_t attr_mod_ho; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_sw); p_node = p_sw->p_node; CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); if (osm_switch_get_mcast_fwd_tbl_size(p_sw) == 0) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Multicast not supported by switch 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); goto Exit; } context.mft_context.node_guid = osm_node_get_node_guid(p_node); context.mft_context.set_method = FALSE; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); max_block_id_ho = osm_mcast_tbl_get_max_block(p_tbl); if (max_block_id_ho > IB_MCAST_MAX_BLOCK_ID) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3609: " "Out-of-range mcast block size = %u on switch 0x%016" PRIx64 "\n", max_block_id_ho, cl_ntoh64(osm_node_get_node_guid(p_node))); goto Exit; } max_position = osm_mcast_tbl_get_max_position(p_tbl); CL_ASSERT(max_position <= IB_MCAST_POSITION_MAX); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Max MFT block = %u, Max position = %u\n", max_block_id_ho, max_position); p_physp = osm_node_get_physp_ptr(p_node, 0); p_dr_path = osm_physp_get_dr_path_ptr(p_physp); for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Retrieving MFT block %u\n", block_id_ho); for (position = 0; position <= max_position; position++) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Retrieving MFT position %u\n", position); attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT; status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_MCAST_FWD_TBL, cl_hton32(attr_mod_ho), TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) /* continue the loop despite the error */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3607: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); } } Exit: OSM_LOG_EXIT(sm->p_log); } #endif /********************************************************************** Lock must be held on entry to this function. **********************************************************************/ static void si_rcv_process_new(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { osm_switch_t *p_sw; osm_switch_t *p_check; ib_switch_info_t *p_si; ib_smp_t *p_smp; cl_qmap_t *p_sw_guid_tbl; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_sw_guid_tbl = &sm->p_subn->sw_guid_tbl; p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); osm_dump_switch_info_v2(sm->p_log, p_si, FILE_ID, OSM_LOG_DEBUG); p_sw = osm_switch_new(p_node, p_madw); if (p_sw == NULL) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3608: " "Unable to allocate new switch object\n"); goto Exit; } /* set subnet max mlid to the minimum MulticastFDBCap of all switches */ if (p_si->mcast_cap && cl_ntoh16(p_si->mcast_cap) + IB_LID_MCAST_START_HO - 1 < sm->p_subn->max_mcast_lid_ho) { sm->p_subn->max_mcast_lid_ho = cl_ntoh16(p_si->mcast_cap) + IB_LID_MCAST_START_HO - 1; OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Subnet max multicast lid is 0x%X\n", sm->p_subn->max_mcast_lid_ho); } /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */ if (cl_ntoh16(p_si->lin_cap) < sm->p_subn->max_ucast_lid_ho) { sm->p_subn->max_ucast_lid_ho = cl_ntoh16(p_si->lin_cap); OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Subnet max unicast lid is 0x%X\n", sm->p_subn->max_ucast_lid_ho); } p_check = (osm_switch_t *) cl_qmap_insert(p_sw_guid_tbl, osm_node_get_node_guid (p_node), &p_sw->map_item); if (p_check != p_sw) { /* This shouldn't happen since we hold the lock! */ OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3605: " "Unable to add new switch object to database\n"); osm_switch_delete(&p_sw); goto Exit; } p_node->sw = p_sw; /* Update the switch info according to the info we just received. */ osm_switch_set_switch_info(p_sw, p_si); #if 0 /* Don't bother retrieving the current unicast and multicast tables from the switches. The current version of SM does not support silent take-over of an existing multicast configuration. Gathering the multicast tables can also generate large amounts of extra subnet-init traffic. The code to retrieve the tables was fully debugged. */ si_rcv_get_fwd_tbl(sm, p_sw); if (!sm->p_subn->opt.disable_multicast) si_rcv_get_mcast_fwd_tbl(sm, p_sw); #endif Exit: OSM_LOG_EXIT(sm->p_log); } /********************************************************************** Lock must be held on entry to this function. Return 1 if the caller is expected to send a change_detected event. this can not be done internally as the event needs the lock... **********************************************************************/ static boolean_t si_rcv_process_existing(IN osm_sm_t * sm, IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { osm_switch_t *p_sw = p_node->sw; ib_switch_info_t *p_si; osm_si_context_t *p_si_context; ib_smp_t *p_smp; osm_epi_lft_change_event_t lft_change; boolean_t is_change_detected = FALSE; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); p_si_context = osm_madw_get_si_context_ptr(p_madw); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received logical %cetResp()\n", p_si_context->set_method ? 'S' : 'G'); osm_switch_set_switch_info(p_sw, p_si); if (p_si_context->light_sweep == TRUE && !p_si_context->set_method) { /* If state changed bit is on the mad was returned with an error - signal a change to the state manager. */ if (ib_smp_get_status(p_smp) != 0) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "GetResp() received with error in light sweep. " "Commencing heavy sweep\n"); is_change_detected = TRUE; } else if (ib_switch_info_get_state_change(p_si)) { osm_dump_switch_info_v2(sm->p_log, p_si, FILE_ID, OSM_LOG_DEBUG); is_change_detected = TRUE; } } if (sm->p_subn->first_time_master_sweep == FALSE && p_si_context->set_method && p_si_context->lft_top_change) { lft_change.p_sw = p_sw; lft_change.flags = LFT_CHANGED_LFT_TOP; lft_change.lft_top = cl_ntoh16(p_si->lin_top); lft_change.block_num = 0; osm_opensm_report_event(sm->p_subn->p_osm, OSM_EVENT_ID_LFT_CHANGE, &lft_change); } OSM_LOG_EXIT(sm->p_log); return is_change_detected; } static void si_rcv_get_sp0_info(IN osm_sm_t * sm, IN osm_node_t * node) { osm_madw_context_t context; osm_physp_t *physp; ib_api_status_t status; int mlnx_epi_supported = 0; physp = osm_node_get_physp_ptr(node, 0); context.pi_context.node_guid = osm_node_get_node_guid(node); context.pi_context.port_guid = osm_physp_get_port_guid(physp); context.pi_context.set_method = FALSE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp), IB_MAD_ATTR_PORT_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3611: " "Failure initiating PortInfo request (%s)\n", ib_get_err_str(status)); if (ib_switch_info_is_enhanced_port0(&node->sw->switch_info) && sm->p_subn->opt.fdr10) { mlnx_epi_supported = is_mlnx_ext_port_info_supported(node->node_info.device_id); if (mlnx_epi_supported) { status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp), IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3616: " "Failure initiating MLNX ExtPortInfo request (%s)\n", ib_get_err_str(status)); } } } void osm_si_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_switch_info_t *p_si; ib_smp_t *p_smp; osm_node_t *p_node; ib_net64_t node_guid; osm_si_context_t *p_context; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); p_context = osm_madw_get_si_context_ptr(p_madw); node_guid = p_context->node_guid; OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Switch GUID 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit2; } CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_node = osm_get_node_by_guid(sm->p_subn, node_guid); if (!p_node) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3606: " "SwitchInfo received for nonexistent node " "with GUID 0x%" PRIx64 "\n", cl_ntoh64(node_guid)); goto Exit; } /* Hack for bad value in Mellanox switch */ if (cl_ntoh16(p_si->lin_top) > IB_LID_UCAST_END_HO) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3610: " "\n\t\t\t\tBad LinearFDBTop value = 0x%X " "on switch 0x%" PRIx64 "\n\t\t\t\tForcing internal correction to 0x%X\n", cl_ntoh16(p_si->lin_top), cl_ntoh64(osm_node_get_node_guid(p_node)), 0); p_si->lin_top = 0; } /* Acquire the switch object for this switch. */ if (!p_node->sw) { si_rcv_process_new(sm, p_node, p_madw); /* A new switch was found during the sweep so we need to ignore the current LFT settings. */ sm->p_subn->ignore_existing_lfts = TRUE; } else if (si_rcv_process_existing(sm, p_node, p_madw)) /* we might get back a request for signaling change was detected */ sm->p_subn->force_heavy_sweep = TRUE; if (p_context->light_sweep || p_context->set_method) goto Exit; si_rcv_get_sp0_info(sm, p_node); Exit: CL_PLOCK_RELEASE(sm->p_lock); Exit2: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_switch.c0000644000205000001450000005404612600532055013643 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 osm_switch_t. * This object represents an Infiniband switch. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_SWITCH_C #include struct switch_port_path { uint8_t port_num; uint32_t path_count; int found_sys_guid; int found_node_guid; uint32_t forwarded_to; }; cl_status_t osm_switch_set_hops(IN osm_switch_t * p_sw, IN uint16_t lid_ho, IN uint8_t port_num, IN uint8_t num_hops) { if (!lid_ho || lid_ho > p_sw->max_lid_ho) return -1; if (port_num >= p_sw->num_ports) return -1; if (!p_sw->hops[lid_ho]) { p_sw->hops[lid_ho] = malloc(p_sw->num_ports); if (!p_sw->hops[lid_ho]) return -1; memset(p_sw->hops[lid_ho], OSM_NO_PATH, p_sw->num_ports); } p_sw->hops[lid_ho][port_num] = num_hops; if (p_sw->hops[lid_ho][0] > num_hops) p_sw->hops[lid_ho][0] = num_hops; return 0; } void osm_switch_delete(IN OUT osm_switch_t ** pp_sw) { osm_switch_t *p_sw = *pp_sw; unsigned i; osm_mcast_tbl_destroy(&p_sw->mcast_tbl); if (p_sw->p_prof) free(p_sw->p_prof); if (p_sw->search_ordering_ports) free(p_sw->search_ordering_ports); if (p_sw->lft) free(p_sw->lft); if (p_sw->new_lft) free(p_sw->new_lft); if (p_sw->hops) { for (i = 0; i < p_sw->num_hops; i++) if (p_sw->hops[i]) free(p_sw->hops[i]); free(p_sw->hops); } free(*pp_sw); *pp_sw = NULL; } osm_switch_t *osm_switch_new(IN osm_node_t * p_node, IN const osm_madw_t * p_madw) { osm_switch_t *p_sw; ib_switch_info_t *p_si; ib_smp_t *p_smp; uint8_t num_ports; uint32_t port_num; CL_ASSERT(p_madw); CL_ASSERT(p_node); p_smp = osm_madw_get_smp_ptr(p_madw); p_si = ib_smp_get_payload_ptr(p_smp); num_ports = osm_node_get_num_physp(p_node); CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO); if (!p_si->lin_cap) /* The switch doesn't support LFT */ return NULL; p_sw = malloc(sizeof(*p_sw)); if (!p_sw) return NULL; memset(p_sw, 0, sizeof(*p_sw)); p_sw->p_node = p_node; p_sw->switch_info = *p_si; p_sw->num_ports = num_ports; p_sw->need_update = 2; p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports); if (!p_sw->p_prof) goto err; memset(p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports); osm_mcast_tbl_init(&p_sw->mcast_tbl, osm_node_get_num_physp(p_node), cl_ntoh16(p_si->mcast_cap)); for (port_num = 0; port_num < num_ports; port_num++) osm_port_prof_construct(&p_sw->p_prof[port_num]); return p_sw; err: osm_switch_delete(&p_sw); return NULL; } boolean_t osm_switch_get_lft_block(IN const osm_switch_t * p_sw, IN uint16_t block_id, OUT uint8_t * p_block) { uint16_t base_lid_ho = block_id * IB_SMP_DATA_SIZE; CL_ASSERT(p_sw); CL_ASSERT(p_block); if (base_lid_ho > p_sw->max_lid_ho) return FALSE; CL_ASSERT(base_lid_ho + IB_SMP_DATA_SIZE - 1 <= IB_LID_UCAST_END_HO); memcpy(p_block, &(p_sw->new_lft[base_lid_ho]), IB_SMP_DATA_SIZE); return TRUE; } static struct osm_remote_node * switch_find_guid_common(IN const osm_switch_t * p_sw, IN struct osm_remote_guids_count *r, IN uint8_t port_num, IN int find_sys_guid, IN int find_node_guid) { struct osm_remote_node *p_remote_guid = NULL; osm_physp_t *p_physp; osm_physp_t *p_rem_physp; osm_node_t *p_rem_node; uint64_t sys_guid; uint64_t node_guid; unsigned int i; CL_ASSERT(p_sw); if (!r) goto out; p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); if (!p_physp) goto out; p_rem_physp = osm_physp_get_remote(p_physp); p_rem_node = osm_physp_get_node_ptr(p_rem_physp); sys_guid = p_rem_node->node_info.sys_guid; node_guid = p_rem_node->node_info.node_guid; for (i = 0; i < r->count; i++) { if ((!find_sys_guid || r->guids[i].node->node_info.sys_guid == sys_guid) && (!find_node_guid || r->guids[i].node->node_info.node_guid == node_guid)) { p_remote_guid = &r->guids[i]; break; } } out: return p_remote_guid; } static struct osm_remote_node * switch_find_sys_guid_count(IN const osm_switch_t * p_sw, IN struct osm_remote_guids_count *r, IN uint8_t port_num) { return switch_find_guid_common(p_sw, r, port_num, 1, 0); } static struct osm_remote_node * switch_find_node_guid_count(IN const osm_switch_t * p_sw, IN struct osm_remote_guids_count *r, IN uint8_t port_num) { return switch_find_guid_common(p_sw, r, port_num, 0, 1); } uint8_t osm_switch_recommend_path(IN const osm_switch_t * p_sw, IN osm_port_t * p_port, IN uint16_t lid_ho, IN unsigned start_from, IN boolean_t ignore_existing, IN boolean_t routing_for_lmc, IN boolean_t dor, IN boolean_t port_shifting, IN uint32_t scatter_ports, IN osm_lft_type_enum lft_enum) { /* We support an enhanced LMC aware routing mode: In the case of LMC > 0, we can track the remote side system and node for all of the lids of the target and try and avoid routing again through the same system / node. Assume if routing_for_lmc is true that this procedure was provided the tracking array and counter via p_port->priv, and we can conduct this algorithm. */ uint16_t base_lid; uint8_t hops; uint8_t least_hops; uint8_t port_num; uint8_t num_ports; uint32_t least_paths = 0xFFFFFFFF; unsigned i; /* The follwing will track the least paths if the route should go through a new system/node */ uint32_t least_paths_other_sys = 0xFFFFFFFF; uint32_t least_paths_other_nodes = 0xFFFFFFFF; uint32_t least_forwarded_to = 0xFFFFFFFF; uint32_t check_count; uint8_t best_port = 0; /* These vars track the best port if it connects to not used system/node. */ uint8_t best_port_other_sys = 0; uint8_t best_port_other_node = 0; boolean_t port_found = FALSE; osm_physp_t *p_physp; osm_physp_t *p_rem_physp; osm_node_t *p_rem_node; osm_node_t *p_rem_node_first = NULL; struct osm_remote_node *p_remote_guid = NULL; struct osm_remote_node null_remote_node = {NULL, 0, 0}; struct switch_port_path port_paths[IB_NODE_NUM_PORTS_MAX]; unsigned int port_paths_total_paths = 0; unsigned int port_paths_count = 0; uint8_t scatter_possible_ports[IB_NODE_NUM_PORTS_MAX]; unsigned int scatter_possible_ports_count = 0; int found_sys_guid = 0; int found_node_guid = 0; CL_ASSERT(lid_ho > 0); if (p_port->p_node->sw) { if (p_port->p_node->sw == p_sw) return 0; base_lid = osm_port_get_base_lid(p_port); } else { p_physp = p_port->p_physp; if (!p_physp || !p_physp->p_remote_physp || !p_physp->p_remote_physp->p_node->sw) return OSM_NO_PATH; if (p_physp->p_remote_physp->p_node->sw == p_sw) return p_physp->p_remote_physp->port_num; base_lid = osm_node_get_base_lid(p_physp->p_remote_physp->p_node, 0); } base_lid = cl_ntoh16(base_lid); num_ports = p_sw->num_ports; least_hops = osm_switch_get_least_hops(p_sw, base_lid); if (least_hops == OSM_NO_PATH) return OSM_NO_PATH; /* First, inquire with the forwarding table for an existing route. If one is found, honor it unless: 1. the ignore existing flag is set. 2. the physical port is not a valid one or not healthy 3. the physical port has a remote port (the link is up) 4. the port has min-hops to the target (avoid loops) */ if (!ignore_existing) { port_num = osm_switch_get_port_by_lid(p_sw, lid_ho, lft_enum); if (port_num != OSM_NO_PATH) { CL_ASSERT(port_num < num_ports); p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); /* Don't be too trusting of the current forwarding table! Verify that the port number is legal and that the LID is reachable through this port. */ if (p_physp && osm_physp_is_healthy(p_physp) && osm_physp_get_remote(p_physp)) { hops = osm_switch_get_hop_count(p_sw, base_lid, port_num); /* If we aren't using pre-defined user routes function, then we need to make sure that the current path is the minimum one. In case of having such a user function - this check will not be done, and the old routing will be used. Note: This means that it is the user's job to clean all data in the forwarding tables that he wants to be overridden by the minimum hop function. */ if (hops == least_hops) return port_num; } } } /* This algorithm selects a port based on a static load balanced selection across equal hop-count ports. There is lots of room for improved sophistication here, possibly guided by user configuration info. */ /* OpenSM routing is "local" - not considering a full lid to lid path. As such we can not guarantee a path will not loop if we do not always follow least hops. So we must abort if not least hops. */ /* port number starts with one and num_ports is 1 + num phys ports */ for (i = start_from; i < start_from + num_ports; i++) { port_num = osm_switch_get_dimn_port(p_sw, i % num_ports); if (!port_num || osm_switch_get_hop_count(p_sw, base_lid, port_num) != least_hops) continue; /* let us make sure it is not down or unhealthy */ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); if (!p_physp || !osm_physp_is_healthy(p_physp) || /* we require all - non sma ports to be linked to be routed through */ !osm_physp_get_remote(p_physp)) continue; /* We located a least-hop port, possibly one of many. For this port, check the running total count of the number of paths through this port. Select the port routing the least number of paths. */ check_count = osm_port_prof_path_count_get(&p_sw->p_prof[port_num]); if (dor) { /* Get the Remote Node */ p_rem_physp = osm_physp_get_remote(p_physp); p_rem_node = osm_physp_get_node_ptr(p_rem_physp); /* use the first dimension, but spread traffic * out among the group of ports representing * that dimension */ if (!p_rem_node_first) p_rem_node_first = p_rem_node; else if (p_rem_node != p_rem_node_first) continue; if (routing_for_lmc) { struct osm_remote_guids_count *r = p_port->priv; uint8_t rem_port = osm_physp_get_port_num(p_rem_physp); unsigned int j; for (j = 0; j < r->count; j++) { p_remote_guid = &r->guids[j]; if ((p_remote_guid->node == p_rem_node) && (p_remote_guid->port == rem_port)) break; } if (j == r->count) p_remote_guid = &null_remote_node; } /* Advanced LMC routing requires tracking of the best port by the node connected to the other side of it. */ } else if (routing_for_lmc) { /* Is the sys guid already used ? */ p_remote_guid = switch_find_sys_guid_count(p_sw, p_port->priv, port_num); /* If not update the least hops for this case */ if (!p_remote_guid) { if (check_count < least_paths_other_sys) { least_paths_other_sys = check_count; best_port_other_sys = port_num; least_forwarded_to = 0; } found_sys_guid = 0; } else { /* same sys found - try node */ /* Else is the node guid already used ? */ p_remote_guid = switch_find_node_guid_count(p_sw, p_port->priv, port_num); /* If not update the least hops for this case */ if (!p_remote_guid && check_count < least_paths_other_nodes) { least_paths_other_nodes = check_count; best_port_other_node = port_num; least_forwarded_to = 0; } /* else prior sys and node guid already used */ if (!p_remote_guid) found_node_guid = 0; else found_node_guid = 1; found_sys_guid = 1; } /* same sys found */ } port_paths[port_paths_count].port_num = port_num; port_paths[port_paths_count].path_count = check_count; if (routing_for_lmc) { port_paths[port_paths_count].found_sys_guid = found_sys_guid; port_paths[port_paths_count].found_node_guid = found_node_guid; } if (routing_for_lmc && p_remote_guid) port_paths[port_paths_count].forwarded_to = p_remote_guid->forwarded_to; else port_paths[port_paths_count].forwarded_to = 0; port_paths_total_paths += check_count; port_paths_count++; /* routing for LMC mode */ /* the count is min but also lower then the max subscribed */ if (check_count < least_paths) { port_found = TRUE; best_port = port_num; least_paths = check_count; scatter_possible_ports_count = 0; scatter_possible_ports[scatter_possible_ports_count++] = port_num; if (routing_for_lmc && p_remote_guid && p_remote_guid->forwarded_to < least_forwarded_to) least_forwarded_to = p_remote_guid->forwarded_to; } else if (scatter_ports && check_count == least_paths) { scatter_possible_ports[scatter_possible_ports_count++] = port_num; } else if (routing_for_lmc && p_remote_guid && check_count == least_paths && p_remote_guid->forwarded_to < least_forwarded_to) { least_forwarded_to = p_remote_guid->forwarded_to; best_port = port_num; } } if (port_found == FALSE) return OSM_NO_PATH; if (port_shifting && port_paths_count) { /* In the port_paths[] array, we now have all the ports that we * can route out of. Using some shifting math below, possibly * select a different one so that lids won't align in LFTs * * If lmc > 0, we need to loop through these ports to find the * least_forwarded_to port, best_port_other_sys, and * best_port_other_node just like before but through the different * ordering. */ least_paths = 0xFFFFFFFF; least_paths_other_sys = 0xFFFFFFFF; least_paths_other_nodes = 0xFFFFFFFF; least_forwarded_to = 0xFFFFFFFF; best_port = 0; best_port_other_sys = 0; best_port_other_node = 0; for (i = 0; i < port_paths_count; i++) { unsigned int idx; idx = (port_paths_total_paths/port_paths_count + i) % port_paths_count; if (routing_for_lmc) { if (!port_paths[idx].found_sys_guid && port_paths[idx].path_count < least_paths_other_sys) { least_paths_other_sys = port_paths[idx].path_count; best_port_other_sys = port_paths[idx].port_num; least_forwarded_to = 0; } else if (!port_paths[idx].found_node_guid && port_paths[idx].path_count < least_paths_other_nodes) { least_paths_other_nodes = port_paths[idx].path_count; best_port_other_node = port_paths[idx].port_num; least_forwarded_to = 0; } } if (port_paths[idx].path_count < least_paths) { best_port = port_paths[idx].port_num; least_paths = port_paths[idx].path_count; if (routing_for_lmc && (port_paths[idx].found_sys_guid || port_paths[idx].found_node_guid) && port_paths[idx].forwarded_to < least_forwarded_to) least_forwarded_to = port_paths[idx].forwarded_to; } else if (routing_for_lmc && (port_paths[idx].found_sys_guid || port_paths[idx].found_node_guid) && port_paths[idx].path_count == least_paths && port_paths[idx].forwarded_to < least_forwarded_to) { least_forwarded_to = port_paths[idx].forwarded_to; best_port = port_paths[idx].port_num; } } } /* if we are in enhanced routing mode and the best port is not the local port 0 */ if (routing_for_lmc && best_port && !scatter_ports) { /* Select the least hop port of the non used sys first */ if (best_port_other_sys) best_port = best_port_other_sys; else if (best_port_other_node) best_port = best_port_other_node; } else if (scatter_ports) { /* * There is some danger that this random could "rebalance" the routes * every time, to combat this there is a global srandom that * occurs at the start of every sweep. */ unsigned int idx = random() % scatter_possible_ports_count; best_port = scatter_possible_ports[idx]; } return best_port; } void osm_switch_clear_hops(IN osm_switch_t * p_sw) { unsigned i; for (i = 0; i < p_sw->num_hops; i++) if (p_sw->hops[i]) memset(p_sw->hops[i], OSM_NO_PATH, p_sw->num_ports); } static int alloc_lft(IN osm_switch_t * p_sw, uint16_t lids) { uint16_t lft_size; /* Ensure LFT is in units of LFT block size */ lft_size = (lids / IB_SMP_DATA_SIZE + 1) * IB_SMP_DATA_SIZE; if (lft_size > p_sw->lft_size) { uint8_t *new_lft = realloc(p_sw->lft, lft_size); if (!new_lft) return -1; memset(new_lft + p_sw->lft_size, OSM_NO_PATH, lft_size - p_sw->lft_size); p_sw->lft = new_lft; p_sw->lft_size = lft_size; } return 0; } int osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids) { uint8_t **hops; uint8_t *new_lft; unsigned i; if (alloc_lft(p_sw, max_lids)) return -1; for (i = 0; i < p_sw->num_ports; i++) osm_port_prof_construct(&p_sw->p_prof[i]); osm_switch_clear_hops(p_sw); if (!(new_lft = realloc(p_sw->new_lft, p_sw->lft_size))) return -1; p_sw->new_lft = new_lft; memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size); if (!p_sw->hops) { hops = malloc((max_lids + 1) * sizeof(hops[0])); if (!hops) return -1; memset(hops, 0, (max_lids + 1) * sizeof(hops[0])); p_sw->hops = hops; p_sw->num_hops = max_lids + 1; } else if (max_lids + 1 > p_sw->num_hops) { hops = realloc(p_sw->hops, (max_lids + 1) * sizeof(hops[0])); if (!hops) return -1; memset(hops + p_sw->num_hops, 0, (max_lids + 1 - p_sw->num_hops) * sizeof(hops[0])); p_sw->hops = hops; p_sw->num_hops = max_lids + 1; } p_sw->max_lid_ho = max_lids; return 0; } uint8_t osm_switch_get_port_least_hops(IN const osm_switch_t * p_sw, IN const osm_port_t * p_port) { uint16_t lid; if (p_port->p_node->sw) { if (p_port->p_node->sw == p_sw) return 0; lid = osm_node_get_base_lid(p_port->p_node, 0); return osm_switch_get_least_hops(p_sw, cl_ntoh16(lid)); } else { osm_physp_t *p = p_port->p_physp; uint8_t hops; if (!p || !p->p_remote_physp || !p->p_remote_physp->p_node->sw) return OSM_NO_PATH; if (p->p_remote_physp->p_node->sw == p_sw) return 1; lid = osm_node_get_base_lid(p->p_remote_physp->p_node, 0); hops = osm_switch_get_least_hops(p_sw, cl_ntoh16(lid)); return hops != OSM_NO_PATH ? hops + 1 : OSM_NO_PATH; } } uint8_t osm_switch_recommend_mcast_path(IN osm_switch_t * p_sw, IN osm_port_t * p_port, IN uint16_t mlid_ho, IN boolean_t ignore_existing) { uint16_t base_lid; uint8_t hops; uint8_t port_num; uint8_t num_ports; uint8_t least_hops; CL_ASSERT(mlid_ho >= IB_LID_MCAST_START_HO); if (p_port->p_node->sw) { if (p_port->p_node->sw == p_sw) return 0; base_lid = osm_port_get_base_lid(p_port); } else { osm_physp_t *p_physp = p_port->p_physp; if (!p_physp || !p_physp->p_remote_physp || !p_physp->p_remote_physp->p_node->sw) return OSM_NO_PATH; if (p_physp->p_remote_physp->p_node->sw == p_sw) return p_physp->p_remote_physp->port_num; base_lid = osm_node_get_base_lid(p_physp->p_remote_physp->p_node, 0); } base_lid = cl_ntoh16(base_lid); num_ports = p_sw->num_ports; /* If the user wants us to ignore existing multicast routes, then simply return the shortest hop count path to the target port. Otherwise, return the first port that has a path to the target, picking from the ports that are already in the multicast group. */ if (!ignore_existing) { for (port_num = 1; port_num < num_ports; port_num++) { if (!osm_mcast_tbl_is_port (&p_sw->mcast_tbl, mlid_ho, port_num)) continue; /* Don't be too trusting of the current forwarding table! Verify that the LID is reachable through this port. */ hops = osm_switch_get_hop_count(p_sw, base_lid, port_num); if (hops != OSM_NO_PATH) return port_num; } } /* Either no existing mcast paths reach this port or we are ignoring existing paths. Determine the best multicast path to the target. Note that this algorithm is slightly different from the one used for unicast route recommendation. In this case (multicast), we must NOT perform any sort of load balancing. We MUST take the FIRST port found that has <= the lowest hop count path. This prevents more than one multicast path to the same remote switch which prevents a multicast loop. Multicast loops are bad since the same multicast packet will go around and around, inevitably creating a black hole that will destroy the Earth in a firey conflagration. */ least_hops = osm_switch_get_least_hops(p_sw, base_lid); if (least_hops == OSM_NO_PATH) return OSM_NO_PATH; for (port_num = 1; port_num < num_ports; port_num++) if (osm_switch_get_hop_count(p_sw, base_lid, port_num) == least_hops) break; CL_ASSERT(port_num < num_ports); return port_num; } opensm-3.3.20/opensm/osm_prtn.c0000644000205000001450000003071112654645013013326 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2012 Mellanox Technologies LTD. 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 osm_prtn_t. * This object represents an IBA partition. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_PRTN_C #include #include #include #include #include #include #include extern int osm_prtn_config_parse_file(osm_log_t * p_log, osm_subn_t * p_subn, const char *file_name); static uint16_t global_pkey_counter; osm_prtn_t *osm_prtn_new(IN const char *name, IN uint16_t pkey) { osm_prtn_t *p = malloc(sizeof(*p)); if (!p) return NULL; memset(p, 0, sizeof(*p)); p->pkey = pkey; p->sl = OSM_DEFAULT_SL; p->mgrps = NULL; p->nmgrps = 0; cl_map_construct(&p->full_guid_tbl); cl_map_init(&p->full_guid_tbl, 32); cl_map_construct(&p->part_guid_tbl); cl_map_init(&p->part_guid_tbl, 32); if (name && *name) strncpy(p->name, name, sizeof(p->name)); else snprintf(p->name, sizeof(p->name), "%04x", cl_ntoh16(pkey)); return p; } void osm_prtn_delete(IN osm_subn_t * p_subn, IN OUT osm_prtn_t ** pp_prtn) { char gid_str[INET6_ADDRSTRLEN]; int i = 0; osm_prtn_t *p = *pp_prtn; cl_map_remove_all(&p->full_guid_tbl); cl_map_destroy(&p->full_guid_tbl); cl_map_remove_all(&p->part_guid_tbl); cl_map_destroy(&p->part_guid_tbl); if (p->mgrps) { /* Clean up mgrps */ for (i = 0; i < p->nmgrps; i++) { /* osm_mgrp_cleanup will not delete * "well_known" groups */ p->mgrps[i]->well_known = FALSE; OSM_LOG(&p_subn->p_osm->log, OSM_LOG_DEBUG, "removing mgroup %s from partition (0x%x)\n", inet_ntop(AF_INET6, p->mgrps[i]->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), cl_hton16(p->pkey)); osm_mgrp_cleanup(p_subn, p->mgrps[i]); } free(p->mgrps); } free(p); *pp_prtn = NULL; } ib_api_status_t osm_prtn_add_port(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, ib_net64_t guid, boolean_t full, boolean_t indx0) { ib_api_status_t status = IB_SUCCESS; cl_map_t *p_tbl; osm_port_t *p_port; osm_physp_t *p_physp; p_port = osm_get_port_by_guid(p_subn, guid); if (!p_port) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "port 0x%" PRIx64 " not found\n", cl_ntoh64(guid)); return status; } p_physp = p_port->p_physp; if (!p_physp) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "no physical for port 0x%" PRIx64 "\n", cl_ntoh64(guid)); return status; } /* Set the pkey to be inserted to block 0 index 0 */ if (indx0) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Setting pkey 0x%04x at indx0 " "for port 0x%" PRIx64 "\n", cl_ntoh16(p->pkey), cl_ntoh64(guid)); osm_pkey_tbl_set_indx0_pkey(p_log, p->pkey, full, &p_physp->pkeys); } else if (ib_pkey_get_base(p_physp->pkeys.indx0_pkey) == ib_pkey_get_base(p->pkey)) p_physp->pkeys.indx0_pkey = 0; p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl; if (p_subn->opt.allow_both_pkeys) { if (cl_map_remove(p_tbl, guid)) OSM_LOG(p_log, OSM_LOG_VERBOSE, "port 0x%" PRIx64 " already in partition \'%s\' (0x%04x) full %d." " Will overwrite\n", cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey), full); } else { if (cl_map_remove(&p->part_guid_tbl, guid) || cl_map_remove(&p->full_guid_tbl, guid)) OSM_LOG(p_log, OSM_LOG_VERBOSE, "port 0x%" PRIx64 " already in partition \'%s\' (0x%04x)." " Will overwrite\n", cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey)); } if (cl_map_insert(p_tbl, guid, p_physp) == NULL) return IB_INSUFFICIENT_MEMORY; return status; } ib_api_status_t osm_prtn_add_all(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, unsigned type, boolean_t full, boolean_t indx0) { cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl; cl_map_item_t *p_item; osm_port_t *p_port; ib_api_status_t status = IB_SUCCESS; p_item = cl_qmap_head(p_port_tbl); while (p_item != cl_qmap_end(p_port_tbl)) { p_port = (osm_port_t *) p_item; p_item = cl_qmap_next(p_item); if (!type || osm_node_get_type(p_port->p_node) == type) { status = osm_prtn_add_port(p_log, p_subn, p, osm_port_get_guid(p_port), full, indx0); if (status != IB_SUCCESS) goto _err; } } _err: return status; } static ib_api_status_t track_mgrp_w_partition(osm_log_t *p_log, osm_prtn_t *p, osm_mgrp_t *mgrp, osm_subn_t *p_subn, const ib_gid_t *mgid, ib_net16_t pkey) { char gid_str[INET6_ADDRSTRLEN]; osm_mgrp_t **tmp; int i = 0; /* check if we are already tracking this group */ for (i = 0; i < p->nmgrps; i++) if (p->mgrps[i] == mgrp) return (IB_SUCCESS); /* otherwise add it to our list */ tmp = realloc(p->mgrps, (p->nmgrps +1) * sizeof(*p->mgrps)); if (tmp) { p->mgrps = tmp; p->mgrps[p->nmgrps] = mgrp; p->nmgrps++; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "realloc error to create MC group (%s) in " "partition (pkey 0x%04x)\n", inet_ntop(AF_INET6, mgid->raw, gid_str, sizeof gid_str), cl_ntoh16(pkey)); mgrp->well_known = FALSE; osm_mgrp_cleanup(p_subn, mgrp); return (IB_ERROR); } mgrp->well_known = TRUE; return (IB_SUCCESS); } ib_api_status_t osm_prtn_add_mcgroup(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, uint8_t rate, uint8_t mtu, uint8_t sl, uint8_t scope, uint32_t Q_Key, uint8_t tclass, uint32_t FlowLabel, const ib_gid_t *mgid) { char gid_str[INET6_ADDRSTRLEN]; ib_member_rec_t mc_rec; ib_net64_t comp_mask; ib_net16_t pkey; osm_mgrp_t *mgrp; osm_sa_t *p_sa = &p_subn->p_osm->sa; uint8_t hop_limit; pkey = p->pkey | cl_hton16(0x8000); if (!scope) scope = OSM_DEFAULT_MGRP_SCOPE; hop_limit = (scope == IB_MC_SCOPE_LINK_LOCAL) ? 0 : IB_HOPLIMIT_MAX; memset(&mc_rec, 0, sizeof(mc_rec)); mc_rec.mgid = *mgid; mc_rec.qkey = CL_HTON32(Q_Key); mc_rec.mtu = mtu | (IB_PATH_SELECTOR_EXACTLY << 6); mc_rec.tclass = tclass; mc_rec.pkey = pkey; mc_rec.rate = rate | (IB_PATH_SELECTOR_EXACTLY << 6); mc_rec.pkt_life = p_subn->opt.subnet_timeout; mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(sl, FlowLabel, hop_limit); /* Scope in MCMemberRecord (if present) needs to be consistent with MGID */ mc_rec.scope_state = ib_member_set_scope_state(scope, IB_MC_REC_STATE_FULL_MEMBER); ib_mgid_set_scope(&mc_rec.mgid, scope); /* don't update rate, mtu */ comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL; mgrp = osm_mcmr_rcv_find_or_create_new_mgrp(p_sa, comp_mask, &mc_rec); if (!mgrp) { OSM_LOG(p_log, OSM_LOG_ERROR, "Failed to create MC group (%s) with pkey 0x%04x\n", inet_ntop(AF_INET6, mgid->raw, gid_str, sizeof gid_str), cl_ntoh16(pkey)); return IB_ERROR; } return (track_mgrp_w_partition(p_log, p, mgrp, p_subn, mgid, pkey)); } static uint16_t generate_pkey(osm_subn_t * p_subn) { uint16_t pkey; cl_qmap_t *m = &p_subn->prtn_pkey_tbl; while (global_pkey_counter < cl_ntoh16(IB_DEFAULT_PARTIAL_PKEY) - 1) { pkey = ++global_pkey_counter; pkey = cl_hton16(pkey); if (cl_qmap_get(m, pkey) == cl_qmap_end(m)) return pkey; } return 0; } osm_prtn_t *osm_prtn_find_by_name(osm_subn_t * p_subn, const char *name) { cl_map_item_t *p_next; osm_prtn_t *p; p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { p = (osm_prtn_t *) p_next; p_next = cl_qmap_next(&p->map_item); if (!strncmp(p->name, name, sizeof(p->name))) return p; } return NULL; } osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn, const char *name, uint16_t pkey) { osm_prtn_t *p = NULL, *p_check; pkey &= cl_hton16((uint16_t) ~ 0x8000); if (!pkey) { if (name && (p = osm_prtn_find_by_name(p_subn, name))) return p; if (!(pkey = generate_pkey(p_subn))) return NULL; } p = osm_prtn_new(name, pkey); if (!p) { OSM_LOG(p_log, OSM_LOG_ERROR, "Unable to create" " partition \'%s\' (0x%04x)\n", name, cl_ntoh16(pkey)); return NULL; } p_check = (osm_prtn_t *) cl_qmap_insert(&p_subn->prtn_pkey_tbl, p->pkey, &p->map_item); if (p != p_check) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Duplicated partition" " definition: \'%s\' (0x%04x) prev name \'%s\'" ". Will use it\n", name, cl_ntoh16(pkey), p_check->name); osm_prtn_delete(p_subn, &p); p = p_check; } return p; } static ib_api_status_t prtn_make_default(osm_log_t * p_log, osm_subn_t * p_subn, boolean_t no_config) { ib_api_status_t status = IB_UNKNOWN_ERROR; osm_prtn_t *p; p = osm_prtn_make_new(p_log, p_subn, "Default", IB_DEFAULT_PARTIAL_PKEY); if (!p) goto _err; status = osm_prtn_add_all(p_log, p_subn, p, 0, no_config, FALSE); if (status != IB_SUCCESS) goto _err; cl_map_remove(&p->part_guid_tbl, p_subn->sm_port_guid); status = osm_prtn_add_port(p_log, p_subn, p, p_subn->sm_port_guid, TRUE, FALSE); /* ipv4 broadcast group */ if (no_config) osm_prtn_add_mcgroup(p_log, p_subn, p, OSM_DEFAULT_MGRP_RATE, OSM_DEFAULT_MGRP_MTU, OSM_DEFAULT_SL, 0, OSM_IPOIB_BROADCAST_MGRP_QKEY, 0, 0, &osm_ipoib_broadcast_mgid); _err: return status; } ib_api_status_t osm_prtn_make_partitions(osm_log_t * p_log, osm_subn_t * p_subn) { struct stat statbuf; const char *file_name; boolean_t is_config = TRUE; boolean_t is_wrong_config = FALSE; ib_api_status_t status = IB_SUCCESS; cl_map_item_t *p_next; osm_prtn_t *p; file_name = p_subn->opt.partition_config_file ? p_subn->opt.partition_config_file : OSM_DEFAULT_PARTITION_CONFIG_FILE; if (stat(file_name, &statbuf)) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Partition configuration " "%s is not accessible (%s)\n", file_name, strerror(errno)); is_config = FALSE; } retry_default: /* clean up current port maps */ p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { p = (osm_prtn_t *) p_next; p_next = cl_qmap_next(&p->map_item); cl_map_remove_all(&p->part_guid_tbl); cl_map_remove_all(&p->full_guid_tbl); } global_pkey_counter = 0; status = prtn_make_default(p_log, p_subn, !is_config); if (status != IB_SUCCESS) goto _err; if (is_config && osm_prtn_config_parse_file(p_log, p_subn, file_name)) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Partition configuration " "was not fully processed\n"); is_wrong_config = TRUE; } /* and now clean up empty partitions */ p_next = cl_qmap_head(&p_subn->prtn_pkey_tbl); while (p_next != cl_qmap_end(&p_subn->prtn_pkey_tbl)) { p = (osm_prtn_t *) p_next; p_next = cl_qmap_next(&p->map_item); if (cl_map_count(&p->part_guid_tbl) == 0 && cl_map_count(&p->full_guid_tbl) == 0) { cl_qmap_remove_item(&p_subn->prtn_pkey_tbl, (cl_map_item_t *) p); osm_prtn_delete(p_subn, &p); } } if (is_config && is_wrong_config) { OSM_LOG(p_log, OSM_LOG_ERROR, "Partition configuration " "in error; retrying with default config\n"); is_config = FALSE; goto retry_default; } _err: return status; } opensm-3.3.20/opensm/osm_prtn_config.c0000644000205000001450000005324712654625547014676 00000000000000/* * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2012-2015 Mellanox Technologies LTD. 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 opensm partition management configuration */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_PRTN_CONFIG_C #include #include #include #include #include typedef enum { LIMITED, FULL, BOTH } membership_t; const ib_gid_t osm_ipoib_broadcast_mgid = { { 0xff, /* multicast field */ 0x12, /* non-permanent bit, link local scope */ 0x40, 0x1b, /* IPv4 signature */ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ }, }; struct group_flags { unsigned mtu, rate, sl, scope_mask; uint32_t Q_Key; uint8_t TClass; uint32_t FlowLabel; }; struct precreate_mgroup { ib_gid_t mgid; struct group_flags flags; }; struct part_conf { osm_log_t *p_log; osm_subn_t *p_subn; osm_prtn_t *p_prtn; unsigned is_ipoib; struct group_flags flags; membership_t membership; boolean_t indx0; }; extern osm_prtn_t *osm_prtn_make_new(osm_log_t * p_log, osm_subn_t * p_subn, const char *name, uint16_t pkey); extern ib_api_status_t osm_prtn_add_all(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, unsigned type, boolean_t full, boolean_t indx0); extern ib_api_status_t osm_prtn_add_port(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, ib_net64_t guid, boolean_t full, boolean_t indx0); ib_api_status_t osm_prtn_add_mcgroup(osm_log_t * p_log, osm_subn_t * p_subn, osm_prtn_t * p, uint8_t rate, uint8_t mtu, uint8_t sl, uint8_t scope, uint32_t Q_Key, uint8_t TClass, uint32_t FlowLabel, const ib_gid_t *mgid); static inline boolean_t mgid_is_broadcast(const ib_gid_t *mgid) { return (memcmp(mgid, &osm_ipoib_broadcast_mgid, sizeof(osm_ipoib_broadcast_mgid)) == 0); } static inline boolean_t mgid_is_ip(const ib_gid_t *mgid) { ib_net16_t ipsig = *(ib_net16_t *)&mgid->raw[2]; return (ipsig == cl_hton16(0x401b) || ipsig == cl_hton16(0x601b)); } static inline boolean_t ip_mgroup_pkey_ok(struct part_conf *conf, struct precreate_mgroup *group) { ib_net16_t mpkey = *(ib_net16_t *)&group->mgid.raw[4]; char gid_str[INET6_ADDRSTRLEN]; if (mgid_is_broadcast(&group->mgid) /* user requested "wild card" of pkey */ || mpkey == 0x0000 /* user was smart enough to match */ || mpkey == (conf->p_prtn->pkey | cl_hton16(0x8000))) return (TRUE); OSM_LOG(conf->p_log, OSM_LOG_ERROR, "IP MC group (%s) specified with invalid pkey 0x%04x " "for partition pkey = 0x%04x (%s)\n", inet_ntop(AF_INET6, group->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(mpkey), cl_ntoh16(conf->p_prtn->pkey), conf->p_prtn->name); return (FALSE); } static inline boolean_t ip_mgroup_rate_ok(struct part_conf *conf, struct precreate_mgroup *group) { char gid_str[INET6_ADDRSTRLEN]; if (group->flags.rate == conf->flags.rate) return (TRUE); OSM_LOG(conf->p_log, OSM_LOG_ERROR, "IP MC group (%s) specified with invalid rate (%d): " "partition pkey = 0x%04x (%s) " "[Partition broadcast group rate = %d]\n", inet_ntop(AF_INET6, group->mgid.raw, gid_str, sizeof gid_str), group->flags.rate, cl_ntoh16(conf->p_prtn->pkey), conf->p_prtn->name, conf->flags.rate); return (FALSE); } static inline boolean_t ip_mgroup_mtu_ok(struct part_conf *conf, struct precreate_mgroup *group) { char gid_str[INET6_ADDRSTRLEN]; if (group->flags.mtu == conf->flags.mtu) return (TRUE); OSM_LOG(conf->p_log, OSM_LOG_ERROR, "IP MC group (%s) specified with invalid mtu (%d): " "partition pkey = 0x%04x (%s) " "[Partition broadcast group mtu = %d]\n", inet_ntop(AF_INET6, group->mgid.raw, gid_str, sizeof gid_str), group->flags.mtu, cl_ntoh16(conf->p_prtn->pkey), conf->p_prtn->name, conf->flags.mtu); return (FALSE); } static void __create_mgrp(struct part_conf *conf, struct precreate_mgroup *group) { unsigned int scope; if (!group->flags.scope_mask) { osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn, (uint8_t) group->flags.rate, (uint8_t) group->flags.mtu, group->flags.sl, 0, group->flags.Q_Key, group->flags.TClass, group->flags.FlowLabel, &group->mgid); } else { for (scope = 0; scope < 16; scope++) { if (((1<flags.scope_mask) == 0) continue; osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn, (uint8_t)group->flags.rate, (uint8_t)group->flags.mtu, (uint8_t)group->flags.sl, (uint8_t)scope, group->flags.Q_Key, group->flags.TClass, group->flags.FlowLabel, &group->mgid); } } } static int partition_create(unsigned lineno, struct part_conf *conf, char *name, char *id, char *flag, char *flag_val) { ib_net16_t pkey; if (!id && name && isdigit(*name)) { id = name; name = NULL; } if (id) { char *end; pkey = cl_hton16((uint16_t)strtoul(id, &end, 0)); if (end == id || *end) return -1; } else pkey = 0; conf->p_prtn = osm_prtn_make_new(conf->p_log, conf->p_subn, name, pkey); if (!conf->p_prtn) return -1; if (!conf->p_subn->opt.qos && conf->flags.sl != OSM_DEFAULT_SL) { OSM_LOG(conf->p_log, OSM_LOG_DEBUG, "Overriding SL %d" " to default SL %d on partition %s" " as QoS is not enabled.\n", conf->flags.sl, OSM_DEFAULT_SL, name); conf->flags.sl = OSM_DEFAULT_SL; } conf->p_prtn->sl = (uint8_t) conf->flags.sl; if (conf->is_ipoib) { struct precreate_mgroup broadcast_mgroup; memset(&broadcast_mgroup, 0, sizeof(broadcast_mgroup)); broadcast_mgroup.mgid = osm_ipoib_broadcast_mgid; pkey = CL_HTON16(0x8000) | conf->p_prtn->pkey; memcpy(&broadcast_mgroup.mgid.raw[4], &pkey , sizeof(pkey)); broadcast_mgroup.flags.mtu = conf->flags.mtu; broadcast_mgroup.flags.rate = conf->flags.rate; broadcast_mgroup.flags.sl = conf->flags.sl; broadcast_mgroup.flags.Q_Key = conf->flags.Q_Key ? conf->flags.Q_Key : OSM_IPOIB_BROADCAST_MGRP_QKEY; broadcast_mgroup.flags.TClass = conf->flags.TClass; broadcast_mgroup.flags.FlowLabel = conf->flags.FlowLabel; __create_mgrp(conf, &broadcast_mgroup); } return 0; } /* returns 1 if processed 0 if _not_ */ static int parse_group_flag(unsigned lineno, osm_log_t * p_log, struct group_flags *flags, char *flag, char *val) { int rc = 0; int len = strlen(flag); if (!strncmp(flag, "mtu", len)) { rc = 1; if (!val || (flags->mtu = strtoul(val, NULL, 0)) == 0) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'mtu\' requires valid value" " - skipped\n", lineno); } else if (!strncmp(flag, "rate", len)) { rc = 1; if (!val || (flags->rate = strtoul(val, NULL, 0)) == 0) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'rate\' requires valid value" " - skipped\n", lineno); } else if (!strncmp(flag, "scope", len)) { unsigned int scope; rc = 1; if (!val || (scope = strtoul(val, NULL, 0)) == 0 || scope > 0xF) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'scope\' requires valid value" " - skipped\n", lineno); else flags->scope_mask |= (1<Q_Key = strtoul(val, NULL, 0)) == 0) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'Q_Key\' requires valid value" " - using '0'\n", lineno); } else if (!strncmp(flag, "TClass", strlen(flag))) { rc =1; if (!val || (flags->TClass = strtoul(val, NULL, 0)) == 0) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'TClass\' requires valid value" " - using '0'\n", lineno); } else if (!strncmp(flag, "sl", len)) { unsigned sl; char *end; rc = 1; if (!val || !*val || (sl = strtoul(val, &end, 0)) > 15 || (*end && !isspace(*end))) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'sl\' requires valid value" " - skipped\n", lineno); else flags->sl = sl; } else if (!strncmp(flag, "FlowLabel", len)) { uint32_t FlowLabel; char *end; rc = 1; if (!val || !*val || (FlowLabel = strtoul(val, &end, 0)) > 0xFFFFF || (*end && !isspace(*end))) OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'FlowLabel\' requires valid value" " - skipped\n", lineno); else flags->FlowLabel = FlowLabel; } return rc; } static int partition_add_flag(unsigned lineno, struct part_conf *conf, char *flag, char *val) { int len = strlen(flag); /* ipoib gc group flags are processed here. */ if (parse_group_flag(lineno, conf->p_log, &conf->flags, flag, val)) return 0; /* partition flags go here. */ if (!strncmp(flag, "ipoib", len)) { conf->is_ipoib = 1; } else if (!strncmp(flag, "defmember", len)) { if (!val || (strncmp(val, "limited", strlen(val)) && strncmp(val, "both", strlen(val)) && strncmp(val, "full", strlen(val)))) OSM_LOG(conf->p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "flag \'defmember\' requires valid value (limited or full or both)" " - skipped\n", lineno); else { if (!strncmp(val, "full", strlen(val))) conf->membership = FULL; else if (!strncmp(val, "both", strlen(val))) conf->membership = BOTH; else conf->membership = LIMITED; } } else if (!strcmp(flag, "indx0")) conf->indx0 = TRUE; else { OSM_LOG(conf->p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "unrecognized partition flag \'%s\'" " - ignored\n", lineno, flag); } return 0; } static void manage_membership_change(struct part_conf *conf, osm_prtn_t * p, unsigned type, membership_t membership, ib_net64_t guid) { cl_map_t *p_tbl; cl_map_iterator_t p_next, p_item; osm_physp_t *p_physp; /* In allow_both_pkeys mode */ /* if membership of the PKEY is set to FULL */ /* need to clean up the part_guid_tbl table entry for this guid */ /* if membership of the PKEY is set to LIMITED */ /* need to clean up the full_guid_tbl table entry for this guid */ /* as it could be populated because of previous definitions */ if (!conf->p_subn->opt.allow_both_pkeys || membership == BOTH) return; switch (type){ /* ALL = 0 */ case 0: cl_map_remove_all(membership == LIMITED ? &p->full_guid_tbl : &p->part_guid_tbl); break; /* specific GUID */ case 0xFF: cl_map_remove(membership == LIMITED ? &p->full_guid_tbl : &p->part_guid_tbl, cl_hton64(guid)); break; case IB_NODE_TYPE_CA: case IB_NODE_TYPE_SWITCH: case IB_NODE_TYPE_ROUTER: p_tbl = (membership == LIMITED) ? &p->full_guid_tbl : &p->part_guid_tbl; p_next = cl_map_head(p_tbl); while (p_next != cl_map_end(p_tbl)) { p_item = p_next; p_next = cl_map_next(p_item); p_physp = (osm_physp_t *) cl_map_obj(p_item); if (osm_node_get_type(p_physp->p_node) == type) cl_map_remove_item(p_tbl, p_item); } break; default: break; } } static int partition_add_all(struct part_conf *conf, osm_prtn_t * p, unsigned type, membership_t membership) { manage_membership_change(conf, p, type, membership, 0); if (membership != LIMITED && osm_prtn_add_all(conf->p_log, conf->p_subn, p, type, TRUE, conf->indx0) != IB_SUCCESS) return -1; if ((membership == LIMITED || (membership == BOTH && conf->p_subn->opt.allow_both_pkeys)) && osm_prtn_add_all(conf->p_log, conf->p_subn, p, type, FALSE, conf->indx0) != IB_SUCCESS) return -1; return 0; } static int partition_add_port(unsigned lineno, struct part_conf *conf, char *name, char *flag) { osm_prtn_t *p = conf->p_prtn; ib_net64_t guid; membership_t membership = conf->membership; if (!name || !*name || !strncmp(name, "NONE", strlen(name))) return 0; if (flag) { /* reset default membership to limited */ membership = LIMITED; if (!strncmp(flag, "full", strlen(flag))) membership = FULL; else if (!strncmp(flag, "both", strlen(flag))) membership = BOTH; else if (strncmp(flag, "limited", strlen(flag))) { OSM_LOG(conf->p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "unrecognized port flag \'%s\'." " Assume \'limited\'\n", lineno, flag); } } if (!strncmp(name, "ALL", strlen(name))) return partition_add_all(conf, p, 0, membership); else if (!strncmp(name, "ALL_CAS", strlen(name))) return partition_add_all(conf, p, IB_NODE_TYPE_CA, membership); else if (!strncmp(name, "ALL_SWITCHES", strlen(name))) return partition_add_all(conf, p, IB_NODE_TYPE_SWITCH, membership); else if (!strncmp(name, "ALL_ROUTERS", strlen(name))) return partition_add_all(conf, p, IB_NODE_TYPE_ROUTER, membership); else if (!strncmp(name, "SELF", strlen(name))) { guid = cl_ntoh64(conf->p_subn->sm_port_guid); } else { char *end; guid = strtoull(name, &end, 0); if (!guid || *end) return -1; } manage_membership_change(conf, p, 0xFF, membership, guid); if (membership != LIMITED && osm_prtn_add_port(conf->p_log, conf->p_subn, p, cl_hton64(guid), TRUE, conf->indx0) != IB_SUCCESS) return -1; if ((membership == LIMITED || (membership == BOTH && conf->p_subn->opt.allow_both_pkeys)) && osm_prtn_add_port(conf->p_log, conf->p_subn, p, cl_hton64(guid), FALSE, conf->indx0) != IB_SUCCESS) return -1; return 0; } /* conf file parser */ #define STRIP_HEAD_SPACES(p) while (*(p) == ' ' || *(p) == '\t' || \ *(p) == '\n') { (p)++; } #define STRIP_TAIL_SPACES(p) { char *q = (p) + strlen(p); \ while ( q != (p) && ( *q == '\0' || \ *q == ' ' || *q == '\t' || \ *q == '\n')) { *q-- = '\0'; }; } static int parse_name_token(char *str, char **name, char **val) { int len = 0; char *p, *q; *name = *val = NULL; p = str; while (*p == ' ' || *p == '\t' || *p == '\n') p++; q = strchr(p, '='); if (q) *q++ = '\0'; len = strlen(str) + 1; str = q; q = p + strlen(p); while (q != p && (*q == '\0' || *q == ' ' || *q == '\t' || *q == '\n')) *q-- = '\0'; *name = p; p = str; if (!p) return len; while (*p == ' ' || *p == '\t' || *p == '\n') p++; q = p + strlen(p); len += (int)(q - str) + 1; while (q != p && (*q == '\0' || *q == ' ' || *q == '\t' || *q == '\n')) *q-- = '\0'; *val = p; return len; } static int parse_mgroup_flags(osm_log_t * p_log, struct precreate_mgroup *mgroup, char *p, unsigned lineno) { int ret, len = 0; char *flag, *val, *q; do { flag = val = NULL; q = strchr(p, ','); if (q) *q++ = '\0'; ret = parse_name_token(p, &flag, &val); if (!parse_group_flag(lineno, p_log, &mgroup->flags, flag, val)) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "PARSE WARN: line %d: " "unrecognized mgroup flag \'%s\'" " - ignored\n", lineno, flag); } p += ret; len += ret; } while (q); return (len); } static int mgroup_create(char *p, char *mgid, unsigned lineno, struct part_conf *conf) { int ret = 0; struct precreate_mgroup mgroup; memset(&mgroup, 0, sizeof(mgroup)); if (inet_pton(AF_INET6, mgid, &mgroup.mgid) != 1 || mgroup.mgid.raw[0] != 0xff) { OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR partition conf file line %d: " "mgid \"%s\": gid is not multicast\n", lineno, mgid); return 0; } /* inherit partition flags */ mgroup.flags.mtu = conf->flags.mtu; mgroup.flags.rate = conf->flags.rate; mgroup.flags.sl = conf->flags.sl; mgroup.flags.Q_Key = conf->flags.Q_Key; mgroup.flags.FlowLabel = conf->flags.FlowLabel; mgroup.flags.scope_mask = conf->flags.scope_mask; /* override with user specified flags */ ret = parse_mgroup_flags(conf->p_log, &mgroup, p, lineno); /* check/verify special IP group parameters */ if (mgid_is_ip(&mgroup.mgid)) { ib_net16_t pkey = conf->p_prtn->pkey | cl_hton16(0x8000); if (!ip_mgroup_pkey_ok(conf, &mgroup) || !ip_mgroup_rate_ok(conf, &mgroup) || !ip_mgroup_mtu_ok(conf, &mgroup)) goto error; /* set special IP settings */ memcpy(&mgroup.mgid.raw[4], &pkey, sizeof(pkey)); if (mgroup.flags.Q_Key == 0) mgroup.flags.Q_Key = OSM_IPOIB_BROADCAST_MGRP_QKEY; } /* don't create multiple copies of the group */ if (osm_get_mgrp_by_mgid(conf->p_subn, &mgroup.mgid)) goto error; /* create the group */ __create_mgrp(conf, &mgroup); error: return ret; } static struct part_conf *new_part_conf(osm_log_t * p_log, osm_subn_t * p_subn) { static struct part_conf part; struct part_conf *conf = ∂ memset(conf, 0, sizeof(*conf)); conf->p_log = p_log; conf->p_subn = p_subn; conf->p_prtn = NULL; conf->is_ipoib = 0; conf->flags.sl = OSM_DEFAULT_SL; conf->flags.rate = OSM_DEFAULT_MGRP_RATE; conf->flags.mtu = OSM_DEFAULT_MGRP_MTU; conf->membership = LIMITED; conf->indx0 = FALSE; return conf; } static int flush_part_conf(struct part_conf *conf) { memset(conf, 0, sizeof(*conf)); return 0; } static int parse_part_conf(struct part_conf *conf, char *str, int lineno) { int ret, len = 0; char *name, *id, *flag, *flval; char *q, *p; p = str; if (*p == '\t' || *p == '\0' || *p == '\n') p++; len += (int)(p - str); str = p; if (conf->p_prtn) goto skip_header; q = strchr(p, ':'); if (!q) { OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: " "no partition definition found\n", lineno); fprintf(stderr, "\nPARSE ERROR: line %d: " "no partition definition found\n", lineno); return -1; } *q++ = '\0'; str = q; name = id = flag = flval = NULL; q = strchr(p, ','); if (q) *q = '\0'; ret = parse_name_token(p, &name, &id); p += ret; len += ret; while (q) { flag = flval = NULL; q = strchr(p, ','); if (q) *q++ = '\0'; ret = parse_name_token(p, &flag, &flval); if (!flag) { OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: " "bad partition flags\n", lineno); fprintf(stderr, "\nPARSE ERROR: line %d: " "bad partition flags\n", lineno); return -1; } p += ret; len += ret; partition_add_flag(lineno, conf, flag, flval); } if (p != str || (partition_create(lineno, conf, name, id, flag, flval) < 0)) { OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: " "bad partition definition\n", lineno); fprintf(stderr, "\nPARSE ERROR: line %d: " "bad partition definition\n", lineno); return -1; } skip_header: do { name = flag = NULL; q = strchr(p, ','); if (q) *q++ = '\0'; ret = parse_name_token(p, &name, &flag); len += ret; if (strcmp(name, "mgid") == 0) { /* parse an mgid line if specified. */ len += mgroup_create(p+ret, flag, lineno, conf); goto done; /* We're done: this consumes the line */ } if (partition_add_port(lineno, conf, name, flag) < 0) { OSM_LOG(conf->p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: " "bad PortGUID\n", lineno); fprintf(stderr, "PARSE ERROR: line %d: " "bad PortGUID\n", lineno); return -1; } p += ret; } while (q); done: return len; } /** * @return 1 on error, 0 on success */ int osm_prtn_config_parse_file(osm_log_t * p_log, osm_subn_t * p_subn, const char *file_name) { char line[4096]; struct part_conf *conf = NULL; FILE *file; int lineno; int is_parse_success; line[0] = '\0'; file = fopen(file_name, "r"); if (!file) { OSM_LOG(p_log, OSM_LOG_VERBOSE, "Cannot open config file \'%s\': %s\n", file_name, strerror(errno)); return -1; } lineno = 0; is_parse_success = 0; while (fgets(line, sizeof(line) - 1, file) != NULL) { char *q, *p = line; lineno++; p = line; q = strchr(p, '#'); if (q) *q = '\0'; do { int len; while (*p == ' ' || *p == '\t' || *p == '\n') p++; if (*p == '\0') break; if (!conf && !(conf = new_part_conf(p_log, p_subn))) { OSM_LOG(p_log, OSM_LOG_ERROR, "PARSE ERROR: line %d: " "internal: cannot create config\n", lineno); fprintf(stderr, "PARSE ERROR: line %d: " "internal: cannot create config\n", lineno); is_parse_success = -1; break; } q = strchr(p, ';'); if (q) *q = '\0'; len = parse_part_conf(conf, p, lineno); if (len < 0) { is_parse_success = -1; break; } is_parse_success = 1; p += len; if (q) { flush_part_conf(conf); conf = NULL; } } while (q); if (is_parse_success == -1) break; } fclose(file); return (is_parse_success == 1) ? 0 : 1; } opensm-3.3.20/opensm/osm_qos.c0000644000205000001450000004336212725277041013154 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2010-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 OpenSM QoS infrastructure primitives */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_QOS_C #include #include #include struct qos_config { uint8_t max_vls; uint8_t vl_high_limit; ib_vl_arb_table_t vlarb_high[2]; ib_vl_arb_table_t vlarb_low[2]; ib_slvl_table_t sl2vl; }; typedef struct qos_mad_item { cl_list_item_t list_item; osm_madw_t *p_madw; } qos_mad_item_t; typedef struct qos_mad_list { cl_list_item_t list_item; cl_qlist_t port_mad_list; } qos_mad_list_t; static void qos_build_config(struct qos_config *cfg, osm_qos_options_t * opt, osm_qos_options_t * dflt); /* * QoS primitives */ static qos_mad_item_t *osm_qos_mad_create(IN osm_sm_t * sm, IN osm_physp_t * p, IN uint32_t data_size, IN uint8_t * p_data, IN ib_net16_t attr_id, IN uint32_t attr_mod) { qos_mad_item_t *p_mad; osm_madw_context_t context; osm_madw_t *p_madw; osm_node_t *p_node; osm_physp_t *physp0; ib_net64_t m_key; p_node = osm_physp_get_node_ptr(p); if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p) != 0) { physp0 = osm_node_get_physp_ptr(p_node, 0); m_key = ib_port_info_get_m_key(&physp0->port_info); } else m_key = ib_port_info_get_m_key(&p->port_info); switch (attr_id){ case IB_MAD_ATTR_SLVL_TABLE: context.slvl_context.node_guid = osm_node_get_node_guid(p_node); context.slvl_context.port_guid = osm_physp_get_port_guid(p); context.slvl_context.set_method = TRUE; break; case IB_MAD_ATTR_VL_ARBITRATION: context.vla_context.node_guid = osm_node_get_node_guid(p_node); context.vla_context.port_guid = osm_physp_get_port_guid(p); context.vla_context.set_method = TRUE; break; default: return NULL; } p_mad = (qos_mad_item_t *) malloc(sizeof(*p_mad)); if (!p_mad) return NULL; memset(p_mad, 0, sizeof(*p_mad)); p_madw = osm_prepare_req_set(sm, osm_physp_get_dr_path_ptr(p), p_data, data_size, attr_id, cl_hton32(attr_mod), FALSE, m_key, CL_DISP_MSGID_NONE, &context); if (p_madw == NULL) { free(p_mad); return NULL; } p_mad->p_madw = p_madw; return p_mad; } static void osm_qos_mad_delete(qos_mad_item_t ** p_item) { free(*p_item); *p_item = NULL; } static ib_api_status_t vlarb_update_table_block(osm_sm_t * sm, osm_physp_t * p, uint8_t port_num, unsigned force_update, const ib_vl_arb_table_t * table_block, unsigned block_length, unsigned block_num, cl_qlist_t *mad_list) { struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; ib_vl_arb_table_t block; uint32_t attr_mod; unsigned vl_mask, i; qos_mad_item_t *p_mad; vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1; memset(&block, 0, sizeof(block)); memcpy(&block, table_block, block_length * sizeof(block.vl_entry[0])); if (re && re->update_vlarb) re->update_vlarb(re->context, p, port_num, &block, block_length, block_num); for (i = 0; i < block_length; i++) block.vl_entry[i].vl &= vl_mask; if (!force_update && !memcmp(&p->vl_arb[block_num], &block, block_length * sizeof(block.vl_entry[0]))) return IB_SUCCESS; attr_mod = ((block_num + 1) << 16) | port_num; p_mad = osm_qos_mad_create(sm,p,sizeof(block),(uint8_t *) & block, IB_MAD_ATTR_VL_ARBITRATION, attr_mod); if (!p_mad) return IB_INSUFFICIENT_MEMORY; /* * Zero the stored VL Arbitration block, so in case the MAD will * end up with error, we will resend it in the next sweep. */ memset(&p->vl_arb[block_num], 0, block_length * sizeof(block.vl_entry[0])); cl_qlist_insert_tail(mad_list, &p_mad->list_item); return IB_SUCCESS; } static ib_api_status_t vlarb_update(osm_sm_t * sm, osm_physp_t * p, uint8_t port_num, unsigned force_update, const struct qos_config *qcfg, cl_qlist_t *mad_list) { ib_api_status_t status = IB_SUCCESS; ib_port_info_t *p_pi = &p->port_info; unsigned len; if (p_pi->vl_arb_low_cap > 0) { len = p_pi->vl_arb_low_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? p_pi->vl_arb_low_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; if ((status = vlarb_update_table_block(sm, p, port_num, force_update, &qcfg->vlarb_low[0], len, 0, mad_list)) != IB_SUCCESS) return status; } if (p_pi->vl_arb_low_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { len = p_pi->vl_arb_low_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; if ((status = vlarb_update_table_block(sm, p, port_num, force_update, &qcfg->vlarb_low[1], len, 1, mad_list)) != IB_SUCCESS) return status; } if (p_pi->vl_arb_high_cap > 0) { len = p_pi->vl_arb_high_cap < IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK ? p_pi->vl_arb_high_cap : IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; if ((status = vlarb_update_table_block(sm, p, port_num, force_update, &qcfg->vlarb_high[0], len, 2, mad_list)) != IB_SUCCESS) return status; } if (p_pi->vl_arb_high_cap > IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { len = p_pi->vl_arb_high_cap % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; if ((status = vlarb_update_table_block(sm, p, port_num, force_update, &qcfg->vlarb_high[1], len, 3, mad_list)) != IB_SUCCESS) return status; } return status; } static ib_api_status_t sl2vl_update_table(osm_sm_t * sm, osm_physp_t * p, uint8_t in_port, uint32_t attr_mod, unsigned force_update, const ib_slvl_table_t * sl2vl_table, cl_qlist_t *mad_list) { ib_slvl_table_t tbl, *p_tbl; unsigned vl_mask; uint8_t vl1, vl2; int i; qos_mad_item_t *p_mad; vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1; for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) { vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4; vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf; if (vl1 != 15) vl1 &= vl_mask; if (vl2 != 15) vl2 &= vl_mask; tbl.raw_vl_by_sl[i] = (vl1 << 4) | vl2; } p_tbl = osm_physp_get_slvl_tbl(p, in_port); if (!force_update && !memcmp(p_tbl, &tbl, sizeof(tbl))) return IB_SUCCESS; p_mad = osm_qos_mad_create(sm, p, sizeof(tbl), (uint8_t *) & tbl, IB_MAD_ATTR_SLVL_TABLE, attr_mod); if (!p_mad) return IB_INSUFFICIENT_MEMORY; /* * Zero the stored SL2VL block, so in case the MAD will * end up with error, we will resend it in the next sweep. */ memset(p_tbl, 0, sizeof(tbl)); cl_qlist_insert_tail(mad_list, &p_mad->list_item); return IB_SUCCESS; } static int qos_extports_setup(osm_sm_t * sm, osm_node_t *node, const struct qos_config *qcfg, cl_qlist_t *port_mad_list) { osm_physp_t *p0, *p; unsigned force_update; unsigned num_ports = osm_node_get_num_physp(node); struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; int ret = 0; unsigned in, out; uint8_t op_vl, common_op_vl = 0, max_num = 0; uint8_t op_vl_arr[15]; /* * Do nothing unless the most recent routing attempt was successful. */ if (!re) return ret; for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (!p) continue; if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || sm->p_subn->need_update; p->vl_high_limit = qcfg->vl_high_limit; if (vlarb_update(sm, p, p->port_num, force_update, qcfg, port_mad_list)) ret = -1; } p0 = osm_node_get_physp_ptr(node, 0); if (!(p0->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) return ret; if (ib_switch_info_get_opt_sl2vlmapping(&node->sw->switch_info) && sm->p_subn->opt.use_optimized_slvl && !re->update_sl2vl) { /* we should find the op_vl that is used by majority of ports */ memset(&op_vl_arr[0], 0, sizeof(op_vl_arr)); p0 = osm_node_get_physp_ptr(node, 1); for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (!p) continue; if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; op_vl = ib_port_info_get_op_vls(&p->port_info); op_vl_arr[op_vl]++; if (op_vl_arr[op_vl] > max_num){ max_num = op_vl_arr[op_vl]; common_op_vl = op_vl; /* remember the port with most common op_vl */ p0 = p; } } if (!p0) return -1; force_update = node->sw->need_update || sm->p_subn->need_update; if (sl2vl_update_table(sm, p0, p0->port_num, 0x30000, force_update, &qcfg->sl2vl, port_mad_list)) ret = -1; /* * Overwrite default ALL configuration if port's * op_vl is different. */ for (out = 1; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (!p) continue; if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || force_update; if (ib_port_info_get_op_vls(&p->port_info) != common_op_vl && sl2vl_update_table(sm, p, p->port_num, 0x20000 | out, force_update, &qcfg->sl2vl, port_mad_list)) ret = -1; } return ret; } /* non optimized sl2vl configuration */ out = ib_switch_info_is_enhanced_port0(&node->sw->switch_info) ? 0 : 1; for (; out < num_ports; out++) { p = osm_node_get_physp_ptr(node, out); if (!p) continue; if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN) continue; force_update = p->need_update || sm->p_subn->need_update; /* go over all in ports */ for (in = 0; in < num_ports; in++) { const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl; ib_slvl_table_t routing_sl2vl; if (re->update_sl2vl) { routing_sl2vl = *port_sl2vl; re->update_sl2vl(re->context, p, in, out, &routing_sl2vl); port_sl2vl = &routing_sl2vl; } if (sl2vl_update_table(sm, p, in, in << 8 | out, force_update, port_sl2vl, port_mad_list)) ret = -1; } } return ret; } static int qos_endport_setup(osm_sm_t * sm, osm_physp_t * p, const struct qos_config *qcfg, int vlarb_only, cl_qlist_t *port_mad_list) { unsigned force_update = p->need_update || sm->p_subn->need_update; struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used; const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl; ib_slvl_table_t routing_sl2vl; p->vl_high_limit = qcfg->vl_high_limit; if (vlarb_update(sm, p, 0, force_update, qcfg, port_mad_list)) return -1; if (vlarb_only) return 0; if (!(p->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) return 0; if (re && re->update_sl2vl) { routing_sl2vl = *port_sl2vl; re->update_sl2vl(re->context, p, 0, 0, &routing_sl2vl); port_sl2vl = &routing_sl2vl; } if (sl2vl_update_table(sm, p, 0, 0, force_update, port_sl2vl, port_mad_list)) return -1; return 0; } int osm_qos_setup(osm_opensm_t * p_osm) { struct qos_config ca_config, sw0_config, swe_config, rtr_config; struct qos_config *cfg; cl_qmap_t *p_tbl; cl_map_item_t *p_next; osm_port_t *p_port; osm_node_t *p_node; int ret = 0; int vlarb_only; qos_mad_list_t *p_list, *p_list_next; qos_mad_item_t *p_port_mad; cl_qlist_t qos_mad_list; if (!p_osm->subn.opt.qos) return 0; OSM_LOG_ENTER(&p_osm->log); qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options, &p_osm->subn.opt.qos_options); qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options, &p_osm->subn.opt.qos_options); qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options, &p_osm->subn.opt.qos_options); qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options, &p_osm->subn.opt.qos_options); cl_qlist_init(&qos_mad_list); cl_plock_excl_acquire(&p_osm->lock); /* read QoS policy config file */ osm_qos_parse_policy_file(&p_osm->subn); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { vlarb_only = 0; p_port = (osm_port_t *) p_next; p_next = cl_qmap_next(p_next); p_list = (qos_mad_list_t *) malloc(sizeof(*p_list)); if (!p_list) { cl_plock_release(&p_osm->lock); return -1; } memset(p_list, 0, sizeof(*p_list)); cl_qlist_init(&p_list->port_mad_list); p_node = p_port->p_node; if (p_node->sw) { if (qos_extports_setup(&p_osm->sm, p_node, &swe_config, &p_list->port_mad_list)) { cl_plock_release(&p_osm->lock); ret = -1; } /* skip base port 0 */ if (!ib_switch_info_is_enhanced_port0 (&p_node->sw->switch_info)) goto Continue; if (ib_switch_info_get_opt_sl2vlmapping(&p_node->sw->switch_info) && p_osm->sm.p_subn->opt.use_optimized_slvl && !memcmp(&swe_config.sl2vl, &sw0_config.sl2vl, sizeof(swe_config.sl2vl))) vlarb_only = 1; cfg = &sw0_config; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER) cfg = &rtr_config; else cfg = &ca_config; if (qos_endport_setup(&p_osm->sm, p_port->p_physp, cfg, vlarb_only, &p_list->port_mad_list)) { cl_plock_release(&p_osm->lock); ret = -1; } Continue: /* if MAD list is not empty, add it to the global MAD list */ if (cl_qlist_count(&p_list->port_mad_list)) { cl_qlist_insert_tail(&qos_mad_list, &p_list->list_item); } else { free(p_list); } } while (cl_qlist_count(&qos_mad_list)) { p_list_next = (qos_mad_list_t *) cl_qlist_head(&qos_mad_list); while (p_list_next != (qos_mad_list_t *) cl_qlist_end(&qos_mad_list)) { p_list = p_list_next; p_list_next = (qos_mad_list_t *) cl_qlist_next(&p_list->list_item); /* next MAD to send*/ p_port_mad = (qos_mad_item_t *) cl_qlist_remove_head(&p_list->port_mad_list); osm_send_req_mad(&p_osm->sm, p_port_mad->p_madw); osm_qos_mad_delete(&p_port_mad); /* remove the QoS MAD from global MAD list */ if (cl_qlist_count(&p_list->port_mad_list) == 0) { cl_qlist_remove_item(&qos_mad_list, &p_list->list_item); free(p_list); } } } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; } /* * QoS config stuff */ static int parse_one_unsigned(const char *str, char delim, unsigned *val) { char *end; *val = strtoul(str, &end, 0); if (*end) end++; return (int)(end - str); } static int parse_vlarb_entry(const char *str, ib_vl_arb_element_t * e) { unsigned val; const char *p = str; p += parse_one_unsigned(p, ':', &val); e->vl = val % 15; p += parse_one_unsigned(p, ',', &val); e->weight = (uint8_t) val; return (int)(p - str); } static int parse_sl2vl_entry(const char *str, uint8_t * raw) { unsigned val1, val2; const char *p = str; p += parse_one_unsigned(p, ',', &val1); p += parse_one_unsigned(p, ',', &val2); *raw = (val1 << 4) | (val2 & 0xf); return (int)(p - str); } static void qos_build_config(struct qos_config *cfg, osm_qos_options_t * opt, osm_qos_options_t * dflt) { int i; const char *p; memset(cfg, 0, sizeof(*cfg)); if (opt->max_vls > 0) cfg->max_vls = opt->max_vls; else { if (dflt->max_vls > 0) cfg->max_vls = dflt->max_vls; else cfg->max_vls = OSM_DEFAULT_QOS_MAX_VLS; } if (opt->high_limit >= 0) cfg->vl_high_limit = (uint8_t) opt->high_limit; else { if (dflt->high_limit >= 0) cfg->vl_high_limit = (uint8_t) dflt->high_limit; else cfg->vl_high_limit = (uint8_t) OSM_DEFAULT_QOS_HIGH_LIMIT; } if (opt->vlarb_high) p = opt->vlarb_high; else { if (dflt->vlarb_high) p = dflt->vlarb_high; else p = OSM_DEFAULT_QOS_VLARB_HIGH; } for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { p += parse_vlarb_entry(p, &cfg->vlarb_high[i / IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. vl_entry[i % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); } if (opt->vlarb_low) p = opt->vlarb_low; else { if (dflt->vlarb_low) p = dflt->vlarb_low; else p = OSM_DEFAULT_QOS_VLARB_LOW; } for (i = 0; i < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK; i++) { p += parse_vlarb_entry(p, &cfg->vlarb_low[i / IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]. vl_entry[i % IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK]); } p = opt->sl2vl ? opt->sl2vl : dflt->sl2vl; if (opt->sl2vl) p = opt->sl2vl; else { if (dflt->sl2vl) p = dflt->sl2vl; else p = OSM_DEFAULT_QOS_SL2VL; } for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]); } opensm-3.3.20/opensm/osm_router.c0000644000205000001450000000437012104655725013666 00000000000000/* * Copyright (c) 2004-2009 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 osm_router_t. * This object represents an Infiniband router. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_ROUTER_C #include void osm_router_delete(IN OUT osm_router_t ** pp_rtr) { free(*pp_rtr); *pp_rtr = NULL; } osm_router_t *osm_router_new(IN osm_port_t * p_port) { osm_router_t *p_rtr; CL_ASSERT(p_port); p_rtr = malloc(sizeof(*p_rtr)); if (p_rtr) { memset(p_rtr, 0, sizeof(*p_rtr)); p_rtr->p_port = p_port; } return p_rtr; } opensm-3.3.20/opensm/osm_trap_rcv.c0000644000205000001450000005331412344101022014146 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. 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 osm_trap_rcv_t. * This object represents the Trap Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_TRAP_RCV_C #include #include #include #include #include #include #include extern void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t *p_physp); /********************************************************************** * * TRAP HANDLING: * * Assuming traps can be caused by bad hardware we should provide * a mechanism for filtering their propagation into the actual logic * of OpenSM such that it is not overloaded by them. * * We will provide a trap filtering mechanism with "Aging" capability. * This mechanism will track incoming traps, clasify them by their * source and content and provide back their age. * * A timer running in the background will toggle a timer counter * that should be referenced by the aging algorithm. * To provide an efficient handling of aging, we also track all traps * in a sorted list by their aging. * * The generic Aging Tracker mechanism is implemented in the * cl_aging_tracker object. * **********************************************************************/ static osm_physp_t *get_physp_by_lid_and_num(IN osm_sm_t * sm, IN ib_net16_t lid, IN uint8_t num) { osm_port_t *p_port = osm_get_port_by_lid(sm->p_subn, lid); if (!p_port) return NULL; if (osm_node_get_num_physp(p_port->p_node) <= num) return NULL; return osm_node_get_physp_ptr(p_port->p_node, num); } static uint64_t aging_tracker_callback(IN uint64_t key, IN uint32_t num_regs, IN void *context) { osm_sm_t *sm = context; ib_net16_t lid; uint8_t port_num; osm_physp_t *p_physp; OSM_LOG_ENTER(sm->p_log); if (osm_exit_flag) /* We got an exit flag - do nothing */ return 0; lid = (ib_net16_t) ((key & 0x0000FFFF00000000ULL) >> 32); port_num = (uint8_t) ((key & 0x00FF000000000000ULL) >> 48); CL_PLOCK_ACQUIRE(sm->p_lock); p_physp = get_physp_by_lid_and_num(sm, lid, port_num); if (!p_physp) OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Cannot find port num:%u with lid:%u\n", port_num, cl_ntoh16(lid)); /* make sure the physp is still valid */ /* If the health port was false - set it to true */ else if (!osm_physp_is_healthy(p_physp)) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Clearing health bit of port num:%u with lid:%u\n", port_num, cl_ntoh16(lid)); /* Clear its health bit */ osm_physp_set_health(p_physp, TRUE); } CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG_EXIT(sm->p_log); /* We want to remove the event from the tracker - so need to return zero. */ return 0; } /********************************************************************** * CRC calculation for notice identification **********************************************************************/ #define CRC32_POLYNOMIAL 0xEDB88320L /* calculate the crc for a given buffer */ static uint32_t trap_calc_crc32(void *buffer, uint32_t count) { uint32_t temp1, temp2; uint32_t crc = -1L; unsigned char *p = (unsigned char *)buffer; /* precalculated table for faster crc calculation */ static uint32_t crc_table[256]; static boolean_t first = TRUE; int i, j; /* if we need to initialize the lookup table */ if (first) { /* calc the CRC table */ for (i = 0; i <= 255; i++) { crc = i; for (j = 8; j > 0; j--) if (crc & 1) crc = (crc >> 1) ^ CRC32_POLYNOMIAL; else crc >>= 1; crc_table[i] = crc; } first = FALSE; } crc = -1L; /* do the calculation */ while (count-- != 0) { temp1 = (crc >> 8) & 0x00FFFFFFL; temp2 = crc_table[((int)crc ^ *p++) & 0xFF]; crc = temp1 ^ temp2; } return crc; } /* The key is created in the following manner: port_num lid crc \______/ \___/ \___/ 16b 16b 32b */ static uint64_t trap_get_key(IN uint16_t lid, IN uint8_t port_num, IN ib_mad_notice_attr_t * p_ntci) { uint32_t crc = trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t)); return ((uint64_t) port_num << 48) | ((uint64_t) lid << 32) | crc; } static int print_num_received(IN uint32_t num_received) { uint32_t i; /* Series is 10, 20, 50, 100, 200, 500, ... */ i = num_received; while (i >= 10) { if (i % 10) break; i = i / 10; } if (i == 1 || i == 2 || i == 5) return 1; else return 0; } static int disable_port(osm_sm_t *sm, osm_physp_t *p) { uint8_t payload[IB_SMP_DATA_SIZE]; osm_madw_context_t context; ib_port_info_t *pi = (ib_port_info_t *)payload; osm_physp_t *physp0; osm_port_t *p_port; ib_net64_t m_key; ib_api_status_t status; /* select the nearest port to master opensm */ if (p->p_remote_physp && p->dr_path.hop_count > p->p_remote_physp->dr_path.hop_count) p = p->p_remote_physp; /* If trap 131, might want to disable peer port if available */ /* but peer port has been observed not to respond to SM requests */ memcpy(payload, &p->port_info, sizeof(ib_port_info_t)); /* Set port to disabled/down */ ib_port_info_set_port_state(pi, IB_LINK_DOWN); ib_port_info_set_port_phys_state(IB_PORT_PHYS_STATE_DISABLED, pi); /* Issue set of PortInfo */ context.pi_context.node_guid = osm_node_get_node_guid(p->p_node); context.pi_context.port_guid = osm_physp_get_port_guid(p); context.pi_context.set_method = TRUE; context.pi_context.light_sweep = FALSE; context.pi_context.active_transition = FALSE; context.pi_context.client_rereg = FALSE; if (osm_node_get_type(p->p_node) == IB_NODE_TYPE_SWITCH && osm_physp_get_port_num(p) != 0) { physp0 = osm_node_get_physp_ptr(p->p_node, 0); m_key = ib_port_info_get_m_key(&physp0->port_info); } else m_key = ib_port_info_get_m_key(&p->port_info); if (osm_node_get_type(p->p_node) != IB_NODE_TYPE_SWITCH) { if (!pi->base_lid) { p_port = osm_get_port_by_guid(sm->p_subn, osm_physp_get_port_guid(p)); pi->base_lid = p_port->lid; } pi->master_sm_base_lid = sm->p_subn->sm_base_lid; } status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p), payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO, cl_hton32(osm_physp_get_port_num(p)), FALSE, m_key, CL_DISP_MSGID_NONE, &context); return status; } static void log_trap_info(osm_log_t *p_log, ib_mad_notice_attr_t *p_ntci, ib_net16_t source_lid, ib_net64_t trans_id) { if (!OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_ERROR)) return; if (ib_notice_is_generic(p_ntci)) { char str[32]; if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_LINK_INTEGRITY_THRESHOLD_TRAP)) || (p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_BUFFER_OVERRUN_THRESHOLD_TRAP)) || (p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_WATCHDOG_TIMER_EXPIRED_TRAP))) snprintf(str, sizeof(str), " Port %u", p_ntci->data_details.ntc_129_131.port_num); else str[0] = '\0'; OSM_LOG(p_log, OSM_LOG_ERROR, "Received Generic Notice type:%u " "num:%u (%s) Producer:%u (%s) " "from LID:%u%s TID:0x%016" PRIx64 "\n", ib_notice_get_type(p_ntci), cl_ntoh16(p_ntci->g_or_v.generic.trap_num), ib_get_trap_str(p_ntci->g_or_v.generic.trap_num), cl_ntoh32(ib_notice_get_prod_type(p_ntci)), ib_get_producer_type_str(ib_notice_get_prod_type(p_ntci)), cl_hton16(source_lid), str, cl_ntoh64(trans_id)); if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_BAD_PKEY_TRAP)) || (p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_BAD_QKEY_TRAP))) { OSM_LOG(p_log, OSM_LOG_ERROR, "Bad %s_Key:0x%x on SL:%d from " "LID1:%u QP1:0x%x to " "LID2:%u QP2:0x%x\n", (p_ntci->g_or_v.generic.trap_num == CL_HTON16(257)) ? "P" : "Q", cl_ntoh32(p_ntci->data_details.ntc_257_258.key), cl_ntoh32(p_ntci->data_details.ntc_257_258.qp1) >> 28, cl_ntoh16(p_ntci->data_details.ntc_257_258.lid1), cl_ntoh32(p_ntci->data_details.ntc_257_258.qp1) & 0xfff, cl_ntoh16(p_ntci->data_details.ntc_257_258.lid2), cl_ntoh32(p_ntci->data_details.ntc_257_258.qp2)); } } else OSM_LOG(p_log, OSM_LOG_ERROR, "Received Vendor Notice type:%u vend:0x%06X " "dev:%u from LID:%u TID:0x%016" PRIx64 "\n", ib_notice_get_type(p_ntci), cl_ntoh32(ib_notice_get_vend_id(p_ntci)), cl_ntoh16(p_ntci->g_or_v.vend.dev_id), cl_ntoh16(source_lid), cl_ntoh64(trans_id)); } static int shutup_noisy_port(osm_sm_t *sm, ib_net16_t lid, uint8_t port, unsigned num) { osm_physp_t *p = get_physp_by_lid_and_num(sm, lid, port); if (!p) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3805: " "Failed to find physical port by lid:%u num:%u\n", cl_ntoh16(lid), port); return -1; } /* When babbling port policy option is enabled and Threshold for disabling a "babbling" port is exceeded */ if (sm->p_subn->opt.babbling_port_policy && num >= 250) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Disabling noisy physical port 0x%016" PRIx64 ": lid %u, num %u\n", cl_ntoh64(osm_physp_get_port_guid(p)), cl_ntoh16(lid), port); if (disable_port(sm, p)) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3811: " "Failed to disable noisy physical port 0x%016" PRIx64 ": lid %u, num %u\n", cl_ntoh64(osm_physp_get_port_guid(p)), cl_ntoh16(lid), port); else return 1; } /* check if the current state of the p_physp is healthy. If it is - then this is a first change of state. Run a heavy sweep. */ if (osm_physp_is_healthy(p)) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Marking unhealthy physical port by lid:%u num:%u\n", cl_ntoh16(lid), port); osm_physp_set_health(p, FALSE); return 2; } return 0; } static void trap_rcv_process_request(IN osm_sm_t * sm, IN const osm_madw_t * p_madw) { uint8_t payload[sizeof(ib_mad_notice_attr_t)]; ib_smp_t *p_smp; ib_mad_notice_attr_t *p_ntci = (ib_mad_notice_attr_t *) payload; ib_api_status_t status; osm_madw_t tmp_madw; /* we need a copy to last after repress */ uint64_t trap_key; uint32_t num_received; osm_physp_t *p_physp; osm_port_t *p_port; ib_net16_t source_lid = 0; boolean_t is_gsi = TRUE; uint8_t port_num = 0; boolean_t physp_change_trap = FALSE; uint64_t event_wheel_timeout = OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT; boolean_t run_heavy_sweep = FALSE; char buf[1024]; osm_dr_path_t *p_path; unsigned n; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); if (osm_exit_flag) /* We got an exit flag - do nothing Otherwise we start a sweep on the trap 144 caused by cleaning up SM Cap bit... */ goto Exit2; /* update the is_gsi flag according to the mgmt_class field */ if (p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_LID || p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) is_gsi = FALSE; /* No real need to grab the lock for this function. */ memset(payload, 0, sizeof(payload)); memset(&tmp_madw, 0, sizeof(tmp_madw)); p_smp = osm_madw_get_smp_ptr(p_madw); if (p_smp->method != IB_MAD_METHOD_TRAP) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3801: " "Unsupported method 0x%X\n", p_smp->method); goto Exit2; } /* * The NOTICE Attribute is part of the SMP CLASS attributes * As such the actual attribute data resides inside the SMP * payload. */ memcpy(payload, &p_smp->data, IB_SMP_DATA_SIZE); memcpy(&tmp_madw, p_madw, sizeof(tmp_madw)); if (is_gsi == FALSE) { /* We are in smi flow */ /* * When we receive a TRAP with dlid = 0 - it means it * came from our own node. So we need to fix it. */ if (p_madw->mad_addr.addr_type.smi.source_lid == 0) { /* Check if the sm_base_lid is 0. If yes - this means that the local lid wasn't configured yet. Don't send a response to the trap. */ if (sm->p_subn->sm_base_lid == 0) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received SLID=0 Trap with local LID=0. Ignoring MAD\n"); goto Exit2; } OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Received SLID=0 Trap. Using local LID:%u instead\n", cl_ntoh16(sm->p_subn->sm_base_lid)); tmp_madw.mad_addr.addr_type.smi.source_lid = sm->p_subn->sm_base_lid; } source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid; /* Print some info about the incoming Trap */ log_trap_info(sm->p_log, p_ntci, source_lid, p_smp->trans_id); } osm_dump_notice_v2(sm->p_log, p_ntci, FILE_ID, OSM_LOG_VERBOSE); CL_PLOCK_ACQUIRE(sm->p_lock); p_physp = osm_get_physp_by_mad_addr(sm->p_log, sm->p_subn, &tmp_madw.mad_addr); if (p_physp) p_smp->m_key = ib_port_info_get_m_key(&p_physp->port_info); else OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3809: " "Failed to find source physical port for trap\n"); status = osm_resp_send(sm, &tmp_madw, 0, payload); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3802: " "Error sending response (%s)\n", ib_get_err_str(status)); goto Exit; } /* * We would like to filter out recurring Traps so we track them by * their source lid and content. If the same trap was already * received within the aging time window more than 10 times, * we simply ignore it. This is done only if we are in smi mode */ if (is_gsi == FALSE) { if (ib_notice_is_generic(p_ntci) && (p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_LINK_INTEGRITY_THRESHOLD_TRAP) || p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_BUFFER_OVERRUN_THRESHOLD_TRAP) || p_ntci->g_or_v.generic.trap_num == CL_HTON16(SM_WATCHDOG_TIMER_EXPIRED_TRAP))) { /* If this is a trap 129, 130, or 131 - then this is a * trap signaling a change on a physical port. * Mark the physp_change_trap flag as TRUE. */ physp_change_trap = TRUE; /* The source_lid should be based on the source_lid from the trap */ source_lid = p_ntci->data_details.ntc_129_131.lid; port_num = p_ntci->data_details.ntc_129_131.port_num; } /* try to find it in the aging tracker */ trap_key = trap_get_key(source_lid, port_num, p_ntci); num_received = cl_event_wheel_num_regs(&sm->trap_aging_tracker, trap_key); /* Now we know how many times it provided this trap */ if (num_received > 10) { if (print_num_received(num_received)) OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Received trap %u times consecutively\n", num_received); /* * If the trap provides info about a bad port * we mark it as unhealthy. */ if (physp_change_trap == TRUE) { int ret = shutup_noisy_port(sm, source_lid, port_num, num_received); if (ret == 1) /* port disabled */ goto Exit; else if (ret == 2) /* unhealthy - run sweep */ run_heavy_sweep = TRUE; /* in any case increase timeout interval */ event_wheel_timeout = OSM_DEFAULT_UNHEALTHY_TIMEOUT; } } /* restart the aging anyway */ /* If physp_change_trap is TRUE - then use a callback to unset the healthy bit. If not - no need to use a callback. */ if (physp_change_trap == TRUE) cl_event_wheel_reg(&sm->trap_aging_tracker, trap_key, cl_get_time_stamp() + event_wheel_timeout, aging_tracker_callback, sm); else cl_event_wheel_reg(&sm->trap_aging_tracker, trap_key, cl_get_time_stamp() + event_wheel_timeout, NULL, NULL); /* If was already registered do nothing more */ if (num_received > 10 && run_heavy_sweep == FALSE) { if (print_num_received(num_received)) OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Ignoring noisy traps.\n"); goto Exit; } } /* Check for node description update. IB Spec v1.2.1 pg 823 */ if (!ib_notice_is_generic(p_ntci)) goto check_sweep; if (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == SM_LOCAL_CHANGES_TRAP && p_ntci->data_details.ntc_144.local_changes & TRAP_144_MASK_OTHER_LOCAL_CHANGES && p_ntci->data_details.ntc_144.change_flgs & TRAP_144_MASK_NODE_DESCRIPTION_CHANGE) { OSM_LOG(sm->p_log, OSM_LOG_INFO, "Trap 144 Node description update\n"); if (p_physp) { osm_req_get_node_desc(sm, p_physp); if (!(p_ntci->data_details.ntc_144.change_flgs & ~TRAP_144_MASK_NODE_DESCRIPTION_CHANGE) && p_ntci->data_details.ntc_144.new_cap_mask == p_physp->port_info.capability_mask) goto check_report; } else OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3812: No physical port found for " "trap 144: \"node description update\"\n"); goto check_sweep; } else if (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == SM_SYS_IMG_GUID_CHANGED_TRAP) { if (p_physp) { CL_PLOCK_RELEASE(sm->p_lock); CL_PLOCK_EXCL_ACQUIRE(sm->p_lock); p_physp = osm_get_physp_by_mad_addr(sm->p_log, sm->p_subn, &tmp_madw.mad_addr); if (p_physp) { /* this assumes that trap 145 content is not broken? */ p_physp->p_node->node_info.sys_guid = p_ntci->data_details.ntc_145.new_sys_guid; } CL_PLOCK_RELEASE(sm->p_lock); CL_PLOCK_ACQUIRE(sm->p_lock); } else OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3813: No physical port found for " "trap 145: \"SystemImageGUID update\"\n"); goto check_report; } check_sweep: if (osm_log_is_active_v2(sm->p_log, OSM_LOG_INFO, FILE_ID)) { if (ib_notice_is_generic(p_ntci) && cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == SM_LINK_STATE_CHANGED_TRAP) { p_path = (p_physp) ? osm_physp_get_dr_path_ptr(p_physp) : NULL; if (p_path) { n = sprintf(buf, "SM class trap %u: ", cl_ntoh16(p_ntci->g_or_v.generic.trap_num)); n += snprintf(buf + n, sizeof(buf) - n, "Directed Path Dump of %u hop path: " "Path = ", p_path->hop_count); osm_dump_dr_path_as_buf(sizeof(buf) - n, p_path, buf + n); osm_log_v2(sm->p_log, OSM_LOG_INFO, FILE_ID, "%s\n", buf); } } } /* do a sweep if we received a trap */ if (sm->p_subn->opt.sweep_on_trap) { /* if this is trap number 128 or run_heavy_sweep is TRUE - update the force_heavy_sweep flag of the subnet. Sweep also on traps 144 - these traps signal a change of certain port capabilities. TODO: In the future this can be changed to just getting PortInfo on this port instead of sweeping the entire subnet. */ if (ib_notice_is_generic(p_ntci) && (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == SM_LINK_STATE_CHANGED_TRAP || cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == SM_LOCAL_CHANGES_TRAP || run_heavy_sweep)) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Forcing heavy sweep. Received trap:%u\n", cl_ntoh16(p_ntci->g_or_v.generic.trap_num)); sm->p_subn->force_heavy_sweep = TRUE; } osm_sm_signal(sm, OSM_SIGNAL_SWEEP); } /* If we reached here due to trap 129/130/131 - do not need to do the notice report. Just goto exit. We know this is the case if physp_change_trap is TRUE. */ if (physp_change_trap == TRUE) goto Exit; check_report: /* We are going to report the notice - so need to fix the IssuerGID accordingly. See IBA 1.2 p.739 or IBA 1.1 p.653 for details. */ if (is_gsi) { if (!tmp_madw.mad_addr.addr_type.gsi.global_route) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3806: " "Received gsi trap with global_route FALSE. " "Cannot update issuer_gid!\n"); goto Exit; } memcpy(&p_ntci->issuer_gid, &tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid, sizeof(ib_gid_t)); } else { /* Need to use the IssuerLID */ p_port = osm_get_port_by_lid(sm->p_subn, source_lid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Cannot find port corresponding to lid:%u\n", cl_ntoh16(source_lid)); goto Exit; } p_ntci->issuer_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix; p_ntci->issuer_gid.unicast.interface_id = p_port->guid; } /* we need a lock here as the InformInfo DB must be stable */ status = osm_report_notice(sm->p_log, sm->p_subn, p_ntci); if (status != IB_SUCCESS) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3803: " "Error sending trap reports (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: CL_PLOCK_RELEASE(sm->p_lock); Exit2: OSM_LOG_EXIT(sm->p_log); } void osm_trap_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_smp_t __attribute__((unused)) *p_smp; OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); /* Only Trap requests get here */ CL_ASSERT(!ib_smp_is_response(p_smp)); trap_rcv_process_request(sm, p_madw); OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/osm_ucast_mgr.c0000644000205000001450000007777212607211645014347 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 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 osm_ucast_mgr_t. * This file implements the Unicast Manager object. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_MGR_C #include #include #include #include #include #include #include #include void osm_ucast_mgr_construct(IN osm_ucast_mgr_t * p_mgr) { memset(p_mgr, 0, sizeof(*p_mgr)); } void osm_ucast_mgr_destroy(IN osm_ucast_mgr_t * p_mgr) { CL_ASSERT(p_mgr); OSM_LOG_ENTER(p_mgr->p_log); if (p_mgr->cache_valid) osm_ucast_cache_invalidate(p_mgr); OSM_LOG_EXIT(p_mgr->p_log); } ib_api_status_t osm_ucast_mgr_init(IN osm_ucast_mgr_t * p_mgr, IN osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); osm_ucast_mgr_construct(p_mgr); p_mgr->sm = sm; p_mgr->p_log = sm->p_log; p_mgr->p_subn = sm->p_subn; p_mgr->p_lock = sm->p_lock; if (sm->p_subn->opt.use_ucast_cache) cl_qmap_init(&p_mgr->cache_sw_tbl); OSM_LOG_EXIT(p_mgr->p_log); return status; } /********************************************************************** Add each switch's own and neighbor LIDs to its LID matrix **********************************************************************/ static void ucast_mgr_process_hop_0_1(IN cl_map_item_t * p_map_item, IN void *context) { osm_switch_t * p_sw = (osm_switch_t *) p_map_item; osm_node_t *p_remote_node; uint16_t lid, remote_lid; uint8_t i; lid = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0)); osm_switch_set_hops(p_sw, lid, 0, 0); for (i = 1; i < p_sw->num_ports; i++) { osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, i); p_remote_node = (p && p->p_remote_physp) ? p->p_remote_physp->p_node : NULL; if (p_remote_node && p_remote_node->sw && p_remote_node != p_sw->p_node) { remote_lid = osm_node_get_base_lid(p_remote_node, 0); remote_lid = cl_ntoh16(remote_lid); osm_switch_set_hops(p_sw, remote_lid, i, p->hop_wf); } } } static void ucast_mgr_process_neighbor(IN osm_ucast_mgr_t * p_mgr, IN osm_switch_t * p_this_sw, IN osm_switch_t * p_remote_sw, IN uint8_t port_num, IN uint8_t remote_port_num) { osm_switch_t *p_sw; cl_map_item_t *item; uint16_t lid_ho; uint8_t hops; osm_physp_t *p; OSM_LOG_ENTER(p_mgr->p_log); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 ", port %u, remote port %u\n", cl_ntoh64(osm_node_get_node_guid(p_this_sw->p_node)), cl_ntoh64(osm_node_get_node_guid(p_remote_sw->p_node)), port_num, remote_port_num); p = osm_node_get_physp_ptr(p_this_sw->p_node, port_num); for (item = cl_qmap_head(&p_mgr->p_subn->sw_guid_tbl); item != cl_qmap_end(&p_mgr->p_subn->sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; lid_ho = cl_ntoh16(osm_node_get_base_lid(p_sw->p_node, 0)); hops = osm_switch_get_least_hops(p_remote_sw, lid_ho); if (hops == OSM_NO_PATH) continue; hops += p->hop_wf; if (hops < osm_switch_get_hop_count(p_this_sw, lid_ho, port_num)) { if (osm_switch_set_hops (p_this_sw, lid_ho, port_num, hops) != 0) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A03: " "cannot set hops for lid %u at switch 0x%" PRIx64 "\n", lid_ho, cl_ntoh64(osm_node_get_node_guid (p_this_sw->p_node))); p_mgr->some_hop_count_set = TRUE; } } OSM_LOG_EXIT(p_mgr->p_log); } static struct osm_remote_node *find_and_add_remote_sys(osm_switch_t * sw, uint8_t port, boolean_t dor, struct osm_remote_guids_count *r) { unsigned i; osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, port); osm_node_t *node = p->p_remote_physp->p_node; uint8_t rem_port = osm_physp_get_port_num(p->p_remote_physp); for (i = 0; i < r->count; i++) if (r->guids[i].node == node) if (!dor || (r->guids[i].port == rem_port)) return &r->guids[i]; r->guids[i].node = node; r->guids[i].forwarded_to = 0; r->guids[i].port = rem_port; r->count++; return &r->guids[i]; } static void ucast_mgr_process_port(IN osm_ucast_mgr_t * p_mgr, IN osm_switch_t * p_sw, IN osm_port_t * p_port, IN unsigned lid_offset) { uint16_t min_lid_ho; uint16_t max_lid_ho; uint16_t lid_ho; uint8_t port; boolean_t is_ignored_by_port_prof; ib_net64_t node_guid; unsigned start_from = 1; OSM_LOG_ENTER(p_mgr->p_log); osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho); /* If the lids are zero - then there was some problem with * the initialization. Don't handle this port. */ if (min_lid_ho == 0 || max_lid_ho == 0) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A04: " "Port 0x%" PRIx64 " (%s port %d) has LID 0. An " "initialization error occurred. Ignoring port\n", cl_ntoh64(osm_port_get_guid(p_port)), p_port->p_node->print_desc, p_port->p_physp->port_num); goto Exit; } lid_ho = min_lid_ho + lid_offset; if (lid_ho > max_lid_ho) goto Exit; if (lid_offset && !p_mgr->is_dor) /* ignore potential overflow - it is handled in osm_switch.c */ start_from = osm_switch_get_port_by_lid(p_sw, lid_ho - 1, OSM_NEW_LFT) + 1; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing port 0x%" PRIx64 " (\'%s\' port %u), LID %u [%u,%u]\n", cl_ntoh64(osm_port_get_guid(p_port)), p_port->p_node->print_desc, p_port->p_physp->port_num, lid_ho, min_lid_ho, max_lid_ho); /* TODO - This should be runtime error, not a CL_ASSERT() */ CL_ASSERT(max_lid_ho <= IB_LID_UCAST_END_HO); node_guid = osm_node_get_node_guid(p_sw->p_node); /* The lid matrix contains the number of hops to each lid from each port. From this information we determine how best to distribute the LID range across the ports that can reach those LIDs. */ port = osm_switch_recommend_path(p_sw, p_port, lid_ho, start_from, p_mgr->p_subn->ignore_existing_lfts, p_mgr->p_subn->opt.lmc, p_mgr->is_dor, p_mgr->p_subn->opt.port_shifting, !lid_offset && p_port->use_scatter, OSM_LFT); if (port == OSM_NO_PATH) { /* do not try to overwrite the ppro of non existing port ... */ is_ignored_by_port_prof = TRUE; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "No path to get to LID %u from switch 0x%" PRIx64 "\n", lid_ho, cl_ntoh64(node_guid)); } else { osm_physp_t *p = osm_node_get_physp_ptr(p_sw->p_node, port); if (!p) goto Exit; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Routing LID %u to port %u for switch 0x%" PRIx64 "\n", lid_ho, port, cl_ntoh64(node_guid)); /* we would like to optionally ignore this port in equalization as in the case of the Mellanox Anafa Internal PCI TCA port */ is_ignored_by_port_prof = p->is_prof_ignored; /* We also would ignore this route if the target lid is of a switch and the port_profile_switch_node is not TRUE */ if (!p_mgr->p_subn->opt.port_profile_switch_nodes) is_ignored_by_port_prof |= (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH); } /* We have selected the port for this LID. Write it to the forwarding tables. */ p_sw->new_lft[lid_ho] = port; if (!is_ignored_by_port_prof) { struct osm_remote_node *rem_node_used; osm_switch_count_path(p_sw, port); if (port > 0 && p_port->priv && (rem_node_used = find_and_add_remote_sys(p_sw, port, p_mgr->is_dor, p_port->priv))) rem_node_used->forwarded_to++; } Exit: OSM_LOG_EXIT(p_mgr->p_log); } static void alloc_ports_priv(osm_ucast_mgr_t * mgr) { cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl; struct osm_remote_guids_count *r; osm_port_t *port; cl_map_item_t *item; unsigned lmc; for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl); item = cl_qmap_next(item)) { port = (osm_port_t *) item; lmc = ib_port_info_get_lmc(&port->p_physp->port_info); r = malloc(sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc)); if (!r) { OSM_LOG(mgr->p_log, OSM_LOG_ERROR, "ERR 3A09: " "cannot allocate memory to track remote" " systems for lmc > 0\n"); port->priv = NULL; continue; } memset(r, 0, sizeof(*r) + sizeof(r->guids[0]) * (1 << lmc)); port->priv = r; } } static void free_ports_priv(osm_ucast_mgr_t * mgr) { cl_qmap_t *port_tbl = &mgr->p_subn->port_guid_tbl; osm_port_t *port; cl_map_item_t *item; for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl); item = cl_qmap_next(item)) { port = (osm_port_t *) item; if (port->priv) { free(port->priv); port->priv = NULL; } } } static void ucast_mgr_process_tbl(IN cl_map_item_t * p_map_item, IN void *context) { osm_ucast_mgr_t *p_mgr = context; osm_switch_t * p_sw = (osm_switch_t *) p_map_item; unsigned i, lids_per_port; OSM_LOG_ENTER(p_mgr->p_log); CL_ASSERT(p_sw && p_sw->p_node); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing switch 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); /* Initialize LIDs in buffer to invalid port number. */ memset(p_sw->new_lft, OSM_NO_PATH, p_sw->max_lid_ho + 1); alloc_ports_priv(p_mgr); /* Iterate through every port setting LID routes for each port based on base LID and LMC value. */ lids_per_port = 1 << p_mgr->p_subn->opt.lmc; for (i = 0; i < lids_per_port; i++) { cl_qlist_t *list = &p_mgr->port_order_list; cl_list_item_t *item; for (item = cl_qlist_head(list); item != cl_qlist_end(list); item = cl_qlist_next(item)) { osm_port_t *port = cl_item_obj(item, port, list_item); ucast_mgr_process_port(p_mgr, p_sw, port, i); } } free_ports_priv(p_mgr); OSM_LOG_EXIT(p_mgr->p_log); } static void ucast_mgr_process_neighbors(IN cl_map_item_t * p_map_item, IN void *context) { osm_switch_t * p_sw = (osm_switch_t *) p_map_item; osm_ucast_mgr_t * p_mgr = context; osm_node_t *p_node; osm_node_t *p_remote_node; uint32_t port_num; uint8_t remote_port_num; uint32_t num_ports; osm_physp_t *p_physp; OSM_LOG_ENTER(p_mgr->p_log); p_node = p_sw->p_node; CL_ASSERT(p_node); CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing switch with GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); num_ports = osm_node_get_num_physp(p_node); /* Start with port 1 to skip the switch's management port. */ for (port_num = 1; port_num < num_ports; port_num++) { p_remote_node = osm_node_get_remote_node(p_node, (uint8_t) port_num, &remote_port_num); if (p_remote_node && p_remote_node->sw && (p_remote_node != p_node)) { /* make sure the link is healthy. If it is not - don't propagate through it. */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !osm_link_is_healthy(p_physp)) continue; ucast_mgr_process_neighbor(p_mgr, p_sw, p_remote_node->sw, (uint8_t) port_num, remote_port_num); } } OSM_LOG_EXIT(p_mgr->p_log); } static int set_hop_wf(void *ctx, uint64_t guid, char *p) { osm_ucast_mgr_t *m = ctx; osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid)); osm_physp_t *physp; unsigned port, hop_wf; char *e; if (!node || !node->sw) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "switch with guid 0x%016" PRIx64 " is not found\n", guid); return 0; } if (!p || !*p || !(port = strtoul(p, &e, 0)) || (p == e) || port >= node->sw->num_ports) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "bad port specified for guid 0x%016" PRIx64 "\n", guid); return 0; } p = e + 1; if (!*p || !(hop_wf = strtoul(p, &e, 0)) || p == e || hop_wf >= 0x100) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "bad hop weight factor specified for guid 0x%016" PRIx64 "port %u\n", guid, port); return 0; } physp = osm_node_get_physp_ptr(node, port); if (!physp) return 0; physp->hop_wf = hop_wf; return 0; } static void set_default_hop_wf(cl_map_item_t * p_map_item, void *ctx) { osm_switch_t *sw = (osm_switch_t *) p_map_item; int i; for (i = 1; i < sw->num_ports; i++) { osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i); if (p) p->hop_wf = 1; } } static int set_search_ordering_ports(void *ctx, uint64_t guid, char *p) { osm_subn_t *p_subn = ctx; osm_node_t *node = osm_get_node_by_guid(p_subn, cl_hton64(guid)); osm_switch_t *sw; uint8_t *search_ordering_ports = NULL; uint8_t port; unsigned int *ports = NULL; const int bpw = sizeof(*ports)*8; int words; int i = 1; /* port 0 maps to port 0 */ if (!node || !(sw = node->sw)) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE, "switch with guid 0x%016" PRIx64 " is not found\n", guid); return 0; } if (sw->search_ordering_ports) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE, "switch with guid 0x%016" PRIx64 " already listed\n", guid); return 0; } search_ordering_ports = malloc(sizeof(*search_ordering_ports)*sw->num_ports); if (!search_ordering_ports) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A07: cannot allocate memory for search_ordering_ports\n"); return -1; } memset(search_ordering_ports, 0, sizeof(*search_ordering_ports)*sw->num_ports); /* the ports array is for record keeping of which ports have * been seen */ words = (sw->num_ports + bpw - 1)/bpw; ports = malloc(words*sizeof(*ports)); if (!ports) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A08: cannot allocate memory for ports\n"); free(search_ordering_ports); return -1; } memset(ports, 0, words*sizeof(*ports)); while ((*p != '\0') && (*p != '#')) { char *e; port = strtoul(p, &e, 0); if ((p == e) || (port == 0) || (port >= sw->num_ports) || !osm_node_get_physp_ptr(node, port)) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE, "bad port %d specified for guid 0x%016" PRIx64 "\n", port, guid); free(search_ordering_ports); free(ports); return 0; } if (ports[port/bpw] & (1u << (port%bpw))) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_VERBOSE, "port %d already specified for guid 0x%016" PRIx64 "\n", port, guid); free(search_ordering_ports); free(ports); return 0; } ports[port/bpw] |= (1u << (port%bpw)); search_ordering_ports[i++] = port; p = e; while (isspace(*p)) { p++; } } if (i > 1) { for (port = 1; port < sw->num_ports; port++) { /* fill out the rest of the search_ordering_ports array * in sequence using the remaining unspecified * ports. */ if (!(ports[port/bpw] & (1u << (port%bpw)))) { search_ordering_ports[i++] = port; } } sw->search_ordering_ports = search_ordering_ports; } else { free(search_ordering_ports); } free(ports); return 0; } int osm_ucast_mgr_build_lid_matrices(IN osm_ucast_mgr_t * p_mgr) { uint32_t i; uint32_t iteration_max; cl_qmap_t *p_sw_guid_tbl; p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl; OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Starting switches' Min Hop Table Assignment\n"); /* Set up the weighting factors for the routing. */ cl_qmap_apply_func(p_sw_guid_tbl, set_default_hop_wf, NULL); if (p_mgr->p_subn->opt.hop_weights_file) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Fetching hop weight factor file \'%s\'\n", p_mgr->p_subn->opt.hop_weights_file); if (parse_node_map(p_mgr->p_subn->opt.hop_weights_file, set_hop_wf, p_mgr)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: " "cannot parse hop_weights_file \'%s\'\n", p_mgr->p_subn->opt.hop_weights_file); } } /* Set the switch matrices for each switch's own port 0 LID(s) then set the lid matrices for the each switch's leaf nodes. */ cl_qmap_apply_func(p_sw_guid_tbl, ucast_mgr_process_hop_0_1, p_mgr); /* Get the switch matrices for each switch's neighbors. This process requires a number of iterations equal to the number of switches in the subnet minus 1. In each iteration, a switch learns the lid/port/hop information (as contained by a switch's lid matrix) from its immediate neighbors. After each iteration, a switch (and it's neighbors) know more routing information than it did on the previous iteration. Thus, by repeatedly absorbing the routing information of neighbor switches, every switch eventually learns how to route all LIDs on the subnet. Note that there may not be any switches in the subnet if we are in simple p2p configuration. */ iteration_max = cl_qmap_count(p_sw_guid_tbl); /* If there are switches in the subnet, iterate until the lid matrix has been constructed. Otherwise, just immediately indicate we're done if no switches exist. */ if (iteration_max) { iteration_max--; /* we need to find out when the propagation of hop counts has relaxed. So this global variable is preset to 0 on each iteration and if if non of the switches was set will exit the while loop */ p_mgr->some_hop_count_set = TRUE; for (i = 0; (i < iteration_max) && p_mgr->some_hop_count_set; i++) { p_mgr->some_hop_count_set = FALSE; cl_qmap_apply_func(p_sw_guid_tbl, ucast_mgr_process_neighbors, p_mgr); } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Min-hop propagated in %d steps\n", i); } return 0; } static int ucast_mgr_setup_all_switches(osm_subn_t * p_subn) { osm_switch_t *p_sw; uint16_t lids; lids = (uint16_t) cl_ptr_vector_get_size(&p_subn->port_lid_tbl); lids = lids ? lids - 1 : 0; for (p_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); p_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) { if (osm_switch_prepare_path_rebuild(p_sw, lids)) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0B: " "cannot setup switch 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid (p_sw->p_node))); return -1; } if (p_sw->search_ordering_ports) { free(p_sw->search_ordering_ports); p_sw->search_ordering_ports = NULL; } } if (p_subn->opt.port_search_ordering_file) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_DEBUG, "Fetching dimension ports file \'%s\'\n", p_subn->opt.port_search_ordering_file); if (parse_node_map(p_subn->opt.port_search_ordering_file, set_search_ordering_ports, p_subn)) { OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "ERR 3A0F: " "cannot parse port_search_ordering_file \'%s\'\n", p_subn->opt.port_search_ordering_file); } } return 0; } static int add_guid_to_order_list(void *ctx, uint64_t guid, char *p) { osm_ucast_mgr_t *m = ctx; osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid)); if (!port) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "port guid not found: 0x%016" PRIx64 "\n", guid); return 0; } if (port->flag) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "port guid specified multiple times 0x%016" PRIx64 "\n", guid); return 0; } cl_qlist_insert_tail(&m->port_order_list, &port->list_item); port->flag = 1; port->use_scatter = (m->p_subn->opt.guid_routing_order_no_scatter == TRUE) ? 0 : m->p_subn->opt.scatter_ports; return 0; } static void add_port_to_order_list(cl_map_item_t * p_map_item, void *ctx) { osm_port_t *port = (osm_port_t *) p_map_item; osm_ucast_mgr_t *m = ctx; if (!port->flag) { port->use_scatter = m->p_subn->opt.scatter_ports; cl_qlist_insert_tail(&m->port_order_list, &port->list_item); } else port->flag = 0; } static int mark_ignored_port(void *ctx, uint64_t guid, char *p) { osm_ucast_mgr_t *m = ctx; osm_node_t *node = osm_get_node_by_guid(m->p_subn, cl_hton64(guid)); osm_physp_t *physp; unsigned port; if (!node || !node->sw) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "switch with guid 0x%016" PRIx64 " is not found\n", guid); return 0; } if (!p || !*p || !(port = strtoul(p, NULL, 0)) || port >= node->sw->num_ports) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "bad port specified for guid 0x%016" PRIx64 "\n", guid); return 0; } physp = osm_node_get_physp_ptr(node, port); if (!physp) return 0; physp->is_prof_ignored = 1; return 0; } static void clear_prof_ignore_flag(cl_map_item_t * p_map_item, void *ctx) { osm_switch_t *sw = (osm_switch_t *) p_map_item; int i; for (i = 1; i < sw->num_ports; i++) { osm_physp_t *p = osm_node_get_physp_ptr(sw->p_node, i); if (p) p->is_prof_ignored = 0; } } static void add_sw_endports_to_order_list(osm_switch_t * sw, osm_ucast_mgr_t * m) { osm_port_t *port; osm_physp_t *p; int i; for (i = 1; i < sw->num_ports; i++) { p = osm_node_get_physp_ptr(sw->p_node, i); if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) { port = osm_get_port_by_guid(m->p_subn, p->p_remote_physp-> port_guid); if (!port || port->flag) continue; cl_qlist_insert_tail(&m->port_order_list, &port->list_item); port->flag = 1; port->use_scatter = m->p_subn->opt.scatter_ports; } } } static void sw_count_endport_links(osm_switch_t * sw) { osm_physp_t *p; int i; sw->endport_links = 0; for (i = 1; i < sw->num_ports; i++) { p = osm_node_get_physp_ptr(sw->p_node, i); if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) sw->endport_links++; } } static int compar_sw_load(const void *s1, const void *s2) { #define get_sw_endport_links(s) (*(osm_switch_t **)s)->endport_links return get_sw_endport_links(s2) - get_sw_endport_links(s1); } static void sort_ports_by_switch_load(osm_ucast_mgr_t * m) { int i, num = cl_qmap_count(&m->p_subn->sw_guid_tbl); void **s = malloc(num * sizeof(*s)); if (!s) { OSM_LOG(m->p_log, OSM_LOG_ERROR, "ERR 3A0C: " "No memory, skip by switch load sorting.\n"); return; } s[0] = cl_qmap_head(&m->p_subn->sw_guid_tbl); for (i = 1; i < num; i++) s[i] = cl_qmap_next(s[i - 1]); for (i = 0; i < num; i++) sw_count_endport_links(s[i]); qsort(s, num, sizeof(*s), compar_sw_load); for (i = 0; i < num; i++) add_sw_endports_to_order_list(s[i], m); free(s); } static int ucast_mgr_build_lfts(osm_ucast_mgr_t * p_mgr) { cl_qlist_init(&p_mgr->port_order_list); if (p_mgr->p_subn->opt.guid_routing_order_file) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Fetching guid routing order file \'%s\'\n", p_mgr->p_subn->opt.guid_routing_order_file); if (parse_node_map(p_mgr->p_subn->opt.guid_routing_order_file, add_guid_to_order_list, p_mgr)) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0D: " "cannot parse guid routing order file \'%s\'\n", p_mgr->p_subn->opt.guid_routing_order_file); } sort_ports_by_switch_load(p_mgr); if (p_mgr->p_subn->opt.port_prof_ignore_file) { cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, clear_prof_ignore_flag, NULL); if (parse_node_map(p_mgr->p_subn->opt.port_prof_ignore_file, mark_ignored_port, p_mgr)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A0E: " "cannot parse port prof ignore file \'%s\'\n", p_mgr->p_subn->opt.port_prof_ignore_file); } } cl_qmap_apply_func(&p_mgr->p_subn->port_guid_tbl, add_port_to_order_list, p_mgr); cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_process_tbl, p_mgr); cl_qlist_remove_all(&p_mgr->port_order_list); return 0; } static void ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item, IN void *cxt) { osm_ucast_mgr_t *p_mgr = cxt; osm_switch_t * p_sw = (osm_switch_t *) p_map_item; osm_node_t *p_node; osm_physp_t *p_physp; osm_dr_path_t *p_path; osm_madw_context_t context; ib_api_status_t status; ib_switch_info_t si; boolean_t set_swinfo_require = FALSE; uint16_t lin_top; uint8_t life_state; CL_ASSERT(p_mgr); OSM_LOG_ENTER(p_mgr->p_log); CL_ASSERT(p_sw && p_sw->max_lid_ho); p_node = p_sw->p_node; CL_ASSERT(p_node); if (p_mgr->max_lid < p_sw->max_lid_ho) p_mgr->max_lid = p_sw->max_lid_ho; p_physp = osm_node_get_physp_ptr(p_node, 0); CL_ASSERT(p_physp); p_path = osm_physp_get_dr_path_ptr(p_physp); /* Set the top of the unicast forwarding table. */ si = p_sw->switch_info; lin_top = cl_hton16(p_sw->max_lid_ho); if (lin_top != si.lin_top) { set_swinfo_require = TRUE; si.lin_top = lin_top; context.si_context.lft_top_change = TRUE; } else context.si_context.lft_top_change = FALSE; life_state = si.life_state; ib_switch_info_set_life_time(&si, p_mgr->p_subn->opt.packet_life_time); if (life_state != si.life_state) set_swinfo_require = TRUE; if (set_swinfo_require) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Setting switch FT top to LID %u\n", p_sw->max_lid_ho); context.si_context.light_sweep = FALSE; context.si_context.node_guid = osm_node_get_node_guid(p_node); context.si_context.set_method = TRUE; status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si, sizeof(si), IB_MAD_ATTR_SWITCH_INFO, 0, FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: " "Sending SwitchInfo attribute failed (%s)\n", ib_get_err_str(status)); } OSM_LOG_EXIT(p_mgr->p_log); } static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr, IN uint16_t block_id_ho) { osm_madw_context_t context; osm_dr_path_t *p_path; osm_physp_t *p_physp; ib_api_status_t status; /* Send linear forwarding table blocks to the switch as long as the switch indicates it has blocks needing configuration. */ if (!p_sw->new_lft) { /* any routing should provide the new_lft */ CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache && p_mgr->cache_valid && !p_sw->need_update); return -1; } p_physp = osm_node_get_physp_ptr(p_sw->p_node, 0); if (!p_physp) return -1; p_path = osm_physp_get_dr_path_ptr(p_physp); context.lft_context.node_guid = osm_node_get_node_guid(p_sw->p_node); context.lft_context.set_method = TRUE; if (!p_sw->need_update && !p_mgr->p_subn->need_update && !memcmp(p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE, p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, IB_SMP_DATA_SIZE)) return 0; /* * Zero the stored LFT block, so in case the MAD will end up * with error, we will resend it in the next sweep. */ memset(p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, 0, IB_SMP_DATA_SIZE); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Writing FT block %u to switch 0x%" PRIx64 "\n", block_id_ho, cl_ntoh64(context.lft_context.node_guid)); status = osm_req_set(p_mgr->sm, p_path, p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE, IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL, cl_hton32(block_id_ho), FALSE, ib_port_info_get_m_key(&p_physp->port_info), CL_DISP_MSGID_NONE, &context); if (status != IB_SUCCESS) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A10: " "Sending linear fwd. tbl. block failed (%s)\n", ib_get_err_str(status)); return -1; } return 0; } static void ucast_mgr_pipeline_fwd_tbl(osm_ucast_mgr_t * p_mgr) { cl_qmap_t *tbl; cl_map_item_t *item; unsigned i, max_block = p_mgr->max_lid / IB_SMP_DATA_SIZE + 1; tbl = &p_mgr->p_subn->sw_guid_tbl; for (i = 0; i < max_block; i++) for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl); item = cl_qmap_next(item)) set_lft_block((osm_switch_t *)item, p_mgr, i); } void osm_ucast_mgr_set_fwd_tables(osm_ucast_mgr_t * p_mgr) { p_mgr->max_lid = 0; cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, ucast_mgr_set_fwd_top, p_mgr); ucast_mgr_pipeline_fwd_tbl(p_mgr); } static int ucast_mgr_route(struct osm_routing_engine *r, osm_opensm_t * osm) { int ret; OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "building routing with \'%s\' routing algorithm...\n", r->name); /* Set the before each lft build to keep the routes in place between sweeps */ if (osm->subn.opt.scatter_ports) srandom(osm->subn.opt.scatter_ports); if (!r->build_lid_matrices || (ret = r->build_lid_matrices(r->context)) > 0) ret = osm_ucast_mgr_build_lid_matrices(&osm->sm.ucast_mgr); if (ret < 0) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "%s: cannot build lid matrices\n", r->name); return ret; } if (!r->ucast_build_fwd_tables || (ret = r->ucast_build_fwd_tables(r->context)) > 0) ret = ucast_mgr_build_lfts(&osm->sm.ucast_mgr); if (ret < 0) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "%s: cannot build fwd tables\n", r->name); return ret; } osm->routing_engine_used = r; osm_ucast_mgr_set_fwd_tables(&osm->sm.ucast_mgr); return 0; } int osm_ucast_mgr_process(IN osm_ucast_mgr_t * p_mgr) { osm_opensm_t *p_osm; struct osm_routing_engine *p_routing_eng; cl_qmap_t *p_sw_guid_tbl; int failed = 0; OSM_LOG_ENTER(p_mgr->p_log); p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl; p_osm = p_mgr->p_subn->p_osm; p_routing_eng = p_osm->routing_engine_list; CL_PLOCK_EXCL_ACQUIRE(p_mgr->p_lock); /* If there are no switches in the subnet, we are done. */ if (cl_qmap_count(p_sw_guid_tbl) == 0 || ucast_mgr_setup_all_switches(p_mgr->p_subn) < 0) goto Exit; failed = -1; p_osm->routing_engine_used = NULL; while (p_routing_eng) { failed = ucast_mgr_route(p_routing_eng, p_osm); if (!failed) break; p_routing_eng = p_routing_eng->next; } if (!p_osm->routing_engine_used && p_osm->no_fallback_routing_engine != TRUE) { /* If configured routing algorithm failed, use default MinHop */ failed = ucast_mgr_route(p_osm->default_routing_engine, p_osm); } if (p_osm->routing_engine_used) { OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "%s tables configured on all switches\n", osm_routing_engine_type_str(p_osm-> routing_engine_used->type)); if (p_mgr->p_subn->opt.use_ucast_cache) p_mgr->cache_valid = TRUE; } else { p_mgr->p_subn->subnet_initialization_error = TRUE; OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "No routing engine able to successfully configure " " switch tables on current fabric\n"); } Exit: CL_PLOCK_RELEASE(p_mgr->p_lock); OSM_LOG_EXIT(p_mgr->p_log); return failed; } static int ucast_build_lid_matrices(void *context) { return osm_ucast_mgr_build_lid_matrices(context); } static int ucast_build_lfts(void *context) { return ucast_mgr_build_lfts(context); } int osm_ucast_minhop_setup(struct osm_routing_engine *r, osm_opensm_t * osm) { r->context = &osm->sm.ucast_mgr; r->build_lid_matrices = ucast_build_lid_matrices; r->ucast_build_fwd_tables = ucast_build_lfts; return 0; } static int ucast_dor_build_lfts(void *context) { osm_ucast_mgr_t *mgr = context; int ret; mgr->is_dor = 1; ret = ucast_mgr_build_lfts(mgr); mgr->is_dor = 0; return ret; } int osm_ucast_dor_setup(struct osm_routing_engine *r, osm_opensm_t * osm) { r->context = &osm->sm.ucast_mgr; r->build_lid_matrices = ucast_build_lid_matrices; r->ucast_build_fwd_tables = ucast_dor_build_lfts; return 0; } int ucast_dummy_build_lid_matrices(void *context) { return 0; } opensm-3.3.20/opensm/osm_ucast_updn.c0000644000205000001450000004560612273514661014522 00000000000000/* * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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 Up Down Algorithm using ranking & Min Hop * Calculation functions */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_UPDN_C #include #include #include /* //////////////////////////// */ /* Local types */ /* //////////////////////////// */ /* direction */ typedef enum updn_switch_dir { UP = 0, DOWN } updn_switch_dir_t; /* updn structure */ typedef struct updn { unsigned num_roots; osm_opensm_t *p_osm; } updn_t; struct updn_node { cl_list_item_t list; osm_switch_t *sw; uint64_t id; updn_switch_dir_t dir; unsigned rank; unsigned visited; }; /* This function returns direction based on rank and guid info of current & remote ports */ static updn_switch_dir_t updn_get_dir(unsigned cur_rank, unsigned rem_rank, uint64_t cur_id, uint64_t rem_id) { /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect directly, but in case they are we assign to root node an UP direction to allow UPDN to discover the subnet correctly (and not from the point of view of the last root node). */ if (!cur_rank && !rem_rank) return UP; if (cur_rank < rem_rank) return DOWN; else if (cur_rank > rem_rank) return UP; else { /* Equal rank, decide by id number, bigger == UP direction */ if (cur_id > rem_id) return UP; else return DOWN; } } /********************************************************************** * This function does the bfs of min hop table calculation by guid index * as a starting point. **********************************************************************/ static int updn_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn, IN osm_switch_t * p_sw) { uint8_t pn, pn_rem; cl_qlist_t list; uint16_t lid; struct updn_node *u; updn_switch_dir_t next_dir, current_dir; OSM_LOG_ENTER(p_log); lid = osm_node_get_base_lid(p_sw->p_node, 0); lid = cl_ntoh16(lid); osm_switch_set_hops(p_sw, lid, 0, 0); OSM_LOG(p_log, OSM_LOG_DEBUG, "Starting from switch - port GUID 0x%" PRIx64 " lid %u\n", cl_ntoh64(p_sw->p_node->node_info.port_guid), lid); u = p_sw->priv; u->dir = UP; /* Update list with the new element */ cl_qlist_init(&list); cl_qlist_insert_tail(&list, &u->list); /* BFS the list till no next element */ while (!cl_is_qlist_empty(&list)) { u = (struct updn_node *)cl_qlist_remove_head(&list); u->visited = 0; /* cleanup */ current_dir = u->dir; /* Go over all ports of the switch and find unvisited remote nodes */ for (pn = 1; pn < u->sw->num_ports; pn++) { osm_node_t *p_remote_node; struct updn_node *rem_u; uint8_t current_min_hop, remote_min_hop, set_hop_return_value; osm_switch_t *p_remote_sw; p_remote_node = osm_node_get_remote_node(u->sw->p_node, pn, &pn_rem); /* If no remote node OR remote node is not a SWITCH continue to next pn */ if (!p_remote_node || !p_remote_node->sw) continue; /* Fetch remote guid only after validation of remote node */ p_remote_sw = p_remote_node->sw; rem_u = p_remote_sw->priv; /* Decide which direction to mark it (UP/DOWN) */ next_dir = updn_get_dir(u->rank, rem_u->rank, u->id, rem_u->id); /* Check if this is a legal step : the only illegal step is going from DOWN to UP */ if ((current_dir == DOWN) && (next_dir == UP)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)), cl_ntoh64(osm_node_get_node_guid(p_remote_node))); /* Illegal step */ continue; } /* Set MinHop value for the current lid */ current_min_hop = osm_switch_get_least_hops(u->sw, lid); /* Check hop count if better insert into list && update the remote node Min Hop Table */ remote_min_hop = osm_switch_get_hop_count(p_remote_sw, lid, pn_rem); if (current_min_hop + 1 < remote_min_hop) { set_hop_return_value = osm_switch_set_hops(p_remote_sw, lid, pn_rem, current_min_hop + 1); if (set_hop_return_value) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AA01: " "Invalid value returned from set min hop is: %d\n", set_hop_return_value); } /* Check if remote port has already been visited */ if (!rem_u->visited) { /* Insert updn_switch item into the list */ rem_u->dir = next_dir; rem_u->visited = 1; cl_qlist_insert_tail(&list, &rem_u->list); } } } } OSM_LOG_EXIT(p_log); return 0; } /* NOTE : PLS check if we need to decide that the first */ /* rank is a SWITCH for BFS purpose */ static int updn_subn_rank(IN updn_t * p_updn) { osm_switch_t *p_sw; osm_physp_t *p_physp, *p_remote_physp; cl_qlist_t list; cl_map_item_t *item; struct updn_node *u, *remote_u; uint8_t num_ports, port_num; osm_log_t *p_log = &p_updn->p_osm->log; unsigned max_rank = 0; OSM_LOG_ENTER(p_log); cl_qlist_init(&list); /* add all roots to the list */ for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; u = p_sw->priv; if (!u->rank) cl_qlist_insert_tail(&list, &u->list); } /* BFS the list till it's empty */ while (!cl_is_qlist_empty(&list)) { u = (struct updn_node *)cl_qlist_remove_head(&list); /* Go over all remote nodes and rank them (if not already visited) */ p_sw = u->sw; num_ports = p_sw->num_ports; OSM_LOG(p_log, OSM_LOG_DEBUG, "Handling switch GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); for (port_num = 1; port_num < num_ports; port_num++) { ib_net64_t port_guid; /* Current port fetched in order to get remote side */ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); if (!p_physp) continue; p_remote_physp = p_physp->p_remote_physp; /* make sure that all the following occur on p_remote_physp: 1. The port isn't NULL 2. It is a switch */ if (p_remote_physp && p_remote_physp->p_node->sw) { remote_u = p_remote_physp->p_node->sw->priv; port_guid = p_remote_physp->port_guid; if (remote_u->rank > u->rank + 1) { remote_u->rank = u->rank + 1; max_rank = remote_u->rank; cl_qlist_insert_tail(&list, &remote_u->list); OSM_LOG(p_log, OSM_LOG_DEBUG, "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid), remote_u->rank); } } } } /* Print Summary of ranking */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Subnet ranking completed. Max Node Rank = %d\n", max_rank); OSM_LOG_EXIT(p_log); return 0; } /* hack: preserve min hops entries to any other root switches */ static void updn_clear_non_root_hops(updn_t * updn, osm_switch_t * sw) { osm_port_t *port; unsigned i; for (i = 0; i < sw->num_hops; i++) if (sw->hops[i]) { port = osm_get_port_by_lid_ho(&updn->p_osm->subn, i); if (!port || !port->p_node->sw || ((struct updn_node *)port->p_node->sw->priv)-> rank != 0) memset(sw->hops[i], 0xff, sw->num_ports); } } static int updn_set_min_hop_table(IN updn_t * p_updn) { osm_subn_t *p_subn = &p_updn->p_osm->subn; osm_log_t *p_log = &p_updn->p_osm->log; osm_switch_t *p_sw; cl_map_item_t *item; OSM_LOG_ENTER(p_log); /* Go over all the switches in the subnet - for each init their Min Hop Table */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Init Min Hop Table of all switches [\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; /* Clear Min Hop Table */ if (p_subn->opt.connect_roots) updn_clear_non_root_hops(p_updn, p_sw); else osm_switch_clear_hops(p_sw); } OSM_LOG(p_log, OSM_LOG_VERBOSE, "Init Min Hop Table of all switches ]\n"); /* Now do the BFS for each port in the subnet */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "BFS through all port guids in the subnet [\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; updn_bfs_by_node(p_log, p_subn, p_sw); } OSM_LOG(p_log, OSM_LOG_VERBOSE, "BFS through all port guids in the subnet ]\n"); /* Cleanup */ OSM_LOG_EXIT(p_log); return 0; } static int updn_build_lid_matrices(IN updn_t * p_updn) { int status; OSM_LOG_ENTER(&p_updn->p_osm->log); OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE, "Ranking all port guids in the list\n"); if (!p_updn->num_roots) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0A: " "No guids were provided or number of guids is 0\n"); status = -1; goto _exit; } /* Check if it's not a switched subnet */ if (cl_is_qmap_empty(&p_updn->p_osm->subn.sw_guid_tbl)) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA0B: " "This is not a switched subnet, cannot perform UPDN algorithm\n"); status = -1; goto _exit; } /* Rank the subnet switches */ updn_subn_rank(p_updn); /* After multiple ranking need to set Min Hop Table by UpDn algorithm */ OSM_LOG(&p_updn->p_osm->log, OSM_LOG_VERBOSE, "Setting all switches' Min Hop Table\n"); status = updn_set_min_hop_table(p_updn); _exit: OSM_LOG_EXIT(&p_updn->p_osm->log); return status; } static struct updn_node *create_updn_node(osm_switch_t * sw) { struct updn_node *u; u = malloc(sizeof(*u)); if (!u) return NULL; memset(u, 0, sizeof(*u)); u->sw = sw; u->id = cl_ntoh64(osm_node_get_node_guid(sw->p_node)); u->rank = 0xffffffff; return u; } static void delete_updn_node(struct updn_node *u) { u->sw->priv = NULL; free(u); } /* Find Root nodes automatically by Min Hop Table info */ static void updn_find_root_nodes_by_min_hop(OUT updn_t * p_updn) { osm_opensm_t *p_osm = p_updn->p_osm; osm_switch_t *p_sw; osm_port_t *p_port; osm_physp_t *p_physp; cl_map_item_t *item; double thd1, thd2; unsigned i, cas_num = 0; unsigned *cas_per_sw; uint16_t lid_ho; OSM_LOG_ENTER(&p_osm->log); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Current number of ports in the subnet is %d\n", cl_qmap_count(&p_osm->subn.port_guid_tbl)); lid_ho = (uint16_t) cl_ptr_vector_get_size(&p_updn->p_osm->subn.port_lid_tbl) + 1; cas_per_sw = malloc(lid_ho * sizeof(*cas_per_sw)); if (!cas_per_sw) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR AA14: " "cannot alloc mem for CAs per switch counter array\n"); goto _exit; } memset(cas_per_sw, 0, lid_ho * sizeof(*cas_per_sw)); /* Find the Maximum number of CAs (and routers) for histogram normalization */ OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Finding the number of CAs and storing them in cl_map\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.port_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.port_guid_tbl); item = cl_qmap_next(item)) { p_port = (osm_port_t *)item; if (!p_port->p_node->sw) { p_physp = p_port->p_physp->p_remote_physp; if (!p_physp || !p_physp->p_node->sw) continue; lid_ho = osm_node_get_base_lid(p_physp->p_node, 0); lid_ho = cl_ntoh16(lid_ho); cas_per_sw[lid_ho]++; cas_num++; } } thd1 = cas_num * 0.9; thd2 = cas_num * 0.05; OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Found %u CAs and RTRs, %u SWs in the subnet. " "Thresholds are thd1 = %f && thd2 = %f\n", cas_num, cl_qmap_count(&p_osm->subn.sw_guid_tbl), thd1, thd2); OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "Passing through all switches to collect Min Hop info\n"); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { unsigned hop_hist[IB_SUBNET_PATH_HOPS_MAX]; uint16_t max_lid_ho; uint8_t hop_val; uint16_t numHopBarsOverThd1 = 0; uint16_t numHopBarsOverThd2 = 0; p_sw = (osm_switch_t *) item; memset(hop_hist, 0, sizeof(hop_hist)); max_lid_ho = p_sw->max_lid_ho; for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) if (cas_per_sw[lid_ho]) { hop_val = osm_switch_get_least_hops(p_sw, lid_ho); if (hop_val >= IB_SUBNET_PATH_HOPS_MAX) continue; hop_hist[hop_val] += cas_per_sw[lid_ho]; } /* Now recognize the spines by requiring one bar to be above 90% of the number of CAs and RTRs */ for (i = 0; i < IB_SUBNET_PATH_HOPS_MAX; i++) { if (hop_hist[i] > thd1) numHopBarsOverThd1++; if (hop_hist[i] > thd2) numHopBarsOverThd2++; } /* If thd conditions are valid - rank the root node */ if (numHopBarsOverThd1 == 1 && numHopBarsOverThd2 == 1) { OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Ranking GUID 0x%" PRIx64 " as root node\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); ((struct updn_node *)p_sw->priv)->rank = 0; p_updn->num_roots++; } } free(cas_per_sw); _exit: OSM_LOG_EXIT(&p_osm->log); return; } static void dump_roots(cl_map_item_t *item, FILE *file, void *cxt) { osm_switch_t *sw = (osm_switch_t *)item; if (!((struct updn_node *)sw->priv)->rank) fprintf(file, "0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(sw->p_node))); } static int update_id(void *cxt, uint64_t guid, char *p) { osm_opensm_t *osm = cxt; osm_switch_t *sw; uint64_t id; char *e; sw = osm_get_switch_by_guid(&osm->subn, cl_hton64(guid)); if (!sw) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "switch with guid 0x%" PRIx64 " is not found\n", guid); return 0; } id = strtoull(p, &e, 0); if (*e && !isspace(*e)) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "ERR AA05: cannot parse node id \'%s\'", p); return -1; } OSM_LOG(&osm->log, OSM_LOG_DEBUG, "update node 0x%" PRIx64 " id to 0x%" PRIx64 "\n", guid, id); ((struct updn_node *)sw->priv)->id = id; return 0; } static int rank_root_node(void *cxt, uint64_t guid, char *p) { updn_t *updn = cxt; osm_switch_t *sw; sw = osm_get_switch_by_guid(&updn->p_osm->subn, cl_hton64(guid)); if (!sw) { OSM_LOG(&updn->p_osm->log, OSM_LOG_VERBOSE, "switch with guid 0x%" PRIx64 " is not found\n", guid); return 0; } OSM_LOG(&updn->p_osm->log, OSM_LOG_DEBUG, "Ranking root port GUID 0x%" PRIx64 "\n", guid); ((struct updn_node *)sw->priv)->rank = 0; updn->num_roots++; return 0; } /* UPDN callback function */ static int updn_lid_matrices(void *ctx) { updn_t *p_updn = ctx; cl_map_item_t *item; osm_switch_t *p_sw; int ret = 0; OSM_LOG_ENTER(&p_updn->p_osm->log); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; p_sw->priv = create_updn_node(p_sw); if (!p_sw->priv) { OSM_LOG(&(p_updn->p_osm->log), OSM_LOG_ERROR, "ERR AA0C: " "cannot create updn node\n"); OSM_LOG_EXIT(&p_updn->p_osm->log); return -1; } } /* First setup root nodes */ p_updn->num_roots = 0; if (p_updn->p_osm->subn.opt.root_guid_file) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "UPDN - Fetching root nodes from file \'%s\'\n", p_updn->p_osm->subn.opt.root_guid_file); ret = parse_node_map(p_updn->p_osm->subn.opt.root_guid_file, rank_root_node, p_updn); if (ret) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA02: " "cannot parse root guids file \'%s\'\n", p_updn->p_osm->subn.opt.root_guid_file); osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); updn_find_root_nodes_by_min_hop(p_updn); } else if (p_updn->p_osm->subn.opt.connect_roots && p_updn->num_roots > 1) osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); } else { osm_ucast_mgr_build_lid_matrices(&p_updn->p_osm->sm.ucast_mgr); updn_find_root_nodes_by_min_hop(p_updn); } if (p_updn->p_osm->subn.opt.ids_guid_file) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "UPDN - update node ids from file \'%s\'\n", p_updn->p_osm->subn.opt.ids_guid_file); ret = parse_node_map(p_updn->p_osm->subn.opt.ids_guid_file, update_id, p_updn->p_osm); if (ret) OSM_LOG(&p_updn->p_osm->log, OSM_LOG_ERROR, "ERR AA03: " "cannot parse node ids file \'%s\'\n", p_updn->p_osm->subn.opt.ids_guid_file); } /* Only if there are assigned root nodes do the algorithm, otherwise perform do nothing */ if (p_updn->num_roots) { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_DEBUG, "activating UPDN algorithm\n"); ret = updn_build_lid_matrices(p_updn); } else { OSM_LOG(&p_updn->p_osm->log, OSM_LOG_INFO, "disabling UPDN algorithm, no root nodes were found\n"); ret = -1; } if (OSM_LOG_IS_ACTIVE_V2(&p_updn->p_osm->log, OSM_LOG_ROUTING)) osm_dump_qmap_to_file(p_updn->p_osm, "opensm-updn-roots.dump", &p_updn->p_osm->subn.sw_guid_tbl, dump_roots, NULL); for (item = cl_qmap_head(&p_updn->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_updn->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; delete_updn_node(p_sw->priv); } OSM_LOG_EXIT(&p_updn->p_osm->log); return ret; } static void updn_delete(void *context) { free(context); } int osm_ucast_updn_setup(struct osm_routing_engine *r, osm_opensm_t *osm) { updn_t *updn; updn = malloc(sizeof(updn_t)); if (!updn) return -1; memset(updn, 0, sizeof(updn_t)); updn->p_osm = osm; r->context = updn; r->destroy = updn_delete; r->build_lid_matrices = updn_lid_matrices; return 0; } opensm-3.3.20/opensm/osm_ucast_lash.c0000644000205000001450000010605712600532125014466 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2007 Simula Research Laboratory. All rights reserved. * Copyright (c) 2007 Silicon Graphics Inc. All rights reserved. * Copyright (c) 2008,2009 System Fabric Works, Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. 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 LASH algorithm Calculation functions */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_LASH_C #include #include #include #include #include typedef struct _reachable_dest { int switch_id; struct _reachable_dest *next; } reachable_dest_t; static void connect_switches(lash_t * p_lash, int sw1, int sw2, int phy_port_1) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned num = p_lash->switches[sw1]->node->num_links; switch_t *s1 = p_lash->switches[sw1]; mesh_node_t *node = s1->node; switch_t *s2; link_t *l; unsigned int i; /* * if doing mesh analysis: * - do not consider connections to self * - collapse multiple connections between * pair of switches to a single locical link */ if (p_lash->p_osm->subn.opt.do_mesh_analysis) { if (sw1 == sw2) return; /* see if we are already linked to sw2 */ for (i = 0; i < num; i++) { l = node->links[i]; if (node->links[i]->switch_id == sw2) { l->ports[l->num_ports++] = phy_port_1; return; } } } l = node->links[num]; l->switch_id = sw2; l->link_id = -1; l->ports[l->num_ports++] = phy_port_1; s2 = p_lash->switches[sw2]; for (i = 0; i < s2->node->num_links; i++) { if (s2->node->links[i]->switch_id == sw1) { s2->node->links[i]->link_id = num; l->link_id = i; break; } } node->num_links++; OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH connect: %d, %d, %d\n", sw1, sw2, phy_port_1); } static osm_switch_t *get_osm_switch_from_port(const osm_port_t * port) { osm_physp_t *p = port->p_physp; if (p->p_node->sw) return p->p_node->sw; else if (p->p_remote_physp && p->p_remote_physp->p_node->sw) return p->p_remote_physp->p_node->sw; return NULL; } static int cycle_exists(cdg_vertex_t * start, cdg_vertex_t * current, cdg_vertex_t * prev, int visit_num) { int i, new_visit_num; int cycle_found = 0; if (current != NULL && current->visiting_number > 0) { if (visit_num > current->visiting_number && current->seen == 0) { cycle_found = 1; } } else { if (current == NULL) { current = start; CL_ASSERT(prev == NULL); } current->visiting_number = visit_num; if (prev != NULL) { prev->next = current; CL_ASSERT(prev->to == current->from); CL_ASSERT(prev->visiting_number > 0); } new_visit_num = visit_num + 1; for (i = 0; i < current->num_deps; i++) { cycle_found = cycle_exists(start, current->deps[i].v, current, new_visit_num); if (cycle_found == 1) i = current->num_deps; } current->seen = 1; if (prev != NULL) prev->next = NULL; } return cycle_found; } static inline int get_next_switch(lash_t *p_lash, int sw, int link) { return p_lash->switches[sw]->node->links[link]->switch_id; } static void remove_semipermanent_depend_for_sp(lash_t * p_lash, int sw, int dest_switch, int lane) { switch_t **switches = p_lash->switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int i_next_switch, output_link, i, next_link, i_next_next_switch, depend = 0; cdg_vertex_t *v; int __attribute__((unused)) found; output_link = switches[sw]->routing_table[dest_switch].out_link; i_next_switch = get_next_switch(p_lash, sw, output_link); while (sw != dest_switch) { v = cdg_vertex_matrix[lane][sw][i_next_switch]; CL_ASSERT(v != NULL); if (v->num_using_vertex == 1) { cdg_vertex_matrix[lane][sw][i_next_switch] = NULL; free(v); } else { v->num_using_vertex--; if (i_next_switch != dest_switch) { next_link = switches[i_next_switch]->routing_table[dest_switch].out_link; i_next_next_switch = get_next_switch(p_lash, i_next_switch, next_link); found = 0; for (i = 0; i < v->num_deps; i++) if (v->deps[i].v == cdg_vertex_matrix[lane][i_next_switch] [i_next_next_switch]) { found = 1; depend = i; } CL_ASSERT(found); if (v->deps[depend].num_used == 1) { for (i = depend; i < v->num_deps - 1; i++) { v->deps[i].v = v->deps[i + 1].v; v->deps[i].num_used = v->deps[i + 1].num_used; } v->num_deps--; } else v->deps[depend].num_used--; } } sw = i_next_switch; output_link = switches[sw]->routing_table[dest_switch].out_link; if (sw != dest_switch) i_next_switch = get_next_switch(p_lash, sw, output_link); } } inline static void enqueue(cl_list_t * bfsq, switch_t * sw) { CL_ASSERT(sw->q_state == UNQUEUED); sw->q_state = Q_MEMBER; cl_list_insert_tail(bfsq, sw); } inline static void dequeue(cl_list_t * bfsq, switch_t ** sw) { *sw = (switch_t *) cl_list_remove_head(bfsq); CL_ASSERT((*sw)->q_state == Q_MEMBER); (*sw)->q_state = MST_MEMBER; } static int get_phys_connection(switch_t *sw, int switch_to) { unsigned int i; for (i = 0; i < sw->node->num_links; i++) if (sw->node->links[i]->switch_id == switch_to) return i; return i; } static void shortest_path(lash_t * p_lash, int ir) { switch_t **switches = p_lash->switches, *sw, *swi; unsigned int i; cl_list_t bfsq; cl_list_construct(&bfsq); cl_list_init(&bfsq, 20); enqueue(&bfsq, switches[ir]); while (!cl_is_list_empty(&bfsq)) { dequeue(&bfsq, &sw); for (i = 0; i < sw->node->num_links; i++) { swi = switches[sw->node->links[i]->switch_id]; if (swi->q_state == UNQUEUED) { enqueue(&bfsq, swi); sw->dij_channels[sw->used_channels++] = swi->id; } } } cl_list_destroy(&bfsq); } static int generate_routing_func_for_mst(lash_t * p_lash, int sw_id, reachable_dest_t ** destinations) { int i, next_switch; switch_t *sw = p_lash->switches[sw_id]; int num_channels = sw->used_channels; reachable_dest_t *dest, *i_dest, *concat_dest = NULL, *prev; for (i = 0; i < num_channels; i++) { next_switch = sw->dij_channels[i]; if (generate_routing_func_for_mst(p_lash, next_switch, &dest)) return -1; i_dest = dest; prev = i_dest; while (i_dest != NULL) { if (sw->routing_table[i_dest->switch_id].out_link == NONE) sw->routing_table[i_dest->switch_id].out_link = get_phys_connection(sw, next_switch); prev = i_dest; i_dest = i_dest->next; } CL_ASSERT(prev->next == NULL); prev->next = concat_dest; concat_dest = dest; } i_dest = (reachable_dest_t *) malloc(sizeof(reachable_dest_t)); if (!i_dest) return -1; i_dest->switch_id = sw->id; i_dest->next = concat_dest; *destinations = i_dest; return 0; } static int generate_cdg_for_sp(lash_t * p_lash, int sw, int dest_switch, int lane) { unsigned num_switches = p_lash->num_switches; switch_t **switches = p_lash->switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int next_switch, output_link, j, exists; cdg_vertex_t *v, *prev = NULL; output_link = switches[sw]->routing_table[dest_switch].out_link; next_switch = get_next_switch(p_lash, sw, output_link); while (sw != dest_switch) { if (cdg_vertex_matrix[lane][sw][next_switch] == NULL) { v = calloc(1, sizeof(*v) + (num_switches - 1) * sizeof(v->deps[0])); if (!v) return -1; v->from = sw; v->to = next_switch; v->temp = 1; cdg_vertex_matrix[lane][sw][next_switch] = v; } else v = cdg_vertex_matrix[lane][sw][next_switch]; v->num_using_vertex++; if (prev != NULL) { exists = 0; for (j = 0; j < prev->num_deps; j++) if (prev->deps[j].v == v) { exists = 1; prev->deps[j].num_used++; } if (exists == 0) { prev->deps[prev->num_deps].v = v; prev->deps[prev->num_deps].num_used++; prev->num_deps++; CL_ASSERT(prev->num_deps < (int)num_switches); if (prev->temp == 0) prev->num_temp_depend++; } } sw = next_switch; output_link = switches[sw]->routing_table[dest_switch].out_link; if (sw != dest_switch) { CL_ASSERT(output_link != NONE); next_switch = get_next_switch(p_lash, sw, output_link); } prev = v; } return 0; } static void set_temp_depend_to_permanent_for_sp(lash_t * p_lash, int sw, int dest_switch, int lane) { switch_t **switches = p_lash->switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int next_switch, output_link; cdg_vertex_t *v; output_link = switches[sw]->routing_table[dest_switch].out_link; next_switch = get_next_switch(p_lash, sw, output_link); while (sw != dest_switch) { v = cdg_vertex_matrix[lane][sw][next_switch]; CL_ASSERT(v != NULL); if (v->temp == 1) v->temp = 0; else v->num_temp_depend = 0; sw = next_switch; output_link = switches[sw]->routing_table[dest_switch].out_link; if (sw != dest_switch) next_switch = get_next_switch(p_lash, sw, output_link); } } static void remove_temp_depend_for_sp(lash_t * p_lash, int sw, int dest_switch, int lane) { switch_t **switches = p_lash->switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int next_switch, output_link, i; cdg_vertex_t *v; output_link = switches[sw]->routing_table[dest_switch].out_link; next_switch = get_next_switch(p_lash, sw, output_link); while (sw != dest_switch) { v = cdg_vertex_matrix[lane][sw][next_switch]; CL_ASSERT(v != NULL); if (v->temp == 1) { cdg_vertex_matrix[lane][sw][next_switch] = NULL; free(v); } else { CL_ASSERT(v->num_temp_depend <= v->num_deps); v->num_deps = v->num_deps - v->num_temp_depend; v->num_temp_depend = 0; v->num_using_vertex--; for (i = v->num_deps; i < p_lash->num_switches - 1; i++) v->deps[i].num_used = 0; } sw = next_switch; output_link = switches[sw]->routing_table[dest_switch].out_link; if (sw != dest_switch) next_switch = get_next_switch(p_lash, sw, output_link); } } static int balance_virtual_lanes(lash_t * p_lash, unsigned lanes_needed) { unsigned num_switches = p_lash->num_switches; cdg_vertex_t ****cdg_vertex_matrix = p_lash->cdg_vertex_matrix; int *num_mst_in_lane = p_lash->num_mst_in_lane; int ***virtual_location = p_lash->virtual_location; int min_filled_lane, max_filled_lane, trials; int old_min_filled_lane, old_max_filled_lane, new_num_min_lane, new_num_max_lane; unsigned int i, j; int src, dest, start, next_switch, output_link; int next_switch2, output_link2; int stop = 0, cycle_found; int cycle_found2; unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl; max_filled_lane = 0; min_filled_lane = lanes_needed - 1; trials = num_mst_in_lane[max_filled_lane]; if (lanes_needed == 1) stop = 1; while (stop == 0) { src = abs(rand()) % (num_switches); dest = abs(rand()) % (num_switches); while (virtual_location[src][dest][max_filled_lane] != 1) { start = dest; if (dest == num_switches - 1) dest = 0; else dest++; while (dest != start && virtual_location[src][dest][max_filled_lane] != 1) { if (dest == num_switches - 1) dest = 0; else dest++; } if (virtual_location[src][dest][max_filled_lane] != 1) { if (src == num_switches - 1) src = 0; else src++; } } if (generate_cdg_for_sp(p_lash, src, dest, min_filled_lane) || generate_cdg_for_sp(p_lash, dest, src, min_filled_lane)) return -1; output_link = p_lash->switches[src]->routing_table[dest].out_link; next_switch = get_next_switch(p_lash, src, output_link); output_link2 = p_lash->switches[dest]->routing_table[src].out_link; next_switch2 = get_next_switch(p_lash, dest, output_link2); CL_ASSERT(cdg_vertex_matrix[min_filled_lane][src][next_switch] != NULL); CL_ASSERT(cdg_vertex_matrix[min_filled_lane][dest][next_switch2] != NULL); cycle_found = cycle_exists(cdg_vertex_matrix[min_filled_lane][src][next_switch], NULL, NULL, 1); cycle_found2 = cycle_exists(cdg_vertex_matrix[min_filled_lane][dest][next_switch2], NULL, NULL, 1); for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (cdg_vertex_matrix[min_filled_lane][i][j] != NULL) { cdg_vertex_matrix[min_filled_lane][i][j]->visiting_number = 0; cdg_vertex_matrix[min_filled_lane][i][j]->seen = 0; } if (cycle_found == 1 || cycle_found2 == 1) { remove_temp_depend_for_sp(p_lash, src, dest, min_filled_lane); remove_temp_depend_for_sp(p_lash, dest, src, min_filled_lane); virtual_location[src][dest][max_filled_lane] = 2; virtual_location[dest][src][max_filled_lane] = 2; trials--; trials--; } else { set_temp_depend_to_permanent_for_sp(p_lash, src, dest, min_filled_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest, src, min_filled_lane); num_mst_in_lane[max_filled_lane]--; num_mst_in_lane[max_filled_lane]--; num_mst_in_lane[min_filled_lane]++; num_mst_in_lane[min_filled_lane]++; remove_semipermanent_depend_for_sp(p_lash, src, dest, max_filled_lane); remove_semipermanent_depend_for_sp(p_lash, dest, src, max_filled_lane); virtual_location[src][dest][max_filled_lane] = 0; virtual_location[dest][src][max_filled_lane] = 0; virtual_location[src][dest][min_filled_lane] = 1; virtual_location[dest][src][min_filled_lane] = 1; p_lash->switches[src]->routing_table[dest].lane = min_filled_lane + start_vl; p_lash->switches[dest]->routing_table[src].lane = min_filled_lane + start_vl; } if (trials == 0) stop = 1; else { if (num_mst_in_lane[max_filled_lane] - num_mst_in_lane[min_filled_lane] < p_lash->balance_limit) stop = 1; } old_min_filled_lane = min_filled_lane; old_max_filled_lane = max_filled_lane; new_num_min_lane = MAX_INT; new_num_max_lane = 0; for (i = 0; i < lanes_needed; i++) { if (num_mst_in_lane[i] < new_num_min_lane) { new_num_min_lane = num_mst_in_lane[i]; min_filled_lane = i; } if (num_mst_in_lane[i] > new_num_max_lane) { new_num_max_lane = num_mst_in_lane[i]; max_filled_lane = i; } } if (old_min_filled_lane != min_filled_lane) { trials = num_mst_in_lane[max_filled_lane]; for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (virtual_location[i][j][max_filled_lane] == 2) virtual_location[i][j][max_filled_lane] = 1; } if (old_max_filled_lane != max_filled_lane) { trials = num_mst_in_lane[max_filled_lane]; for (i = 0; i < num_switches; i++) for (j = 0; j < num_switches; j++) if (virtual_location[i][j][old_max_filled_lane] == 2) virtual_location[i][j][old_max_filled_lane] = 1; } } return 0; } static switch_t *switch_create(lash_t * p_lash, unsigned id, osm_switch_t * p_sw) { unsigned num_switches = p_lash->num_switches; unsigned num_ports = p_sw->num_ports; switch_t *sw; unsigned int i; sw = malloc(sizeof(*sw) + num_switches * sizeof(sw->routing_table[0])); if (!sw) return NULL; memset(sw, 0, sizeof(*sw)); for (i = 0; i < num_switches; i++) { sw->routing_table[i].out_link = NONE; sw->routing_table[i].lane = NONE; } sw->id = id; sw->dij_channels = malloc(num_ports * sizeof(int)); if (!sw->dij_channels) { free(sw); return NULL; } sw->p_sw = p_sw; p_sw->priv = sw; if (osm_mesh_node_create(p_lash, sw)) { free(sw->dij_channels); free(sw); return NULL; } return sw; } static void switch_delete(lash_t *p_lash, switch_t * sw) { if (sw->dij_channels) free(sw->dij_channels); free(sw); } static void delete_mesh_switches(lash_t *p_lash) { if (p_lash->switches) { unsigned id; for (id = 0; ((int)id) < p_lash->num_switches; id++) if (p_lash->switches[id]) osm_mesh_node_delete(p_lash, p_lash->switches[id]); } } static void free_lash_structures(lash_t * p_lash) { unsigned int i, j, k; unsigned num_switches = p_lash->num_switches; osm_log_t *p_log = &p_lash->p_osm->log; OSM_LOG_ENTER(p_log); delete_mesh_switches(p_lash); /* free cdg_vertex_matrix */ for (i = 0; i < p_lash->vl_min; i++) { for (j = 0; j < num_switches; j++) { for (k = 0; k < num_switches; k++) if (p_lash->cdg_vertex_matrix[i][j][k]) free(p_lash->cdg_vertex_matrix[i][j][k]); if (p_lash->cdg_vertex_matrix[i][j]) free(p_lash->cdg_vertex_matrix[i][j]); } if (p_lash->cdg_vertex_matrix[i]) free(p_lash->cdg_vertex_matrix[i]); } if (p_lash->cdg_vertex_matrix) free(p_lash->cdg_vertex_matrix); /* free virtual_location */ for (i = 0; i < num_switches; i++) { for (j = 0; j < num_switches; j++) { if (p_lash->virtual_location[i][j]) free(p_lash->virtual_location[i][j]); } if (p_lash->virtual_location[i]) free(p_lash->virtual_location[i]); } if (p_lash->virtual_location) free(p_lash->virtual_location); OSM_LOG_EXIT(p_log); } static int init_lash_structures(lash_t * p_lash) { unsigned vl_min = p_lash->vl_min; unsigned num_switches = p_lash->num_switches; osm_log_t *p_log = &p_lash->p_osm->log; int status = 0; unsigned int i, j, k; OSM_LOG_ENTER(p_log); /* initialise cdg_vertex_matrix[num_switches][num_switches][num_switches] */ p_lash->cdg_vertex_matrix = (cdg_vertex_t ****) malloc(vl_min * sizeof(cdg_vertex_t ***)); if (p_lash->cdg_vertex_matrix == NULL) goto Exit_Mem_Error; for (i = 0; i < vl_min; i++) { p_lash->cdg_vertex_matrix[i] = (cdg_vertex_t ***) malloc(num_switches * sizeof(cdg_vertex_t **)); if (p_lash->cdg_vertex_matrix[i] == NULL) goto Exit_Mem_Error; } for (i = 0; i < vl_min; i++) { for (j = 0; j < num_switches; j++) { p_lash->cdg_vertex_matrix[i][j] = (cdg_vertex_t **) malloc(num_switches * sizeof(cdg_vertex_t *)); if (p_lash->cdg_vertex_matrix[i][j] == NULL) goto Exit_Mem_Error; for (k = 0; k < num_switches; k++) p_lash->cdg_vertex_matrix[i][j][k] = NULL; } } /* * initialise virtual_location[num_switches][num_switches][num_layers], * default value = 0 */ p_lash->virtual_location = (int ***)malloc(num_switches * sizeof(int ***)); if (p_lash->virtual_location == NULL) goto Exit_Mem_Error; for (i = 0; i < num_switches; i++) { p_lash->virtual_location[i] = (int **)malloc(num_switches * sizeof(int **)); if (p_lash->virtual_location[i] == NULL) goto Exit_Mem_Error; } for (i = 0; i < num_switches; i++) { for (j = 0; j < num_switches; j++) { p_lash->virtual_location[i][j] = (int *)malloc(vl_min * sizeof(int *)); if (p_lash->virtual_location[i][j] == NULL) goto Exit_Mem_Error; for (k = 0; k < vl_min; k++) p_lash->virtual_location[i][j][k] = 0; } } /* initialise num_mst_in_lane[num_switches], default 0 */ memset(p_lash->num_mst_in_lane, 0, IB_MAX_NUM_VLS * sizeof(p_lash->num_mst_in_lane[0])); goto Exit; Exit_Mem_Error: status = -1; OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D01: " "Could not allocate required memory for LASH errno %d, errno %d for lack of memory\n", errno, ENOMEM); Exit: OSM_LOG_EXIT(p_log); return status; } static int lash_core(lash_t * p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; unsigned num_switches = p_lash->num_switches; switch_t **switches = p_lash->switches; unsigned lanes_needed = 1; unsigned int i, j, k, dest_switch = 0; reachable_dest_t *dests, *idest; int cycle_found = 0; unsigned v_lane; int stop = 0, output_link, i_next_switch; int output_link2, i_next_switch2; int cycle_found2 = 0; int status = -1; int *switch_bitmap = NULL; /* Bitmap to check if we have processed this pair */ unsigned start_vl = p_lash->p_osm->subn.opt.lash_start_vl; OSM_LOG_ENTER(p_log); if (p_lash->p_osm->subn.opt.do_mesh_analysis && osm_do_mesh_analysis(p_lash)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D05: Mesh analysis failed\n"); goto Exit; } for (i = 0; i < num_switches; i++) { shortest_path(p_lash, i); if (generate_routing_func_for_mst(p_lash, i, &dests)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D06: " "generate_routing_func_for_mst failed\n"); goto Exit; } idest = dests; while (idest != NULL) { dests = dests->next; free(idest); idest = dests; } for (j = 0; j < num_switches; j++) { switches[j]->used_channels = 0; switches[j]->q_state = UNQUEUED; } } switch_bitmap = calloc(num_switches * num_switches, sizeof(int)); if (!switch_bitmap) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D04: " "Failed allocating switch_bitmap - out of memory\n"); goto Exit; } for (i = 0; i < num_switches; i++) { for (dest_switch = 0; dest_switch < num_switches; dest_switch++) if (dest_switch != i && switch_bitmap[i * num_switches + dest_switch] == 0) { v_lane = 0; stop = 0; while (v_lane < lanes_needed && stop == 0) { if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) || generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D07: generate_cdg_for_sp failed\n"); goto Exit; } output_link = switches[i]->routing_table[dest_switch].out_link; output_link2 = switches[dest_switch]->routing_table[i].out_link; i_next_switch = get_next_switch(p_lash, i, output_link); i_next_switch2 = get_next_switch(p_lash, dest_switch, output_link2); CL_ASSERT(p_lash-> cdg_vertex_matrix[v_lane][i][i_next_switch] != NULL); CL_ASSERT(p_lash-> cdg_vertex_matrix[v_lane][dest_switch] [i_next_switch2] != NULL); cycle_found = cycle_exists(p_lash-> cdg_vertex_matrix[v_lane][i] [i_next_switch], NULL, NULL, 1); cycle_found2 = cycle_exists(p_lash-> cdg_vertex_matrix[v_lane][dest_switch] [i_next_switch2], NULL, NULL, 1); for (j = 0; j < num_switches; j++) for (k = 0; k < num_switches; k++) if (p_lash-> cdg_vertex_matrix[v_lane][j][k] != NULL) { p_lash-> cdg_vertex_matrix[v_lane][j] [k]->visiting_number = 0; p_lash-> cdg_vertex_matrix[v_lane][j] [k]->seen = 0; } if (cycle_found == 1 || cycle_found2 == 1) { remove_temp_depend_for_sp(p_lash, i, dest_switch, v_lane); remove_temp_depend_for_sp(p_lash, dest_switch, i, v_lane); v_lane++; } else { set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch, v_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i, v_lane); stop = 1; p_lash->num_mst_in_lane[v_lane]++; p_lash->num_mst_in_lane[v_lane]++; } } switches[i]->routing_table[dest_switch].lane = v_lane + start_vl; switches[dest_switch]->routing_table[i].lane = v_lane + start_vl; if (cycle_found == 1 || cycle_found2 == 1) { if (++lanes_needed > p_lash->vl_min) goto Error_Not_Enough_Lanes; if (generate_cdg_for_sp(p_lash, i, dest_switch, v_lane) || generate_cdg_for_sp(p_lash, dest_switch, i, v_lane)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D08: generate_cdg_for_sp failed\n"); goto Exit; } set_temp_depend_to_permanent_for_sp(p_lash, i, dest_switch, v_lane); set_temp_depend_to_permanent_for_sp(p_lash, dest_switch, i, v_lane); p_lash->num_mst_in_lane[v_lane]++; p_lash->num_mst_in_lane[v_lane]++; } p_lash->virtual_location[i][dest_switch][v_lane] = 1; p_lash->virtual_location[dest_switch][i][v_lane] = 1; switch_bitmap[i * num_switches + dest_switch] = 1; switch_bitmap[dest_switch * num_switches + i] = 1; } } for (i = 0; i < lanes_needed; i++) OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n", i, p_lash->num_mst_in_lane[i]); OSM_LOG(p_log, OSM_LOG_INFO, "Lanes needed: %d, Balancing\n", lanes_needed); if (balance_virtual_lanes(p_lash, lanes_needed)) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D09: Balancing failed\n"); goto Exit; } for (i = 0; i < lanes_needed; i++) OSM_LOG(p_log, OSM_LOG_INFO, "Lanes in layer %d: %d\n", i, p_lash->num_mst_in_lane[i]); status = 0; goto Exit; Error_Not_Enough_Lanes: OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D02: " "Lane requirements (%d) exceed available lanes (%d)" " with starting lane (%d)\n", lanes_needed, p_lash->vl_min, start_vl); Exit: if (switch_bitmap) free(switch_bitmap); OSM_LOG_EXIT(p_log); return status; } static unsigned get_lash_id(osm_switch_t * p_sw) { return ((switch_t *) p_sw->priv)->id; } static int get_next_port(switch_t *sw, int link) { link_t *l = sw->node->links[link]; int port = l->next_port++; /* * note if not doing mesh analysis * then num_ports is always 1 */ if (l->next_port >= l->num_ports) l->next_port = 0; return l->ports[port]; } static void populate_fwd_tbls(lash_t * p_lash) { osm_log_t *p_log = &p_lash->p_osm->log; osm_subn_t *p_subn = &p_lash->p_osm->subn; osm_switch_t *p_sw, *p_next_sw, *p_dst_sw; osm_port_t *port; uint16_t max_lid_ho, lid; OSM_LOG_ENTER(p_log); p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); /* Go through each switch individually */ while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { uint64_t current_guid; switch_t *sw; p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); max_lid_ho = p_sw->max_lid_ho; current_guid = p_sw->p_node->node_info.port_guid; sw = p_sw->priv; memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size); for (lid = 1; lid <= max_lid_ho; lid++) { port = osm_get_port_by_lid_ho(p_subn, lid); if (!port) continue; p_dst_sw = get_osm_switch_from_port(port); if (p_dst_sw == p_sw) { uint8_t egress_port = port->p_node->sw ? 0 : port->p_physp->p_remote_physp->port_num; p_sw->new_lft[lid] = egress_port; OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH fwd MY SRC SRC GUID 0x%016" PRIx64 " src lash id (%d), src lid no (%u) src lash port (%d) " "DST GUID 0x%016" PRIx64 " src lash id (%d), src lash port (%d)\n", cl_ntoh64(current_guid), -1, lid, egress_port, cl_ntoh64(current_guid), -1, egress_port); } else if (p_dst_sw) { unsigned dst_lash_switch_id = get_lash_id(p_dst_sw); uint8_t lash_egress_port = (uint8_t) sw-> routing_table[dst_lash_switch_id].out_link; uint8_t physical_egress_port = get_next_port(sw, lash_egress_port); p_sw->new_lft[lid] = physical_egress_port; OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH fwd SRC GUID 0x%016" PRIx64 " src lash id (%d), " "src lid no (%u) src lash port (%d) " "DST GUID 0x%016" PRIx64 " src lash id (%d), src lash port (%d)\n", cl_ntoh64(current_guid), sw->id, lid, lash_egress_port, cl_ntoh64(p_dst_sw->p_node->node_info. port_guid), dst_lash_switch_id, physical_egress_port); } } /* for */ } OSM_LOG_EXIT(p_log); } static void osm_lash_process_switch(lash_t * p_lash, osm_switch_t * p_sw) { osm_log_t *p_log = &p_lash->p_osm->log; int i, port_count; osm_physp_t *p_current_physp, *p_remote_physp; unsigned switch_a_lash_id, switch_b_lash_id; OSM_LOG_ENTER(p_log); switch_a_lash_id = get_lash_id(p_sw); port_count = osm_node_get_num_physp(p_sw->p_node); /* starting at port 1, ignoring management port on switch */ for (i = 1; i < port_count; i++) { p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i); if (p_current_physp) { p_remote_physp = p_current_physp->p_remote_physp; if (p_remote_physp && p_remote_physp->p_node->sw) { int physical_port_a_num = osm_physp_get_port_num(p_current_physp); int physical_port_b_num = osm_physp_get_port_num(p_remote_physp); switch_b_lash_id = get_lash_id(p_remote_physp->p_node->sw); connect_switches(p_lash, switch_a_lash_id, switch_b_lash_id, physical_port_a_num); OSM_LOG(p_log, OSM_LOG_VERBOSE, "LASH SUCCESS connected G 0x%016" PRIx64 " , lash_id(%u), P(%u) " " to G 0x%016" PRIx64 " , lash_id(%u) , P(%u)\n", cl_ntoh64(osm_physp_get_port_guid (p_current_physp)), switch_a_lash_id, physical_port_a_num, cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), switch_b_lash_id, physical_port_b_num); } } } OSM_LOG_EXIT(p_log); } static void lash_cleanup(lash_t * p_lash) { osm_subn_t *p_subn = &p_lash->p_osm->subn; osm_switch_t *p_next_sw, *p_sw; /* drop any existing references to old lash switches */ p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); p_sw->priv = NULL; } if (p_lash->switches) { unsigned id; for (id = 0; ((int)id) < p_lash->num_switches; id++) if (p_lash->switches[id]) switch_delete(p_lash, p_lash->switches[id]); free(p_lash->switches); } p_lash->switches = NULL; } /* static int discover_network_properties() Traverse the topology of the network in order to determine - the maximum number of switches, - the minimum number of virtual layers */ static int discover_network_properties(lash_t * p_lash) { int i, id = 0; uint8_t vl_min; osm_subn_t *p_subn = &p_lash->p_osm->subn; osm_switch_t *p_next_sw, *p_sw; osm_log_t *p_log = &p_lash->p_osm->log; p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl); p_lash->switches = calloc(p_lash->num_switches, sizeof(switch_t *)); if (!p_lash->switches) return -1; vl_min = 5; /* set to a high value */ p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { uint16_t port_count; p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); p_lash->switches[id] = switch_create(p_lash, id, p_sw); if (!p_lash->switches[id]) return -1; id++; port_count = osm_node_get_num_physp(p_sw->p_node); /* Note, ignoring port 0. management port */ for (i = 1; i < port_count; i++) { osm_physp_t *p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i); if (p_current_physp && p_current_physp->p_remote_physp) { ib_port_info_t *p_port_info = &p_current_physp->port_info; uint8_t port_vl_min = ib_port_info_get_op_vls(p_port_info); if (port_vl_min && port_vl_min < vl_min) vl_min = port_vl_min; } } /* for */ } /* while */ vl_min = 1 << (vl_min - 1); if (vl_min > 15) vl_min = 15; if (p_lash->p_osm->subn.opt.lash_start_vl >= vl_min) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D03: " "Start VL(%d) too high for min operational vl(%d)\n", p_lash->p_osm->subn.opt.lash_start_vl, vl_min); return -1; } p_lash->vl_min = vl_min - p_lash->p_osm->subn.opt.lash_start_vl; OSM_LOG(p_log, OSM_LOG_INFO, "min operational vl(%d) start vl(%d) max_switches(%d)\n", p_lash->vl_min, p_lash->p_osm->subn.opt.lash_start_vl, p_lash->num_switches); return 0; } static void process_switches(lash_t * p_lash) { osm_switch_t *p_sw, *p_next_sw; osm_subn_t *p_subn = &p_lash->p_osm->subn; /* Go through each switch and process it. i.e build the connection structure required by LASH */ p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl); while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) { p_sw = p_next_sw; p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item); osm_lash_process_switch(p_lash, p_sw); } } static int lash_process(void *context) { lash_t *p_lash = context; osm_log_t *p_log = &p_lash->p_osm->log; int status = 0; OSM_LOG_ENTER(p_log); p_lash->balance_limit = 6; /* everything starts here */ lash_cleanup(p_lash); status = discover_network_properties(p_lash); if (status) goto Exit; status = init_lash_structures(p_lash); if (status) goto Exit; process_switches(p_lash); status = lash_core(p_lash); if (status) goto Exit; populate_fwd_tbls(p_lash); Exit: if (p_lash->vl_min) free_lash_structures(p_lash); OSM_LOG_EXIT(p_log); return status; } static lash_t *lash_create(osm_opensm_t * p_osm) { lash_t *p_lash; p_lash = calloc(1, sizeof(lash_t)); if (!p_lash) return NULL; p_lash->p_osm = p_osm; return p_lash; } static void lash_delete(void *context) { lash_t *p_lash = context; if (p_lash->switches) { unsigned id; for (id = 0; ((int)id) < p_lash->num_switches; id++) if (p_lash->switches[id]) switch_delete(p_lash, p_lash->switches[id]); free(p_lash->switches); } free(p_lash); } static uint8_t get_lash_sl(void *context, uint8_t path_sl_hint, const ib_net16_t slid, const ib_net16_t dlid) { unsigned dst_id; unsigned src_id; osm_port_t *p_src_port, *p_dst_port; osm_switch_t *p_sw; lash_t *p_lash = context; osm_opensm_t *p_osm = p_lash->p_osm; if (!(p_osm->routing_engine_used && p_osm->routing_engine_used->type == OSM_ROUTING_ENGINE_TYPE_LASH)) return OSM_DEFAULT_SL; p_src_port = osm_get_port_by_lid(&p_osm->subn, slid); if (!p_src_port) return OSM_DEFAULT_SL; p_dst_port = osm_get_port_by_lid(&p_osm->subn, dlid); if (!p_dst_port) return OSM_DEFAULT_SL; p_sw = get_osm_switch_from_port(p_dst_port); if (!p_sw || !p_sw->priv) return OSM_DEFAULT_SL; dst_id = get_lash_id(p_sw); p_sw = get_osm_switch_from_port(p_src_port); if (!p_sw || !p_sw->priv) return OSM_DEFAULT_SL; src_id = get_lash_id(p_sw); if (src_id == dst_id) return p_osm->subn.opt.lash_start_vl; return (uint8_t) ((switch_t *) p_sw->priv)->routing_table[dst_id].lane; } int osm_ucast_lash_setup(struct osm_routing_engine *r, osm_opensm_t *p_osm) { lash_t *p_lash = lash_create(p_osm); if (!p_lash) return -1; r->context = p_lash; r->ucast_build_fwd_tables = lash_process; r->path_sl = get_lash_sl; r->destroy = lash_delete; return 0; } opensm-3.3.20/opensm/osm_ucast_file.c0000644000205000001450000002457012453773071014472 00000000000000/* * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2006,2008-2009 Mellanox Technologies LTD. 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 OpenSM unicast routing module which loads * routes from the dump file */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_FILE_C #include #include #include static uint16_t remap_lid(osm_opensm_t * p_osm, uint16_t lid, ib_net64_t guid) { osm_port_t *p_port; uint16_t min_lid, max_lid; uint8_t lmc; p_port = osm_get_port_by_guid(&p_osm->subn, guid); if (!p_port) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "cannot find port guid 0x%016" PRIx64 " , will use the same lid\n", cl_ntoh64(guid)); return lid; } osm_port_get_lid_range_ho(p_port, &min_lid, &max_lid); if (min_lid <= lid && lid <= max_lid) return lid; lmc = osm_port_get_lmc(p_port); return min_lid + (lid & ((1 << lmc) - 1)); } static void add_path(osm_opensm_t * p_osm, osm_switch_t * p_sw, uint16_t lid, uint8_t port_num, ib_net64_t port_guid) { uint16_t new_lid; uint8_t old_port; new_lid = port_guid ? remap_lid(p_osm, lid, port_guid) : lid; old_port = osm_switch_get_port_by_lid(p_sw, new_lid, OSM_LFT); if (old_port != OSM_NO_PATH && old_port != port_num) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "LID collision is detected on switch " "0x016%" PRIx64 ", will overwrite LID %u entry\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node)), new_lid); } p_sw->new_lft[new_lid] = port_num; if (!(p_osm->subn.opt.port_profile_switch_nodes && port_guid && osm_get_switch_by_guid(&p_osm->subn, port_guid))) osm_switch_count_path(p_sw, port_num); OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "route 0x%04x(was 0x%04x) %u 0x%016" PRIx64 " is added to switch 0x%016" PRIx64 "\n", new_lid, lid, port_num, cl_ntoh64(port_guid), cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); } static void add_lid_hops(osm_opensm_t * p_osm, osm_switch_t * p_sw, uint16_t lid, ib_net64_t guid, uint8_t hops[], unsigned len) { uint8_t i; if (len > p_sw->num_ports) len = p_sw->num_ports; for (i = 0; i < len; i++) osm_switch_set_hops(p_sw, lid, i, hops[i]); } static int do_ucast_file_load(void *context) { char line[1024]; char *file_name; FILE *file; ib_net64_t sw_guid, port_guid; osm_opensm_t *p_osm = context; osm_switch_t *p_sw; uint16_t lid; uint8_t port_num; unsigned lineno; int status = -1; file_name = p_osm->subn.opt.lfts_file; if (!file_name) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "LFTs file name is not given; " "using default routing algorithm\n"); return 1; } file = fopen(file_name, "r"); if (!file) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6302: " "Can't open ucast dump file \'%s\': %m\n", file_name); goto Exit; } lineno = 0; p_sw = NULL; while (fgets(line, sizeof(line) - 1, file) != NULL) { char *p, *q; lineno++; p = line; while (isspace(*p)) p++; if (*p == '#') continue; if (!strncmp(p, "Multicast mlids", 15)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6303: " "Multicast dump file detected; " "skipping parsing. Using default " "routing algorithm\n"); } else if (!strncmp(p, "Unicast lids", 12)) { q = strstr(p, " guid 0x"); if (!q) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse switch definition\n", file_name, lineno); goto Exit; } p = q + 8; sw_guid = strtoull(p, &q, 16); if (q == p || !isspace(*q)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse switch guid: \'%s\'\n", file_name, lineno, p); goto Exit; } sw_guid = cl_hton64(sw_guid); p_sw = osm_get_switch_by_guid(&p_osm->subn, sw_guid); if (!p_sw) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "cannot find switch %016" PRIx64 "\n", cl_ntoh64(sw_guid)); continue; } memset(p_sw->new_lft, OSM_NO_PATH, p_sw->lft_size); } else if (p_sw && !strncmp(p, "0x", 2)) { p += 2; lid = (uint16_t) strtoul(p, &q, 16); if (q == p || !isspace(*q)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse lid: \'%s\'\n", file_name, lineno, p); goto Exit; } p = q; while (isspace(*p)) p++; port_num = (uint8_t) strtoul(p, &q, 10); if (q == p || !isspace(*q)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse port: \'%s\'\n", file_name, lineno, p); goto Exit; } if (port_num >= osm_node_get_num_physp(p_sw->p_node)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "Invalid port %d found " "for switch %016" PRIx64 "\n", port_num, cl_ntoh64(osm_node_get_node_guid (p_sw->p_node))); goto Exit; } p = q; /* additionally try to extract guid */ q = strstr(p, " portguid 0x"); if (!q) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "PARSE WARNING: %s:%u: " "cannot find port guid " "(maybe broken dump): \'%s\'\n", file_name, lineno, p); port_guid = 0; } else { p = q + 12; port_guid = strtoull(p, &q, 16); if (q == p || (!isspace(*q) && *q != ':')) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "PARSE WARNING: %s:%u: " "cannot parse port guid " "(maybe broken dump): \'%s\'\n", file_name, lineno, p); port_guid = 0; } } port_guid = cl_hton64(port_guid); add_path(p_osm, p_sw, lid, port_num, port_guid); } } status = 0; Exit: if (file) fclose(file); return status; } static int do_lid_matrix_file_load(void *context) { char line[1024]; uint8_t hops[256]; char *file_name; FILE *file; ib_net64_t guid; osm_opensm_t *p_osm = context; osm_switch_t *p_sw; unsigned lineno; uint16_t lid; int status = -1; file_name = p_osm->subn.opt.lid_matrix_dump_file; if (!file_name) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "lid matrix file name is not given; " "using default lid matrix generation algorithm\n"); return 1; } file = fopen(file_name, "r"); if (!file) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 6305: " "Can't open lid matrix file \'%s\': %m\n", file_name); goto Exit; } lineno = 0; p_sw = NULL; while (fgets(line, sizeof(line) - 1, file) != NULL) { char *p, *q; lineno++; p = line; while (isspace(*p)) p++; if (*p == '#') continue; if (!strncmp(p, "Switch", 6)) { q = strstr(p, " guid 0x"); if (!q) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse switch definition\n", file_name, lineno); goto Exit; } p = q + 8; guid = strtoull(p, &q, 16); if (q == p || !isspace(*q)) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse switch guid: \'%s\'\n", file_name, lineno, p); goto Exit; } guid = cl_hton64(guid); p_sw = osm_get_switch_by_guid(&p_osm->subn, guid); if (!p_sw) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "cannot find switch %016" PRIx64 "\n", cl_ntoh64(guid)); continue; } } else if (p_sw && !strncmp(p, "0x", 2)) { unsigned long num; unsigned len = 0; memset(hops, 0xff, sizeof(hops)); p += 2; num = strtoul(p, &q, 16); if (num > 0xffff || q == p || (*q != ':' && !isspace(*q))) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse lid: \'%s\'\n", file_name, lineno, p); goto Exit; } /* Just checked the range, so casting is safe */ lid = (uint16_t) num; p = q; while (isspace(*p) || *p == ':') p++; while (len < 256 && *p && *p != '#') { num = strtoul(p, &q, 16); if (num > 0xff || q == p) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "PARSE ERROR: %s:%u: " "cannot parse hops number: \'%s\'\n", file_name, lineno, p); goto Exit; } /* Just checked the range, so casting is safe */ hops[len++] = (uint8_t) num; p = q; while (isspace(*p)) p++; } /* additionally try to extract guid */ q = strstr(p, " portguid 0x"); if (!q) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "PARSE WARNING: %s:%u: " "cannot find port guid " "(maybe broken dump): \'%s\'\n", file_name, lineno, p); guid = 0; } else { p = q + 12; guid = strtoull(p, &q, 16); if (q == p || !isspace(*q)) { OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, "PARSE WARNING: %s:%u: " "cannot parse port guid " "(maybe broken dump): \'%s\'\n", file_name, lineno, p); guid = 0; } } guid = cl_hton64(guid); add_lid_hops(p_osm, p_sw, lid, guid, hops, len); } } status = 0; Exit: if (file) fclose(file); return status; } int osm_ucast_file_setup(struct osm_routing_engine *r, osm_opensm_t *osm) { r->context = osm; r->build_lid_matrices = do_lid_matrix_file_load; r->ucast_build_fwd_tables = do_ucast_file_load; return 0; } opensm-3.3.20/opensm/osm_ucast_ftree.c0000644000205000001450000041122012725277041014646 00000000000000/* * Copyright (c) 2009 Simula Research Laboratory. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 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 OpenSM FatTree routing */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_FTREE_C #include #include /* * FatTree rank is bounded between 2 and 8: * - Tree of rank 1 has only trivial routing paths, * so no need to use FatTree routing. * - Why maximum rank is 8: * Each node (switch) is assigned a unique tuple. * Switches are stored in two cl_qmaps - one is * ordered by guid, and the other by a key that is * generated from tuple. Since cl_qmap supports only * a 64-bit key, the maximal tuple length is 8 bytes. * which means that maximal tree rank is 8. * Note that the above also implies that each switch * can have at max 255 up/down ports. */ #define FAT_TREE_MIN_RANK 2 #define FAT_TREE_MAX_RANK 8 typedef enum { FTREE_DIRECTION_DOWN = -1, FTREE_DIRECTION_SAME, FTREE_DIRECTION_UP } ftree_direction_t; /*************************************************** ** ** Forward references ** ***************************************************/ struct ftree_sw_t_; struct ftree_hca_t_; struct ftree_port_t_; struct ftree_port_group_t_; struct ftree_fabric_t_; /*************************************************** ** ** ftree_tuple_t definition ** ***************************************************/ #define FTREE_TUPLE_BUFF_LEN 1024 #define FTREE_TUPLE_LEN 8 typedef uint8_t ftree_tuple_t[FTREE_TUPLE_LEN]; typedef uint64_t ftree_tuple_key_t; /*************************************************** ** ** ftree_sw_table_element_t definition ** ***************************************************/ typedef struct { cl_map_item_t map_item; struct ftree_sw_t_ *p_sw; } ftree_sw_tbl_element_t; /*************************************************** ** ** ftree_port_t definition ** ***************************************************/ typedef struct ftree_port_t_ { cl_map_item_t map_item; uint8_t port_num; /* port number on the current node */ uint8_t remote_port_num; /* port number on the remote node */ uint32_t counter_up; /* number of allocated routes upwards */ uint32_t counter_down; /* number of allocated routes downwards */ } ftree_port_t; /*************************************************** ** ** ftree_port_group_t definition ** ***************************************************/ typedef union ftree_hca_or_sw_ { struct ftree_hca_t_ *p_hca; struct ftree_sw_t_ *p_sw; } ftree_hca_or_sw; typedef struct ftree_port_group_t_ { cl_map_item_t map_item; uint16_t lid; /* lid of the current node */ uint16_t remote_lid; /* lid of the remote node */ ib_net64_t port_guid; /* port guid of this port */ ib_net64_t node_guid; /* this node's guid */ uint8_t node_type; /* this node's type */ ib_net64_t remote_port_guid; /* port guid of the remote port */ ib_net64_t remote_node_guid; /* node guid of the remote node */ uint8_t remote_node_type; /* IB_NODE_TYPE_{CA,SWITCH,ROUTER,...} */ ftree_hca_or_sw hca_or_sw; /* pointer to this hca/switch */ ftree_hca_or_sw remote_hca_or_sw; /* pointer to remote hca/switch */ cl_ptr_vector_t ports; /* vector of ports to the same lid */ boolean_t is_cn; /* whether this port is a compute node */ boolean_t is_io; /* whether this port is an I/O node */ uint32_t counter_down; /* number of allocated routes downwards */ uint32_t counter_up; /* number of allocated routes upwards */ } ftree_port_group_t; /*************************************************** ** ** ftree_sw_t definition ** ***************************************************/ typedef struct ftree_sw_t_ { cl_map_item_t map_item; osm_switch_t *p_osm_sw; uint32_t rank; ftree_tuple_t tuple; uint16_t lid; ftree_port_group_t **down_port_groups; uint8_t down_port_groups_num; ftree_port_group_t **sibling_port_groups; uint8_t sibling_port_groups_num; ftree_port_group_t **up_port_groups; uint8_t up_port_groups_num; boolean_t is_leaf; unsigned down_port_groups_idx; uint8_t *hops; uint32_t min_counter_down; boolean_t counter_up_changed; } ftree_sw_t; /*************************************************** ** ** ftree_hca_t definition ** ***************************************************/ typedef struct ftree_hca_t_ { cl_map_item_t map_item; osm_node_t *p_osm_node; ftree_port_group_t **up_port_groups; uint8_t *disconnected_ports; uint16_t up_port_groups_num; unsigned cn_num; } ftree_hca_t; /*************************************************** ** ** ftree_fabric_t definition ** ***************************************************/ typedef struct ftree_fabric_t_ { osm_opensm_t *p_osm; osm_subn_t *p_subn; cl_qmap_t hca_tbl; cl_qmap_t sw_tbl; cl_qmap_t sw_by_tuple_tbl; cl_qmap_t cn_guid_tbl; cl_qmap_t io_guid_tbl; unsigned cn_num; unsigned ca_ports; uint8_t leaf_switch_rank; uint8_t max_switch_rank; ftree_sw_t **leaf_switches; uint32_t leaf_switches_num; uint16_t max_cn_per_leaf; uint16_t lft_max_lid; boolean_t fabric_built; } ftree_fabric_t; static inline osm_subn_t *ftree_get_subnet(IN ftree_fabric_t * p_ftree) { return p_ftree->p_subn; } /*************************************************** ** ** comparators ** ***************************************************/ static int compare_switches_by_index(IN const void *p1, IN const void *p2) { ftree_sw_t **pp_sw1 = (ftree_sw_t **) p1; ftree_sw_t **pp_sw2 = (ftree_sw_t **) p2; uint16_t i; for (i = 0; i < FTREE_TUPLE_LEN; i++) { if ((*pp_sw1)->tuple[i] > (*pp_sw2)->tuple[i]) return 1; if ((*pp_sw1)->tuple[i] < (*pp_sw2)->tuple[i]) return -1; } return 0; } /***************************************************/ static int compare_port_groups_by_remote_switch_index(IN const void *p1, IN const void *p2) { ftree_port_group_t **pp_g1 = (ftree_port_group_t **) p1; ftree_port_group_t **pp_g2 = (ftree_port_group_t **) p2; return compare_switches_by_index(&((*pp_g1)->remote_hca_or_sw.p_sw), &((*pp_g2)->remote_hca_or_sw.p_sw)); } /*************************************************** ** ** ftree_tuple_t functions ** ***************************************************/ static void tuple_init(IN ftree_tuple_t tuple) { memset(tuple, 0xFF, FTREE_TUPLE_LEN); } /***************************************************/ static inline boolean_t tuple_assigned(IN ftree_tuple_t tuple) { return (tuple[0] != 0xFF); } /***************************************************/ #define FTREE_TUPLE_BUFFERS_NUM 6 static const char *tuple_to_str(IN ftree_tuple_t tuple) { static char buffer[FTREE_TUPLE_BUFFERS_NUM][FTREE_TUPLE_BUFF_LEN]; static uint8_t ind = 0; char *ret_buffer; uint32_t i; if (!tuple_assigned(tuple)) return "INDEX.NOT.ASSIGNED"; buffer[ind][0] = '\0'; for (i = 0; (i < FTREE_TUPLE_LEN) && (tuple[i] != 0xFF); i++) { if ((strlen(buffer[ind]) + 10) > FTREE_TUPLE_BUFF_LEN) return "INDEX.TOO.LONG"; if (i != 0) strcat(buffer[ind], "."); sprintf(&buffer[ind][strlen(buffer[ind])], "%u", tuple[i]); } ret_buffer = buffer[ind]; ind = (ind + 1) % FTREE_TUPLE_BUFFERS_NUM; return ret_buffer; } /* tuple_to_str() */ /***************************************************/ static inline ftree_tuple_key_t tuple_to_key(IN ftree_tuple_t tuple) { ftree_tuple_key_t key; memcpy(&key, tuple, FTREE_TUPLE_LEN); return key; } /***************************************************/ static inline void tuple_from_key(IN ftree_tuple_t tuple, IN ftree_tuple_key_t key) { memcpy(tuple, &key, FTREE_TUPLE_LEN); } /*************************************************** ** ** ftree_sw_tbl_element_t functions ** ***************************************************/ static ftree_sw_tbl_element_t *sw_tbl_element_create(IN ftree_sw_t * p_sw) { ftree_sw_tbl_element_t *p_element = (ftree_sw_tbl_element_t *) malloc(sizeof(ftree_sw_tbl_element_t)); if (!p_element) return NULL; memset(p_element, 0, sizeof(ftree_sw_tbl_element_t)); p_element->p_sw = p_sw; return p_element; } /***************************************************/ static void sw_tbl_element_destroy(IN ftree_sw_tbl_element_t * p_element) { free(p_element); } /*************************************************** ** ** ftree_port_t functions ** ***************************************************/ static ftree_port_t *port_create(IN uint8_t port_num, IN uint8_t remote_port_num) { ftree_port_t *p_port = (ftree_port_t *) malloc(sizeof(ftree_port_t)); if (!p_port) return NULL; memset(p_port, 0, sizeof(ftree_port_t)); p_port->port_num = port_num; p_port->remote_port_num = remote_port_num; return p_port; } /***************************************************/ static void port_destroy(IN ftree_port_t * p_port) { free(p_port); } /*************************************************** ** ** ftree_port_group_t functions ** ***************************************************/ static ftree_port_group_t *port_group_create(IN uint16_t lid, IN uint16_t remote_lid, IN ib_net64_t port_guid, IN ib_net64_t node_guid, IN uint8_t node_type, IN void *p_hca_or_sw, IN ib_net64_t remote_port_guid, IN ib_net64_t remote_node_guid, IN uint8_t remote_node_type, IN void *p_remote_hca_or_sw, IN boolean_t is_cn, IN boolean_t is_io) { ftree_port_group_t *p_group = (ftree_port_group_t *) malloc(sizeof(ftree_port_group_t)); if (p_group == NULL) return NULL; memset(p_group, 0, sizeof(ftree_port_group_t)); p_group->lid = lid; p_group->remote_lid = remote_lid; memcpy(&p_group->port_guid, &port_guid, sizeof(ib_net64_t)); memcpy(&p_group->node_guid, &node_guid, sizeof(ib_net64_t)); memcpy(&p_group->remote_port_guid, &remote_port_guid, sizeof(ib_net64_t)); memcpy(&p_group->remote_node_guid, &remote_node_guid, sizeof(ib_net64_t)); p_group->node_type = node_type; switch (node_type) { case IB_NODE_TYPE_CA: p_group->hca_or_sw.p_hca = (ftree_hca_t *) p_hca_or_sw; break; case IB_NODE_TYPE_SWITCH: p_group->hca_or_sw.p_sw = (ftree_sw_t *) p_hca_or_sw; break; default: /* we shouldn't get here - port is created only in hca or switch */ CL_ASSERT(0); } p_group->remote_node_type = remote_node_type; switch (remote_node_type) { case IB_NODE_TYPE_CA: p_group->remote_hca_or_sw.p_hca = (ftree_hca_t *) p_remote_hca_or_sw; break; case IB_NODE_TYPE_SWITCH: p_group->remote_hca_or_sw.p_sw = (ftree_sw_t *) p_remote_hca_or_sw; break; default: /* we shouldn't get here - port is created only in hca or switch */ CL_ASSERT(0); } cl_ptr_vector_init(&p_group->ports, 0, /* min size */ 8); /* grow size */ p_group->is_cn = is_cn; p_group->is_io = is_io; return p_group; } /* port_group_create() */ /***************************************************/ static void port_group_destroy(IN ftree_port_group_t * p_group) { uint32_t i; uint32_t size; ftree_port_t *p_port; if (!p_group) return; /* remove all the elements of p_group->ports vector */ size = cl_ptr_vector_get_size(&p_group->ports); for (i = 0; i < size; i++) if (cl_ptr_vector_at(&p_group->ports, i, (void *)&p_port) == CL_SUCCESS) port_destroy(p_port); cl_ptr_vector_destroy(&p_group->ports); free(p_group); } /* port_group_destroy() */ /***************************************************/ static void port_group_dump(IN ftree_fabric_t * p_ftree, IN ftree_port_group_t * p_group, IN ftree_direction_t direction) { ftree_port_t *p_port; uint32_t size; uint32_t i; char *buff; if (!p_group) return; if (!OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) return; size = cl_ptr_vector_get_size(&p_group->ports); buff = calloc(10, 1024); if (!buff) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB33: " "Failed to allocate buffer\n"); return; } for (i = 0; i < size; i++) { cl_ptr_vector_at(&p_group->ports, i, (void *)&p_port); CL_ASSERT(p_port); if (i != 0) strcat(buff, ", "); sprintf(buff + strlen(buff), "%u", p_port->port_num); } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, " Port Group of size %u, port(s): %s, direction: %s\n" " Local <--> Remote GUID (LID):" "0x%016" PRIx64 " (0x%04x) <--> 0x%016" PRIx64 " (0x%04x)\n", size, buff, (direction == FTREE_DIRECTION_DOWN) ? "DOWN" : (direction == FTREE_DIRECTION_SAME) ? "SIBLING" : "UP", cl_ntoh64(p_group->port_guid), p_group->lid, cl_ntoh64(p_group->remote_port_guid), p_group->remote_lid); free(buff); } /* port_group_dump() */ /***************************************************/ static void port_group_add_port(IN ftree_port_group_t * p_group, IN uint8_t port_num, IN uint8_t remote_port_num) { uint16_t i; ftree_port_t *p_port; for (i = 0; i < cl_ptr_vector_get_size(&p_group->ports); i++) { cl_ptr_vector_at(&p_group->ports, i, (void *)&p_port); if (p_port->port_num == port_num) return; } p_port = port_create(port_num, remote_port_num); CL_ASSERT(p_port); cl_ptr_vector_insert(&p_group->ports, p_port, NULL); } /*************************************************** ** ** ftree_sw_t functions ** ***************************************************/ static ftree_sw_t *sw_create(IN osm_switch_t * p_osm_sw) { ftree_sw_t *p_sw; uint8_t ports_num; /* make sure that the switch has ports */ if (p_osm_sw->num_ports == 1) return NULL; p_sw = (ftree_sw_t *) malloc(sizeof(ftree_sw_t)); if (p_sw == NULL) return NULL; memset(p_sw, 0, sizeof(ftree_sw_t)); p_sw->p_osm_sw = p_osm_sw; p_sw->rank = 0xFFFFFFFF; tuple_init(p_sw->tuple); p_sw->lid = cl_ntoh16(osm_node_get_base_lid(p_sw->p_osm_sw->p_node, 0)); ports_num = osm_node_get_num_physp(p_sw->p_osm_sw->p_node); p_sw->down_port_groups = (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *)); if (p_sw->down_port_groups == NULL) goto FREE_P_SW; memset(p_sw->down_port_groups, 0, ports_num * sizeof(ftree_port_group_t *)); p_sw->up_port_groups = (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *)); if (p_sw->up_port_groups == NULL) goto FREE_DOWN; memset(p_sw->up_port_groups, 0, ports_num * sizeof(ftree_port_group_t *)); p_sw->sibling_port_groups = (ftree_port_group_t **) malloc(ports_num * sizeof(ftree_port_group_t *)); if (p_sw->sibling_port_groups == NULL) goto FREE_UP; memset(p_sw->sibling_port_groups, 0, ports_num * sizeof(ftree_port_group_t *)); /* initialize lft buffer */ memset(p_osm_sw->new_lft, OSM_NO_PATH, p_osm_sw->lft_size); p_sw->hops = malloc((p_osm_sw->max_lid_ho + 1) * sizeof(*(p_sw->hops))); if (p_sw->hops == NULL) goto FREE_SIBLING; memset(p_sw->hops, OSM_NO_PATH, p_osm_sw->max_lid_ho + 1); return p_sw; FREE_SIBLING: free(p_sw->sibling_port_groups); FREE_UP: free(p_sw->up_port_groups); FREE_DOWN: free(p_sw->down_port_groups); FREE_P_SW: free(p_sw); return NULL; } /* sw_create() */ /***************************************************/ static void sw_destroy(IN ftree_sw_t * p_sw) { uint8_t i; if (!p_sw) return; free(p_sw->hops); for (i = 0; i < p_sw->down_port_groups_num; i++) port_group_destroy(p_sw->down_port_groups[i]); for (i = 0; i < p_sw->sibling_port_groups_num; i++) port_group_destroy(p_sw->sibling_port_groups[i]); for (i = 0; i < p_sw->up_port_groups_num; i++) port_group_destroy(p_sw->up_port_groups[i]); free(p_sw->down_port_groups); free(p_sw->sibling_port_groups); free(p_sw->up_port_groups); free(p_sw); } /* sw_destroy() */ /***************************************************/ static uint64_t sw_get_guid_no(IN ftree_sw_t * p_sw) { if (!p_sw) return 0; return osm_node_get_node_guid(p_sw->p_osm_sw->p_node); } /***************************************************/ static uint64_t sw_get_guid_ho(IN ftree_sw_t * p_sw) { return cl_ntoh64(sw_get_guid_no(p_sw)); } /***************************************************/ static void sw_dump(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw) { uint32_t i; if (!p_sw) return; if (!OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) return; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch index: %s, GUID: 0x%016" PRIx64 ", Ports: %u DOWN, %u SIBLINGS, %u UP\n", tuple_to_str(p_sw->tuple), sw_get_guid_ho(p_sw), p_sw->down_port_groups_num, p_sw->sibling_port_groups_num, p_sw->up_port_groups_num); for (i = 0; i < p_sw->down_port_groups_num; i++) port_group_dump(p_ftree, p_sw->down_port_groups[i], FTREE_DIRECTION_DOWN); for (i = 0; i < p_sw->sibling_port_groups_num; i++) port_group_dump(p_ftree, p_sw->sibling_port_groups[i], FTREE_DIRECTION_SAME); for (i = 0; i < p_sw->up_port_groups_num; i++) port_group_dump(p_ftree, p_sw->up_port_groups[i], FTREE_DIRECTION_UP); } /* sw_dump() */ /***************************************************/ static boolean_t sw_ranked(IN ftree_sw_t * p_sw) { return (p_sw->rank != 0xFFFFFFFF); } /***************************************************/ static ftree_port_group_t *sw_get_port_group_by_remote_lid(IN ftree_sw_t * p_sw, IN uint16_t remote_lid, IN ftree_direction_t direction) { uint32_t i; uint32_t size; ftree_port_group_t **port_groups; if (direction == FTREE_DIRECTION_UP) { port_groups = p_sw->up_port_groups; size = p_sw->up_port_groups_num; } else if (direction == FTREE_DIRECTION_SAME) { port_groups = p_sw->sibling_port_groups; size = p_sw->sibling_port_groups_num; } else { port_groups = p_sw->down_port_groups; size = p_sw->down_port_groups_num; } for (i = 0; i < size; i++) if (remote_lid == port_groups[i]->remote_lid) return port_groups[i]; return NULL; } /* sw_get_port_group_by_remote_lid() */ /***************************************************/ static void sw_add_port(IN ftree_sw_t * p_sw, IN uint8_t port_num, IN uint8_t remote_port_num, IN uint16_t lid, IN uint16_t remote_lid, IN ib_net64_t port_guid, IN ib_net64_t remote_port_guid, IN ib_net64_t remote_node_guid, IN uint8_t remote_node_type, IN void *p_remote_hca_or_sw, IN ftree_direction_t direction) { ftree_port_group_t *p_group = sw_get_port_group_by_remote_lid(p_sw, remote_lid, direction); if (!p_group) { p_group = port_group_create(lid, remote_lid, port_guid, sw_get_guid_no(p_sw), IB_NODE_TYPE_SWITCH, p_sw, remote_port_guid, remote_node_guid, remote_node_type, p_remote_hca_or_sw, FALSE, FALSE); CL_ASSERT(p_group); if (direction == FTREE_DIRECTION_UP) { p_sw->up_port_groups[p_sw->up_port_groups_num++] = p_group; } else if (direction == FTREE_DIRECTION_SAME) { p_sw-> sibling_port_groups[p_sw->sibling_port_groups_num++] = p_group; } else p_sw->down_port_groups[p_sw->down_port_groups_num++] = p_group; } port_group_add_port(p_group, port_num, remote_port_num); } /* sw_add_port() */ /***************************************************/ static inline cl_status_t sw_set_hops(IN ftree_sw_t * p_sw, IN uint16_t lid, IN uint8_t port_num, IN uint8_t hops, IN boolean_t is_target_sw) { /* set local min hop table(LID) */ p_sw->hops[lid] = hops; if (is_target_sw) return osm_switch_set_hops(p_sw->p_osm_sw, lid, port_num, hops); return 0; } /***************************************************/ static int set_hops_on_remote_sw(IN ftree_port_group_t * p_group, IN uint16_t target_lid, IN uint8_t hops, IN boolean_t is_target_sw) { ftree_port_t *p_port; uint8_t i, ports_num; ftree_sw_t *p_remote_sw = p_group->remote_hca_or_sw.p_sw; /* if lid is a switch, we set the min hop table in the osm_switch struct */ CL_ASSERT(p_group->remote_node_type == IB_NODE_TYPE_SWITCH); p_remote_sw->hops[target_lid] = hops; /* If target lid is a switch we set the min hop table values * for each port on the associated osm_sw struct */ if (!is_target_sw) return 0; ports_num = (uint8_t) cl_ptr_vector_get_size(&p_group->ports); for (i = 0; i < ports_num; i++) { cl_ptr_vector_at(&p_group->ports, i, (void *)&p_port); if (sw_set_hops(p_remote_sw, target_lid, p_port->remote_port_num, hops, is_target_sw)) return -1; } return 0; } /***************************************************/ static inline uint8_t sw_get_least_hops(IN ftree_sw_t * p_sw, IN uint16_t target_lid) { CL_ASSERT(p_sw->hops != NULL); return p_sw->hops[target_lid]; } /*************************************************** ** ** ftree_hca_t functions ** ***************************************************/ static ftree_hca_t *hca_create(IN osm_node_t * p_osm_node) { ftree_hca_t *p_hca = (ftree_hca_t *) malloc(sizeof(ftree_hca_t)); if (p_hca == NULL) return NULL; memset(p_hca, 0, sizeof(ftree_hca_t)); p_hca->p_osm_node = p_osm_node; p_hca->up_port_groups = (ftree_port_group_t **) malloc(osm_node_get_num_physp(p_hca->p_osm_node) * sizeof(ftree_port_group_t *)); if (!p_hca->up_port_groups) { free(p_hca); return NULL; } memset(p_hca->up_port_groups, 0, osm_node_get_num_physp(p_hca->p_osm_node) * sizeof(ftree_port_group_t *)); p_hca->disconnected_ports = (uint8_t *) calloc(osm_node_get_num_physp(p_hca->p_osm_node) + 1, sizeof(uint8_t)); if (!p_hca->disconnected_ports) { free(p_hca->up_port_groups); free(p_hca); return NULL; } p_hca->up_port_groups_num = 0; return p_hca; } /***************************************************/ static void hca_destroy(IN ftree_hca_t * p_hca) { uint32_t i; if (!p_hca) return; for (i = 0; i < p_hca->up_port_groups_num; i++) port_group_destroy(p_hca->up_port_groups[i]); free(p_hca->up_port_groups); free(p_hca->disconnected_ports); free(p_hca); } /***************************************************/ static uint64_t hca_get_guid_no(IN ftree_hca_t * p_hca) { if (!p_hca) return 0; return osm_node_get_node_guid(p_hca->p_osm_node); } /***************************************************/ static uint64_t hca_get_guid_ho(IN ftree_hca_t * p_hca) { return cl_ntoh64(hca_get_guid_no(p_hca)); } /***************************************************/ static void hca_dump(IN ftree_fabric_t * p_ftree, IN ftree_hca_t * p_hca) { uint32_t i; if (!p_hca) return; if (!OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) return; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "CA GUID: 0x%016" PRIx64 ", Ports: %u UP\n", hca_get_guid_ho(p_hca), p_hca->up_port_groups_num); for (i = 0; i < p_hca->up_port_groups_num; i++) port_group_dump(p_ftree, p_hca->up_port_groups[i], FTREE_DIRECTION_UP); } static ftree_port_group_t *hca_get_port_group_by_lid(IN ftree_hca_t * p_hca, IN uint16_t lid) { uint32_t i; for (i = 0; i < p_hca->up_port_groups_num; i++) if (lid == p_hca->up_port_groups[i]->lid) return p_hca->up_port_groups[i]; return NULL; } /***************************************************/ static void hca_add_port(IN ftree_fabric_t * p_ftree, IN ftree_hca_t * p_hca, IN uint8_t port_num, IN uint8_t remote_port_num, IN uint16_t lid, IN uint16_t remote_lid, IN ib_net64_t port_guid, IN ib_net64_t remote_port_guid, IN ib_net64_t remote_node_guid, IN uint8_t remote_node_type, IN void *p_remote_hca_or_sw, IN boolean_t is_cn, IN boolean_t is_io) { ftree_port_group_t *p_group; /* this function is supposed to be called only for adding ports in hca's that lead to switches */ CL_ASSERT(remote_node_type == IB_NODE_TYPE_SWITCH); p_group = hca_get_port_group_by_lid(p_hca, lid); if (!p_group) { p_group = port_group_create(lid, remote_lid, port_guid, hca_get_guid_no(p_hca), IB_NODE_TYPE_CA, p_hca, remote_port_guid, remote_node_guid, remote_node_type, p_remote_hca_or_sw, is_cn, is_io); CL_ASSERT(p_group); p_hca->up_port_groups[p_hca->up_port_groups_num++] = p_group; port_group_add_port(p_group, port_num, remote_port_num); } else OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB32: Duplicated LID for CA GUID: 0x%016" PRIx64 "\n", cl_ntoh64(port_guid)); } /* hca_add_port() */ /*************************************************** ** ** ftree_fabric_t functions ** ***************************************************/ static ftree_fabric_t *fabric_create() { ftree_fabric_t *p_ftree = (ftree_fabric_t *) malloc(sizeof(ftree_fabric_t)); if (p_ftree == NULL) return NULL; memset(p_ftree, 0, sizeof(ftree_fabric_t)); cl_qmap_init(&p_ftree->hca_tbl); cl_qmap_init(&p_ftree->sw_tbl); cl_qmap_init(&p_ftree->sw_by_tuple_tbl); cl_qmap_init(&p_ftree->cn_guid_tbl); cl_qmap_init(&p_ftree->io_guid_tbl); return p_ftree; } /***************************************************/ static void fabric_clear(ftree_fabric_t * p_ftree) { ftree_hca_t *p_hca; ftree_hca_t *p_next_hca; ftree_sw_t *p_sw; ftree_sw_t *p_next_sw; ftree_sw_tbl_element_t *p_element; ftree_sw_tbl_element_t *p_next_element; name_map_item_t *p_guid_element, *p_next_guid_element; if (!p_ftree) return; /* remove all the elements of hca_tbl */ p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); hca_destroy(p_hca); } cl_qmap_remove_all(&p_ftree->hca_tbl); /* remove all the elements of sw_tbl */ p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); sw_destroy(p_sw); } cl_qmap_remove_all(&p_ftree->sw_tbl); /* remove all the elements of sw_by_tuple_tbl */ p_next_element = (ftree_sw_tbl_element_t *) cl_qmap_head(&p_ftree->sw_by_tuple_tbl); while (p_next_element != (ftree_sw_tbl_element_t *) cl_qmap_end(&p_ftree->sw_by_tuple_tbl)) { p_element = p_next_element; p_next_element = (ftree_sw_tbl_element_t *) cl_qmap_next(&p_element->map_item); sw_tbl_element_destroy(p_element); } cl_qmap_remove_all(&p_ftree->sw_by_tuple_tbl); /* remove all the elements of cn_guid_tbl */ p_next_guid_element = (name_map_item_t *) cl_qmap_head(&p_ftree->cn_guid_tbl); while (p_next_guid_element != (name_map_item_t *) cl_qmap_end(&p_ftree->cn_guid_tbl)) { p_guid_element = p_next_guid_element; p_next_guid_element = (name_map_item_t *) cl_qmap_next(&p_guid_element->item); free(p_guid_element); } cl_qmap_remove_all(&p_ftree->cn_guid_tbl); /* remove all the elements of io_guid_tbl */ p_next_guid_element = (name_map_item_t *) cl_qmap_head(&p_ftree->io_guid_tbl); while (p_next_guid_element != (name_map_item_t *) cl_qmap_end(&p_ftree->io_guid_tbl)) { p_guid_element = p_next_guid_element; p_next_guid_element = (name_map_item_t *) cl_qmap_next(&p_guid_element->item); free(p_guid_element); } cl_qmap_remove_all(&p_ftree->io_guid_tbl); /* free the leaf switches array */ if ((p_ftree->leaf_switches_num > 0) && (p_ftree->leaf_switches)) free(p_ftree->leaf_switches); p_ftree->leaf_switches_num = 0; p_ftree->cn_num = 0; p_ftree->ca_ports = 0; p_ftree->leaf_switch_rank = 0; p_ftree->max_switch_rank = 0; p_ftree->max_cn_per_leaf = 0; p_ftree->lft_max_lid = 0; p_ftree->leaf_switches = NULL; p_ftree->fabric_built = FALSE; } /* fabric_destroy() */ /***************************************************/ static void fabric_destroy(ftree_fabric_t * p_ftree) { if (!p_ftree) return; fabric_clear(p_ftree); free(p_ftree); } /***************************************************/ static uint8_t fabric_get_rank(ftree_fabric_t * p_ftree) { return p_ftree->leaf_switch_rank + 1; } /***************************************************/ static void fabric_add_hca(ftree_fabric_t * p_ftree, osm_node_t * p_osm_node) { ftree_hca_t *p_hca; CL_ASSERT(osm_node_get_type(p_osm_node) == IB_NODE_TYPE_CA); p_hca = hca_create(p_osm_node); if (!p_hca) return; cl_qmap_insert(&p_ftree->hca_tbl, p_osm_node->node_info.node_guid, &p_hca->map_item); } /***************************************************/ static void fabric_add_sw(ftree_fabric_t * p_ftree, osm_switch_t * p_osm_sw) { ftree_sw_t *p_sw; CL_ASSERT(osm_node_get_type(p_osm_sw->p_node) == IB_NODE_TYPE_SWITCH); p_sw = sw_create(p_osm_sw); if (!p_sw) return; cl_qmap_insert(&p_ftree->sw_tbl, p_osm_sw->p_node->node_info.node_guid, &p_sw->map_item); /* track the max lid (in host order) that exists in the fabric */ if (p_sw->lid > p_ftree->lft_max_lid) p_ftree->lft_max_lid = p_sw->lid; } /***************************************************/ static void fabric_add_sw_by_tuple(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw) { CL_ASSERT(tuple_assigned(p_sw->tuple)); cl_qmap_insert(&p_ftree->sw_by_tuple_tbl, tuple_to_key(p_sw->tuple), &sw_tbl_element_create(p_sw)->map_item); } /***************************************************/ static ftree_sw_t *fabric_get_sw_by_tuple(IN ftree_fabric_t * p_ftree, IN ftree_tuple_t tuple) { ftree_sw_tbl_element_t *p_element; CL_ASSERT(tuple_assigned(tuple)); tuple_to_key(tuple); p_element = (ftree_sw_tbl_element_t *) cl_qmap_get(&p_ftree->sw_by_tuple_tbl, tuple_to_key(tuple)); if (p_element == (ftree_sw_tbl_element_t *) cl_qmap_end(&p_ftree->sw_by_tuple_tbl)) return NULL; return p_element->p_sw; } /***************************************************/ static ftree_sw_t *fabric_get_sw_by_guid(IN ftree_fabric_t * p_ftree, IN uint64_t guid) { ftree_sw_t *p_sw; p_sw = (ftree_sw_t *) cl_qmap_get(&p_ftree->sw_tbl, guid); if (p_sw == (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) return NULL; return p_sw; } /***************************************************/ static ftree_hca_t *fabric_get_hca_by_guid(IN ftree_fabric_t * p_ftree, IN uint64_t guid) { ftree_hca_t *p_hca; p_hca = (ftree_hca_t *) cl_qmap_get(&p_ftree->hca_tbl, guid); if (p_hca == (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) return NULL; return p_hca; } /***************************************************/ static void fabric_dump(ftree_fabric_t * p_ftree) { uint32_t i; ftree_hca_t *p_hca; ftree_sw_t *p_sw; if (!OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) return; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "\n" " |-------------------------------|\n" " |- Full fabric topology dump -|\n" " |-------------------------------|\n\n"); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "-- CAs:\n"); for (p_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); p_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl); p_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item)) { hca_dump(p_ftree, p_hca); } for (i = 0; i <= p_ftree->max_switch_rank; i++) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "-- Rank %u switches\n", i); for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl); p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) { if (p_sw->rank == i) sw_dump(p_ftree, p_sw); } } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "\n" " |---------------------------------------|\n" " |- Full fabric topology dump completed -|\n" " |---------------------------------------|\n\n"); } /* fabric_dump() */ /***************************************************/ static void fabric_dump_general_info(IN ftree_fabric_t * p_ftree) { uint32_t i, j; ftree_sw_t *p_sw; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, "General fabric topology info\n"); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, "============================\n"); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - FatTree rank (roots to leaf switches): %u\n", p_ftree->leaf_switch_rank + 1); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - FatTree max switch rank: %u\n", p_ftree->max_switch_rank); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - Fabric has %u CAs, %u CA ports (%u of them CNs), %u switches\n", cl_qmap_count(&p_ftree->hca_tbl), p_ftree->ca_ports, p_ftree->cn_num, cl_qmap_count(&p_ftree->sw_tbl)); CL_ASSERT(p_ftree->ca_ports >= p_ftree->cn_num); for (i = 0; i <= p_ftree->max_switch_rank; i++) { j = 0; for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl); p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) { if (p_sw->rank == i) j++; } if (i == 0) OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - Fabric has %u switches at rank %u (roots)\n", j, i); else if (i == p_ftree->leaf_switch_rank) OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - Fabric has %u switches at rank %u (%u of them leafs)\n", j, i, p_ftree->leaf_switches_num); else OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_INFO, " - Fabric has %u switches at rank %u\n", j, i); } if (OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, " - Root switches:\n"); for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl); p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) { if (p_sw->rank == 0) OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, " GUID: 0x%016" PRIx64 ", LID: %u, Index %s\n", sw_get_guid_ho(p_sw), p_sw->lid, tuple_to_str(p_sw->tuple)); } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, " - Leaf switches (sorted by index):\n"); for (i = 0; i < p_ftree->leaf_switches_num; i++) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, " GUID: 0x%016" PRIx64 ", LID: %u, Index %s\n", sw_get_guid_ho(p_ftree->leaf_switches[i]), p_ftree->leaf_switches[i]->lid, tuple_to_str(p_ftree->leaf_switches[i]->tuple)); } } } /* fabric_dump_general_info() */ /***************************************************/ static void fabric_dump_hca_ordering(IN ftree_fabric_t * p_ftree) { ftree_hca_t *p_hca; ftree_sw_t *p_sw; ftree_port_group_t *p_group_on_sw; ftree_port_group_t *p_group_on_hca; uint32_t i; uint32_t j; unsigned printed_hcas_on_leaf; char path[1024]; FILE *p_hca_ordering_file; const char *filename = "opensm-ftree-ca-order.dump"; snprintf(path, sizeof(path), "%s/%s", p_ftree->p_osm->subn.opt.dump_files_dir, filename); p_hca_ordering_file = fopen(path, "w"); if (!p_hca_ordering_file) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB01: " "cannot open file \'%s\': %s\n", filename, strerror(errno)); return; } /* for each leaf switch (in indexing order) */ for (i = 0; i < p_ftree->leaf_switches_num; i++) { p_sw = p_ftree->leaf_switches[i]; printed_hcas_on_leaf = 0; /* for each real CA (CNs and not) connected to this switch */ for (j = 0; j < p_sw->down_port_groups_num; j++) { p_group_on_sw = p_sw->down_port_groups[j]; if (p_group_on_sw->remote_node_type != IB_NODE_TYPE_CA) continue; p_hca = p_group_on_sw->remote_hca_or_sw.p_hca; p_group_on_hca = hca_get_port_group_by_lid(p_hca, p_group_on_sw-> remote_lid); /* treat non-compute nodes as dummies */ if (!p_group_on_hca->is_cn) continue; fprintf(p_hca_ordering_file, "0x%04x\t%s\n", p_group_on_hca->lid, p_hca->p_osm_node->print_desc); printed_hcas_on_leaf++; } /* now print missing HCAs */ for (j = 0; j < (p_ftree->max_cn_per_leaf - printed_hcas_on_leaf); j++) fprintf(p_hca_ordering_file, "0xFFFF\tDUMMY\n"); } /* done going through all the leaf switches */ fclose(p_hca_ordering_file); } /* fabric_dump_hca_ordering() */ /***************************************************/ static void fabric_assign_tuple(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw, IN ftree_tuple_t new_tuple) { memcpy(p_sw->tuple, new_tuple, FTREE_TUPLE_LEN); fabric_add_sw_by_tuple(p_ftree, p_sw); } /***************************************************/ static void fabric_assign_first_tuple(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw, IN unsigned int subtree) { uint8_t i; ftree_tuple_t new_tuple; if (p_ftree->leaf_switch_rank >= FTREE_TUPLE_LEN) return; tuple_init(new_tuple); new_tuple[0] = (uint8_t) p_sw->rank; for (i = 1; i <= p_ftree->leaf_switch_rank; i++) new_tuple[i] = 0; if (p_sw->rank == 0) { if (p_ftree->leaf_switch_rank > 1) new_tuple[p_ftree->leaf_switch_rank] = subtree; for (i = 0; i < 0xFF; i++) { new_tuple[1] = i; if (fabric_get_sw_by_tuple(p_ftree, new_tuple) == NULL) break; } if (i == 0xFF) { /* new tuple not found - there are more than 255 ports in one direction */ return; } } fabric_assign_tuple(p_ftree, p_sw, new_tuple); } /***************************************************/ static void fabric_get_new_tuple(IN ftree_fabric_t * p_ftree, OUT ftree_tuple_t new_tuple, IN ftree_tuple_t from_tuple, IN ftree_direction_t direction) { ftree_sw_t *p_sw; ftree_tuple_t temp_tuple; uint8_t var_index; uint8_t i; tuple_init(new_tuple); memcpy(temp_tuple, from_tuple, FTREE_TUPLE_LEN); if (direction == FTREE_DIRECTION_DOWN) { temp_tuple[0]++; var_index = from_tuple[0] + 1; } else { temp_tuple[0]--; var_index = from_tuple[0]; } for (i = 0; i < 0xFF; i++) { temp_tuple[var_index] = i; p_sw = fabric_get_sw_by_tuple(p_ftree, temp_tuple); if (p_sw == NULL) /* found free tuple */ break; } if (i == 0xFF) { /* new tuple not found - there are more than 255 ports in one direction */ return; } memcpy(new_tuple, temp_tuple, FTREE_TUPLE_LEN); } /* fabric_get_new_tuple() */ /***************************************************/ static inline boolean_t fabric_roots_provided(IN ftree_fabric_t * p_ftree) { return (p_ftree->p_osm->subn.opt.root_guid_file != NULL); } /***************************************************/ static inline boolean_t fabric_cns_provided(IN ftree_fabric_t * p_ftree) { return (p_ftree->p_osm->subn.opt.cn_guid_file != NULL); } /***************************************************/ static inline boolean_t fabric_ios_provided(IN ftree_fabric_t * p_ftree) { return (p_ftree->p_osm->subn.opt.io_guid_file != NULL); } /***************************************************/ static int fabric_mark_leaf_switches(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw; ftree_hca_t *p_hca; ftree_hca_t *p_next_hca; unsigned i; int res = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Marking leaf switches in fabric\n"); /* Scan all the CAs, if they have CNs - find CN port and mark switch that is connected to this port as leaf switch. Also, ensure that this marked leaf has rank of p_ftree->leaf_switch_rank. */ p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); if (!p_hca->cn_num) continue; for (i = 0; i < p_hca->up_port_groups_num; i++) { if (!p_hca->up_port_groups[i]->is_cn) continue; /* In CAs, port group alway has one port, and since this port group is CN, we know that this port is compute node */ CL_ASSERT(p_hca->up_port_groups[i]->remote_node_type == IB_NODE_TYPE_SWITCH); p_sw = p_hca->up_port_groups[i]->remote_hca_or_sw.p_sw; /* check if this switch was already processed */ if (p_sw->is_leaf) continue; p_sw->is_leaf = TRUE; /* ensure that this leaf switch is at the correct tree level */ if (p_sw->rank != p_ftree->leaf_switch_rank) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB26: CN port 0x%" PRIx64 " is connected to switch 0x%" PRIx64 " with rank %u, " "while FatTree leaf rank is %u\n", cl_ntoh64(p_hca-> up_port_groups[i]->port_guid), sw_get_guid_ho(p_sw), p_sw->rank, p_ftree->leaf_switch_rank); res = -1; goto Exit; } } } Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_mark_leaf_switches() */ /***************************************************/ static void bfs_fabric_indexing(IN ftree_fabric_t * p_ftree, IN ftree_sw_t *p_first_sw) { ftree_sw_t *p_remote_sw; ftree_sw_t *p_sw = NULL; ftree_tuple_t new_tuple; uint32_t i; cl_list_t bfs_list; OSM_LOG_ENTER(&p_ftree->p_osm->log); cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl)); /* * Now run BFS and assign indexes to all switches * Pseudo code of the algorithm is as follows: * * * Add first switch to BFS queue * * While (BFS queue not empty) * - Pop the switch from the head of the queue * - Scan all the downward and upward ports * - For each port * + Get the remote switch * + Assign index to the remote switch * + Add remote switch to the BFS queue */ cl_list_insert_tail(&bfs_list, p_first_sw); while (!cl_is_list_empty(&bfs_list)) { p_sw = (ftree_sw_t *) cl_list_remove_head(&bfs_list); /* Discover all the nodes from ports that are pointing down */ if (p_sw->rank >= p_ftree->leaf_switch_rank) { /* whether downward ports are pointing to CAs or switches, we don't assign indexes to switches that are located lower than leaf switches */ } else { /* This is not the leaf switch */ for (i = 0; i < p_sw->down_port_groups_num; i++) { /* Work with port groups that are pointing to switches only. No need to assign indexing to HCAs */ if (p_sw-> down_port_groups[i]->remote_node_type != IB_NODE_TYPE_SWITCH) continue; p_remote_sw = p_sw->down_port_groups[i]-> remote_hca_or_sw.p_sw; if (tuple_assigned(p_remote_sw->tuple)) { /* this switch has been already indexed */ continue; } /* allocate new tuple */ fabric_get_new_tuple(p_ftree, new_tuple, p_sw->tuple, FTREE_DIRECTION_DOWN); /* Assign the new tuple to the remote switch. This fuction also adds the switch into the switch_by_tuple table. */ fabric_assign_tuple(p_ftree, p_remote_sw, new_tuple); /* add the newly discovered switch to the BFS queue */ cl_list_insert_tail(&bfs_list, p_remote_sw); } /* Done assigning indexes to all the remote switches that are pointed by the downgoing ports. Now sort port groups according to remote index. */ qsort(p_sw->down_port_groups, /* array */ p_sw->down_port_groups_num, /* number of elements */ sizeof(ftree_port_group_t *), /* size of each element */ compare_port_groups_by_remote_switch_index); /* comparator */ } /* Done indexing switches from ports that go down. Now do the same with ports that are pointing up. if we started from root (rank == 0), the leaf is bsf termination point */ if (p_sw->rank != 0 && (p_first_sw->rank != 0 || !p_sw->is_leaf)) { /* This is not the root switch, which means that all the ports that are pointing up are taking us to another switches. */ for (i = 0; i < p_sw->up_port_groups_num; i++) { p_remote_sw = p_sw->up_port_groups[i]-> remote_hca_or_sw.p_sw; if (tuple_assigned(p_remote_sw->tuple)) continue; /* allocate new tuple */ fabric_get_new_tuple(p_ftree, new_tuple, p_sw->tuple, FTREE_DIRECTION_UP); /* Assign the new tuple to the remote switch. This fuction also adds the switch to the switch_by_tuple table. */ fabric_assign_tuple(p_ftree, p_remote_sw, new_tuple); /* add the newly discovered switch to the BFS queue */ cl_list_insert_tail(&bfs_list, p_remote_sw); } /* Done assigning indexes to all the remote switches that are pointed by the upgoing ports. Now sort port groups according to remote index. */ qsort(p_sw->up_port_groups, /* array */ p_sw->up_port_groups_num, /* number of elements */ sizeof(ftree_port_group_t *), /* size of each element */ compare_port_groups_by_remote_switch_index); /* comparator */ } /* Done assigning indexes to all the switches that are directly connected to the current switch - go to the next switch in the BFS queue */ } cl_list_destroy(&bfs_list); OSM_LOG_EXIT(&p_ftree->p_osm->log); } static void fabric_make_indexing(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw = NULL; unsigned int subtree = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Starting FatTree indexing\n"); /* using the first switch as a starting point for indexing algorithm. */ for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl); p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) { if (ftree_get_subnet(p_ftree)->opt.quasi_ftree_indexing) { /* find first root switch */ if (p_sw->rank != 0) continue; } else { /* find first leaf switch */ if (!p_sw->is_leaf) continue; } /* Assign the first tuple to the switch that is used as BFS starting point in the subtree. The tuple will be as follows: [rank].0...0.subtree This fuction also adds the switch it into the switch_by_tuple table. */ if (!tuple_assigned(p_sw->tuple)) { fabric_assign_first_tuple(p_ftree, p_sw, subtree++); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Indexing starting point:\n" " - Switch rank : %u\n" " - Switch index : %s\n" " - Node LID : %u\n" " - Node GUID : 0x%016" PRIx64 "\n", p_sw->rank, tuple_to_str(p_sw->tuple), p_sw->lid, sw_get_guid_ho(p_sw)); } bfs_fabric_indexing(p_ftree, p_sw); if (ftree_get_subnet(p_ftree)->opt.quasi_ftree_indexing == FALSE) goto Exit; } p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { if (p_sw->is_leaf) { qsort(p_sw->up_port_groups, /* array */ p_sw->up_port_groups_num, /* number of elements */ sizeof(ftree_port_group_t *), /* size of each element */ compare_port_groups_by_remote_switch_index); /* comparator */ } p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); } Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_make_indexing() */ /***************************************************/ static int fabric_create_leaf_switch_array(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw; ftree_sw_t *p_next_sw; ftree_sw_t **all_switches_at_leaf_level; unsigned i; unsigned all_leaf_idx = 0; unsigned first_leaf_idx; unsigned last_leaf_idx; int res = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); /* create array of ALL the switches that have leaf rank */ all_switches_at_leaf_level = (ftree_sw_t **) malloc(cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *)); if (!all_switches_at_leaf_level) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_SYS, FILE_ID, "Fat-tree routing: Memory allocation failed\n"); res = -1; goto Exit; } memset(all_switches_at_leaf_level, 0, cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *)); p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); if (p_sw->rank == p_ftree->leaf_switch_rank) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Adding switch 0x%" PRIx64 " to full leaf switch array\n", sw_get_guid_ho(p_sw)); all_switches_at_leaf_level[all_leaf_idx++] = p_sw; } } /* quick-sort array of leaf switches by index */ qsort(all_switches_at_leaf_level, /* array */ all_leaf_idx, /* number of elements */ sizeof(ftree_sw_t *), /* size of each element */ compare_switches_by_index); /* comparator */ /* check the first and the last REAL leaf (the one that has CNs) in the array of all the leafs */ first_leaf_idx = all_leaf_idx; last_leaf_idx = 0; for (i = 0; i < all_leaf_idx; i++) { if (all_switches_at_leaf_level[i]->is_leaf) { if (i < first_leaf_idx) first_leaf_idx = i; last_leaf_idx = i; } } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Full leaf array info: first_leaf_idx = %u, last_leaf_idx = %u\n", first_leaf_idx, last_leaf_idx); if (first_leaf_idx >= last_leaf_idx) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Faild to find leaf switches - topology is not " "fat-tree\n"); res = -1; goto Exit; } /* Create array of REAL leaf switches, sorted by index. This array may contain switches at the same rank w/o CNs, in case this is the order of indexing. */ p_ftree->leaf_switches_num = last_leaf_idx - first_leaf_idx + 1; p_ftree->leaf_switches = (ftree_sw_t **) malloc(p_ftree->leaf_switches_num * sizeof(ftree_sw_t *)); if (!p_ftree->leaf_switches) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_SYS, FILE_ID, "Fat-tree routing: Memory allocation failed\n"); res = -1; goto Exit; } memcpy(p_ftree->leaf_switches, &(all_switches_at_leaf_level[first_leaf_idx]), p_ftree->leaf_switches_num * sizeof(ftree_sw_t *)); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Created array of %u leaf switches\n", p_ftree->leaf_switches_num); Exit: free(all_switches_at_leaf_level); OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_create_leaf_switch_array() */ /***************************************************/ static void fabric_set_max_cn_per_leaf(IN ftree_fabric_t * p_ftree) { unsigned i; unsigned j; unsigned cns_on_this_leaf; ftree_sw_t *p_sw; ftree_port_group_t *p_group, *p_up_group; ftree_hca_t *p_hca; for (i = 0; i < p_ftree->leaf_switches_num; i++) { p_sw = p_ftree->leaf_switches[i]; cns_on_this_leaf = 0; for (j = 0; j < p_sw->down_port_groups_num; j++) { p_group = p_sw->down_port_groups[j]; if (p_group->remote_node_type != IB_NODE_TYPE_CA) continue; p_hca = p_group->remote_hca_or_sw.p_hca; /* * Get the hca port group corresponding * to the LID of remote HCA port */ p_up_group = hca_get_port_group_by_lid(p_hca, p_group->remote_lid); CL_ASSERT(p_up_group); if (p_up_group->is_cn) cns_on_this_leaf++; } if (cns_on_this_leaf > p_ftree->max_cn_per_leaf) p_ftree->max_cn_per_leaf = cns_on_this_leaf; } } /* fabric_set_max_cn_per_leaf() */ /***************************************************/ static boolean_t fabric_validate_topology(IN ftree_fabric_t * p_ftree) { ftree_port_group_t *p_group; ftree_port_group_t *p_ref_group; ftree_sw_t *p_sw; ftree_sw_t *p_next_sw; ftree_sw_t **reference_sw_arr; uint16_t tree_rank = fabric_get_rank(p_ftree); boolean_t res = TRUE; uint8_t i; OSM_LOG_ENTER(&p_ftree->p_osm->log); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Validating fabric topology\n"); reference_sw_arr = (ftree_sw_t **) malloc(tree_rank * sizeof(ftree_sw_t *)); if (reference_sw_arr == NULL) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_SYS, FILE_ID, "Fat-tree routing: Memory allocation failed\n"); return FALSE; } memset(reference_sw_arr, 0, tree_rank * sizeof(ftree_sw_t *)); p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (res && p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); if (!reference_sw_arr[p_sw->rank]) /* This is the first switch in the current level that we're checking - use it as a reference */ reference_sw_arr[p_sw->rank] = p_sw; else { /* compare this switch properties to the reference switch */ if (reference_sw_arr[p_sw->rank]->up_port_groups_num != p_sw->up_port_groups_num) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB09: Different number of upward port groups on switches:\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u groups\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u groups\n", sw_get_guid_ho (reference_sw_arr[p_sw->rank]), reference_sw_arr[p_sw->rank]->lid, tuple_to_str (reference_sw_arr[p_sw->rank]->tuple), reference_sw_arr[p_sw-> rank]-> up_port_groups_num, sw_get_guid_ho(p_sw), p_sw->lid, tuple_to_str(p_sw->tuple), p_sw->up_port_groups_num); res = FALSE; break; } if (p_sw->rank != (tree_rank - 1) && reference_sw_arr[p_sw-> rank]->down_port_groups_num != p_sw->down_port_groups_num) { /* we're allowing some hca's to be missing */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0A: Different number of downward port groups on switches:\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u port groups\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u port groups\n", sw_get_guid_ho (reference_sw_arr[p_sw->rank]), reference_sw_arr[p_sw->rank]->lid, tuple_to_str (reference_sw_arr[p_sw->rank]->tuple), reference_sw_arr[p_sw-> rank]-> down_port_groups_num, sw_get_guid_ho(p_sw), p_sw->lid, tuple_to_str(p_sw->tuple), p_sw->down_port_groups_num); res = FALSE; break; } if (reference_sw_arr[p_sw->rank]->up_port_groups_num != 0) { p_ref_group = reference_sw_arr[p_sw-> rank]->up_port_groups[0]; for (i = 0; i < p_sw->up_port_groups_num; i++) { p_group = p_sw->up_port_groups[i]; if (cl_ptr_vector_get_size (&p_ref_group->ports) != cl_ptr_vector_get_size (&p_group->ports)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0B: Different number of ports in an upward port group on switches:\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u ports\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u ports\n", sw_get_guid_ho (reference_sw_arr [p_sw->rank]), reference_sw_arr[p_sw-> rank]-> lid, tuple_to_str (reference_sw_arr [p_sw->rank]->tuple), cl_ptr_vector_get_size (&p_ref_group->ports), sw_get_guid_ho(p_sw), p_sw->lid, tuple_to_str(p_sw-> tuple), cl_ptr_vector_get_size (&p_group->ports)); res = FALSE; break; } } } if (reference_sw_arr[p_sw->rank]->down_port_groups_num != 0 && p_sw->rank != (tree_rank - 1)) { /* we're allowing some hca's to be missing */ p_ref_group = reference_sw_arr[p_sw-> rank]->down_port_groups[0]; for (i = 0; i < p_sw->down_port_groups_num; i++) { p_group = p_sw->down_port_groups[0]; if (cl_ptr_vector_get_size (&p_ref_group->ports) != cl_ptr_vector_get_size (&p_group->ports)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0C: Different number of ports in an downward port group on switches:\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u ports\n" " GUID 0x%016" PRIx64 ", LID %u, Index %s - %u ports\n", sw_get_guid_ho (reference_sw_arr [p_sw->rank]), reference_sw_arr[p_sw-> rank]-> lid, tuple_to_str (reference_sw_arr [p_sw->rank]->tuple), cl_ptr_vector_get_size (&p_ref_group->ports), sw_get_guid_ho(p_sw), p_sw->lid, tuple_to_str(p_sw-> tuple), cl_ptr_vector_get_size (&p_group->ports)); res = FALSE; break; } } } } /* end of else */ } /* end of while */ if (res == TRUE) OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Fabric topology has been identified as FatTree\n"); else OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0D: Fabric topology hasn't been identified as FatTree\n"); free(reference_sw_arr); OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_validate_topology() */ /*************************************************** ***************************************************/ static void set_sw_fwd_table(IN cl_map_item_t * const p_map_item, IN void *context) { ftree_sw_t *p_sw = (ftree_sw_t * const)p_map_item; ftree_fabric_t *p_ftree = (ftree_fabric_t *) context; p_sw->p_osm_sw->max_lid_ho = p_ftree->lft_max_lid; } /*************************************************** ***************************************************/ /* * Function: Finds the least loaded port group and stores its counter * Given : A switch */ static inline void recalculate_min_counter_down(ftree_sw_t * p_sw) { uint32_t min = (1 << 30); uint32_t i; for (i = 0; i < p_sw->down_port_groups_num; i++) { if (p_sw->down_port_groups[i]->counter_down < min) { min = p_sw->down_port_groups[i]->counter_down; } } p_sw->min_counter_down = min; return; } /* * Function: Return the counter value of the least loaded down port group * Given : A switch */ static inline uint32_t find_lowest_loaded_group_on_sw(ftree_sw_t * p_sw) { return p_sw->min_counter_down; } /* * Function: Compare the load of two port groups and return which is the least loaded * Given : Two port groups with remote switch * When both port groups are equally loaded, it picks the one whom * remote switch down ports are least loaded. * This way, it prefers the switch from where it will be easier to go down (creating upward routes). * If both are equal, it picks the lowest INDEX to be deterministic. */ static inline int port_group_compare_load_down(const ftree_port_group_t * p1, const ftree_port_group_t * p2) { int temp = p1->counter_down - p2->counter_down; if (temp > 0) return 1; if (temp < 0) return -1; /* Find the less loaded remote sw and choose this one */ do { uint32_t load1 = find_lowest_loaded_group_on_sw(p1->remote_hca_or_sw.p_sw); uint32_t load2 = find_lowest_loaded_group_on_sw(p2->remote_hca_or_sw.p_sw); temp = load1 - load2; if (temp > 0) return 1; } while (0); /* If they are both equal, choose the lowest index */ return compare_port_groups_by_remote_switch_index(&p1, &p2); } static inline int port_group_compare_load_up(const ftree_port_group_t * p1, const ftree_port_group_t * p2) { int temp = p1->counter_up - p2->counter_up; if (temp > 0) return 1; if (temp < 0) return -1; /* If they are both equal, choose the lowest index */ return compare_port_groups_by_remote_switch_index (&p1,&p2); } /* * Function: Sorts an array of port group by up load order * Given : A port group array and its length * As the list is mostly sorted, we used a bubble sort instead of qsort * as it is much faster. * * Important note: * This function and bubble_sort_down must NOT be factorized. * Although most of the code is the same and a function pointer could be used * for the compareason function, it would prevent the compareason function to be inlined * and cost a great deal to performances. */ static inline void bubble_sort_up(ftree_port_group_t ** p_group_array, uint32_t nmemb) { uint32_t i = 0; uint32_t j = 0; ftree_port_group_t *tmp = p_group_array[0]; /* As this function is a great number of times, we only go into the loop * if one of the port counters has changed, thus saving some tests */ if (tmp->hca_or_sw.p_sw->counter_up_changed == FALSE) { return; } /* While we did modifications on the array order */ /* i may grew above array length but next loop will fail and tmp will be null for the next time * this way we save a test i < nmemb for each pass through the loop */ for (i = 0; tmp; i++) { /* Assume the array is orderd */ tmp = NULL; /* Comparing elements j and j-1 */ for (j = 1; j < (nmemb - i); j++) { /* If they are the wrong way around */ if (port_group_compare_load_up(p_group_array[j], p_group_array[j - 1]) < 0) { /* We invert them */ tmp = p_group_array[j - 1]; p_group_array[j - 1] = p_group_array[j]; p_group_array[j] = tmp; /* This sets tmp != NULL so the main loop will make another pass */ } } } /* We have reordered the array so as long noone changes the counter * it's not necessary to do it again */ p_group_array[0]->hca_or_sw.p_sw->counter_up_changed = FALSE; } static inline void bubble_sort_siblings(ftree_port_group_t ** p_group_array, uint32_t nmemb) { uint32_t i = 0; uint32_t j = 0; ftree_port_group_t *tmp = p_group_array[0]; /* While we did modifications on the array order */ /* i may grew above array length but next loop will fail and tmp will be null for the next time * this way we save a test i < nmemb for each pass through the loop */ for (i = 0; tmp != NULL; i++) { /* Assume the array is orderd */ tmp = NULL; /* Comparing elements j and j-1 */ for (j = 1; j < (nmemb - i); j++) { /* If they are the wrong way around */ if (port_group_compare_load_up(p_group_array[j], p_group_array[j - 1]) < 0) { /* We invert them */ tmp = p_group_array[j - 1]; p_group_array[j - 1] = p_group_array[j]; p_group_array[j] = tmp; } } } } /* * Function: Sorts an array of port group. Order is decide through * port_group_compare_load_down ( up counters, least load remote switch, biggest GUID) * Given : A port group array and its length. Each port group points to a remote switch (not a HCA) * As the list is mostly sorted, we used a bubble sort instead of qsort * as it is much faster. * * Important note: * This function and bubble_sort_up must NOT be factorized. * Although most of the code is the same and a function pointer could be used * for the compareason function, it would prevent the compareason function to be inlined * and cost a great deal to performances. */ static inline void bubble_sort_down(ftree_port_group_t ** p_group_array, uint32_t nmemb) { uint32_t i = 0; uint32_t j = 0; ftree_port_group_t *tmp = p_group_array[0]; /* While we did modifications on the array order */ /* i may grew above array length but next loop will fail and tmp will be null for the next time * this way we save a test i < nmemb for each pass through the loop */ for (i = 0; tmp; i++) { /* Assume the array is orderd */ tmp = NULL; /* Comparing elements j and j-1 */ for (j = 1; j < (nmemb - i); j++) { /* If they are the wrong way around */ if (port_group_compare_load_down (p_group_array[j], p_group_array[j - 1]) < 0) { /* We invert them */ tmp = p_group_array[j - 1]; p_group_array[j - 1] = p_group_array[j]; p_group_array[j] = tmp; } } } } /*************************************************** ***************************************************/ /* * Function: assign-up-going-port-by-descending-down * Given : a switch and a LID * Pseudo code: * foreach down-going-port-group (in indexing order) * skip this group if the LFT(LID) port is part of this group * find the least loaded port of the group (scan in indexing order) * r-port is the remote port connected to it * assign the remote switch node LFT(LID) to r-port * increase r-port usage counter * assign-up-going-port-by-descending-down to r-port node (recursion) */ static boolean_t fabric_route_upgoing_by_going_down(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw, IN ftree_sw_t * p_prev_sw, IN uint16_t target_lid, IN boolean_t is_main_path, IN boolean_t is_target_a_sw, IN uint8_t current_hops) { ftree_sw_t *p_remote_sw; uint16_t ports_num; ftree_port_group_t *p_group; ftree_port_t *p_port; ftree_port_t *p_min_port; uint16_t j; uint16_t k; boolean_t created_route = FALSE; boolean_t routed = 0; uint8_t least_hops; /* if there is no down-going ports */ if (p_sw->down_port_groups_num == 0) return FALSE; /* foreach down-going port group (in load order) */ bubble_sort_up(p_sw->down_port_groups, p_sw->down_port_groups_num); if (p_sw->sibling_port_groups_num > 0) bubble_sort_siblings(p_sw->sibling_port_groups, p_sw->sibling_port_groups_num); for (k = 0; k < (p_sw->down_port_groups_num + ((target_lid != 0) ? p_sw->sibling_port_groups_num : 0)); k++) { if (k < p_sw->down_port_groups_num) { p_group = p_sw->down_port_groups[k]; } else { p_group = p_sw->sibling_port_groups[k - p_sw-> down_port_groups_num]; } /* If this port group doesn't point to a switch, mark that the route was created and skip to the next group */ if (p_group->remote_node_type != IB_NODE_TYPE_SWITCH) { created_route = TRUE; continue; } if (p_prev_sw && p_group->remote_lid == p_prev_sw->lid) { /* This port group has a port that was used when we entered this switch, which means that the current group points to the switch where we were at the previous step of the algorithm (before going up). Skipping this group. */ continue; } /* find the least loaded port of the group (in indexing order) */ p_min_port = NULL; ports_num = (uint16_t) cl_ptr_vector_get_size(&p_group->ports); if(ports_num == 0) continue; for (j = 0; j < ports_num; j++) { cl_ptr_vector_at(&p_group->ports, j, (void *)&p_port); /* first port that we're checking - set as port with the lowest load */ /* or this port is less loaded - use it as min */ if (!p_min_port || p_port->counter_up < p_min_port->counter_up) p_min_port = p_port; } /* At this point we have selected a port in this group with the lowest load of upgoing routes. Set on the remote switch how to get to the target_lid - set LFT(target_lid) on the remote switch to the remote port */ p_remote_sw = p_group->remote_hca_or_sw.p_sw; least_hops = sw_get_least_hops(p_remote_sw, target_lid); if (least_hops != OSM_NO_PATH) { /* Loop in the fabric - we already routed the remote switch on our way UP, and now we see it again on our way DOWN */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Loop of length %d in the fabric:\n " "Switch %s (LID %u) closes loop through switch %s (LID %u)\n", current_hops, tuple_to_str(p_remote_sw->tuple), p_group->lid, tuple_to_str(p_sw->tuple), p_group->remote_lid); /* We skip only if we have come through a longer path */ if (current_hops + 1 >= least_hops) continue; } /* Four possible cases: * * 1. is_main_path == TRUE: * - going DOWN(TRUE,TRUE) through ALL the groups * + promoting port counter * + setting path in remote switch fwd tbl * + setting hops in remote switch on all the ports of each group * * 2. is_main_path == FALSE: * - going DOWN(TRUE,FALSE) through ALL the groups but only if * the remote (lower) switch hasn't been already configured * for this target LID (or with a longer path) * + promoting port counter * + setting path in remote switch fwd tbl if it hasn't been set yet * + setting hops in remote switch on all the ports of each group * if it hasn't been set yet */ /* setting fwd tbl port only */ p_remote_sw->p_osm_sw->new_lft[target_lid] = p_min_port->remote_port_num; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s: set path to CA LID %u through port %u\n", tuple_to_str(p_remote_sw->tuple), target_lid, p_min_port->remote_port_num); /* On the remote switch that is pointed by the p_group, set hops for ALL the ports in the remote group. */ set_hops_on_remote_sw(p_group, target_lid, current_hops + 1, is_target_a_sw); /* Recursion step: Assign upgoing ports by stepping down, starting on REMOTE switch */ routed = fabric_route_upgoing_by_going_down(p_ftree, p_remote_sw, /* remote switch - used as a route-upgoing alg. start point */ NULL, /* prev. position - NULL to mark that we went down and not up */ target_lid, /* LID that we're routing to */ is_main_path, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ current_hops + 1); /* Number of hops done to this point */ created_route |= routed; /* Counters are promoted only if a route toward a node is created */ if (routed) { p_min_port->counter_up++; p_group->counter_up++; p_group->hca_or_sw.p_sw->counter_up_changed = TRUE; } } /* done scanning all the down-going port groups */ /* if the route was created, promote the index that indicates which group should we start with when going through all the downgoing groups */ if (created_route) p_sw->down_port_groups_idx = (p_sw->down_port_groups_idx + 1) % p_sw->down_port_groups_num; return created_route; } /* fabric_route_upgoing_by_going_down() */ /***************************************************/ /* * Function: assign-down-going-port-by-ascending-up * Given : a switch and a LID * Pseudo code: * find the least loaded port of all the upgoing groups (scan in indexing order) * assign the LFT(LID) of remote switch to that port * track that port usage * assign-up-going-port-by-descending-down on CURRENT switch * assign-down-going-port-by-ascending-up on REMOTE switch (recursion) */ static boolean_t fabric_route_downgoing_by_going_up(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw, IN ftree_sw_t * p_prev_sw, IN uint16_t target_lid, IN boolean_t is_main_path, IN boolean_t is_target_a_sw, IN uint16_t reverse_hop_credit, IN uint16_t reverse_hops, IN uint8_t current_hops) { ftree_sw_t *p_remote_sw; uint16_t ports_num; ftree_port_group_t *p_group; ftree_port_t *p_port; ftree_port_group_t *p_min_group; ftree_port_t *p_min_port; uint16_t i; uint16_t j; boolean_t created_route = FALSE; boolean_t routed = FALSE; /* Assign upgoing ports by stepping down, starting on THIS switch */ created_route = fabric_route_upgoing_by_going_down(p_ftree, p_sw, /* local switch - used as a route-upgoing alg. start point */ p_prev_sw, /* switch that we went up from (NULL means that we went down) */ target_lid, /* LID that we're routing to */ is_main_path, /* whether this path to HCA should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ current_hops); /* Number of hops done up to this point */ /* recursion stop condition - if it's a root switch, */ if (p_sw->rank == 0) { if (reverse_hop_credit > 0) { /* We go up by going down as we have some reverse_hop_credit left */ /* We use the index to scatter a bit the reverse up routes */ p_sw->down_port_groups_idx = (p_sw->down_port_groups_idx + 1) % p_sw->down_port_groups_num; i = p_sw->down_port_groups_idx; for (j = 0; j < p_sw->down_port_groups_num; j++) { p_group = p_sw->down_port_groups[i]; i = (i + 1) % p_sw->down_port_groups_num; /* Skip this port group unless it points to a switch */ if (p_group->remote_node_type != IB_NODE_TYPE_SWITCH) continue; p_remote_sw = p_group->remote_hca_or_sw.p_sw; created_route |= fabric_route_downgoing_by_going_up(p_ftree, p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ p_sw, /* this switch - prev. position switch for the function */ target_lid, /* LID that we're routing to */ is_main_path, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ reverse_hop_credit - 1, /* Remaining reverse_hops allowed */ reverse_hops + 1, /* Number of reverse_hops done up to this point */ current_hops + 1); } } return created_route; } /* We should generate a list of port sorted by load so we can find easily the least * going port and explore the other pots on secondary routes more easily (and quickly) */ bubble_sort_down(p_sw->up_port_groups, p_sw->up_port_groups_num); p_min_group = p_sw->up_port_groups[0]; /* Find the least loaded upgoing port in the selected group */ p_min_port = NULL; ports_num = (uint16_t) cl_ptr_vector_get_size(&p_min_group->ports); for (j = 0; j < ports_num; j++) { cl_ptr_vector_at(&p_min_group->ports, j, (void *)&p_port); if (!p_min_port) { /* first port that we're checking - use it as a port with the lowest load */ p_min_port = p_port; } else if (p_port->counter_down < p_min_port->counter_down) { /* this port is less loaded - use it as min */ p_min_port = p_port; } } /* At this point we have selected a group and port with the lowest load of downgoing routes. Set on the remote switch how to get to the target_lid - set LFT(target_lid) on the remote switch to the remote port */ p_remote_sw = p_min_group->remote_hca_or_sw.p_sw; /* Four possible cases: * * 1. is_main_path == TRUE: * - going UP(TRUE,TRUE) on selected min_group and min_port * + promoting port counter * + setting path in remote switch fwd tbl * + setting hops in remote switch on all the ports of selected group * - going UP(TRUE,FALSE) on rest of the groups, each time on port 0 * + NOT promoting port counter * + setting path in remote switch fwd tbl if it hasn't been set yet * + setting hops in remote switch on all the ports of each group * if it hasn't been set yet * * 2. is_main_path == FALSE: * - going UP(TRUE,FALSE) on ALL the groups, each time on port 0, * but only if the remote (upper) switch hasn't been already * configured for this target LID * + NOT promoting port counter * + setting path in remote switch fwd tbl if it hasn't been set yet * + setting hops in remote switch on all the ports of each group * if it hasn't been set yet */ /* covering first half of case 1, and case 3 */ if (is_main_path) { if (p_sw->is_leaf) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, " - Routing MAIN path for %s CA LID %u: %s --> %s\n", (target_lid != 0) ? "real" : "DUMMY", target_lid, tuple_to_str(p_sw->tuple), tuple_to_str(p_remote_sw->tuple)); } /* The number of downgoing routes is tracked in the p_group->counter_down p_port->counter_down counters of the group and port that belong to the lower side of the link (on switch with higher rank) */ p_min_group->counter_down++; p_min_port->counter_down++; if (p_min_group->counter_down == (p_min_group->remote_hca_or_sw.p_sw->min_counter_down + 1)) { recalculate_min_counter_down (p_min_group->remote_hca_or_sw.p_sw); } /* This LID may already be in the LFT in the reverse_hop feature is used */ /* We update the LFT only if this LID isn't already present. */ /* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */ if ((p_remote_sw->p_osm_sw->new_lft[target_lid] == OSM_NO_PATH) || ((p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH) && (current_hops + 1 < sw_get_least_hops(p_remote_sw, target_lid)))) { p_remote_sw->p_osm_sw->new_lft[target_lid] = p_min_port->remote_port_num; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s: set path to CA LID %u through port %u\n", tuple_to_str(p_remote_sw->tuple), target_lid, p_min_port->remote_port_num); /* On the remote switch that is pointed by the min_group, set hops for ALL the ports in the remote group. */ set_hops_on_remote_sw(p_min_group, target_lid, current_hops + 1, is_target_a_sw); } /* Recursion step: Assign downgoing ports by stepping up, starting on REMOTE switch. */ created_route |= fabric_route_downgoing_by_going_up(p_ftree, p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ p_sw, /* this switch - prev. position switch for the function */ target_lid, /* LID that we're routing to */ is_main_path, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ reverse_hop_credit, /* Remaining reverse_hops allowed */ reverse_hops, /* Number of reverse_hops done up to this point */ current_hops + 1); } /* What's left to do at this point: * * 1. is_main_path == TRUE: * - going UP(TRUE,FALSE) on rest of the groups, each time on port 0, * but only if the remote (upper) switch hasn't been already * configured for this target LID * + NOT promoting port counter * + setting path in remote switch fwd tbl if it hasn't been set yet * + setting hops in remote switch on all the ports of each group * if it hasn't been set yet * * 2. is_main_path == FALSE: * - going UP(TRUE,FALSE) on ALL the groups, each time on port 0, * but only if the remote (upper) switch hasn't been already * configured for this target LID * + NOT promoting port counter * + setting path in remote switch fwd tbl if it hasn't been set yet * + setting hops in remote switch on all the ports of each group * if it hasn't been set yet * * These two rules can be rephrased this way: * - foreach UP port group * + if remote switch has been set with the target LID * - skip this port group * + else * - select port 0 * - do NOT promote port counter * - set path in remote switch fwd tbl * - set hops in remote switch on all the ports of this group * - go UP(TRUE,FALSE) to the remote switch */ for (i = is_main_path ? 1 : 0; i < p_sw->up_port_groups_num; i++) { p_group = p_sw->up_port_groups[i]; p_remote_sw = p_group->remote_hca_or_sw.p_sw; /* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */ if (p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH) if (current_hops + 1 >= sw_get_least_hops(p_remote_sw, target_lid)) continue; if (p_sw->is_leaf) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, " - Routing SECONDARY path for LID %u: %s --> %s\n", target_lid, tuple_to_str(p_sw->tuple), tuple_to_str(p_remote_sw->tuple)); } /* Routing REAL lids on SECONDARY path means routing switch-to-switch or switch-to-CA paths. We can safely assume that switch will initiate very few traffic, so there's no point wasting runtime on trying to balance these routes - always pick port 0. */ p_min_port = NULL; ports_num = (uint16_t) cl_ptr_vector_get_size(&p_group->ports); if(ports_num == 0) continue; for (j = 0; j < ports_num; j++) { cl_ptr_vector_at(&p_group->ports, j, (void *)&p_port); if (!p_min_port) { /* first port that we're checking - use it as a port with the lowest load */ p_min_port = p_port; } else if (p_port->counter_down < p_min_port->counter_down) { /* this port is less loaded - use it as min */ p_min_port = p_port; } } p_port = p_min_port; p_remote_sw->p_osm_sw->new_lft[target_lid] = p_port->remote_port_num; /* On the remote switch that is pointed by the p_group, set hops for ALL the ports in the remote group. */ set_hops_on_remote_sw(p_group, target_lid, current_hops + 1, is_target_a_sw); /* Recursion step: Assign downgoing ports by stepping up, starting on REMOTE switch. */ routed = fabric_route_downgoing_by_going_up(p_ftree, p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ p_sw, /* this switch - prev. position switch for the function */ target_lid, /* LID that we're routing to */ FALSE, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ reverse_hop_credit, /* Remaining reverse_hops allowed */ reverse_hops, /* Number of reverse_hops done up to this point */ current_hops + 1); created_route |= routed; } /* Now doing the same thing with horizontal links */ if (p_sw->sibling_port_groups_num > 0) bubble_sort_down(p_sw->sibling_port_groups, p_sw->sibling_port_groups_num); for (i = 0; i < p_sw->sibling_port_groups_num; i++) { p_group = p_sw->sibling_port_groups[i]; p_remote_sw = p_group->remote_hca_or_sw.p_sw; /* skip if target lid has been already set on remote switch fwd tbl (with a bigger hop count) */ if (p_remote_sw->p_osm_sw->new_lft[target_lid] != OSM_NO_PATH) if (current_hops + 1 >= sw_get_least_hops(p_remote_sw, target_lid)) continue; if (p_sw->is_leaf) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, " - Routing SECONDARY path for LID %u: %s --> %s\n", target_lid, tuple_to_str(p_sw->tuple), tuple_to_str(p_remote_sw->tuple)); } /* Routing REAL lids on SECONDARY path means routing switch-to-switch or switch-to-CA paths. We can safely assume that switch will initiate very few traffic, so there's no point wasting runtime on trying to balance these routes - always pick port 0. */ p_min_port = NULL; ports_num = (uint16_t) cl_ptr_vector_get_size(&p_group->ports); for (j = 0; j < ports_num; j++) { cl_ptr_vector_at(&p_group->ports, j, (void *)&p_port); if (!p_min_port) { /* first port that we're checking - use it as a port with the lowest load */ p_min_port = p_port; } else if (p_port->counter_down < p_min_port->counter_down) { /* this port is less loaded - use it as min */ p_min_port = p_port; } } p_port = p_min_port; p_remote_sw->p_osm_sw->new_lft[target_lid] = p_port->remote_port_num; /* On the remote switch that is pointed by the p_group, set hops for ALL the ports in the remote group. */ set_hops_on_remote_sw(p_group, target_lid, current_hops + 1, is_target_a_sw); /* Recursion step: Assign downgoing ports by stepping up, starting on REMOTE switch. */ routed = fabric_route_downgoing_by_going_up(p_ftree, p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ p_sw, /* this switch - prev. position switch for the function */ target_lid, /* LID that we're routing to */ FALSE, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ reverse_hop_credit, /* Remaining reverse_hops allowed */ reverse_hops, /* Number of reverse_hops done up to this point */ current_hops + 1); created_route |= routed; if (routed) { p_min_group->counter_down++; p_min_port->counter_down++; } } /* If we don't have any reverse hop credits, we are done */ if (reverse_hop_credit == 0) return created_route; if (p_sw->is_leaf) return created_route; /* We explore all the down group ports */ /* We try to reverse jump for each of them */ /* They already have a route to us from the upgoing_by_going_down started earlier */ /* This is only so it'll continue exploring up, after this step backwards */ for (i = 0; i < p_sw->down_port_groups_num; i++) { p_group = p_sw->down_port_groups[i]; p_remote_sw = p_group->remote_hca_or_sw.p_sw; /* Skip this port group unless it points to a switch */ if (p_group->remote_node_type != IB_NODE_TYPE_SWITCH) continue; /* Recursion step: Assign downgoing ports by stepping up, fter doing one step down starting on REMOTE switch. */ created_route |= fabric_route_downgoing_by_going_up(p_ftree, p_remote_sw, /* remote switch - used as a route-downgoing alg. next step point */ p_sw, /* this switch - prev. position switch for the function */ target_lid, /* LID that we're routing to */ TRUE, /* whether this is path to HCA that should by tracked by counters */ is_target_a_sw, /* Whether target lid is a switch or not */ reverse_hop_credit - 1, /* Remaining reverse_hops allowed */ reverse_hops + 1, /* Number of reverse_hops done up to this point */ current_hops + 1); } return created_route; } /* ftree_fabric_route_downgoing_by_going_up() */ /***************************************************/ /* * Pseudo code: * foreach leaf switch (in indexing order) * for each compute node (in indexing order) * obtain the LID of the compute node * set local LFT(LID) of the port connecting to compute node * call assign-down-going-port-by-ascending-up(TRUE,TRUE) on CURRENT switch * for each MISSING compute node * call assign-down-going-port-by-ascending-up(FALSE,TRUE) on CURRENT switch */ static void fabric_route_to_cns(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw; ftree_hca_t *p_hca; ftree_port_group_t *p_leaf_port_group; ftree_port_group_t *p_hca_port_group; ftree_port_t *p_port; unsigned int i, j; uint16_t hca_lid; unsigned routed_targets_on_leaf; OSM_LOG_ENTER(&p_ftree->p_osm->log); /* for each leaf switch (in indexing order) */ for (i = 0; i < p_ftree->leaf_switches_num; i++) { p_sw = p_ftree->leaf_switches[i]; routed_targets_on_leaf = 0; /* for each HCA connected to this switch */ for (j = 0; j < p_sw->down_port_groups_num; j++) { p_leaf_port_group = p_sw->down_port_groups[j]; /* work with this port group only if the remote node is CA */ if (p_leaf_port_group->remote_node_type != IB_NODE_TYPE_CA) continue; p_hca = p_leaf_port_group->remote_hca_or_sw.p_hca; /* work with this port group only if remote HCA has CNs */ if (!p_hca->cn_num) continue; p_hca_port_group = hca_get_port_group_by_lid(p_hca, p_leaf_port_group-> remote_lid); CL_ASSERT(p_hca_port_group); /* work with this port group only if remote port is CN */ if (!p_hca_port_group->is_cn) continue; /* obtain the LID of HCA port */ hca_lid = p_leaf_port_group->remote_lid; /* set local LFT(LID) to the port that is connected to HCA */ cl_ptr_vector_at(&p_leaf_port_group->ports, 0, (void *)&p_port); p_sw->p_osm_sw->new_lft[hca_lid] = p_port->port_num; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s: set path to CN LID %u through port %u\n", tuple_to_str(p_sw->tuple), hca_lid, p_port->port_num); /* set local min hop table(LID) to route to the CA */ sw_set_hops(p_sw, hca_lid, p_port->port_num, 1, FALSE); /* Assign downgoing ports by stepping up. Since we're routing here only CNs, we're routing it as REAL LID and updating fat-tree balancing counters. */ fabric_route_downgoing_by_going_up(p_ftree, p_sw, /* local switch - used as a route-downgoing alg. start point */ NULL, /* prev. position switch */ hca_lid, /* LID that we're routing to */ TRUE, /* whether this path to HCA should by tracked by counters */ FALSE, /* whether target lid is a switch or not */ 0, /* Number of reverse hops allowed */ 0, /* Number of reverse hops done yet */ 1); /* Number of hops done yet */ /* count how many real targets have been routed from this leaf switch */ routed_targets_on_leaf++; } /* We're done with the real targets (all CNs) of this leaf switch. Now route the dummy HCAs that are missing or that are non-CNs. When routing to dummy HCAs we don't fill lid matrices. */ if (p_ftree->max_cn_per_leaf > routed_targets_on_leaf) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Routing %u dummy CAs\n", p_ftree->max_cn_per_leaf - p_sw->down_port_groups_num); for (j = 0; j < p_ftree->max_cn_per_leaf - routed_targets_on_leaf; j++) { ftree_sw_t *p_next_sw, *p_ftree_sw; sw_set_hops(p_sw, 0, 0xFF, 1, FALSE); /* assign downgoing ports by stepping up */ fabric_route_downgoing_by_going_up(p_ftree, p_sw, /* local switch - used as a route-downgoing alg. start point */ NULL, /* prev. position switch */ 0, /* LID that we're routing to - ignored for dummy HCA */ TRUE, /* whether this path to HCA should by tracked by counters */ FALSE, /* Whether the target LID is a switch or not */ 0, /* Number of reverse hops allowed */ 0, /* Number of reverse hops done yet */ 1); /* Number of hops done yet */ p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); /* need to clean the LID 0 hops for dummy node */ while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_ftree_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_ftree_sw->map_item); p_ftree_sw->hops[0] = OSM_NO_PATH; p_ftree_sw->p_osm_sw->new_lft[0] = OSM_NO_PATH; } } } } /* done going through all the leaf switches */ OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_route_to_cns() */ /***************************************************/ /* * Pseudo code: * foreach HCA non-CN port in fabric * obtain the LID of the HCA port * get switch that is connected to this HCA port * set switch LFT(LID) to the port connected to the HCA port * call assign-down-going-port-by-ascending-up(TRUE,TRUE) on the switch * * Routing to these HCAs is routing a REAL hca lid on MAIN path. * We want to allow load-leveling of the traffic to the non-CNs, * because such nodes may include IO nodes with heavy usage * - we should set fwd tables * - we should update port counters * Routing to non-CNs is done after routing to CNs, so updated port * counters will not affect CN-to-CN routing. */ static void fabric_route_to_non_cns(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw; ftree_hca_t *p_hca; ftree_hca_t *p_next_hca; ftree_port_t *p_hca_port; ftree_port_group_t *p_hca_port_group; uint16_t hca_lid; unsigned port_num_on_switch; unsigned i; OSM_LOG_ENTER(&p_ftree->p_osm->log); p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); for (i = 0; i < p_hca->up_port_groups_num; i++) { p_hca_port_group = p_hca->up_port_groups[i]; /* skip this port if it's CN, in which case it has been already routed */ if (p_hca_port_group->is_cn) continue; /* skip this port if it is not connected to switch */ if (p_hca_port_group->remote_node_type != IB_NODE_TYPE_SWITCH) continue; p_sw = p_hca_port_group->remote_hca_or_sw.p_sw; hca_lid = p_hca_port_group->lid; /* set switches LFT(LID) to the port that is connected to HCA */ cl_ptr_vector_at(&p_hca_port_group->ports, 0, (void *)&p_hca_port); port_num_on_switch = p_hca_port->remote_port_num; p_sw->p_osm_sw->new_lft[hca_lid] = port_num_on_switch; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s: set path to non-CN HCA LID %u through port %u\n", tuple_to_str(p_sw->tuple), hca_lid, port_num_on_switch); /* set local min hop table(LID) to route to the CA */ sw_set_hops(p_sw, hca_lid, port_num_on_switch, /* port num */ 1, FALSE); /* hops */ /* Assign downgoing ports by stepping up. We're routing REAL targets. They are not CNs and not included in the leafs array, but we treat them as MAIN path to allow load leveling, which means that the counters will be updated. */ fabric_route_downgoing_by_going_up(p_ftree, p_sw, /* local switch - used as a route-downgoing alg. start point */ NULL, /* prev. position switch */ hca_lid, /* LID that we're routing to */ TRUE, /* whether this path to HCA should by tracked by counters */ FALSE, /* Whether the target LID is a switch or not */ p_hca_port_group->is_io ? p_ftree->p_osm->subn.opt.max_reverse_hops : 0, /* Number or reverse hops allowed */ 0, /* Number or reverse hops done yet */ 1); /* Number of hops done yet */ } /* done with all the port groups of this HCA - go to next HCA */ } OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_route_to_non_cns() */ /***************************************************/ /* * Pseudo code: * foreach switch in fabric * obtain its LID * set local LFT(LID) to port 0 * call assign-down-going-port-by-ascending-up(TRUE,FALSE) on CURRENT switch * * Routing to switch is similar to routing a REAL hca lid on SECONDARY path: * - we should set fwd tables * - we should NOT update port counters */ static void fabric_route_to_switches(IN ftree_fabric_t * p_ftree) { ftree_sw_t *p_sw; ftree_sw_t *p_next_sw; OSM_LOG_ENTER(&p_ftree->p_osm->log); p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); /* set local LFT(LID) to 0 (route to itself) */ p_sw->p_osm_sw->new_lft[p_sw->lid] = 0; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s (LID %u): routing switch-to-switch paths\n", tuple_to_str(p_sw->tuple), p_sw->lid); /* set min hop table of the switch to itself */ sw_set_hops(p_sw, p_sw->lid, 0, /* port_num */ 0, TRUE); /* hops */ fabric_route_downgoing_by_going_up(p_ftree, p_sw, /* local switch - used as a route-downgoing alg. start point */ NULL, /* prev. position switch */ p_sw->lid, /* LID that we're routing to */ FALSE, /* whether this path to HCA should by tracked by counters */ TRUE, /* Whether the target LID is a switch or not */ 0, /* Number of reverse hops allowed */ 0, /* Number of reverse hops done yet */ 0); /* Number of hops done yet */ } OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_route_to_switches() */ /*************************************************** ***************************************************/ static void fabric_route_roots(IN ftree_fabric_t * p_ftree) { uint16_t lid; uint8_t port_num; osm_port_t *p_port; ftree_sw_t *p_sw; ftree_sw_t *p_leaf_sw; OSM_LOG_ENTER(&p_ftree->p_osm->log); /* * We need a switch that will accomodate all the down/up turns in * the fabric. Having these turn in a single place in the fabric * will not create credit loops. * So we need to select this switch. * The idea here is to chose leaf with the highest index. I don't * have any theory to back me up on this. It's just a general thought * that this way the switch that might be a bottleneck for many mcast * groups will be far away from the OpenSM, so it will draw the * multicast traffic away from the SM. */ p_leaf_sw = p_ftree->leaf_switches[p_ftree->leaf_switches_num-1]; /* * Now go over all the switches in the fabric that * have lower rank, and route the missing LIDs to * the selected leaf switch. * In short, this leaf switch now poses a target * for all those missing LIDs. */ for (p_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); p_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl); p_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item)) { if (p_sw->rank >= p_ftree->leaf_switch_rank) continue; for (lid = 1; lid <= p_leaf_sw->p_osm_sw->max_lid_ho; lid ++) { if (p_sw->p_osm_sw->new_lft[lid] != OSM_NO_PATH || p_leaf_sw->hops[lid] == OSM_NO_PATH) continue; p_port = osm_get_port_by_lid_ho(&p_ftree->p_osm->subn, lid); /* we're interested only in switches */ if (!p_port || !p_port->p_node->sw) continue; /* * the missing LID will be routed through the same * port that routes to the selected leaf switch */ port_num = p_sw->p_osm_sw->new_lft[p_leaf_sw->lid]; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Switch %s: setting path to LID %u " "through port %u\n", tuple_to_str(p_sw->tuple), lid, port_num); /* set local lft */ p_sw->p_osm_sw->new_lft[lid] = port_num; /* * Set local min hop table. * The distance to the target LID is a distance * to the selected leaf switch plus the distance * from the leaf to the target LID. */ sw_set_hops(p_sw, lid, port_num, p_sw->hops[p_leaf_sw->lid] + p_leaf_sw->hops[lid], TRUE); } } OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_route_roots() */ /***************************************************/ static int fabric_populate_nodes(IN ftree_fabric_t * p_ftree) { osm_node_t *p_osm_node; osm_node_t *p_next_osm_node; OSM_LOG_ENTER(&p_ftree->p_osm->log); p_next_osm_node = (osm_node_t *) cl_qmap_head(&p_ftree->p_osm->subn.node_guid_tbl); while (p_next_osm_node != (osm_node_t *) cl_qmap_end(&p_ftree->p_osm-> subn.node_guid_tbl)) { p_osm_node = p_next_osm_node; p_next_osm_node = (osm_node_t *) cl_qmap_next(&p_osm_node->map_item); switch (osm_node_get_type(p_osm_node)) { case IB_NODE_TYPE_CA: fabric_add_hca(p_ftree, p_osm_node); break; case IB_NODE_TYPE_ROUTER: break; case IB_NODE_TYPE_SWITCH: fabric_add_sw(p_ftree, p_osm_node->sw); break; default: OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0E: " "Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", cl_ntoh64(osm_node_get_node_guid(p_osm_node)), ib_get_node_type_str(osm_node_get_type (p_osm_node))); OSM_LOG_EXIT(&p_ftree->p_osm->log); return -1; } } OSM_LOG_EXIT(&p_ftree->p_osm->log); return 0; } /* fabric_populate_nodes() */ /*************************************************** ***************************************************/ static boolean_t sw_update_rank(IN ftree_sw_t * p_sw, IN uint32_t new_rank) { if (sw_ranked(p_sw) && p_sw->rank <= new_rank) return FALSE; p_sw->rank = new_rank; return TRUE; } /***************************************************/ static void rank_switches_from_leafs(IN ftree_fabric_t * p_ftree, IN cl_list_t * p_ranking_bfs_list) { ftree_sw_t *p_sw; ftree_sw_t *p_remote_sw; osm_node_t *p_node; osm_node_t *p_remote_node; osm_physp_t *p_osm_port; uint8_t i; unsigned max_rank = 0; while (!cl_is_list_empty(p_ranking_bfs_list)) { p_sw = (ftree_sw_t *) cl_list_remove_head(p_ranking_bfs_list); p_node = p_sw->p_osm_sw->p_node; /* note: skipping port 0 on switches */ for (i = 1; i < osm_node_get_num_physp(p_node); i++) { p_osm_port = osm_node_get_physp_ptr(p_node, i); if (!p_osm_port || !osm_link_is_healthy(p_osm_port)) continue; p_remote_node = osm_node_get_remote_node(p_node, i, NULL); if (!p_remote_node) continue; if (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) continue; p_remote_sw = fabric_get_sw_by_guid(p_ftree, osm_node_get_node_guid (p_remote_node)); if (!p_remote_sw) { /* remote node is not a switch */ continue; } /* if needed, rank the remote switch and add it to the BFS list */ if (sw_update_rank(p_remote_sw, p_sw->rank + 1)) { max_rank = p_remote_sw->rank; cl_list_insert_tail(p_ranking_bfs_list, p_remote_sw); } } } /* set FatTree maximal switch rank */ p_ftree->max_switch_rank = max_rank; } /* rank_switches_from_leafs() */ /***************************************************/ static int rank_leaf_switches(IN ftree_fabric_t * p_ftree, IN ftree_hca_t * p_hca, IN cl_list_t * p_ranking_bfs_list) { ftree_sw_t *p_sw; osm_node_t *p_osm_node = p_hca->p_osm_node; osm_node_t *p_remote_osm_node; osm_physp_t *p_osm_port; static uint8_t i = 0; int res = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); for (i = 0; i < osm_node_get_num_physp(p_osm_node); i++) { p_osm_port = osm_node_get_physp_ptr(p_osm_node, i); if (!p_osm_port || !osm_link_is_healthy(p_osm_port)) continue; p_remote_osm_node = osm_node_get_remote_node(p_osm_node, i, NULL); if (!p_remote_osm_node) continue; switch (osm_node_get_type(p_remote_osm_node)) { case IB_NODE_TYPE_CA: /* HCA connected directly to another HCA - not FatTree */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB0F: " "CA conected directly to another CA: " "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n", hca_get_guid_ho(p_hca), cl_ntoh64(osm_node_get_node_guid (p_remote_osm_node))); res = -1; goto Exit; case IB_NODE_TYPE_ROUTER: /* leaving this port - proceeding to the next one */ continue; case IB_NODE_TYPE_SWITCH: /* continue with this port */ break; default: OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB10: Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", cl_ntoh64(osm_node_get_node_guid (p_remote_osm_node)), ib_get_node_type_str(osm_node_get_type (p_remote_osm_node))); res = -1; goto Exit; } /* remote node is switch */ p_sw = fabric_get_sw_by_guid(p_ftree, osm_node_get_node_guid (p_osm_port->p_remote_physp-> p_node)); CL_ASSERT(p_sw); /* if needed, rank the remote switch and add it to the BFS list */ if (!sw_update_rank(p_sw, 0)) continue; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Marking rank of switch that is directly connected to CA:\n" " - CA guid : 0x%016" PRIx64 "\n" " - Switch guid: 0x%016" PRIx64 "\n" " - Switch LID : %u\n", hca_get_guid_ho(p_hca), sw_get_guid_ho(p_sw), p_sw->lid); cl_list_insert_tail(p_ranking_bfs_list, p_sw); } Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* rank_leaf_switches() */ /***************************************************/ static void sw_reverse_rank(IN cl_map_item_t * const p_map_item, IN void *context) { ftree_fabric_t *p_ftree = (ftree_fabric_t *) context; ftree_sw_t *p_sw = (ftree_sw_t * const)p_map_item; if (p_sw->rank != 0xFFFFFFFF) p_sw->rank = p_ftree->max_switch_rank - p_sw->rank; } /*************************************************** ***************************************************/ static int fabric_construct_hca_ports(IN ftree_fabric_t * p_ftree, IN ftree_hca_t * p_hca) { ftree_sw_t *p_remote_sw; osm_node_t *p_node = p_hca->p_osm_node; osm_node_t *p_remote_node; uint8_t remote_node_type; ib_net64_t remote_node_guid; osm_physp_t *p_remote_osm_port; uint8_t i; uint8_t remote_port_num; boolean_t is_cn; boolean_t is_in_cn_file; boolean_t is_io; boolean_t is_cns_file_provided = fabric_cns_provided(p_ftree); boolean_t is_ios_file_provided = fabric_ios_provided(p_ftree); int res = 0; for (i = 0; i < osm_node_get_num_physp(p_node); i++) { osm_physp_t *p_osm_port = osm_node_get_physp_ptr(p_node, i); is_io = FALSE; is_cn = TRUE; is_in_cn_file = FALSE; if (!p_osm_port || !osm_link_is_healthy(p_osm_port)) continue; if (p_hca->disconnected_ports[i]) continue; p_remote_osm_port = osm_physp_get_remote(p_osm_port); p_remote_node = osm_node_get_remote_node(p_node, i, &remote_port_num); if (!p_remote_osm_port || !p_remote_node) continue; remote_node_type = osm_node_get_type(p_remote_node); remote_node_guid = osm_node_get_node_guid(p_remote_node); switch (remote_node_type) { case IB_NODE_TYPE_ROUTER: /* leaving this port - proceeding to the next one */ continue; case IB_NODE_TYPE_CA: /* HCA connected directly to another HCA - not FatTree */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB11: " "CA conected directly to another CA: " "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node)), cl_ntoh64(remote_node_guid)); res = -1; goto Exit; case IB_NODE_TYPE_SWITCH: /* continue with this port */ break; default: OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB12: Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", cl_ntoh64(remote_node_guid), ib_get_node_type_str(remote_node_type)); res = -1; goto Exit; } /* remote node is switch */ p_remote_sw = fabric_get_sw_by_guid(p_ftree, remote_node_guid); CL_ASSERT(p_remote_sw); /* If CN file is not supplied, then all the CAs considered as Compute Nodes. Otherwise all the CAs are not CNs, and only guids that are present in the CN file will be marked as compute nodes. */ if (is_cns_file_provided == TRUE) { name_map_item_t *p_elem = (name_map_item_t *) cl_qmap_get(&p_ftree->cn_guid_tbl, cl_ntoh64(osm_physp_get_port_guid (p_osm_port))); if (p_elem == (name_map_item_t *) cl_qmap_end(&p_ftree->cn_guid_tbl)) is_cn = FALSE; else is_in_cn_file = TRUE; } if (is_in_cn_file == FALSE && is_ios_file_provided == TRUE) { name_map_item_t *p_elem = (name_map_item_t *) cl_qmap_get(&p_ftree->io_guid_tbl, cl_ntoh64(osm_physp_get_port_guid (p_osm_port))); if (p_elem != (name_map_item_t *) cl_qmap_end(&p_ftree->io_guid_tbl)) { is_io = TRUE; is_cn = FALSE; } } if (is_cn) { p_ftree->cn_num++; p_hca->cn_num++; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Marking CN port GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_osm_port))); } else if (is_io) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Marking I/O port GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_osm_port))); } else { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Marking non-CN port GUID 0x%016" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid(p_osm_port))); } p_ftree->ca_ports++; hca_add_port(p_ftree, p_hca, /* local ftree_hca object */ i, /* local port number */ remote_port_num, /* remote port number */ cl_ntoh16(osm_node_get_base_lid(p_node, i)), /* local lid */ cl_ntoh16(osm_node_get_base_lid(p_remote_node, 0)), /* remote lid */ osm_physp_get_port_guid(p_osm_port), /* local port guid */ osm_physp_get_port_guid(p_remote_osm_port), /* remote port guid */ remote_node_guid, /* remote node guid */ remote_node_type, /* remote node type */ (void *)p_remote_sw, /* remote ftree_hca/sw object */ is_cn, is_io); /* whether this port is compute node */ } Exit: return res; } /* fabric_construct_hca_ports() */ /*************************************************** ***************************************************/ static int fabric_construct_sw_ports(IN ftree_fabric_t * p_ftree, IN ftree_sw_t * p_sw) { ftree_hca_t *p_remote_hca; ftree_sw_t *p_remote_sw; osm_node_t *p_node = p_sw->p_osm_sw->p_node; osm_node_t *p_remote_node; uint16_t remote_lid; uint8_t remote_node_type; ib_net64_t remote_node_guid; osm_physp_t *p_remote_osm_port; ftree_direction_t direction; void *p_remote_hca_or_sw; uint8_t i; uint8_t remote_port_num; int res = 0; CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH); for (i = 1; i < osm_node_get_num_physp(p_node); i++) { osm_physp_t *p_osm_port = osm_node_get_physp_ptr(p_node, i); if (!p_osm_port || !osm_link_is_healthy(p_osm_port)) continue; p_remote_osm_port = osm_physp_get_remote(p_osm_port); if (!p_remote_osm_port) continue; p_remote_node = osm_node_get_remote_node(p_node, i, &remote_port_num); if (!p_remote_node) continue; /* ignore any loopback connection on switch */ if (p_node == p_remote_node) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Ignoring loopback on switch GUID 0x%016" PRIx64 ", LID %u, rank %u\n", sw_get_guid_ho(p_sw), p_sw->lid, p_sw->rank); continue; } remote_node_type = osm_node_get_type(p_remote_node); remote_node_guid = osm_node_get_node_guid(p_remote_node); switch (remote_node_type) { case IB_NODE_TYPE_ROUTER: /* leaving this port - proceeding to the next one */ continue; case IB_NODE_TYPE_CA: /* switch connected to hca */ p_remote_hca = fabric_get_hca_by_guid(p_ftree, remote_node_guid); CL_ASSERT(p_remote_hca); p_remote_hca_or_sw = (void *)p_remote_hca; direction = FTREE_DIRECTION_DOWN; remote_lid = cl_ntoh16(osm_physp_get_base_lid(p_remote_osm_port)); break; case IB_NODE_TYPE_SWITCH: /* switch connected to another switch */ p_remote_sw = fabric_get_sw_by_guid(p_ftree, remote_node_guid); CL_ASSERT(p_remote_sw); p_remote_hca_or_sw = (void *)p_remote_sw; if (p_sw->rank > p_remote_sw->rank) { direction = FTREE_DIRECTION_UP; } else if (p_sw->rank == p_remote_sw->rank) { direction = FTREE_DIRECTION_SAME; } else direction = FTREE_DIRECTION_DOWN; /* switch LID is only in port 0 port_info structure */ remote_lid = cl_ntoh16(osm_node_get_base_lid(p_remote_node, 0)); break; default: OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB13: Node GUID 0x%016" PRIx64 " - Unknown node type: %s\n", cl_ntoh64(remote_node_guid), ib_get_node_type_str(remote_node_type)); res = -1; goto Exit; } sw_add_port(p_sw, /* local ftree_sw object */ i, /* local port number */ remote_port_num, /* remote port number */ p_sw->lid, /* local lid */ remote_lid, /* remote lid */ osm_physp_get_port_guid(p_osm_port), /* local port guid */ osm_physp_get_port_guid(p_remote_osm_port), /* remote port guid */ remote_node_guid, /* remote node guid */ remote_node_type, /* remote node type */ p_remote_hca_or_sw, /* remote ftree_hca/sw object */ direction); /* port direction (up or down) */ /* Track the max lid (in host order) that exists in the fabric */ if (remote_lid > p_ftree->lft_max_lid) p_ftree->lft_max_lid = remote_lid; } Exit: return res; } /* fabric_construct_sw_ports() */ /*************************************************** ***************************************************/ struct rank_root_cxt { ftree_fabric_t *fabric; cl_list_t *list; }; /*************************************************** ***************************************************/ static int rank_root_sw_by_guid(void *cxt, uint64_t guid, char *p) { struct rank_root_cxt *c = cxt; ftree_sw_t *sw; sw = fabric_get_sw_by_guid(c->fabric, cl_hton64(guid)); if (!sw) { /* the specified root guid wasn't found in the fabric */ OSM_LOG(&c->fabric->p_osm->log, OSM_LOG_ERROR, "ERR AB24: " "Root switch GUID 0x%" PRIx64 " not found\n", guid); return 0; } OSM_LOG(&c->fabric->p_osm->log, OSM_LOG_DEBUG, "Ranking root switch with GUID 0x%" PRIx64 "\n", guid); sw->rank = 0; cl_list_insert_tail(c->list, sw); return 0; } /*************************************************** ***************************************************/ static boolean_t fabric_load_roots(IN ftree_fabric_t * p_ftree, IN cl_list_t* p_ranking_bfs_list) { struct rank_root_cxt context; unsigned num_roots; if (p_ranking_bfs_list) { /* Rank all the roots and add them to list */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Fetching root nodes from file %s\n", p_ftree->p_osm->subn.opt.root_guid_file); context.fabric = p_ftree; context.list = p_ranking_bfs_list; if (parse_node_map(p_ftree->p_osm->subn.opt.root_guid_file, rank_root_sw_by_guid, &context)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB2A: " "cannot parse root guids file \'%s\'\n", p_ftree->p_osm->subn.opt.root_guid_file); return FALSE; } num_roots = cl_list_count(p_ranking_bfs_list); if (!num_roots) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB25: " "No valid roots supplied\n"); return FALSE; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Ranked %u valid root switches\n", num_roots); } return TRUE; } /*************************************************** ***************************************************/ static int fabric_rank_from_roots(IN ftree_fabric_t * p_ftree, IN cl_list_t* p_ranking_bfs_list) { osm_node_t *p_osm_node; osm_node_t *p_remote_osm_node; osm_physp_t *p_osm_physp; ftree_sw_t *p_sw; ftree_sw_t *p_remote_sw; int res = 0; unsigned max_rank = 0; unsigned i; OSM_LOG_ENTER(&p_ftree->p_osm->log); if (!p_ranking_bfs_list) { res = -1; goto Exit; } while (!cl_is_list_empty(p_ranking_bfs_list)) { p_sw = (ftree_sw_t *) cl_list_remove_head(p_ranking_bfs_list); p_osm_node = p_sw->p_osm_sw->p_node; /* note: skipping port 0 on switches */ for (i = 1; i < osm_node_get_num_physp(p_osm_node); i++) { p_osm_physp = osm_node_get_physp_ptr(p_osm_node, i); if (!p_osm_physp || !osm_link_is_healthy(p_osm_physp)) continue; p_remote_osm_node = osm_node_get_remote_node(p_osm_node, i, NULL); if (!p_remote_osm_node) continue; if (osm_node_get_type(p_remote_osm_node) != IB_NODE_TYPE_SWITCH) continue; p_remote_sw = fabric_get_sw_by_guid(p_ftree, osm_node_get_node_guid (p_remote_osm_node)); CL_ASSERT(p_remote_sw); /* if needed, rank the remote switch and add it to the BFS list */ if (sw_update_rank(p_remote_sw, p_sw->rank + 1)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Ranking switch 0x%" PRIx64 " with rank %u\n", sw_get_guid_ho(p_remote_sw), p_remote_sw->rank); max_rank = p_remote_sw->rank; cl_list_insert_tail(p_ranking_bfs_list, p_remote_sw); } } /* done with ports of this switch - go to the next switch in the list */ } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Subnet ranking completed. Max Node Rank = %u\n", max_rank); /* set FatTree maximal switch rank */ p_ftree->max_switch_rank = max_rank; Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_rank_from_roots() */ /*************************************************** ***************************************************/ static int fabric_rank_from_hcas(IN ftree_fabric_t * p_ftree) { ftree_hca_t *p_hca; ftree_hca_t *p_next_hca; cl_list_t ranking_bfs_list; int res = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); cl_list_init(&ranking_bfs_list, 10); /* Mark REVERSED rank of all the switches in the subnet. Start from switches that are connected to hca's, and scan all the switches in the subnet. */ p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); if (rank_leaf_switches(p_ftree, p_hca, &ranking_bfs_list) != 0) { res = -1; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB14: " "Subnet ranking failed - subnet is not FatTree"); goto Exit; } } /* Now rank rest of the switches in the fabric, while the list already contains all the ranked leaf switches */ rank_switches_from_leafs(p_ftree, &ranking_bfs_list); /* fix ranking of the switches by reversing the ranking direction */ cl_qmap_apply_func(&p_ftree->sw_tbl, sw_reverse_rank, (void *)p_ftree); Exit: cl_list_destroy(&ranking_bfs_list); OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_rank_from_hcas() */ /*************************************************** * After ranking from HCA's we want to re-rank using * the roots ***************************************************/ static int fabric_rerank_using_root(IN ftree_fabric_t * p_ftree, IN cl_list_t* p_ranking_bfs_list) { ftree_sw_t *p_sw = NULL; ftree_sw_t *p_next_sw; int res; OSM_LOG_ENTER(&p_ftree->p_osm->log); p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); if (p_sw->rank == 0) cl_list_insert_tail(p_ranking_bfs_list, p_sw); else p_sw->rank = 0xFFFFFFFF; } res = fabric_rank_from_roots(p_ftree, p_ranking_bfs_list); OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /*************************************************** ***************************************************/ static int fabric_rank(IN ftree_fabric_t * p_ftree) { int res = -1; cl_list_t ranking_bfs_list; OSM_LOG_ENTER(&p_ftree->p_osm->log); cl_list_init(&ranking_bfs_list, 10); if (fabric_roots_provided(p_ftree) && fabric_load_roots(p_ftree, &ranking_bfs_list)) res = fabric_rank_from_roots(p_ftree, &ranking_bfs_list); else { res = fabric_rank_from_hcas(p_ftree); if (!res) res = fabric_rerank_using_root(p_ftree, &ranking_bfs_list); } if (res) goto Exit; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "FatTree max switch rank is %u\n", p_ftree->max_switch_rank); Exit: cl_list_destroy(&ranking_bfs_list); OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_rank() */ /*************************************************** ***************************************************/ static void fabric_set_leaf_rank(IN ftree_fabric_t * p_ftree) { unsigned i; ftree_sw_t *p_sw; ftree_hca_t *p_hca = NULL; ftree_hca_t *p_next_hca; OSM_LOG_ENTER(&p_ftree->p_osm->log); if (!fabric_roots_provided(p_ftree)) { /* If root file is not provided, the fabric has to be pure fat-tree in terms of ranking. Thus, leaf switches rank is the max rank. */ p_ftree->leaf_switch_rank = p_ftree->max_switch_rank; } else { /* Find the first CN and set the leaf_switch_rank to the rank of the switch that is connected to this CN. Later we will ensure that all the leaf switches have the same rank. */ p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; if (p_hca->cn_num) break; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); } /* we know that there are CNs in the fabric, so just to be sure... */ CL_ASSERT(p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Selected CN port GUID 0x%" PRIx64 "\n", hca_get_guid_ho(p_hca)); for (i = 0; (i < p_hca->up_port_groups_num) && (!p_hca->up_port_groups[i]->is_cn); i++) ; CL_ASSERT(i < p_hca->up_port_groups_num); CL_ASSERT(p_hca->up_port_groups[i]->remote_node_type == IB_NODE_TYPE_SWITCH); p_sw = p_hca->up_port_groups[i]->remote_hca_or_sw.p_sw; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Selected leaf switch GUID 0x%" PRIx64 ", rank %u\n", sw_get_guid_ho(p_sw), p_sw->rank); p_ftree->leaf_switch_rank = p_sw->rank; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "FatTree leaf switch rank is %u\n", p_ftree->leaf_switch_rank); OSM_LOG_EXIT(&p_ftree->p_osm->log); } /* fabric_set_leaf_rank() */ /*************************************************** ***************************************************/ static int fabric_populate_ports(IN ftree_fabric_t * p_ftree) { ftree_hca_t *p_hca; ftree_hca_t *p_next_hca; ftree_sw_t *p_sw; ftree_sw_t *p_next_sw; int res = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); p_next_hca = (ftree_hca_t *) cl_qmap_head(&p_ftree->hca_tbl); while (p_next_hca != (ftree_hca_t *) cl_qmap_end(&p_ftree->hca_tbl)) { p_hca = p_next_hca; p_next_hca = (ftree_hca_t *) cl_qmap_next(&p_hca->map_item); if (fabric_construct_hca_ports(p_ftree, p_hca) != 0) { res = -1; goto Exit; } } p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); if (fabric_construct_sw_ports(p_ftree, p_sw) != 0) { res = -1; goto Exit; } } Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return res; } /* fabric_populate_ports() */ /*************************************************** ***************************************************/ static int add_guid_item_to_map(void *cxt, uint64_t guid, char *p) { cl_qmap_t *map = cxt; name_map_item_t *item; item = malloc(sizeof(*item)); if (!item) return -1; item->guid = guid; cl_qmap_insert(map, guid, &item->item); return 0; } static int fabric_read_guid_files(IN ftree_fabric_t * p_ftree) { int status = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); if (fabric_cns_provided(p_ftree)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Fetching compute nodes from file %s\n", p_ftree->p_osm->subn.opt.cn_guid_file); if (parse_node_map(p_ftree->p_osm->subn.opt.cn_guid_file, add_guid_item_to_map, &p_ftree->cn_guid_tbl)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB23: " "Problem parsing CN guid file\n"); status = -1; goto Exit; } if (!cl_qmap_count(&p_ftree->cn_guid_tbl)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB27: " "Compute node guids file has no valid guids\n"); status = -1; goto Exit; } } if (fabric_ios_provided(p_ftree)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Fetching I/O nodes from file %s\n", p_ftree->p_osm->subn.opt.io_guid_file); if (parse_node_map(p_ftree->p_osm->subn.opt.io_guid_file, add_guid_item_to_map, &p_ftree->io_guid_tbl)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB28: Problem parsing I/O guid file\n"); status = -1; goto Exit; } if (!cl_qmap_count(&p_ftree->io_guid_tbl)) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB29: " "I/O node guids file has no valid guids\n"); status = -1; goto Exit; } } Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return status; } /*fabric_read_guid_files() */ /*************************************************** ***************************************************/ /* Get a Sw and remove all depended HCA's, meaning all * HCA's which this is the only switch they are connected * to */ static int remove_depended_hca(IN ftree_fabric_t *p_ftree, IN ftree_sw_t *p_sw) { ftree_hca_t *p_hca; int counter = 0; int port_num; uint8_t remote_port_num; osm_physp_t* physp; osm_node_t* sw_node; uint64_t remote_hca_guid; sw_node = p_sw->p_osm_sw->p_node; for (port_num = 0; port_num < sw_node->physp_tbl_size; port_num++) { physp = osm_node_get_physp_ptr(sw_node, port_num); if (physp && physp->p_remote_physp) { if (osm_node_get_type(physp->p_remote_physp->p_node) == IB_NODE_TYPE_CA) { remote_hca_guid = osm_node_get_node_guid(physp->p_remote_physp->p_node); p_hca = fabric_get_hca_by_guid(p_ftree, remote_hca_guid); if (!p_hca) continue; remote_port_num = osm_physp_get_port_num(physp->p_remote_physp); p_hca->disconnected_ports[remote_port_num] = 1; } } } return counter; } /*************************************************** ***************************************************/ static void fabric_remove_unranked_sw(IN ftree_fabric_t *p_ftree) { ftree_sw_t *p_sw = NULL; ftree_sw_t *p_next_sw; int removed_hca; int count = 0; p_next_sw = (ftree_sw_t *) cl_qmap_head(&p_ftree->sw_tbl); while (p_next_sw != (ftree_sw_t *) cl_qmap_end(&p_ftree->sw_tbl)) { p_sw = p_next_sw; p_next_sw = (ftree_sw_t *) cl_qmap_next(&p_sw->map_item); if (!sw_ranked(p_sw)) { cl_qmap_remove_item(&p_ftree->sw_tbl,&p_sw->map_item); removed_hca = remove_depended_hca(p_ftree, p_sw); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Removing Unranked sw 0x%" PRIx64 " (with %d dependent hca's)\n", sw_get_guid_ho(p_sw),removed_hca); sw_destroy(p_sw); count++; } } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_DEBUG, "Removed %d invalid switches\n", count); } /*************************************************** ***************************************************/ static int construct_fabric(IN void *context) { ftree_fabric_t *p_ftree = context; int status = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); fabric_clear(p_ftree); if (p_ftree->p_osm->subn.opt.lmc > 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "LMC > 0 is not supported by fat-tree routing.\n" "Falling back to default routing\n"); status = -1; goto Exit; } if (cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl) < 2) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric has %u switches - topology is not fat-tree.\n" "Falling back to default routing\n", cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)); status = -1; goto Exit; } if ((cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl) - cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)) < 2) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric has %u nodes (%u switches) - topology is not fat-tree.\n" "Falling back to default routing\n", cl_qmap_count(&p_ftree->p_osm->subn.node_guid_tbl), cl_qmap_count(&p_ftree->p_osm->subn.sw_guid_tbl)); status = -1; goto Exit; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "\n" " |----------------------------------------|\n" " |- Starting FatTree fabric construction -|\n" " |----------------------------------------|\n\n"); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Populating FatTree Switch and CA tables\n"); if (fabric_populate_nodes(p_ftree) != 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric topology is not fat-tree - " "falling back to default routing\n"); status = -1; goto Exit; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Reading guid files provided by user\n"); if (fabric_read_guid_files(p_ftree) != 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Failed reading guid files - " "falling back to default routing\n"); status = -1; goto Exit; } if (cl_qmap_count(&p_ftree->hca_tbl) < 2) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric has %u CAs - topology is not fat-tree.\n" "Falling back to default routing\n", cl_qmap_count(&p_ftree->hca_tbl)); status = -1; goto Exit; } /* Rank all the switches in the fabric. After that we will know only fabric max switch rank. We will be able to check leaf switches rank and the whole tree rank after filling ports and marking CNs. */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Ranking FatTree\n"); if (fabric_rank(p_ftree) != 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Failed ranking the tree\n"); status = -1; goto Exit; } fabric_remove_unranked_sw(p_ftree); if (p_ftree->max_switch_rank == 0 && cl_qmap_count(&p_ftree->sw_tbl) > 1) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_ERROR, "ERR AB2B: Found more than one root on fabric with " "maximum rank 0\n"); status = -1; goto Exit; } /* For each hca and switch, construct array of ports. This is done after the whole FatTree data structure is ready, because we want the ports to have pointers to ftree_{sw,hca}_t objects, and we need the switches to be already ranked because that's how the port direction is determined. */ OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Populating CA & switch ports\n"); if (fabric_populate_ports(p_ftree) != 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric topology is not a fat-tree\n"); status = -1; goto Exit; } else if (p_ftree->cn_num == 0) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric has no valid compute nodes\n"); status = -1; goto Exit; } /* Now that the CA ports have been created and CNs were marked, we can complete the fabric ranking - set leaf switches rank. */ fabric_set_leaf_rank(p_ftree); if (fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK || fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric rank is %u (should be between %u and %u)\n", fabric_get_rank(p_ftree), FAT_TREE_MIN_RANK, FAT_TREE_MAX_RANK); status = -1; goto Exit; } /* Mark all the switches in the fabric with rank equal to p_ftree->leaf_switch_rank and that are also connected to CNs. As a by-product, this function also runs basic topology validation - it checks that all the CNs are at the same rank. */ if (fabric_mark_leaf_switches(p_ftree)) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric topology is not a fat-tree\n"); status = -1; goto Exit; } /* Assign index to all the switches in the fabric. This function also sorts leaf switch array by the switch index, sorts all the port arrays of the indexed switches by remote switch index, and creates switch-by-tuple table (sw_by_tuple_tbl) */ fabric_make_indexing(p_ftree); /* Create leaf switch array sorted by index. This array contains switches with rank equal to p_ftree->leaf_switch_rank and that are also connected to CNs (REAL leafs), and it may contain switches at the same leaf rank w/o CNs, if this is the order of indexing. In any case, the first and the last switches in the array are REAL leafs. */ if (fabric_create_leaf_switch_array(p_ftree)) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric topology is not a fat-tree\n"); status = -1; goto Exit; } /* calculate and set ftree.max_cn_per_leaf field */ fabric_set_max_cn_per_leaf(p_ftree); /* print general info about fabric topology */ fabric_dump_general_info(p_ftree); /* dump full tree topology */ if (OSM_LOG_IS_ACTIVE_V2(&p_ftree->p_osm->log, OSM_LOG_DEBUG)) fabric_dump(p_ftree); /* the fabric is required to be PURE fat-tree only if the root guid file hasn't been provided by user */ if (!fabric_roots_provided(p_ftree) && !fabric_validate_topology(p_ftree)) { osm_log_v2(&p_ftree->p_osm->log, OSM_LOG_INFO, FILE_ID, "Fabric topology is not a fat-tree\n"); status = -1; goto Exit; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Max LID in switch LFTs: %u\n", p_ftree->lft_max_lid); /* Build the full lid matrices needed for multicast routing */ osm_ucast_mgr_build_lid_matrices(&p_ftree->p_osm->sm.ucast_mgr); Exit: if (status != 0) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Clearing FatTree Fabric data structures\n"); fabric_clear(p_ftree); } else p_ftree->fabric_built = TRUE; OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "\n" " |--------------------------------------------------|\n" " |- Done constructing FatTree fabric (status = %d) -|\n" " |--------------------------------------------------|\n\n", status); OSM_LOG_EXIT(&p_ftree->p_osm->log); return status; } /* construct_fabric() */ /*************************************************** ***************************************************/ static int do_routing(IN void *context) { ftree_fabric_t *p_ftree = context; int status = 0; OSM_LOG_ENTER(&p_ftree->p_osm->log); if (!p_ftree->fabric_built) { status = -1; goto Exit; } OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Starting FatTree routing\n"); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Filling switch forwarding tables for Compute Nodes\n"); fabric_route_to_cns(p_ftree); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Filling switch forwarding tables for non-CN targets\n"); fabric_route_to_non_cns(p_ftree); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Filling switch forwarding tables for switch-to-switch paths\n"); fabric_route_to_switches(p_ftree); if (p_ftree->p_osm->subn.opt.connect_roots) { OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "Connecting switches that are unreachable within " "Up/Down rules\n"); fabric_route_roots(p_ftree); } /* for each switch, set its fwd table */ cl_qmap_apply_func(&p_ftree->sw_tbl, set_sw_fwd_table, (void *)p_ftree); /* write out hca ordering file */ fabric_dump_hca_ordering(p_ftree); OSM_LOG(&p_ftree->p_osm->log, OSM_LOG_VERBOSE, "FatTree routing is done\n"); Exit: OSM_LOG_EXIT(&p_ftree->p_osm->log); return status; } /*************************************************** ***************************************************/ static void delete(IN void *context) { if (!context) return; fabric_destroy((ftree_fabric_t *) context); } /*************************************************** ***************************************************/ int osm_ucast_ftree_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm) { ftree_fabric_t *p_ftree = fabric_create(); if (!p_ftree) return -1; p_ftree->p_osm = p_osm; p_ftree->p_subn = p_osm->sm.ucast_mgr.p_subn; r->context = (void *)p_ftree; r->build_lid_matrices = construct_fabric; r->ucast_build_fwd_tables = do_routing; r->destroy = delete; return 0; } opensm-3.3.20/opensm/osm_torus.c0000644000205000001450000101015012315102466013505 00000000000000/* * Copyright 2009 Sandia Corporation. Under the terms of Contract * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains * certain rights in this software. * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (c) 2010-2012 Mellanox Technologies LTD. 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. * */ /* for getline() in stdio.h */ #define _GNU_SOURCE #include #include #include #include #include #include #include #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #define FILE_ID OSM_FILE_TORUS_C #include #include #include #include #include #define TORUS_MAX_DIM 3 #define PORTGRP_MAX_PORTS 16 #define SWITCH_MAX_PORTGRPS (1 + 2 * TORUS_MAX_DIM) #define DEFAULT_MAX_CHANGES 32 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) typedef ib_net64_t guid_t; /* * An endpoint terminates a link, and is one of three types: * UNKNOWN - Uninitialized endpoint. * SRCSINK - generates or consumes traffic, and thus has an associated LID; * i.e. a CA or router port. * PASSTHRU - Has no associated LID; i.e. a switch port. * * If it is possible to communicate in-band with a switch, it will require * a port with a GUID in the switch to source/sink that traffic, but there * will be no attached link. This code assumes there is only one such port. * * Here is an endpoint taxonomy: * * type == SRCSINK * link == pointer to a valid struct link * ==> This endpoint is a CA or router port connected via a link to * either a switch or another CA/router. Thus: * n_id ==> identifies the CA/router node GUID * sw ==> NULL * port ==> identifies the port on the CA/router this endpoint uses * pgrp ==> NULL * * type == SRCSINK * link == NULL pointer * ==> This endpoint is the switch port used for in-band communication * with the switch itself. Thus: * n_id ==> identifies the node GUID used to talk to the switch * containing this endpoint * sw ==> pointer to valid struct switch containing this endpoint * port ==> identifies the port on the switch this endpoint uses * pgrp ==> NULL, or pointer to the valid struct port_grp holding * the port in a t_switch. * * type == PASSTHRU * link == pointer to valid struct link * ==> This endpoint is a switch port connected via a link to either * another switch or a CA/router. Thus: * n_id ==> identifies the node GUID used to talk to the switch * containing this endpoint - since each switch is assumed * to have only one in-band communication port, this is a * convenient unique name for the switch itself. * sw ==> pointer to valid struct switch containing this endpoint, * or NULL, in the case of a fabric link that has been * disconnected after being transferred to a torus link. * port ==> identifies the port on the switch this endpoint uses. * Note that in the special case of the coordinate direction * links, the port value is -1, as those links aren't * really connected to anything. * pgrp ==> NULL, or pointer to the valid struct port_grp holding * the port in a t_switch. */ enum endpt_type { UNKNOWN = 0, SRCSINK, PASSTHRU }; struct torus; struct t_switch; struct port_grp; struct endpoint { enum endpt_type type; int port; guid_t n_id; /* IBA node GUID */ void *sw; /* void* can point to either switch type */ struct link *link; struct port_grp *pgrp; void *tmp; /* * Note: osm_port is only guaranteed to contain a valid pointer * when the call stack contains torus_build_lfts() or * osm_port_relink_endpoint(). * * Otherwise, the opensm core could have deleted an osm_port object * without notifying us, invalidating the pointer we hold. * * When presented with a pointer to an osm_port_t, it is generally * safe and required to cast osm_port_t:priv to struct endpoint, and * check that the endpoint's osm_port is the same as the original * osm_port_t pointer. Failure to do so means that invalidated * pointers will go undetected. */ struct osm_port *osm_port; }; struct link { struct endpoint end[2]; }; /* * A port group is a collection of endpoints on a switch that share certain * characteristics. All the endpoints in a port group must have the same * type. Furthermore, if that type is PASSTHRU, then the connected links: * 1) are parallel to a given coordinate direction * 2) share the same two switches as endpoints. * * Torus-2QoS uses one master spanning tree for multicast, of which every * multicast group spanning tree is a subtree. to_stree_root is a pointer * to the next port_grp on the path to the master spanning tree root. * to_stree_tip is a pointer to the next port_grp on the path to a master * spanning tree branch tip. * * Each t_switch can have at most one port_grp with a non-NULL to_stree_root. * Exactly one t_switch in the fabric will have all port_grp objects with * to_stree_root NULL; it is the master spanning tree root. * * A t_switch with all port_grp objects where to_stree_tip is NULL is at a * master spanning tree branch tip. */ struct port_grp { enum endpt_type type; size_t port_cnt; /* number of attached ports in group */ size_t port_grp; /* what switch port_grp we're in */ unsigned sw_dlid_cnt; /* switch dlids routed through this group */ unsigned ca_dlid_cnt; /* CA dlids routed through this group */ struct t_switch *sw; /* what switch we're attached to */ struct port_grp *to_stree_root; struct port_grp *to_stree_tip; struct endpoint **port; }; /* * A struct t_switch is used to represent a switch as placed in a torus. * * A t_switch used to build an N-dimensional torus will have 2N+1 port groups, * used as follows, assuming 0 <= d < N: * port_grp[2d] => links leaving in negative direction for coordinate d * port_grp[2d+1] => links leaving in positive direction for coordinate d * port_grp[2N] => endpoints local to switch; i.e., hosts on switch * * struct link objects referenced by a t_switch are assumed to be oriented: * traversing a link from link.end[0] to link.end[1] is always in the positive * coordinate direction. */ struct t_switch { guid_t n_id; /* IBA node GUID */ int i, j, k; unsigned port_cnt; /* including management port */ struct torus *torus; void *tmp; /* * Note: osm_switch is only guaranteed to contain a valid pointer * when the call stack contains torus_build_lfts(). * * Otherwise, the opensm core could have deleted an osm_switch object * without notifying us, invalidating the pointer we hold. * * When presented with a pointer to an osm_switch_t, it is generally * safe and required to cast osm_switch_t:priv to struct t_switch, and * check that the switch's osm_switch is the same as the original * osm_switch_t pointer. Failure to do so means that invalidated * pointers will go undetected. */ struct osm_switch *osm_switch; struct port_grp ptgrp[SWITCH_MAX_PORTGRPS]; struct endpoint **port; }; /* * We'd like to be able to discover the torus topology in a pile of switch * links if we can. We'll use a struct f_switch to store raw topology for a * fabric description, then contruct the torus topology from struct t_switch * objects as we process the fabric and recover it. */ struct f_switch { guid_t n_id; /* IBA node GUID */ unsigned port_cnt; /* including management port */ void *tmp; /* * Same rules apply here as for a struct t_switch member osm_switch. */ struct osm_switch *osm_switch; struct endpoint **port; }; struct fabric { osm_opensm_t *osm; unsigned ca_cnt; unsigned link_cnt; unsigned switch_cnt; unsigned link_cnt_max; unsigned switch_cnt_max; struct link **link; struct f_switch **sw; }; struct coord_dirs { /* * These links define the coordinate directions for the torus. * They are duplicates of links connected to switches. Each of * these links must connect to a common switch. * * In the event that a failed switch was specified as one of these * link endpoints, our algorithm would not be able to find the * torus in the fabric. So, we'll allow multiple instances of * this in the config file to allow improved resiliency. */ struct link xm_link, ym_link, zm_link; struct link xp_link, yp_link, zp_link; /* * A torus dimension has coordinate values 0, 1, ..., radix - 1. * The dateline, where we need to change VLs to avoid credit loops, * for a torus dimension is always between coordinate values * radix - 1 and 0. The following specify the dateline location * relative to the coordinate links shared switch location. * * E.g. if the shared switch is at 0,0,0, the following are all * zero; if the shared switch is at 1,1,1, the following are all * -1, etc. * * Since our SL/VL assignment for a path depends on the position * of the path endpoints relative to the torus datelines, we need * this information to keep SL/VL assignment constant in the event * one of the switches used to specify coordinate directions fails. */ int x_dateline, y_dateline, z_dateline; }; struct torus { osm_opensm_t *osm; unsigned ca_cnt; unsigned link_cnt; unsigned switch_cnt; unsigned seed_cnt, seed_idx; unsigned x_sz, y_sz, z_sz; unsigned port_order[IB_NODE_NUM_PORTS_MAX+1]; unsigned sw_pool_sz; unsigned link_pool_sz; unsigned seed_sz; unsigned portgrp_sz; /* max ports for port groups in this torus */ struct fabric *fabric; struct t_switch **sw_pool; struct link *link_pool; struct coord_dirs *seed; struct t_switch ****sw; struct t_switch *master_stree_root; unsigned flags; unsigned max_changes; int debug; }; /* * Bits to use in torus.flags */ #define X_MESH (1U << 0) #define Y_MESH (1U << 1) #define Z_MESH (1U << 2) #define MSG_DEADLOCK (1U << 29) #define NOTIFY_CHANGES (1U << 30) #define ALL_MESH(flags) \ ((flags & (X_MESH | Y_MESH | Z_MESH)) == (X_MESH | Y_MESH | Z_MESH)) struct torus_context { osm_opensm_t *osm; struct torus *torus; struct fabric fabric; }; static void teardown_fabric(struct fabric *f) { unsigned l, p, s; struct endpoint *port; struct f_switch *sw; if (!f) return; if (f->sw) { /* * Need to free switches, and also find/free the endpoints * we allocated for switch management ports. */ for (s = 0; s < f->switch_cnt; s++) { sw = f->sw[s]; if (!sw) continue; for (p = 0; p < sw->port_cnt; p++) { port = sw->port[p]; if (port && !port->link) free(port); /* management port */ } free(sw); } free(f->sw); } if (f->link) { for (l = 0; l < f->link_cnt; l++) if (f->link[l]) free(f->link[l]); free(f->link); } memset(f, 0, sizeof(*f)); } void teardown_torus(struct torus *t) { unsigned p, s; struct endpoint *port; struct t_switch *sw; if (!t) return; if (t->sw_pool) { /* * Need to free switches, and also find/free the endpoints * we allocated for switch management ports. */ for (s = 0; s < t->switch_cnt; s++) { sw = t->sw_pool[s]; if (!sw) continue; for (p = 0; p < sw->port_cnt; p++) { port = sw->port[p]; if (port && !port->link) free(port); /* management port */ } free(sw); } free(t->sw_pool); } if (t->link_pool) free(t->link_pool); if (t->sw) free(t->sw); if (t->seed) free(t->seed); free(t); } static struct torus_context *torus_context_create(osm_opensm_t *osm) { struct torus_context *ctx; ctx = calloc(1, sizeof(*ctx)); if (ctx) ctx->osm = osm; else OSM_LOG(&osm->log, OSM_LOG_ERROR, "ERR 4E01: calloc: %s\n", strerror(errno)); return ctx; } static void torus_context_delete(void *context) { struct torus_context *ctx = context; teardown_fabric(&ctx->fabric); if (ctx->torus) teardown_torus(ctx->torus); free(ctx); } static bool grow_seed_array(struct torus *t, int new_seeds) { unsigned cnt; void *ptr; cnt = t->seed_cnt + new_seeds; if (cnt > t->seed_sz) { cnt += 2 + cnt / 2; ptr = realloc(t->seed, cnt * sizeof(*t->seed)); if (!ptr) return false; t->seed = ptr; t->seed_sz = cnt; memset(&t->seed[t->seed_cnt], 0, (cnt - t->seed_cnt) * sizeof(*t->seed)); } return true; } static struct f_switch *find_f_sw(struct fabric *f, guid_t sw_guid) { unsigned s; struct f_switch *sw; if (f->sw) { for (s = 0; s < f->switch_cnt; s++) { sw = f->sw[s]; if (sw->n_id == sw_guid) return sw; } } return NULL; } static struct link *find_f_link(struct fabric *f, guid_t guid0, int port0, guid_t guid1, int port1) { unsigned l; struct link *link; if (f->link) { for (l = 0; l < f->link_cnt; l++) { link = f->link[l]; if ((link->end[0].n_id == guid0 && link->end[0].port == port0 && link->end[1].n_id == guid1 && link->end[1].port == port1) || (link->end[0].n_id == guid1 && link->end[0].port == port1 && link->end[1].n_id == guid0 && link->end[1].port == port0)) return link; } } return NULL; } static struct f_switch *alloc_fswitch(struct fabric *f, guid_t sw_id, unsigned port_cnt) { size_t new_sw_sz; unsigned cnt_max; struct f_switch *sw = NULL; void *ptr; if (f->switch_cnt >= f->switch_cnt_max) { cnt_max = 16 + 5 * f->switch_cnt_max / 4; ptr = realloc(f->sw, cnt_max * sizeof(*f->sw)); if (!ptr) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E02: realloc: %s\n", strerror(errno)); goto out; } f->sw = ptr; f->switch_cnt_max = cnt_max; memset(&f->sw[f->switch_cnt], 0, (f->switch_cnt_max - f->switch_cnt)*sizeof(*f->sw)); } new_sw_sz = sizeof(*sw) + port_cnt * sizeof(*sw->port); sw = calloc(1, new_sw_sz); if (!sw) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E03: calloc: %s\n", strerror(errno)); goto out; } sw->port = (void *)(sw + 1); sw->n_id = sw_id; sw->port_cnt = port_cnt; f->sw[f->switch_cnt++] = sw; out: return sw; } static struct link *alloc_flink(struct fabric *f) { unsigned cnt_max; struct link *l = NULL; void *ptr; if (f->link_cnt >= f->link_cnt_max) { cnt_max = 16 + 5 * f->link_cnt_max / 4; ptr = realloc(f->link, cnt_max * sizeof(*f->link)); if (!ptr) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E04: realloc: %s\n", strerror(errno)); goto out; } f->link = ptr; f->link_cnt_max = cnt_max; memset(&f->link[f->link_cnt], 0, (f->link_cnt_max - f->link_cnt) * sizeof(*f->link)); } l = calloc(1, sizeof(*l)); if (!l) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E05: calloc: %s\n", strerror(errno)); goto out; } f->link[f->link_cnt++] = l; out: return l; } /* * Caller must ensure osm_port points to a valid port which contains * a valid osm_physp_t pointer for port 0, the switch management port. */ static bool build_sw_endpoint(struct fabric *f, osm_port_t *osm_port) { int sw_port; guid_t sw_guid; struct osm_switch *osm_sw; struct f_switch *sw; struct endpoint *ep; bool success = false; sw_port = osm_physp_get_port_num(osm_port->p_physp); sw_guid = osm_node_get_node_guid(osm_port->p_node); osm_sw = osm_port->p_node->sw; /* * The switch must already exist. */ sw = find_f_sw(f, sw_guid); if (!sw) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E06: missing switch w/GUID 0x%04"PRIx64"\n", cl_ntoh64(sw_guid)); goto out; } /* * The endpoint may already exist. */ if (sw->port[sw_port]) { if (sw->port[sw_port]->n_id == sw_guid) { ep = sw->port[sw_port]; goto success; } else OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E07: switch port %d has id " "0x%04"PRIx64", expected 0x%04"PRIx64"\n", sw_port, cl_ntoh64(sw->port[sw_port]->n_id), cl_ntoh64(sw_guid)); goto out; } ep = calloc(1, sizeof(*ep)); if (!ep) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E08: allocating endpoint: %s\n", strerror(errno)); goto out; } ep->type = SRCSINK; ep->port = sw_port; ep->n_id = sw_guid; ep->link = NULL; ep->sw = sw; sw->port[sw_port] = ep; success: /* * Fabric objects are temporary, so don't set osm_sw/osm_port priv * pointers using them. Wait until torus objects get constructed. */ sw->osm_switch = osm_sw; ep->osm_port = osm_port; success = true; out: return success; } static bool build_ca_link(struct fabric *f, osm_port_t *osm_port_ca, guid_t sw_guid, int sw_port) { int ca_port; guid_t ca_guid; struct link *l; struct f_switch *sw; bool success = false; ca_port = osm_physp_get_port_num(osm_port_ca->p_physp); ca_guid = osm_node_get_node_guid(osm_port_ca->p_node); /* * The link may already exist. */ l = find_f_link(f, sw_guid, sw_port, ca_guid, ca_port); if (l) { success = true; goto out; } /* * The switch must already exist. */ sw = find_f_sw(f, sw_guid); if (!sw) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E09: missing switch w/GUID 0x%04"PRIx64"\n", cl_ntoh64(sw_guid)); goto out; } l = alloc_flink(f); if (!l) goto out; l->end[0].type = PASSTHRU; l->end[0].port = sw_port; l->end[0].n_id = sw_guid; l->end[0].sw = sw; l->end[0].link = l; sw->port[sw_port] = &l->end[0]; l->end[1].type = SRCSINK; l->end[1].port = ca_port; l->end[1].n_id = ca_guid; l->end[1].sw = NULL; /* Correct for a CA */ l->end[1].link = l; /* * Fabric objects are temporary, so don't set osm_sw/osm_port priv * pointers using them. Wait until torus objects get constructed. */ l->end[1].osm_port = osm_port_ca; ++f->ca_cnt; success = true; out: return success; } static bool build_link(struct fabric *f, guid_t sw_guid0, int sw_port0, guid_t sw_guid1, int sw_port1) { struct link *l; struct f_switch *sw0, *sw1; bool success = false; /* * The link may already exist. */ l = find_f_link(f, sw_guid0, sw_port0, sw_guid1, sw_port1); if (l) { success = true; goto out; } /* * The switches must already exist. */ sw0 = find_f_sw(f, sw_guid0); if (!sw0) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E0A: missing switch w/GUID 0x%04"PRIx64"\n", cl_ntoh64(sw_guid0)); goto out; } sw1 = find_f_sw(f, sw_guid1); if (!sw1) { OSM_LOG(&f->osm->log, OSM_LOG_ERROR, "ERR 4E0B: missing switch w/GUID 0x%04"PRIx64"\n", cl_ntoh64(sw_guid1)); goto out; } l = alloc_flink(f); if (!l) goto out; l->end[0].type = PASSTHRU; l->end[0].port = sw_port0; l->end[0].n_id = sw_guid0; l->end[0].sw = sw0; l->end[0].link = l; sw0->port[sw_port0] = &l->end[0]; l->end[1].type = PASSTHRU; l->end[1].port = sw_port1; l->end[1].n_id = sw_guid1; l->end[1].sw = sw1; l->end[1].link = l; sw1->port[sw_port1] = &l->end[1]; success = true; out: return success; } static bool parse_size(unsigned *tsz, unsigned *tflags, unsigned mask, const char *parse_sep) { char *val, *nextchar; val = strtok(NULL, parse_sep); if (!val) return false; *tsz = strtoul(val, &nextchar, 0); if (*tsz) { if (*nextchar == 't' || *nextchar == 'T') *tflags &= ~mask; else if (*nextchar == 'm' || *nextchar == 'M') *tflags |= mask; /* * A torus of radix two is also a mesh of radix two * with multiple links between switches in that direction. * * Make it so always, otherwise the failure case routing * logic gets confused. */ if (*tsz == 2) *tflags |= mask; } return true; } static bool parse_torus(struct torus *t, const char *parse_sep) { unsigned i, j, k, cnt; char *ptr; bool success = false; /* * There can be only one. Ignore the imposters. */ if (t->sw_pool) goto out; if (!parse_size(&t->x_sz, &t->flags, X_MESH, parse_sep)) goto out; if (!parse_size(&t->y_sz, &t->flags, Y_MESH, parse_sep)) goto out; if (!parse_size(&t->z_sz, &t->flags, Z_MESH, parse_sep)) goto out; /* * Set up a linear array of switch pointers big enough to hold * all expected switches. */ t->sw_pool_sz = t->x_sz * t->y_sz * t->z_sz; t->sw_pool = calloc(t->sw_pool_sz, sizeof(*t->sw_pool)); if (!t->sw_pool) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E0C: Torus switch array calloc: %s\n", strerror(errno)); goto out; } /* * Set things up so that t->sw[i][j][k] can point to the i,j,k switch. */ cnt = t->x_sz * (1 + t->y_sz * (1 + t->z_sz)); t->sw = malloc(cnt * sizeof(void *)); if (!t->sw) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E0D: Torus switch array malloc: %s\n", strerror(errno)); goto out; } ptr = (void *)(t->sw); ptr += t->x_sz * sizeof(void *); for (i = 0; i < t->x_sz; i++) { t->sw[i] = (void *)ptr; ptr += t->y_sz * sizeof(void *); } for (i = 0; i < t->x_sz; i++) for (j = 0; j < t->y_sz; j++) { t->sw[i][j] = (void *)ptr; ptr += t->z_sz * sizeof(void *); } for (i = 0; i < t->x_sz; i++) for (j = 0; j < t->y_sz; j++) for (k = 0; k < t->z_sz; k++) t->sw[i][j][k] = NULL; success = true; out: return success; } static bool parse_unsigned(unsigned *result, const char *parse_sep) { char *val, *nextchar; val = strtok(NULL, parse_sep); if (!val) return false; *result = strtoul(val, &nextchar, 0); return true; } static bool parse_port_order(struct torus *t, const char *parse_sep) { unsigned i, j, k, n; for (i = 0; i < ARRAY_SIZE(t->port_order); i++) { if (!parse_unsigned(&(t->port_order[i]), parse_sep)) break; for (j = 0; j < i; j++) { if (t->port_order[j] == t->port_order[i]) { OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Ignored duplicate port %u in" " port_order parsing\n", t->port_order[j]); i--; /* Ignore duplicate port number */ break; } } } n = i; for (j = 0; j < ARRAY_SIZE(t->port_order); j++) { for (k = 0; k < i; k++) if (t->port_order[k] == j) break; if (k >= i) t->port_order[n++] = j; } return true; } static bool parse_guid(struct torus *t, guid_t *guid, const char *parse_sep) { char *val; bool success = false; val = strtok(NULL, parse_sep); if (!val) goto out; *guid = strtoull(val, NULL, 0); *guid = cl_hton64(*guid); success = true; out: return success; } static bool parse_dir_link(int c_dir, struct torus *t, const char *parse_sep) { guid_t sw_guid0, sw_guid1; struct link *l; bool success = false; if (!parse_guid(t, &sw_guid0, parse_sep)) goto out; if (!parse_guid(t, &sw_guid1, parse_sep)) goto out; if (!t) { success = true; goto out; } switch (c_dir) { case -1: l = &t->seed[t->seed_cnt - 1].xm_link; break; case 1: l = &t->seed[t->seed_cnt - 1].xp_link; break; case -2: l = &t->seed[t->seed_cnt - 1].ym_link; break; case 2: l = &t->seed[t->seed_cnt - 1].yp_link; break; case -3: l = &t->seed[t->seed_cnt - 1].zm_link; break; case 3: l = &t->seed[t->seed_cnt - 1].zp_link; break; default: OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E0E: unknown link direction %d\n", c_dir); goto out; } l->end[0].type = PASSTHRU; l->end[0].port = -1; /* We don't really connect. */ l->end[0].n_id = sw_guid0; l->end[0].sw = NULL; /* Fix this up later. */ l->end[0].link = NULL; /* Fix this up later. */ l->end[1].type = PASSTHRU; l->end[1].port = -1; /* We don't really connect. */ l->end[1].n_id = sw_guid1; l->end[1].sw = NULL; /* Fix this up later. */ l->end[1].link = NULL; /* Fix this up later. */ success = true; out: return success; } static bool parse_dir_dateline(int c_dir, struct torus *t, const char *parse_sep) { char *val; int *dl, max_dl; bool success = false; val = strtok(NULL, parse_sep); if (!val) goto out; if (!t) { success = true; goto out; } switch (c_dir) { case 1: dl = &t->seed[t->seed_cnt - 1].x_dateline; max_dl = t->x_sz; break; case 2: dl = &t->seed[t->seed_cnt - 1].y_dateline; max_dl = t->y_sz; break; case 3: dl = &t->seed[t->seed_cnt - 1].z_dateline; max_dl = t->z_sz; break; default: OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E0F: unknown dateline direction %d\n", c_dir); goto out; } *dl = strtol(val, NULL, 0); if ((*dl < 0 && *dl <= -max_dl) || *dl >= max_dl) OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E10: dateline value for coordinate direction %d " "must be %d < dl < %d\n", c_dir, -max_dl, max_dl); else success = true; out: return success; } static bool parse_config(const char *fn, struct fabric *f, struct torus *t) { FILE *fp; unsigned i; char *keyword; char *line_buf = NULL; const char *parse_sep = " \n\t\015"; size_t line_buf_sz = 0; size_t line_cntr = 0; ssize_t llen; bool kw_success, success = true; if (!grow_seed_array(t, 2)) return false; for (i = 0; i < ARRAY_SIZE(t->port_order); i++) t->port_order[i] = i; fp = fopen(fn, "r"); if (!fp) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E11: Opening %s: %s\n", fn, strerror(errno)); return false; } t->flags |= NOTIFY_CHANGES; t->portgrp_sz = PORTGRP_MAX_PORTS; t->max_changes = DEFAULT_MAX_CHANGES; next_line: llen = getline(&line_buf, &line_buf_sz, fp); if (llen < 0) goto out; ++line_cntr; keyword = strtok(line_buf, parse_sep); if (!keyword) goto next_line; if (strcmp("torus", keyword) == 0) { kw_success = parse_torus(t, parse_sep); } else if (strcmp("mesh", keyword) == 0) { t->flags |= X_MESH | Y_MESH | Z_MESH; kw_success = parse_torus(t, parse_sep); } else if (strcmp("port_order", keyword) == 0) { kw_success = parse_port_order(t, parse_sep); } else if (strcmp("next_seed", keyword) == 0) { kw_success = grow_seed_array(t, 1); t->seed_cnt++; } else if (strcmp("portgroup_max_ports", keyword) == 0) { kw_success = parse_unsigned(&t->portgrp_sz, parse_sep); } else if (strcmp("xp_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(1, t, parse_sep); } else if (strcmp("xm_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(-1, t, parse_sep); } else if (strcmp("x_dateline", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_dateline(1, t, parse_sep); } else if (strcmp("yp_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(2, t, parse_sep); } else if (strcmp("ym_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(-2, t, parse_sep); } else if (strcmp("y_dateline", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_dateline(2, t, parse_sep); } else if (strcmp("zp_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(3, t, parse_sep); } else if (strcmp("zm_link", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_link(-3, t, parse_sep); } else if (strcmp("z_dateline", keyword) == 0) { if (!t->seed_cnt) t->seed_cnt++; kw_success = parse_dir_dateline(3, t, parse_sep); } else if (strcmp("max_changes", keyword) == 0) { kw_success = parse_unsigned(&t->max_changes, parse_sep); } else if (keyword[0] == '#') goto next_line; else { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E12: no keyword found: line %u\n", (unsigned)line_cntr); kw_success = false; } if (!kw_success) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E13: parsing '%s': line %u\n", keyword, (unsigned)line_cntr); } success = success && kw_success; goto next_line; out: if (line_buf) free(line_buf); fclose(fp); return success; } static bool capture_fabric(struct fabric *fabric) { osm_subn_t *subnet = &fabric->osm->subn; osm_switch_t *osm_sw; osm_physp_t *lphysp, *rphysp; osm_port_t *lport; osm_node_t *osm_node; cl_map_item_t *item; uint8_t ltype, rtype; int p, port_cnt; guid_t sw_guid; bool success = true; OSM_LOG_ENTER(&fabric->osm->log); /* * On OpenSM data structures: * * Apparently, every port in a fabric has an associated osm_physp_t, * but not every port has an associated osm_port_t. Apparently every * osm_port_t has an associated osm_physp_t. * * So, in order to find the inter-switch links we need to walk the * switch list and examine each port, via its osm_physp_t object. * * But, we need to associate our CA and switch management port * endpoints with the corresponding osm_port_t objects, in order * to simplify computation of LFT entries and perform SL lookup for * path records. Since it is apparently difficult to locate the * osm_port_t that corresponds to a given osm_physp_t, we also * need to walk the list of ports indexed by GUID to get access * to the appropriate osm_port_t objects. * * Need to allocate our switches before we do anything else. */ item = cl_qmap_head(&subnet->sw_guid_tbl); while (item != cl_qmap_end(&subnet->sw_guid_tbl)) { osm_sw = (osm_switch_t *)item; item = cl_qmap_next(item); osm_sw->priv = NULL; /* avoid stale pointer dereferencing */ osm_node = osm_sw->p_node; if (osm_node_get_type(osm_node) != IB_NODE_TYPE_SWITCH) continue; port_cnt = osm_node_get_num_physp(osm_node); sw_guid = osm_node_get_node_guid(osm_node); success = alloc_fswitch(fabric, sw_guid, port_cnt); if (!success) goto out; } /* * Now build all our endpoints. */ item = cl_qmap_head(&subnet->port_guid_tbl); while (item != cl_qmap_end(&subnet->port_guid_tbl)) { lport = (osm_port_t *)item; item = cl_qmap_next(item); lport->priv = NULL; /* avoid stale pointer dereferencing */ lphysp = lport->p_physp; if (!(lphysp && osm_physp_is_valid(lphysp))) continue; ltype = osm_node_get_type(lphysp->p_node); /* * Switch management port is always port 0. */ if (lphysp->port_num == 0 && ltype == IB_NODE_TYPE_SWITCH) { success = build_sw_endpoint(fabric, lport); if (!success) goto out; continue; } rphysp = lphysp->p_remote_physp; if (!(rphysp && osm_physp_is_valid(rphysp))) continue; rtype = osm_node_get_type(rphysp->p_node); if ((ltype != IB_NODE_TYPE_CA && ltype != IB_NODE_TYPE_ROUTER) || rtype != IB_NODE_TYPE_SWITCH) continue; success = build_ca_link(fabric, lport, osm_node_get_node_guid(rphysp->p_node), osm_physp_get_port_num(rphysp)); if (!success) goto out; } /* * Lastly, build all our interswitch links. */ item = cl_qmap_head(&subnet->sw_guid_tbl); while (item != cl_qmap_end(&subnet->sw_guid_tbl)) { osm_sw = (osm_switch_t *)item; item = cl_qmap_next(item); port_cnt = osm_node_get_num_physp(osm_sw->p_node); for (p = 0; p < port_cnt; p++) { lphysp = osm_node_get_physp_ptr(osm_sw->p_node, p); if (!(lphysp && osm_physp_is_valid(lphysp))) continue; rphysp = lphysp->p_remote_physp; if (!(rphysp && osm_physp_is_valid(rphysp))) continue; if (lphysp == rphysp) continue; /* ignore loopbacks */ ltype = osm_node_get_type(lphysp->p_node); rtype = osm_node_get_type(rphysp->p_node); if (ltype != IB_NODE_TYPE_SWITCH || rtype != IB_NODE_TYPE_SWITCH) continue; success = build_link(fabric, osm_node_get_node_guid(lphysp->p_node), osm_physp_get_port_num(lphysp), osm_node_get_node_guid(rphysp->p_node), osm_physp_get_port_num(rphysp)); if (!success) goto out; } } out: OSM_LOG_EXIT(&fabric->osm->log); return success; } /* * diagnose_fabric() is just intended to report on fabric elements that * could not be placed into the torus. We want to warn that there were * non-torus fabric elements, but they will be ignored for routing purposes. * Having them is not an error, and diagnose_fabric() thus has no return * value. */ static void diagnose_fabric(struct fabric *f) { struct link *l; struct endpoint *ep; unsigned k, p; /* * Report on any links that didn't get transferred to the torus. */ for (k = 0; k < f->link_cnt; k++) { l = f->link[k]; if (!(l->end[0].sw && l->end[1].sw)) continue; OSM_LOG(&f->osm->log, OSM_LOG_INFO, "Found non-torus fabric link:" " sw GUID 0x%04"PRIx64" port %d <->" " sw GUID 0x%04"PRIx64" port %d\n", cl_ntoh64(l->end[0].n_id), l->end[0].port, cl_ntoh64(l->end[1].n_id), l->end[1].port); } /* * Report on any switches with ports using endpoints that didn't * get transferred to the torus. */ for (k = 0; k < f->switch_cnt; k++) for (p = 0; p < f->sw[k]->port_cnt; p++) { if (!f->sw[k]->port[p]) continue; ep = f->sw[k]->port[p]; /* * We already reported on inter-switch links above. */ if (ep->type == PASSTHRU) continue; OSM_LOG(&f->osm->log, OSM_LOG_INFO, "Found non-torus fabric port:" " sw GUID 0x%04"PRIx64" port %d\n", cl_ntoh64(f->sw[k]->n_id), p); } } static struct t_switch *alloc_tswitch(struct torus *t, struct f_switch *fsw) { unsigned g; size_t new_sw_sz; struct t_switch *sw = NULL; void *ptr; if (!fsw) goto out; if (t->switch_cnt >= t->sw_pool_sz) { /* * This should never happen, but occasionally a particularly * pathological fabric can induce it. So log an error. */ OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E14: unexpectedly requested too many switch " "structures!\n"); goto out; } new_sw_sz = sizeof(*sw) + fsw->port_cnt * sizeof(*sw->port) + SWITCH_MAX_PORTGRPS * t->portgrp_sz * sizeof(*sw->ptgrp[0].port); sw = calloc(1, new_sw_sz); if (!sw) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E15: calloc: %s\n", strerror(errno)); goto out; } sw->port = (void *)(sw + 1); sw->n_id = fsw->n_id; sw->port_cnt = fsw->port_cnt; sw->torus = t; sw->tmp = fsw; ptr = &sw->port[sw->port_cnt]; for (g = 0; g < SWITCH_MAX_PORTGRPS; g++) { sw->ptgrp[g].port_grp = g; sw->ptgrp[g].sw = sw; sw->ptgrp[g].port = ptr; ptr = &sw->ptgrp[g].port[t->portgrp_sz]; } t->sw_pool[t->switch_cnt++] = sw; out: return sw; } /* * install_tswitch() expects the switch coordinates i,j,k to be canonicalized * by caller. */ static bool install_tswitch(struct torus *t, int i, int j, int k, struct f_switch *fsw) { struct t_switch **sw = &t->sw[i][j][k]; if (!*sw) *sw = alloc_tswitch(t, fsw); if (*sw) { (*sw)->i = i; (*sw)->j = j; (*sw)->k = k; } return !!*sw; } static struct link *alloc_tlink(struct torus *t) { if (t->link_cnt >= t->link_pool_sz) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E16: unexpectedly out of pre-allocated link " "structures!\n"); return NULL; } return &t->link_pool[t->link_cnt++]; } static int canonicalize(int v, int vmax) { if (v >= 0 && v < vmax) return v; if (v < 0) v += vmax * (1 - v/vmax); return v % vmax; } static unsigned set_fp_bit(bool present, int i, int j, int k) { return (unsigned)(!present) << (i + 2 * j + 4 * k); } /* * Returns an 11-bit fingerprint of what switches are absent in a cube of * neighboring switches. Each bit 0-7 corresponds to a corner of the cube; * if a bit is set the corresponding switch is absent. * * Bits 8-10 distinguish between 2D and 3D cases. If bit 8+d is set, * for 0 <= d < 3; the d dimension of the desired torus has radix greater * than 1. Thus, if all bits 8-10 are set, the desired torus is 3D. */ static unsigned fingerprint(struct torus *t, int i, int j, int k) { unsigned fp; int ip1, jp1, kp1; int x_sz_gt1, y_sz_gt1, z_sz_gt1; x_sz_gt1 = t->x_sz > 1; y_sz_gt1 = t->y_sz > 1; z_sz_gt1 = t->z_sz > 1; ip1 = canonicalize(i + 1, t->x_sz); jp1 = canonicalize(j + 1, t->y_sz); kp1 = canonicalize(k + 1, t->z_sz); fp = set_fp_bit(t->sw[i][j][k], 0, 0, 0); fp |= set_fp_bit(t->sw[ip1][j][k], x_sz_gt1, 0, 0); fp |= set_fp_bit(t->sw[i][jp1][k], 0, y_sz_gt1, 0); fp |= set_fp_bit(t->sw[ip1][jp1][k], x_sz_gt1, y_sz_gt1, 0); fp |= set_fp_bit(t->sw[i][j][kp1], 0, 0, z_sz_gt1); fp |= set_fp_bit(t->sw[ip1][j][kp1], x_sz_gt1, 0, z_sz_gt1); fp |= set_fp_bit(t->sw[i][jp1][kp1], 0, y_sz_gt1, z_sz_gt1); fp |= set_fp_bit(t->sw[ip1][jp1][kp1], x_sz_gt1, y_sz_gt1, z_sz_gt1); fp |= x_sz_gt1 << 8; fp |= y_sz_gt1 << 9; fp |= z_sz_gt1 << 10; return fp; } static bool connect_tlink(struct port_grp *pg0, struct endpoint *f_ep0, struct port_grp *pg1, struct endpoint *f_ep1, struct torus *t) { struct link *l; bool success = false; if (pg0->port_cnt == t->portgrp_sz) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E17: exceeded port group max " "port count (%d): switch GUID 0x%04"PRIx64"\n", t->portgrp_sz, cl_ntoh64(pg0->sw->n_id)); goto out; } if (pg1->port_cnt == t->portgrp_sz) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E18: exceeded port group max " "port count (%d): switch GUID 0x%04"PRIx64"\n", t->portgrp_sz, cl_ntoh64(pg1->sw->n_id)); goto out; } l = alloc_tlink(t); if (!l) goto out; l->end[0].type = f_ep0->type; l->end[0].port = f_ep0->port; l->end[0].n_id = f_ep0->n_id; l->end[0].sw = pg0->sw; l->end[0].link = l; l->end[0].pgrp = pg0; pg0->port[pg0->port_cnt++] = &l->end[0]; pg0->sw->port[f_ep0->port] = &l->end[0]; if (f_ep0->osm_port) { l->end[0].osm_port = f_ep0->osm_port; l->end[0].osm_port->priv = &l->end[0]; f_ep0->osm_port = NULL; } l->end[1].type = f_ep1->type; l->end[1].port = f_ep1->port; l->end[1].n_id = f_ep1->n_id; l->end[1].sw = pg1->sw; l->end[1].link = l; l->end[1].pgrp = pg1; pg1->port[pg1->port_cnt++] = &l->end[1]; pg1->sw->port[f_ep1->port] = &l->end[1]; if (f_ep1->osm_port) { l->end[1].osm_port = f_ep1->osm_port; l->end[1].osm_port->priv = &l->end[1]; f_ep1->osm_port = NULL; } /* * Disconnect fabric link, so that later we can see if any were * left unconnected in the torus. */ ((struct f_switch *)f_ep0->sw)->port[f_ep0->port] = NULL; f_ep0->sw = NULL; f_ep0->port = -1; ((struct f_switch *)f_ep1->sw)->port[f_ep1->port] = NULL; f_ep1->sw = NULL; f_ep1->port = -1; success = true; out: return success; } static bool link_tswitches(struct torus *t, int cdir, struct t_switch *t_sw0, struct t_switch *t_sw1) { int p; struct port_grp *pg0, *pg1; struct f_switch *f_sw0, *f_sw1; const char *cdir_name = "unknown"; unsigned port_cnt; int success = false; /* * If this is a 2D torus, it is possible for this function to be * called with its two switch arguments being the same switch, in * which case there are no links to install. */ if (t_sw0 == t_sw1 && ((cdir == 0 && t->x_sz == 1) || (cdir == 1 && t->y_sz == 1) || (cdir == 2 && t->z_sz == 1))) { success = true; goto out; } /* * Ensure that t_sw1 is in the positive cdir direction wrt. t_sw0. * ring_next_sw() relies on it. */ switch (cdir) { case 0: if (t->x_sz > 1 && canonicalize(t_sw0->i + 1, t->x_sz) != t_sw1->i) { cdir_name = "x"; goto cdir_error; } break; case 1: if (t->y_sz > 1 && canonicalize(t_sw0->j + 1, t->y_sz) != t_sw1->j) { cdir_name = "y"; goto cdir_error; } break; case 2: if (t->z_sz > 1 && canonicalize(t_sw0->k + 1, t->z_sz) != t_sw1->k) { cdir_name = "z"; goto cdir_error; } break; default: cdir_error: OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E19: " "sw 0x%04"PRIx64" (%d,%d,%d) <--> " "sw 0x%04"PRIx64" (%d,%d,%d) " "invalid torus %s link orientation\n", cl_ntoh64(t_sw0->n_id), t_sw0->i, t_sw0->j, t_sw0->k, cl_ntoh64(t_sw1->n_id), t_sw1->i, t_sw1->j, t_sw1->k, cdir_name); goto out; } f_sw0 = t_sw0->tmp; f_sw1 = t_sw1->tmp; if (!f_sw0 || !f_sw1) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1A: missing fabric switches!\n" " switch GUIDs: 0x%04"PRIx64" 0x%04"PRIx64"\n", cl_ntoh64(t_sw0->n_id), cl_ntoh64(t_sw1->n_id)); goto out; } pg0 = &t_sw0->ptgrp[2*cdir + 1]; pg0->type = PASSTHRU; pg1 = &t_sw1->ptgrp[2*cdir]; pg1->type = PASSTHRU; port_cnt = f_sw0->port_cnt; /* * Find all the links between these two switches. */ for (p = 0; p < port_cnt; p++) { struct endpoint *f_ep0 = NULL, *f_ep1 = NULL; if (!f_sw0->port[p] || !f_sw0->port[p]->link) continue; if (f_sw0->port[p]->link->end[0].n_id == t_sw0->n_id && f_sw0->port[p]->link->end[1].n_id == t_sw1->n_id) { f_ep0 = &f_sw0->port[p]->link->end[0]; f_ep1 = &f_sw0->port[p]->link->end[1]; } else if (f_sw0->port[p]->link->end[1].n_id == t_sw0->n_id && f_sw0->port[p]->link->end[0].n_id == t_sw1->n_id) { f_ep0 = &f_sw0->port[p]->link->end[1]; f_ep1 = &f_sw0->port[p]->link->end[0]; } else continue; if (!(f_ep0->type == PASSTHRU && f_ep1->type == PASSTHRU)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1B: not interswitch " "link:\n 0x%04"PRIx64"/%d <-> 0x%04"PRIx64"/%d\n", cl_ntoh64(f_ep0->n_id), f_ep0->port, cl_ntoh64(f_ep1->n_id), f_ep1->port); goto out; } /* * Skip over links that already have been established in the * torus. */ if (!(f_ep0->sw && f_ep1->sw)) continue; if (!connect_tlink(pg0, f_ep0, pg1, f_ep1, t)) goto out; } success = true; out: return success; } static bool link_srcsink(struct torus *t, int i, int j, int k) { struct endpoint *f_ep0; struct endpoint *f_ep1; struct t_switch *tsw; struct f_switch *fsw; struct port_grp *pg; struct link *fl, *tl; unsigned p, port_cnt; bool success = false; i = canonicalize(i, t->x_sz); j = canonicalize(j, t->y_sz); k = canonicalize(k, t->z_sz); tsw = t->sw[i][j][k]; if (!tsw) return true; fsw = tsw->tmp; /* * link_srcsink is supposed to get called once for every switch in * the fabric. At this point every fsw we encounter must have a * non-null osm_switch. Otherwise something has gone horribly * wrong with topology discovery; the most likely reason is that * the fabric contains a radix-4 torus dimension, but the user gave * a config that didn't say so, breaking all the checking in * safe_x_perpendicular and friends. */ if (!(fsw && fsw->osm_switch)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1C: Invalid topology discovery. " "Verify torus-2QoS.conf contents.\n"); return false; } pg = &tsw->ptgrp[2 * TORUS_MAX_DIM]; pg->type = SRCSINK; tsw->osm_switch = fsw->osm_switch; tsw->osm_switch->priv = tsw; fsw->osm_switch = NULL; port_cnt = fsw->port_cnt; for (p = 0; p < port_cnt; p++) { if (!fsw->port[p]) continue; if (fsw->port[p]->type == SRCSINK) { /* * If the endpoint is the switch port used for in-band * communication with the switch itself, move it to * the torus. */ if (pg->port_cnt == t->portgrp_sz) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1D: exceeded port group max port " "count (%d): switch GUID 0x%04"PRIx64"\n", t->portgrp_sz, cl_ntoh64(tsw->n_id)); goto out; } fsw->port[p]->sw = tsw; fsw->port[p]->pgrp = pg; tsw->port[p] = fsw->port[p]; tsw->port[p]->osm_port->priv = tsw->port[p]; pg->port[pg->port_cnt++] = fsw->port[p]; fsw->port[p] = NULL; } else if (fsw->port[p]->link && fsw->port[p]->type == PASSTHRU) { /* * If the endpoint is a link to a CA, create a new link * in the torus. Disconnect the fabric link. */ fl = fsw->port[p]->link; if (fl->end[0].sw == fsw) { f_ep0 = &fl->end[0]; f_ep1 = &fl->end[1]; } else if (fl->end[1].sw == fsw) { f_ep1 = &fl->end[0]; f_ep0 = &fl->end[1]; } else continue; if (f_ep1->type != SRCSINK) continue; if (pg->port_cnt == t->portgrp_sz) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1E: exceeded port group max port " "count (%d): switch GUID 0x%04"PRIx64"\n", t->portgrp_sz, cl_ntoh64(tsw->n_id)); goto out; } /* * Switch ports connected to links don't get * associated with osm_port_t objects; see * capture_fabric(). So just check CA end. */ if (!f_ep1->osm_port) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E1F: NULL osm_port->priv port " "GUID 0x%04"PRIx64"\n", cl_ntoh64(f_ep1->n_id)); goto out; } tl = alloc_tlink(t); if (!tl) continue; tl->end[0].type = f_ep0->type; tl->end[0].port = f_ep0->port; tl->end[0].n_id = f_ep0->n_id; tl->end[0].sw = tsw; tl->end[0].link = tl; tl->end[0].pgrp = pg; pg->port[pg->port_cnt++] = &tl->end[0]; pg->sw->port[f_ep0->port] = &tl->end[0]; tl->end[1].type = f_ep1->type; tl->end[1].port = f_ep1->port; tl->end[1].n_id = f_ep1->n_id; tl->end[1].sw = NULL; /* Correct for a CA */ tl->end[1].link = tl; tl->end[1].pgrp = NULL; /* Correct for a CA */ tl->end[1].osm_port = f_ep1->osm_port; tl->end[1].osm_port->priv = &tl->end[1]; f_ep1->osm_port = NULL; t->ca_cnt++; f_ep0->sw = NULL; f_ep0->port = -1; fsw->port[p] = NULL; } } success = true; out: return success; } static struct f_switch *ffind_face_corner(struct f_switch *fsw0, struct f_switch *fsw1, struct f_switch *fsw2) { int p0, p3; struct link *l; struct endpoint *far_end; struct f_switch *fsw, *fsw3 = NULL; if (!(fsw0 && fsw1 && fsw2)) goto out; for (p0 = 0; p0 < fsw0->port_cnt; p0++) { /* * Ignore everything except switch links that haven't * been installed into the torus. */ if (!(fsw0->port[p0] && fsw0->port[p0]->sw && fsw0->port[p0]->type == PASSTHRU)) continue; l = fsw0->port[p0]->link; if (l->end[0].n_id == fsw0->n_id) far_end = &l->end[1]; else far_end = &l->end[0]; /* * Ignore CAs */ if (!(far_end->type == PASSTHRU && far_end->sw)) continue; fsw3 = far_end->sw; if (fsw3->n_id == fsw1->n_id) /* existing corner */ continue; for (p3 = 0; p3 < fsw3->port_cnt; p3++) { /* * Ignore everything except switch links that haven't * been installed into the torus. */ if (!(fsw3->port[p3] && fsw3->port[p3]->sw && fsw3->port[p3]->type == PASSTHRU)) continue; l = fsw3->port[p3]->link; if (l->end[0].n_id == fsw3->n_id) far_end = &l->end[1]; else far_end = &l->end[0]; /* * Ignore CAs */ if (!(far_end->type == PASSTHRU && far_end->sw)) continue; fsw = far_end->sw; if (fsw->n_id == fsw2->n_id) goto out; } } fsw3 = NULL; out: return fsw3; } static struct f_switch *tfind_face_corner(struct t_switch *tsw0, struct t_switch *tsw1, struct t_switch *tsw2) { if (!(tsw0 && tsw1 && tsw2)) return NULL; return ffind_face_corner(tsw0->tmp, tsw1->tmp, tsw2->tmp); } /* * This code can break on any torus with a dimension that has radix four. * * What is supposed to happen is that this code will find the * two faces whose shared edge is the desired perpendicular. * * What actually happens is while searching we send two connected * edges that are colinear in a torus dimension with radix four to * ffind_face_corner(), which tries to complete a face by finding a * 4-loop of edges. * * In the radix four torus case, it can find a 4-loop which is a ring in a * dimension with radix four, rather than the desired face. It thus returns * true when it shouldn't, so the wrong edge is returned as the perpendicular. * * The appropriate instance of safe_N_perpendicular() (where N == x, y, z) * should be used to determine if it is safe to call ffind_perpendicular(); * these functions will return false it there is a possibility of finding * a wrong perpendicular. */ struct f_switch *ffind_3d_perpendicular(struct f_switch *fsw0, struct f_switch *fsw1, struct f_switch *fsw2, struct f_switch *fsw3) { int p1; struct link *l; struct endpoint *far_end; struct f_switch *fsw4 = NULL; if (!(fsw0 && fsw1 && fsw2 && fsw3)) goto out; /* * Look at all the ports on the switch, fsw1, that is the base of * the perpendicular. */ for (p1 = 0; p1 < fsw1->port_cnt; p1++) { /* * Ignore everything except switch links that haven't * been installed into the torus. */ if (!(fsw1->port[p1] && fsw1->port[p1]->sw && fsw1->port[p1]->type == PASSTHRU)) continue; l = fsw1->port[p1]->link; if (l->end[0].n_id == fsw1->n_id) far_end = &l->end[1]; else far_end = &l->end[0]; /* * Ignore CAs */ if (!(far_end->type == PASSTHRU && far_end->sw)) continue; fsw4 = far_end->sw; if (fsw4->n_id == fsw3->n_id) /* wrong perpendicular */ continue; if (ffind_face_corner(fsw0, fsw1, fsw4) && ffind_face_corner(fsw2, fsw1, fsw4)) goto out; } fsw4 = NULL; out: return fsw4; } struct f_switch *ffind_2d_perpendicular(struct f_switch *fsw0, struct f_switch *fsw1, struct f_switch *fsw2) { int p1; struct link *l; struct endpoint *far_end; struct f_switch *fsw3 = NULL; if (!(fsw0 && fsw1 && fsw2)) goto out; /* * Look at all the ports on the switch, fsw1, that is the base of * the perpendicular. */ for (p1 = 0; p1 < fsw1->port_cnt; p1++) { /* * Ignore everything except switch links that haven't * been installed into the torus. */ if (!(fsw1->port[p1] && fsw1->port[p1]->sw && fsw1->port[p1]->type == PASSTHRU)) continue; l = fsw1->port[p1]->link; if (l->end[0].n_id == fsw1->n_id) far_end = &l->end[1]; else far_end = &l->end[0]; /* * Ignore CAs */ if (!(far_end->type == PASSTHRU && far_end->sw)) continue; fsw3 = far_end->sw; if (fsw3->n_id == fsw2->n_id) /* wrong perpendicular */ continue; if (ffind_face_corner(fsw0, fsw1, fsw3)) goto out; } fsw3 = NULL; out: return fsw3; } static struct f_switch *tfind_3d_perpendicular(struct t_switch *tsw0, struct t_switch *tsw1, struct t_switch *tsw2, struct t_switch *tsw3) { if (!(tsw0 && tsw1 && tsw2 && tsw3)) return NULL; return ffind_3d_perpendicular(tsw0->tmp, tsw1->tmp, tsw2->tmp, tsw3->tmp); } static struct f_switch *tfind_2d_perpendicular(struct t_switch *tsw0, struct t_switch *tsw1, struct t_switch *tsw2) { if (!(tsw0 && tsw1 && tsw2)) return NULL; return ffind_2d_perpendicular(tsw0->tmp, tsw1->tmp, tsw2->tmp); } static bool safe_x_ring(struct torus *t, int i, int j, int k) { int im1, ip1, ip2; bool success = true; /* * If this x-direction radix-4 ring has at least two links * already installed into the torus, then this ring does not * prevent us from looking for y or z direction perpendiculars. * * It is easier to check for the appropriate switches being installed * into the torus than it is to check for the links, so force the * link installation if the appropriate switches are installed. * * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4). */ if (t->x_sz != 4 || t->flags & X_MESH) goto out; im1 = canonicalize(i - 1, t->x_sz); ip1 = canonicalize(i + 1, t->x_sz); ip2 = canonicalize(i + 2, t->x_sz); if (!!t->sw[im1][j][k] + !!t->sw[ip1][j][k] + !!t->sw[ip2][j][k] < 2) { success = false; goto out; } if (t->sw[ip2][j][k] && t->sw[im1][j][k]) success = link_tswitches(t, 0, t->sw[ip2][j][k], t->sw[im1][j][k]) && success; if (t->sw[im1][j][k] && t->sw[i][j][k]) success = link_tswitches(t, 0, t->sw[im1][j][k], t->sw[i][j][k]) && success; if (t->sw[i][j][k] && t->sw[ip1][j][k]) success = link_tswitches(t, 0, t->sw[i][j][k], t->sw[ip1][j][k]) && success; if (t->sw[ip1][j][k] && t->sw[ip2][j][k]) success = link_tswitches(t, 0, t->sw[ip1][j][k], t->sw[ip2][j][k]) && success; out: return success; } static bool safe_y_ring(struct torus *t, int i, int j, int k) { int jm1, jp1, jp2; bool success = true; /* * If this y-direction radix-4 ring has at least two links * already installed into the torus, then this ring does not * prevent us from looking for x or z direction perpendiculars. * * It is easier to check for the appropriate switches being installed * into the torus than it is to check for the links, so force the * link installation if the appropriate switches are installed. * * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4). */ if (t->y_sz != 4 || (t->flags & Y_MESH)) goto out; jm1 = canonicalize(j - 1, t->y_sz); jp1 = canonicalize(j + 1, t->y_sz); jp2 = canonicalize(j + 2, t->y_sz); if (!!t->sw[i][jm1][k] + !!t->sw[i][jp1][k] + !!t->sw[i][jp2][k] < 2) { success = false; goto out; } if (t->sw[i][jp2][k] && t->sw[i][jm1][k]) success = link_tswitches(t, 1, t->sw[i][jp2][k], t->sw[i][jm1][k]) && success; if (t->sw[i][jm1][k] && t->sw[i][j][k]) success = link_tswitches(t, 1, t->sw[i][jm1][k], t->sw[i][j][k]) && success; if (t->sw[i][j][k] && t->sw[i][jp1][k]) success = link_tswitches(t, 1, t->sw[i][j][k], t->sw[i][jp1][k]) && success; if (t->sw[i][jp1][k] && t->sw[i][jp2][k]) success = link_tswitches(t, 1, t->sw[i][jp1][k], t->sw[i][jp2][k]) && success; out: return success; } static bool safe_z_ring(struct torus *t, int i, int j, int k) { int km1, kp1, kp2; bool success = true; /* * If this z-direction radix-4 ring has at least two links * already installed into the torus, then this ring does not * prevent us from looking for x or y direction perpendiculars. * * It is easier to check for the appropriate switches being installed * into the torus than it is to check for the links, so force the * link installation if the appropriate switches are installed. * * Recall that canonicalize(n - 2, 4) == canonicalize(n + 2, 4). */ if (t->z_sz != 4 || t->flags & Z_MESH) goto out; km1 = canonicalize(k - 1, t->z_sz); kp1 = canonicalize(k + 1, t->z_sz); kp2 = canonicalize(k + 2, t->z_sz); if (!!t->sw[i][j][km1] + !!t->sw[i][j][kp1] + !!t->sw[i][j][kp2] < 2) { success = false; goto out; } if (t->sw[i][j][kp2] && t->sw[i][j][km1]) success = link_tswitches(t, 2, t->sw[i][j][kp2], t->sw[i][j][km1]) && success; if (t->sw[i][j][km1] && t->sw[i][j][k]) success = link_tswitches(t, 2, t->sw[i][j][km1], t->sw[i][j][k]) && success; if (t->sw[i][j][k] && t->sw[i][j][kp1]) success = link_tswitches(t, 2, t->sw[i][j][k], t->sw[i][j][kp1]) && success; if (t->sw[i][j][kp1] && t->sw[i][j][kp2]) success = link_tswitches(t, 2, t->sw[i][j][kp1], t->sw[i][j][kp2]) && success; out: return success; } /* * These functions return true when it safe to call * tfind_3d_perpendicular()/ffind_3d_perpendicular(). */ static bool safe_x_perpendicular(struct torus *t, int i, int j, int k) { /* * If the dimensions perpendicular to the search direction are * not radix 4 torus dimensions, it is always safe to search for * a perpendicular. * * Here we are checking for enough appropriate links having been * installed into the torus to prevent an incorrect link from being * considered as a perpendicular candidate. */ return safe_y_ring(t, i, j, k) && safe_z_ring(t, i, j, k); } static bool safe_y_perpendicular(struct torus *t, int i, int j, int k) { /* * If the dimensions perpendicular to the search direction are * not radix 4 torus dimensions, it is always safe to search for * a perpendicular. * * Here we are checking for enough appropriate links having been * installed into the torus to prevent an incorrect link from being * considered as a perpendicular candidate. */ return safe_x_ring(t, i, j, k) && safe_z_ring(t, i, j, k); } static bool safe_z_perpendicular(struct torus *t, int i, int j, int k) { /* * If the dimensions perpendicular to the search direction are * not radix 4 torus dimensions, it is always safe to search for * a perpendicular. * * Implement this by checking for enough appropriate links having * been installed into the torus to prevent an incorrect link from * being considered as a perpendicular candidate. */ return safe_x_ring(t, i, j, k) && safe_y_ring(t, i, j, k); } /* * Templates for determining 2D/3D case fingerprints. Recall that if * a fingerprint bit is set the corresponding switch is absent from * the all-switches-present template. * * I.e., for the 2D case where the x,y dimensions have a radix greater * than one, and the z dimension has radix 1, fingerprint bits 4-7 are * always zero. * * For the 2D case where the x,z dimensions have a radix greater than * one, and the y dimension has radix 1, fingerprint bits 2,3,6,7 are * always zero. * * For the 2D case where the y,z dimensions have a radix greater than * one, and the x dimension has radix 1, fingerprint bits 1,3,5,7 are * always zero. * * Recall also that bits 8-10 distinguish between 2D and 3D cases. * If bit 8+d is set, for 0 <= d < 3; the d dimension of the desired * torus has radix greater than 1. */ /* * 2D case 0x300 * b0: t->sw[i ][j ][0 ] * b1: t->sw[i+1][j ][0 ] * b2: t->sw[i ][j+1][0 ] * b3: t->sw[i+1][j+1][0 ] * O . . . . . O * 2D case 0x500 . . * b0: t->sw[i ][0 ][k ] . . * b1: t->sw[i+1][0 ][k ] . . * b4: t->sw[i ][0 ][k+1] . . * b5: t->sw[i+1][0 ][k+1] . . * @ . . . . . O * 2D case 0x600 * b0: t->sw[0 ][j ][k ] * b2: t->sw[0 ][j+1][k ] * b4: t->sw[0 ][j ][k+1] * b6: t->sw[0 ][j+1][k+1] */ /* * 3D case 0x700: O * . . . * b0: t->sw[i ][j ][k ] . . . * b1: t->sw[i+1][j ][k ] . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O . . * b5: t->sw[i+1][j ][k+1] . . . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: t->sw[i+1][j+1][k+1] . . . . . . * . . O . . * O . O * . . . * . . . * . . . * . . . * @ */ static void log_no_crnr(struct torus *t, unsigned n, int case_i, int case_j, int case_k, int crnr_i, int crnr_j, int crnr_k) { if (t->debug) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Case 0x%03x " "@ %d %d %d: no corner @ %d %d %d\n", n, case_i, case_j, case_k, crnr_i, crnr_j, crnr_k); } static void log_no_perp(struct torus *t, unsigned n, int case_i, int case_j, int case_k, int perp_i, int perp_j, int perp_k) { if (t->debug) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Case 0x%03x " "@ %d %d %d: no perpendicular @ %d %d %d\n", n, case_i, case_j, case_k, perp_i, perp_j, perp_k); } /* * Handle the 2D cases with a single existing edge. * */ /* * 2D case 0x30c * b0: t->sw[i ][j ][0 ] * b1: t->sw[i+1][j ][0 ] * b2: * b3: * O O * 2D case 0x530 * b0: t->sw[i ][0 ][k ] * b1: t->sw[i+1][0 ][k ] * b4: * b5: * @ . . . . . O * 2D case 0x650 * b0: t->sw[0 ][j ][k ] * b2: t->sw[0 ][j+1][k ] * b4: * b6: */ static bool handle_case_0x30c(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jm1 = canonicalize(j - 1, t->y_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (safe_y_perpendicular(t, i, j, k) && install_tswitch(t, i, jp1, k, tfind_2d_perpendicular(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jm1][k]))) { return true; } log_no_perp(t, 0x30c, i, j, k, i, j, k); if (safe_y_perpendicular(t, ip1, j, k) && install_tswitch(t, ip1, jp1, k, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jm1][k]))) { return true; } log_no_perp(t, 0x30c, i, j, k, ip1, j, k); return false; } static bool handle_case_0x530(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, i, j, k) && install_tswitch(t, i, j, kp1, tfind_2d_perpendicular(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][j][km1]))) { return true; } log_no_perp(t, 0x530, i, j, k, i, j, k); if (safe_z_perpendicular(t, ip1, j, k) && install_tswitch(t, ip1, j, kp1, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][km1]))) { return true; } log_no_perp(t, 0x530, i, j, k, ip1, j, k); return false; } static bool handle_case_0x650(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, i, j, k) && install_tswitch(t, i, j, kp1, tfind_2d_perpendicular(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[i][j][km1]))) { return true; } log_no_perp(t, 0x650, i, j, k, i, j, k); if (safe_z_perpendicular(t, i, jp1, k) && install_tswitch(t, i, jp1, kp1, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][km1]))) { return true; } log_no_perp(t, 0x650, i, j, k, i, jp1, k); return false; } /* * 2D case 0x305 * b0: * b1: t->sw[i+1][j ][0 ] * b2: * b3: t->sw[i+1][j+1][0 ] * O O * 2D case 0x511 . * b0: . * b1: t->sw[i+1][0 ][k ] . * b4: . * b5: t->sw[i+1][0 ][k+1] . * @ O * 2D case 0x611 * b0: * b2: t->sw[0 ][j+1][k ] * b4: * b6: t->sw[0 ][j+1][k+1] */ static bool handle_case_0x305(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (safe_x_perpendicular(t, ip1, j, k) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[ip1][jp1][k], t->sw[ip1][j][k], t->sw[ip2][j][k]))) { return true; } log_no_perp(t, 0x305, i, j, k, ip1, j, k); if (safe_x_perpendicular(t, ip1, jp1, k) && install_tswitch(t, i, jp1, k, tfind_2d_perpendicular(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip2][jp1][k]))) { return true; } log_no_perp(t, 0x305, i, j, k, ip1, jp1, k); return false; } static bool handle_case_0x511(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, ip1, j, k) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip2][j][k]))) { return true; } log_no_perp(t, 0x511, i, j, k, ip1, j, k); if (safe_x_perpendicular(t, ip1, j, kp1) && install_tswitch(t, i, j, kp1, tfind_2d_perpendicular(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip2][j][kp1]))) { return true; } log_no_perp(t, 0x511, i, j, k, ip1, j, kp1); return false; } static bool handle_case_0x611(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, jp1, k) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[i][jp2][k]))) { return true; } log_no_perp(t, 0x611, i, j, k, i, jp1, k); if (safe_y_perpendicular(t, i, jp1, kp1) && install_tswitch(t, i, j, kp1, tfind_2d_perpendicular(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][jp2][kp1]))) { return true; } log_no_perp(t, 0x611, i, j, k, i, jp1, kp1); return false; } /* * 2D case 0x303 * b0: * b1: * b2: t->sw[i ][j+1][0 ] * b3: t->sw[i+1][j+1][0 ] * O . . . . . O * 2D case 0x503 * b0: * b1: * b4: t->sw[i ][0 ][k+1] * b5: t->sw[i+1][0 ][k+1] * @ O * 2D case 0x605 * b0: * b2: * b4: t->sw[0 ][j ][k+1] * b6: t->sw[0 ][j+1][k+1] */ static bool handle_case_0x303(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); if (safe_y_perpendicular(t, i, jp1, k) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[ip1][jp1][k], t->sw[i][jp1][k], t->sw[i][jp2][k]))) { return true; } log_no_perp(t, 0x303, i, j, k, i, jp1, k); if (safe_y_perpendicular(t, ip1, jp1, k) && install_tswitch(t, ip1, j, k, tfind_2d_perpendicular(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][jp2][k]))) { return true; } log_no_perp(t, 0x303, i, j, k, ip1, jp1, k); return false; } static bool handle_case_0x503(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, i, j, kp1) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][j][kp2]))) { return true; } log_no_perp(t, 0x503, i, j, k, i, j, kp1); if (safe_z_perpendicular(t, ip1, j, kp1) && install_tswitch(t, ip1, j, k, tfind_2d_perpendicular(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][j][kp2]))) { return true; } log_no_perp(t, 0x503, i, j, k, ip1, j, kp1); return false; } static bool handle_case_0x605(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, i, j, kp1) && install_tswitch(t, i, j, k, tfind_2d_perpendicular(t->sw[i][jp1][kp1], t->sw[i][j][kp1], t->sw[i][j][kp2]))) { return true; } log_no_perp(t, 0x605, i, j, k, i, j, kp1); if (safe_z_perpendicular(t, i, jp1, kp1) && install_tswitch(t, i, jp1, k, tfind_2d_perpendicular(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[i][jp1][kp2]))) { return true; } log_no_perp(t, 0x605, i, j, k, i, jp1, kp1); return false; } /* * 2D case 0x30a * b0: t->sw[i ][j ][0 ] * b1: * b2: t->sw[i ][j+1][0 ] * b3: * O O * 2D case 0x522 . * b0: t->sw[i ][0 ][k ] . * b1: . * b4: t->sw[i ][0 ][k+1] . * b5: . * @ O * 2D case 0x644 * b0: t->sw[0 ][j ][k ] * b2: * b4: t->sw[0 ][j ][k+1] * b6: */ static bool handle_case_0x30a(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (safe_x_perpendicular(t, i, j, k) && install_tswitch(t, ip1, j, k, tfind_2d_perpendicular(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[im1][j][k]))) { return true; } log_no_perp(t, 0x30a, i, j, k, i, j, k); if (safe_x_perpendicular(t, i, jp1, k) && install_tswitch(t, ip1, jp1, k, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[im1][jp1][k]))) { return true; } log_no_perp(t, 0x30a, i, j, k, i, jp1, k); return false; } static bool handle_case_0x522(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, i, j, k) && install_tswitch(t, ip1, j, k, tfind_2d_perpendicular(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[im1][j][k]))) { return true; } log_no_perp(t, 0x522, i, j, k, i, j, k); if (safe_x_perpendicular(t, i, j, kp1) && install_tswitch(t, ip1, j, kp1, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[im1][j][kp1]))) { return true; } log_no_perp(t, 0x522, i, j, k, i, j, kp1); return false; } static bool handle_case_0x644(struct torus *t, int i, int j, int k) { int jm1 = canonicalize(j - 1, t->y_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, j, k) && install_tswitch(t, i, jp1, k, tfind_2d_perpendicular(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[i][jm1][k]))) { return true; } log_no_perp(t, 0x644, i, j, k, i, j, k); if (safe_y_perpendicular(t, i, j, kp1) && install_tswitch(t, i, jp1, kp1, tfind_2d_perpendicular(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jm1][kp1]))) { return true; } log_no_perp(t, 0x644, i, j, k, i, j, kp1); return false; } /* * Handle the 2D cases where two existing edges meet at a corner. * */ /* * 2D case 0x301 * b0: * b1: t->sw[i+1][j ][0 ] * b2: t->sw[i ][j+1][0 ] * b3: t->sw[i+1][j+1][0 ] * O . . . . . O * 2D case 0x501 . * b0: . * b1: t->sw[i+1][0 ][k ] . * b4: t->sw[i ][0 ][k+1] . * b5: t->sw[i+1][0 ][k+1] . * @ O * 2D case 0x601 * b0: * b2: t->sw[0 ][j+1][k ] * b4: t->sw[0 ][j ][k+1] * b6: t->sw[0 ][j+1][k+1] */ static bool handle_case_0x301(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x301, i, j, k, i, j, k); return false; } static bool handle_case_0x501(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x501, i, j, k, i, j, k); return false; } static bool handle_case_0x601(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x601, i, j, k, i, j, k); return false; } /* * 2D case 0x302 * b0: t->sw[i ][j ][0 ] * b1: * b2: t->sw[i ][j+1][0 ] * b3: t->sw[i+1][j+1][0 ] * O . . . . . O * 2D case 0x502 . * b0: t->sw[i ][0 ][k ] . * b1: . * b4: t->sw[i ][0 ][k+1] . * b5: t->sw[i+1][0 ][k+1] . * @ O * 2D case 0x604 * b0: t->sw[0 ][j ][k ] * b2: * b4: t->sw[0 ][j ][k+1] * b6: t->sw[0 ][j+1][k+1] */ static bool handle_case_0x302(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x302, i, j, k, ip1, j, k); return false; } static bool handle_case_0x502(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x502, i, j, k, ip1, j, k); return false; } static bool handle_case_0x604(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x604, i, j, k, i, jp1, k); return false; } /* * 2D case 0x308 * b0: t->sw[i ][j ][0 ] * b1: t->sw[i+1][j ][0 ] * b2: t->sw[i ][j+1][0 ] * b3: * O O * 2D case 0x520 . * b0: t->sw[i ][0 ][k ] . * b1: t->sw[i+1][0 ][k ] . * b4: t->sw[i ][0 ][k+1] . * b5: . * @ . . . . . O * 2D case 0x640 * b0: t->sw[0 ][j ][k ] * b2: t->sw[0 ][j+1][k ] * b4: t->sw[0 ][j ][k+1] * b6: */ static bool handle_case_0x308(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x308, i, j, k, ip1, jp1, k); return false; } static bool handle_case_0x520(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x520, i, j, k, ip1, j, kp1); return false; } static bool handle_case_0x640(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x640, i, j, k, i, jp1, kp1); return false; } /* * 2D case 0x304 * b0: t->sw[i ][j ][0 ] * b1: t->sw[i+1][j ][0 ] * b2: * b3: t->sw[i+1][j+1][0 ] * O O * 2D case 0x510 . * b0: t->sw[i ][0 ][k ] . * b1: t->sw[i+1][0 ][k ] . * b4: . * b5: t->sw[i+1][0 ][k+1] . * @ . . . . . O * 2D case 0x610 * b0: t->sw[0 ][j ][k ] * b2: t->sw[0 ][j+1][k ] * b4: * b6: t->sw[0 ][j+1][k+1] */ static bool handle_case_0x304(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x304, i, j, k, i, jp1, k); return false; } static bool handle_case_0x510(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x510, i, j, k, i, j, kp1); return false; } static bool handle_case_0x610(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x610, i, j, k, i, j, kp1); return false; } /* * Handle the 3D cases where two existing edges meet at a corner. * */ /* * 3D case 0x71f: O * . . * b0: . . * b1: . . * b2: . . * b3: O O * b4: O * b5: t->sw[i+1][j ][k+1] * b6: t->sw[i ][j+1][k+1] * b7: t->sw[i+1][j+1][k+1] * O * O O * * * * * @ */ static bool handle_case_0x71f(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, ip1, jp1, kp1) && install_tswitch(t, ip1, jp1, k, tfind_3d_perpendicular(t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp2]))) { return true; } log_no_perp(t, 0x71f, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x72f: O * . * b0: . * b1: . * b2: . * b3: O O * b4: t->sw[i ][j ][k+1] . O * b5: . * b6: t->sw[i ][j+1][k+1] . * b7: t->sw[i+1][j+1][k+1] . * O * O O * * * * * @ */ static bool handle_case_0x72f(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, i, jp1, kp1) && install_tswitch(t, i, jp1, k, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp2]))) { return true; } log_no_perp(t, 0x72f, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x737: O * . . * b0: . . * b1: . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: * b6: t->sw[i ][j+1][k+1] * b7: t->sw[i+1][j+1][k+1] * O * O O * * * * * @ */ static bool handle_case_0x737(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, ip1, jp1, kp1) && install_tswitch(t, ip1, j, kp1, tfind_3d_perpendicular(t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1], t->sw[ip1][jp1][k], t->sw[ip1][jp2][kp1]))) { return true; } log_no_perp(t, 0x737, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x73b: O * . * b0: . * b1: . * b2: t->sw[i ][j+1][k ] . * b3: O O * b4: . O * b5: . * b6: t->sw[i ][j+1][k+1] . * b7: t->sw[i+1][j+1][k+1] . * . O * O O * * * * * @ */ static bool handle_case_0x73b(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, jp1, kp1) && install_tswitch(t, i, j, kp1, tfind_3d_perpendicular(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp2][kp1]))) { return true; } log_no_perp(t, 0x73b, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x74f: O * . * b0: . * b1: . * b2: . * b3: O O * b4: t->sw[i ][j ][k+1] O . * b5: t->sw[i+1][j ][k+1] . * b6: . * b7: t->sw[i+1][j+1][k+1] . * O * O O * * * * * @ */ static bool handle_case_0x74f(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, ip1, j, kp1) && install_tswitch(t, ip1, j, k, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp2]))) { return true; } log_no_perp(t, 0x74f, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x757: O * . . * b0: . . * b1: . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: t->sw[i+1][j ][k+1] * b6: * b7: t->sw[i+1][j+1][k+1] * O * O O * * * * * @ */ static bool handle_case_0x757(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, ip1, jp1, kp1) && install_tswitch(t, i, jp1, kp1, tfind_3d_perpendicular(t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[ip1][jp1][k], t->sw[ip2][jp1][kp1]))) { return true; } log_no_perp(t, 0x757, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x75d: O * . * b0: . * b1: t->sw[i+1][j ][k ] . * b2: . * b3: O O * b4: O . * b5: t->sw[i+1][j ][k+1] . * b6: . * b7: t->sw[i+1][j+1][k+1] . * O . * O O * * * * * @ */ static bool handle_case_0x75d(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, ip1, j, kp1) && install_tswitch(t, i, j, kp1, tfind_3d_perpendicular(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[ip2][j][kp1]))) { return true; } log_no_perp(t, 0x75d, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x773: O * . * b0: . * b1: . * b2: t->sw[i ][j+1][k ] . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: . * b6: . * b7: t->sw[i+1][j+1][k+1] . * . O * O O * * * * * @ */ static bool handle_case_0x773(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, ip1, jp1, k) && install_tswitch(t, ip1, j, k, tfind_3d_perpendicular(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip1][jp2][k]))) { return true; } log_no_perp(t, 0x773, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x775: O * . * b0: . * b1: t->sw[i+1][j ][k ] . * b2: . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: . * b6: . * b7: t->sw[i+1][j+1][k+1] . * O . * O O * * * * * @ */ static bool handle_case_0x775(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, ip1, jp1, k) && install_tswitch(t, i, jp1, k, tfind_3d_perpendicular(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip2][jp1][k]))) { return true; } log_no_perp(t, 0x775, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x78f: O * * b0: * b1: * b2: * b3: O O * b4: t->sw[i ][j ][k+1] . O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * O * O O * * * * * @ */ static bool handle_case_0x78f(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); int kp2 = canonicalize(k + 2, t->z_sz); if (safe_z_perpendicular(t, i, j, kp1) && install_tswitch(t, i, j, k, tfind_3d_perpendicular(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[i][j][kp2]))) { return true; } log_no_perp(t, 0x78f, i, j, k, i, j, kp1); return false; } /* * 3D case 0x7ab: O * * b0: * b1: * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * . O * O O * * * * * @ */ static bool handle_case_0x7ab(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, i, jp1, kp1) && install_tswitch(t, ip1, jp1, kp1, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[im1][jp1][kp1]))) { return true; } log_no_perp(t, 0x7ab, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x7ae: O * * b0: t->sw[i ][j ][k ] * b1: * b2: * b3: O O * b4: t->sw[i ][j ][k+1] . O * b5: . * b6: t->sw[i ][j+1][k+1] . * b7: . * O * O . O * . * . * . * . * @ */ static bool handle_case_0x7ae(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, i, j, kp1) && install_tswitch(t, ip1, j, kp1, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[im1][j][kp1]))) { return true; } log_no_perp(t, 0x7ae, i, j, k, i, j, kp1); return false; } /* * 3D case 0x7b3: O * * b0: * b1: * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * . . O * O O * * * * * @ */ static bool handle_case_0x7b3(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jp2 = canonicalize(j + 2, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, jp1, k) && install_tswitch(t, i, j, k, tfind_3d_perpendicular(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[i][jp2][k]))) { return true; } log_no_perp(t, 0x7b3, i, j, k, i, jp1, k); return false; } /* * 3D case 0x7ba: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: O O * b4: . O * b5: . * b6: t->sw[i ][j+1][k+1] . * b7: . * . O * O O * . * . * . * . * @ */ static bool handle_case_0x7ba(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, i, jp1, k) && install_tswitch(t, ip1, jp1, k, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[im1][jp1][k]))) { return true; } log_no_perp(t, 0x7ba, i, j, k, i, jp1, k); return false; } /* * 3D case 0x7cd: O * * b0: * b1: t->sw[i+1][j ][k ] * b2: * b3: O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: . . * O . * O O * * * * * @ */ static bool handle_case_0x7cd(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jm1 = canonicalize(j - 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, ip1, j, kp1) && install_tswitch(t, ip1, jp1, kp1, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jm1][kp1]))) { return true; } log_no_perp(t, 0x7cd, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x7ce: O * * b0: t->sw[i ][j ][k ] * b1: * b2: * b3: O O * b4: t->sw[i ][j ][k+1] O . * b5: t->sw[i+1][j ][k+1] . * b6: . * b7: . * O * O . O * . * . * . * . * @ */ static bool handle_case_0x7ce(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jm1 = canonicalize(j - 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, j, kp1) && install_tswitch(t, i, jp1, kp1, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[i][jm1][kp1]))) { return true; } log_no_perp(t, 0x7ce, i, j, k, i, j, kp1); return false; } /* * 3D case 0x7d5: O * * b0: * b1: t->sw[i+1][j ][k ] * b2: * b3: t->sw[i+1][j+1][k ] O O * b4: O . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: . . * O . . * O O * * * * * @ */ static bool handle_case_0x7d5(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int ip2 = canonicalize(i + 2, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, ip1, j, k) && install_tswitch(t, i, j, k, tfind_3d_perpendicular(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip2][j][k]))) { return true; } log_no_perp(t, 0x7d5, i, j, k, ip1, j, k); return false; } /* * 3D case 0x7dc: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: O O * b4: O . * b5: t->sw[i+1][j ][k+1] . * b6: . * b7: . * O . * O O * . * . * . * . * @ */ static bool handle_case_0x7dc(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jm1 = canonicalize(j - 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, ip1, j, k) && install_tswitch(t, ip1, jp1, k, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jm1][k]))) { return true; } log_no_perp(t, 0x7dc, i, j, k, ip1, j, k); return false; } /* * 3D case 0x7ea: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] O * b5: * b6: * b7: * O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7ea(struct torus *t, int i, int j, int k) { int im1 = canonicalize(i - 1, t->x_sz); int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_x_perpendicular(t, i, j, k) && install_tswitch(t, ip1, j, k, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[i][jp1][k], t->sw[im1][j][k]))) { return true; } log_no_perp(t, 0x7ea, i, j, k, i, j, k); return false; } /* * 3D case 0x7ec: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: O O * b4: t->sw[i ][j ][k+1] O * b5: * b6: * b7: * O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7ec(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int jm1 = canonicalize(j - 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_y_perpendicular(t, i, j, k) && install_tswitch(t, i, jp1, k, tfind_3d_perpendicular(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[ip1][j][k], t->sw[i][jm1][k]))) { return true; } log_no_perp(t, 0x7ec, i, j, k, i, j, k); return false; } /* * 3D case 0x7f1: O * * b0: * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: O * b5: . . * b6: . . * b7: . . * . O . * O O * * * * * @ */ static bool handle_case_0x7f1(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, ip1, jp1, k) && install_tswitch(t, ip1, jp1, kp1, tfind_3d_perpendicular(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[i][jp1][k], t->sw[ip1][jp1][km1]))) { return true; } log_no_perp(t, 0x7f1, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x7f2: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: O * b5: . * b6: . * b7: . * . O * O O * . * . * . * . * @ */ static bool handle_case_0x7f2(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, i, jp1, k) && install_tswitch(t, i, jp1, kp1, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[i][jp1][km1]))) { return true; } log_no_perp(t, 0x7f2, i, j, k, i, jp1, k); return false; } /* * 3D case 0x7f4: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: t->sw[i+1][j+1][k ] O O * b4: O * b5: . * b6: . * b7: . * O . * O O * . * . * . * . * @ */ static bool handle_case_0x7f4(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, ip1, j, k) && install_tswitch(t, ip1, j, kp1, tfind_3d_perpendicular(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip1][j][km1]))) { return true; } log_no_perp(t, 0x7f4, i, j, k, ip1, j, k); return false; } /* * 3D case 0x7f8: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: O O * b4: O * b5: * b6: * b7: * O * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x7f8(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int km1 = canonicalize(k - 1, t->z_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (safe_z_perpendicular(t, i, j, k) && install_tswitch(t, i, j, kp1, tfind_3d_perpendicular(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][j][km1]))) { return true; } log_no_perp(t, 0x7f8, i, j, k, i, j, k); return false; } /* * Handle the cases where three existing edges meet at a corner. */ /* * 3D case 0x717: O * . . . * b0: . . . * b1: . . . * b2: . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: t->sw[i+1][j ][k+1] * b6: t->sw[i ][j+1][k+1] * b7: t->sw[i+1][j+1][k+1] * O * O O * * * * * @ */ static bool handle_case_0x717(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x717, i, j, k, i, j, kp1); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x717, i, j, k, ip1, j, k); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x717, i, j, k, i, jp1, k); return false; } /* * 3D case 0x72b: O * . * b0: . * b1: . * b2: t->sw[i ][j+1][k ] . * b3: O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * . O * O O * * * * * @ */ static bool handle_case_0x72b(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x72b, i, j, k, ip1, j, kp1); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x72b, i, j, k, i, j, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x72b, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x74d: O * . * b0: . * b1: t->sw[i+1][j ][k ] . * b2: . * b3: O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * O . * O O * * * * * @ */ static bool handle_case_0x74d(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x74d, i, j, k, i, jp1, kp1); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x74d, i, j, k, i, j, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x74d, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x771: O * . * b0: . * b1: t->sw[i+1][j ][k ] . * b2: t->sw[i ][j+1][k ] . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * . O . * O O * * * * * @ */ static bool handle_case_0x771(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x771, i, j, k, i, j, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][jp1][kp1], t->sw[ip1][jp1][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x771, i, j, k, ip1, j, kp1); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[ip1][jp1][kp1], t->sw[ip1][jp1][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x771, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x78e: O * * b0: t->sw[i ][j ][k ] * b1: * b2: * b3: O O * b4: t->sw[i ][j ][k+1] . O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * O * O . O * . * . * . * . * @ */ static bool handle_case_0x78e(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x78e, i, j, k, ip1, jp1, kp1); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x78e, i, j, k, ip1, j, k); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x78e, i, j, k, i, jp1, k); return false; } /* * 3D case 0x7b2: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * . . O * O O * . * . * . * . * @ */ static bool handle_case_0x7b2(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7b2, i, j, k, ip1, j, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7b2, i, j, k, ip1, jp1, kp1); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[i][j][k]))) { return true; } log_no_crnr(t, 0x7b2, i, j, k, i, j, kp1); return false; } /* * 3D case 0x7d4: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: t->sw[i+1][j+1][k ] O O * b4: O . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: . . * O . . * O O * . * . * . * . * @ */ static bool handle_case_0x7d4(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7d4, i, j, k, i, jp1, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[i][j][k]))) { return true; } log_no_crnr(t, 0x7d4, i, j, k, i, j, kp1); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7d4, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7e8: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] O * b5: * b6: * b7: * O * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7e8(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7e8, i, j, k, ip1, jp1, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x7e8, i, j, k, ip1, j, kp1); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x7e8, i, j, k, i, jp1, kp1); return false; } /* * Handle the cases where four corners on a single face are missing. */ /* * 3D case 0x70f: O * . . * b0: . . * b1: . . * b2: . . * b3: O O * b4: t->sw[i ][j ][k+1] . O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * O * O O * * * * * @ */ static bool handle_case_0x70f(struct torus *t, int i, int j, int k) { if (handle_case_0x71f(t, i, j, k)) return true; if (handle_case_0x72f(t, i, j, k)) return true; if (handle_case_0x74f(t, i, j, k)) return true; return handle_case_0x78f(t, i, j, k); } /* * 3D case 0x733: O * . . * b0: . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * . . O * O O * * * * * @ */ static bool handle_case_0x733(struct torus *t, int i, int j, int k) { if (handle_case_0x737(t, i, j, k)) return true; if (handle_case_0x73b(t, i, j, k)) return true; if (handle_case_0x773(t, i, j, k)) return true; return handle_case_0x7b3(t, i, j, k); } /* * 3D case 0x755: O * . . * b0: . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * O . . * O O * * * * * @ */ static bool handle_case_0x755(struct torus *t, int i, int j, int k) { if (handle_case_0x757(t, i, j, k)) return true; if (handle_case_0x75d(t, i, j, k)) return true; if (handle_case_0x775(t, i, j, k)) return true; return handle_case_0x7d5(t, i, j, k); } /* * 3D case 0x7aa: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7aa(struct torus *t, int i, int j, int k) { if (handle_case_0x7ab(t, i, j, k)) return true; if (handle_case_0x7ae(t, i, j, k)) return true; if (handle_case_0x7ba(t, i, j, k)) return true; return handle_case_0x7ea(t, i, j, k); } /* * 3D case 0x7cc: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: . . * O . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7cc(struct torus *t, int i, int j, int k) { if (handle_case_0x7cd(t, i, j, k)) return true; if (handle_case_0x7ce(t, i, j, k)) return true; if (handle_case_0x7dc(t, i, j, k)) return true; return handle_case_0x7ec(t, i, j, k); } /* * 3D case 0x7f0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: O * b5: . . * b6: . . * b7: . . * . O . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x7f0(struct torus *t, int i, int j, int k) { if (handle_case_0x7f1(t, i, j, k)) return true; if (handle_case_0x7f2(t, i, j, k)) return true; if (handle_case_0x7f4(t, i, j, k)) return true; return handle_case_0x7f8(t, i, j, k); } /* * Handle the cases where three corners on a single face are missing. */ /* * 3D case 0x707: O * . . . * b0: . . . * b1: . . . * b2: . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * O * O O * * * * * @ */ static bool handle_case_0x707(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x707, i, j, k, ip1, j, k); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x707, i, j, k, i, jp1, k); return false; } /* * 3D case 0x70b: O * . . * b0: . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: O O * b4: t->sw[i ][j ][k+1] . . O . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * . O * O O * * * * * @ */ static bool handle_case_0x70b(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x70b, i, j, k, i, j, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70b, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x70d: O * . . * b0: . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: O O * b4: t->sw[i ][j ][k+1] . O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * O . * O O * * * * * @ */ static bool handle_case_0x70d(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x70d, i, j, k, i, j, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70d, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x70e: O * . . * b0: t->sw[i ][j ][k ] . . * b1: . . * b2: . . * b3: O O * b4: t->sw[i ][j ][k+1] . O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * O * O . O * . * . * . * . * @ */ static bool handle_case_0x70e(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x70e, i, j, k, ip1, j, k); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70e, i, j, k, i, jp1, k); return false; } /* * 3D case 0x713: O * . . . * b0: . . . * b1: . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * . . O * O O * * * * * @ */ static bool handle_case_0x713(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x713, i, j, k, ip1, j, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x713, i, j, k, i, j, kp1); return false; } /* * 3D case 0x715: O * . . . * b0: . . . * b1: t->sw[i+1][j ][k ] . . . * b2: . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O . * b5: t->sw[i+1][j ][k+1] . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * O . . * O O * * * * * @ */ static bool handle_case_0x715(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x715, i, j, k, i, jp1, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x715, i, j, k, i, j, kp1); return false; } /* * 3D case 0x723: O * . . * b0: . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . . * . . O * O O * * * * * @ */ static bool handle_case_0x723(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x723, i, j, k, i, j, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x723, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x72a: O * . * b0: t->sw[i ][j ][k ] . * b1: . * b2: t->sw[i ][j+1][k ] . * b3: O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x72a(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x72a, i, j, k, ip1, jp1, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x72a, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x731: O * . . * b0: . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * . . O . * O O * * * * * @ */ static bool handle_case_0x731(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x731, i, j, k, i, j, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x731, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x732: O * . . * b0: t->sw[i ][j ][k ] . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . * . . O * O O * . * . * . * . * @ */ static bool handle_case_0x732(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x732, i, j, k, ip1, j, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x732, i, j, k, i, j, kp1); return false; } /* * 3D case 0x745: O * . . * b0: . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . . * O . . * O O * * * * * @ */ static bool handle_case_0x745(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x745, i, j, k, i, j, k); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x745, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x74c: O * . * b0: t->sw[i ][j ][k ] . * b1: t->sw[i+1][j ][k ] . * b2: . * b3: O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * O . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x74c(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x74c, i, j, k, ip1, jp1, k); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x74c, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x751: O * . . * b0: . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . . * b7: t->sw[i+1][j+1][k+1] . . . * . O . . * O O * * * * * @ */ static bool handle_case_0x751(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x751, i, j, k, i, j, k); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x751, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x754: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * O . . * O O * . * . * . * . * @ */ static bool handle_case_0x754(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x754, i, j, k, i, jp1, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x754, i, j, k, i, j, kp1); return false; } /* * 3D case 0x770: O * . * b0: t->sw[i ][j ][k ] . * b1: t->sw[i+1][j ][k ] . * b2: t->sw[i ][j+1][k ] . * b3: t->sw[i+1][j+1][k ] O . O * b4: O * b5: . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . * . O . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x770(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x770, i, j, k, ip1, j, kp1); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x770, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x78a: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] . . O . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: . . . * . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x78a(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x78a, i, j, k, ip1, j, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x78a, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x78c: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: O O * b4: t->sw[i ][j ][k+1] . O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: . . . * O . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x78c(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x78c, i, j, k, i, jp1, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x78c, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7a2: O * * b0: t->sw[i ][j ][k ] * b1: * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . . * . . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7a2(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7a2, i, j, k, ip1, j, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7a2, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7a8: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[ip1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . * b6: t->sw[i ][j+1][k+1] . . * b7: . . * . O * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7a8(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7a8, i, j, k, ip1, jp1, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x7a8, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x7b0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: . . . * . . O . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x7b0(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x7b0, i, j, k, i, j, kp1); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7b0, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7c4: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . * b7: . . . * O . . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x7c4(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7c4, i, j, k, i, jp1, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7c4, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7c8: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . * b6: . . * b7: . . * O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7c8(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7c8, i, j, k, ip1, jp1, k); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7c8, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x7d0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: O . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . . * b7: . . . * . O . . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x7d0(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x7d0, i, j, k, i, j, kp1); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7d0, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7e0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] O * b5: . . * b6: . . * b7: . . * . O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7e0(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x7e0, i, j, k, ip1, j, kp1); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7e0, i, j, k, i, jp1, kp1); return false; } /* * Handle the cases where two corners on a single edge are missing. */ /* * 3D case 0x703: O * . . . * b0: . . . * b1: . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . . O * O O * * * * * @ */ static bool handle_case_0x703(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x703, i, j, k, i, j, k); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x703, i, j, k, ip1, j, k); return false; } /* * 3D case 0x705: O * . . . * b0: . . . * b1: t->sw[i+1][j ][k ] . . . * b2: . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . . * O . . * O O * * * * * @ */ static bool handle_case_0x705(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x705, i, j, k, i, j, k); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x705, i, j, k, i, jp1, k); return false; } /* * 3D case 0x70a: O * . . . * b0: t->sw[i ][j ][k ] . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: O O * b4: t->sw[i ][j ][k+1] . . O . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x70a(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x70a, i, j, k, ip1, j, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70a, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x70c: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: O O * b4: t->sw[i ][j ][k+1] . O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * O . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x70c(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70c, i, j, k, i, jp1, k); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x70c, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x711: O * . . . * b0: . . . * b1: t->sw[i+1][j ][k ] . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . . O . . * O O * * * * * @ */ static bool handle_case_0x711(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x711, i, j, k, i, j, k); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x711, i, j, k, i, j, kp1); return false; } /* * 3D case 0x722: O * . . * b0: t->sw[i ][j ][k ] . . * b1: . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . * b7: t->sw[i+1][j+1][k+1] . . . * . . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x722(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x722, i, j, k, ip1, j, k); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][jp1][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x722, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x730: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O * b5: . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . * . . O . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x730(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[i][jp1][k], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x730, i, j, k, i, j, kp1); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x730, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x744: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . * b7: t->sw[i+1][j+1][k+1] . . . * O . . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x744(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x744, i, j, k, i, jp1, k); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[ip1][j][kp1], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x744, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x750: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: O . * b5: t->sw[i+1][j ][k+1] . . . * b6: . . . * b7: t->sw[i+1][j+1][k+1] . . . * . O . . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x750(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x750, i, j, k, i, j, kp1); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][jp1][kp1]))) { return true; } log_no_crnr(t, 0x750, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x788: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[ip1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: O O * b4: t->sw[i ][j ][k+1] . . O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: . . . . * . O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x788(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x788, i, j, k, ip1, jp1, k); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x788, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7a0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] . . O * b5: . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: . . . . * . . O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7a0(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x7a0, i, j, k, ip1, j, kp1); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][jp1][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7a0, i, j, k, ip1, jp1, kp1); return false; } /* * 3D case 0x7c0: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: . . . * b7: . . . . * . O . . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x7c0(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][j][kp1], t->sw[i][j][k], t->sw[i][jp1][k]))) { return true; } log_no_crnr(t, 0x7c0, i, j, k, i, jp1, kp1); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[ip1][j][kp1], t->sw[ip1][j][k], t->sw[ip1][jp1][k]))) { return true; } log_no_crnr(t, 0x7c0, i, j, k, ip1, jp1, kp1); return false; } /* * Handle the cases where a single corner is missing. */ /* * 3D case 0x701: O * . . . * b0: . . . * b1: t->sw[i+1][j ][k ] . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O . . * b5: t->sw[i+1][j ][k+1] . . . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: t->sw[i+1][j+1][k+1] . . . . . . * . . O . . * O O * * * * * @ */ static bool handle_case_0x701(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, i, j, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[ip1][jp1][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x701, i, j, k, i, j, k); return false; } /* * 3D case 0x702: O * . . . * b0: t->sw[i ][j ][k ] . . . * b1: . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . . O * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x702(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x702, i, j, k, ip1, j, k); return false; } /* * 3D case 0x704: O * . . . * b0: t->sw[i ][j ][k ] . . . * b1: t->sw[i+1][j ][k ] . . . * b2: . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . . * O . . * O . O * . . * . . * . . * . . * @ */ static bool handle_case_0x704(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, k, tfind_face_corner(t->sw[i][j][k], t->sw[i][j][kp1], t->sw[i][jp1][kp1]))) { return true; } log_no_crnr(t, 0x704, i, j, k, i, jp1, k); return false; } /* * 3D case 0x708: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: O O * b4: t->sw[i ][j ][k+1] . . O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x708(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); if (install_tswitch(t, ip1, jp1, k, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[ip1][j][k]))) { return true; } log_no_crnr(t, 0x708, i, j, k, ip1, jp1, k); return false; } /* * 3D case 0x710: O * . . . * b0: t->sw[i ][j ][k ] . . . * b1: t->sw[i+1][j ][k ] . . . * b2: t->sw[i ][j+1][k ] . . . * b3: t->sw[i+1][j+1][k ] O . O * b4: . O . * b5: t->sw[i+1][j ][k+1] . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . . O . . * O O * . . * . . * . . * . . * @ */ static bool handle_case_0x710(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, j, kp1, tfind_face_corner(t->sw[i][j][k], t->sw[ip1][j][k], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x710, i, j, k, i, j, kp1); return false; } /* * 3D case 0x720: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] . . O * b5: . . . . * b6: t->sw[i ][j+1][k+1] . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . . O . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x720(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, j, kp1, tfind_face_corner(t->sw[ip1][j][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x720, i, j, k, ip1, j, kp1); return false; } /* * 3D case 0x740: O * . . * b0: t->sw[i ][j ][k ] . . * b1: t->sw[i+1][j ][k ] . . * b2: t->sw[i ][j+1][k ] . . * b3: t->sw[i+1][j+1][k ] O . O * b4: t->sw[i ][j ][k+1] O . . * b5: t->sw[i+1][j ][k+1] . . . . * b6: . . . * b7: t->sw[i+1][j+1][k+1] . . . . * . O . . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x740(struct torus *t, int i, int j, int k) { int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, i, jp1, kp1, tfind_face_corner(t->sw[i][jp1][k], t->sw[i][j][k], t->sw[i][j][kp1]))) { return true; } log_no_crnr(t, 0x740, i, j, k, i, jp1, kp1); return false; } /* * 3D case 0x780: O * * b0: t->sw[i ][j ][k ] * b1: t->sw[i+1][j ][k ] * b2: t->sw[i ][j+1][k ] * b3: t->sw[i+1][j+1][k ] O O * b4: t->sw[i ][j ][k+1] . . O . . * b5: t->sw[i+1][j ][k+1] . . . . . . * b6: t->sw[i ][j+1][k+1] . . . . * b7: . . . . . . * . . O . . * O . O * . . . * . . . * . . . * . . . * @ */ static bool handle_case_0x780(struct torus *t, int i, int j, int k) { int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); if (install_tswitch(t, ip1, jp1, kp1, tfind_face_corner(t->sw[i][jp1][kp1], t->sw[i][j][kp1], t->sw[ip1][j][kp1]))) { return true; } log_no_crnr(t, 0x780, i, j, k, ip1, jp1, kp1); return false; } /* * Make sure links between all known torus/mesh switches are installed. * * We don't have to worry about links that wrap on a mesh coordinate, as * there shouldn't be any; if there are it indicates an input error. */ static void check_tlinks(struct torus *t, int i, int j, int k) { struct t_switch ****sw = t->sw; int ip1 = canonicalize(i + 1, t->x_sz); int jp1 = canonicalize(j + 1, t->y_sz); int kp1 = canonicalize(k + 1, t->z_sz); /* * Don't waste time/code checking return status of link_tswitches() * here. It is unlikely to fail, and the result of any failure here * will be caught elsewhere anyway. */ if (sw[i][j][k] && sw[ip1][j][k]) link_tswitches(t, 0, sw[i][j][k], sw[ip1][j][k]); if (sw[i][jp1][k] && sw[ip1][jp1][k]) link_tswitches(t, 0, sw[i][jp1][k], sw[ip1][jp1][k]); if (sw[i][j][kp1] && sw[ip1][j][kp1]) link_tswitches(t, 0, sw[i][j][kp1], sw[ip1][j][kp1]); if (sw[i][jp1][kp1] && sw[ip1][jp1][kp1]) link_tswitches(t, 0, sw[i][jp1][kp1], sw[ip1][jp1][kp1]); if (sw[i][j][k] && sw[i][jp1][k]) link_tswitches(t, 1, sw[i][j][k], sw[i][jp1][k]); if (sw[ip1][j][k] && sw[ip1][jp1][k]) link_tswitches(t, 1, sw[ip1][j][k], sw[ip1][jp1][k]); if (sw[i][j][kp1] && sw[i][jp1][kp1]) link_tswitches(t, 1, sw[i][j][kp1], sw[i][jp1][kp1]); if (sw[ip1][j][kp1] && sw[ip1][jp1][kp1]) link_tswitches(t, 1, sw[ip1][j][kp1], sw[ip1][jp1][kp1]); if (sw[i][j][k] && sw[i][j][kp1]) link_tswitches(t, 2, sw[i][j][k], sw[i][j][kp1]); if (sw[ip1][j][k] && sw[ip1][j][kp1]) link_tswitches(t, 2, sw[ip1][j][k], sw[ip1][j][kp1]); if (sw[i][jp1][k] && sw[i][jp1][kp1]) link_tswitches(t, 2, sw[i][jp1][k], sw[i][jp1][kp1]); if (sw[ip1][jp1][k] && sw[ip1][jp1][kp1]) link_tswitches(t, 2, sw[ip1][jp1][k], sw[ip1][jp1][kp1]); } static void locate_sw(struct torus *t, int i, int j, int k) { unsigned fp; bool success; i = canonicalize(i, t->x_sz); j = canonicalize(j, t->y_sz); k = canonicalize(k, t->z_sz); /* * By definition, if a coordinate direction is meshed, we don't * allow it to wrap to zero. */ if (t->flags & X_MESH) { int ip1 = canonicalize(i + 1, t->x_sz); if (ip1 < i) goto out; } if (t->flags & Y_MESH) { int jp1 = canonicalize(j + 1, t->y_sz); if (jp1 < j) goto out; } if (t->flags & Z_MESH) { int kp1 = canonicalize(k + 1, t->z_sz); if (kp1 < k) goto out; } /* * There are various reasons that the links are not installed between * known torus switches. These include cases where the search for * new switches only partially succeeds due to missing switches, and * cases where we haven't processed this position yet, but processing * of multiple independent neighbor positions has installed switches * into corners of our case. * * In any event, the topology assumptions made in handling the * fingerprint for this position require that all links be installed * between installed switches for this position. */ again: check_tlinks(t, i, j, k); fp = fingerprint(t, i, j, k); switch (fp) { /* * When all switches are present, we are done. Otherwise, one of * the cases below will be unsuccessful, and we'll be done also. * * Note that check_tlinks() above will ensure all links that are * present are connected, in the event that all our switches are * present due to successful case handling in the surrounding * torus/mesh. */ case 0x300: case 0x500: case 0x600: case 0x700: goto out; /* * Ignore the 2D cases where there isn't enough information to uniquely * locate/place a switch into the cube. */ case 0x30f: /* 0 corners available */ case 0x533: /* 0 corners available */ case 0x655: /* 0 corners available */ case 0x30e: /* 1 corner available */ case 0x532: /* 1 corner available */ case 0x654: /* 1 corner available */ case 0x30d: /* 1 corner available */ case 0x531: /* 1 corner available */ case 0x651: /* 1 corner available */ case 0x30b: /* 1 corner available */ case 0x523: /* 1 corner available */ case 0x645: /* 1 corner available */ case 0x307: /* 1 corner available */ case 0x513: /* 1 corner available */ case 0x615: /* 1 corner available */ goto out; /* * Handle the 2D cases with a single existing edge. * */ case 0x30c: success = handle_case_0x30c(t, i, j, k); break; case 0x303: success = handle_case_0x303(t, i, j, k); break; case 0x305: success = handle_case_0x305(t, i, j, k); break; case 0x30a: success = handle_case_0x30a(t, i, j, k); break; case 0x503: success = handle_case_0x503(t, i, j, k); break; case 0x511: success = handle_case_0x511(t, i, j, k); break; case 0x522: success = handle_case_0x522(t, i, j, k); break; case 0x530: success = handle_case_0x530(t, i, j, k); break; case 0x605: success = handle_case_0x605(t, i, j, k); break; case 0x611: success = handle_case_0x611(t, i, j, k); break; case 0x644: success = handle_case_0x644(t, i, j, k); break; case 0x650: success = handle_case_0x650(t, i, j, k); break; /* * Handle the 2D cases where two existing edges meet at a corner. */ case 0x301: success = handle_case_0x301(t, i, j, k); break; case 0x302: success = handle_case_0x302(t, i, j, k); break; case 0x304: success = handle_case_0x304(t, i, j, k); break; case 0x308: success = handle_case_0x308(t, i, j, k); break; case 0x501: success = handle_case_0x501(t, i, j, k); break; case 0x502: success = handle_case_0x502(t, i, j, k); break; case 0x520: success = handle_case_0x520(t, i, j, k); break; case 0x510: success = handle_case_0x510(t, i, j, k); break; case 0x601: success = handle_case_0x601(t, i, j, k); break; case 0x604: success = handle_case_0x604(t, i, j, k); break; case 0x610: success = handle_case_0x610(t, i, j, k); break; case 0x640: success = handle_case_0x640(t, i, j, k); break; /* * Ignore the 3D cases where there isn't enough information to uniquely * locate/place a switch into the cube. */ case 0x7ff: /* 0 corners available */ case 0x7fe: /* 1 corner available */ case 0x7fd: /* 1 corner available */ case 0x7fb: /* 1 corner available */ case 0x7f7: /* 1 corner available */ case 0x7ef: /* 1 corner available */ case 0x7df: /* 1 corner available */ case 0x7bf: /* 1 corner available */ case 0x77f: /* 1 corner available */ case 0x7fc: /* 2 adj corners available */ case 0x7fa: /* 2 adj corners available */ case 0x7f5: /* 2 adj corners available */ case 0x7f3: /* 2 adj corners available */ case 0x7cf: /* 2 adj corners available */ case 0x7af: /* 2 adj corners available */ case 0x75f: /* 2 adj corners available */ case 0x73f: /* 2 adj corners available */ case 0x7ee: /* 2 adj corners available */ case 0x7dd: /* 2 adj corners available */ case 0x7bb: /* 2 adj corners available */ case 0x777: /* 2 adj corners available */ goto out; /* * Handle the 3D cases where two existing edges meet at a corner. * */ case 0x71f: success = handle_case_0x71f(t, i, j, k); break; case 0x72f: success = handle_case_0x72f(t, i, j, k); break; case 0x737: success = handle_case_0x737(t, i, j, k); break; case 0x73b: success = handle_case_0x73b(t, i, j, k); break; case 0x74f: success = handle_case_0x74f(t, i, j, k); break; case 0x757: success = handle_case_0x757(t, i, j, k); break; case 0x75d: success = handle_case_0x75d(t, i, j, k); break; case 0x773: success = handle_case_0x773(t, i, j, k); break; case 0x775: success = handle_case_0x775(t, i, j, k); break; case 0x78f: success = handle_case_0x78f(t, i, j, k); break; case 0x7ab: success = handle_case_0x7ab(t, i, j, k); break; case 0x7ae: success = handle_case_0x7ae(t, i, j, k); break; case 0x7b3: success = handle_case_0x7b3(t, i, j, k); break; case 0x7ba: success = handle_case_0x7ba(t, i, j, k); break; case 0x7cd: success = handle_case_0x7cd(t, i, j, k); break; case 0x7ce: success = handle_case_0x7ce(t, i, j, k); break; case 0x7d5: success = handle_case_0x7d5(t, i, j, k); break; case 0x7dc: success = handle_case_0x7dc(t, i, j, k); break; case 0x7ea: success = handle_case_0x7ea(t, i, j, k); break; case 0x7ec: success = handle_case_0x7ec(t, i, j, k); break; case 0x7f1: success = handle_case_0x7f1(t, i, j, k); break; case 0x7f2: success = handle_case_0x7f2(t, i, j, k); break; case 0x7f4: success = handle_case_0x7f4(t, i, j, k); break; case 0x7f8: success = handle_case_0x7f8(t, i, j, k); break; /* * Handle the cases where three existing edges meet at a corner. * */ case 0x717: success = handle_case_0x717(t, i, j, k); break; case 0x72b: success = handle_case_0x72b(t, i, j, k); break; case 0x74d: success = handle_case_0x74d(t, i, j, k); break; case 0x771: success = handle_case_0x771(t, i, j, k); break; case 0x78e: success = handle_case_0x78e(t, i, j, k); break; case 0x7b2: success = handle_case_0x7b2(t, i, j, k); break; case 0x7d4: success = handle_case_0x7d4(t, i, j, k); break; case 0x7e8: success = handle_case_0x7e8(t, i, j, k); break; /* * Handle the cases where four corners on a single face are missing. */ case 0x70f: success = handle_case_0x70f(t, i, j, k); break; case 0x733: success = handle_case_0x733(t, i, j, k); break; case 0x755: success = handle_case_0x755(t, i, j, k); break; case 0x7aa: success = handle_case_0x7aa(t, i, j, k); break; case 0x7cc: success = handle_case_0x7cc(t, i, j, k); break; case 0x7f0: success = handle_case_0x7f0(t, i, j, k); break; /* * Handle the cases where three corners on a single face are missing. */ case 0x707: success = handle_case_0x707(t, i, j, k); break; case 0x70b: success = handle_case_0x70b(t, i, j, k); break; case 0x70d: success = handle_case_0x70d(t, i, j, k); break; case 0x70e: success = handle_case_0x70e(t, i, j, k); break; case 0x713: success = handle_case_0x713(t, i, j, k); break; case 0x715: success = handle_case_0x715(t, i, j, k); break; case 0x723: success = handle_case_0x723(t, i, j, k); break; case 0x72a: success = handle_case_0x72a(t, i, j, k); break; case 0x731: success = handle_case_0x731(t, i, j, k); break; case 0x732: success = handle_case_0x732(t, i, j, k); break; case 0x745: success = handle_case_0x745(t, i, j, k); break; case 0x74c: success = handle_case_0x74c(t, i, j, k); break; case 0x751: success = handle_case_0x751(t, i, j, k); break; case 0x754: success = handle_case_0x754(t, i, j, k); break; case 0x770: success = handle_case_0x770(t, i, j, k); break; case 0x78a: success = handle_case_0x78a(t, i, j, k); break; case 0x78c: success = handle_case_0x78c(t, i, j, k); break; case 0x7a2: success = handle_case_0x7a2(t, i, j, k); break; case 0x7a8: success = handle_case_0x7a8(t, i, j, k); break; case 0x7b0: success = handle_case_0x7b0(t, i, j, k); break; case 0x7c4: success = handle_case_0x7c4(t, i, j, k); break; case 0x7c8: success = handle_case_0x7c8(t, i, j, k); break; case 0x7d0: success = handle_case_0x7d0(t, i, j, k); break; case 0x7e0: success = handle_case_0x7e0(t, i, j, k); break; /* * Handle the cases where two corners on a single edge are missing. */ case 0x703: success = handle_case_0x703(t, i, j, k); break; case 0x705: success = handle_case_0x705(t, i, j, k); break; case 0x70a: success = handle_case_0x70a(t, i, j, k); break; case 0x70c: success = handle_case_0x70c(t, i, j, k); break; case 0x711: success = handle_case_0x711(t, i, j, k); break; case 0x722: success = handle_case_0x722(t, i, j, k); break; case 0x730: success = handle_case_0x730(t, i, j, k); break; case 0x744: success = handle_case_0x744(t, i, j, k); break; case 0x750: success = handle_case_0x750(t, i, j, k); break; case 0x788: success = handle_case_0x788(t, i, j, k); break; case 0x7a0: success = handle_case_0x7a0(t, i, j, k); break; case 0x7c0: success = handle_case_0x7c0(t, i, j, k); break; /* * Handle the cases where a single corner is missing. */ case 0x701: success = handle_case_0x701(t, i, j, k); break; case 0x702: success = handle_case_0x702(t, i, j, k); break; case 0x704: success = handle_case_0x704(t, i, j, k); break; case 0x708: success = handle_case_0x708(t, i, j, k); break; case 0x710: success = handle_case_0x710(t, i, j, k); break; case 0x720: success = handle_case_0x720(t, i, j, k); break; case 0x740: success = handle_case_0x740(t, i, j, k); break; case 0x780: success = handle_case_0x780(t, i, j, k); break; default: /* * There's lots of unhandled cases still, but it's not clear * we care. Let debugging show us what they are so we can * learn if we care. */ if (t->debug) OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "Unhandled fingerprint 0x%03x @ %d %d %d\n", fp, i, j, k); goto out; } /* * If we successfully handled a case, we may be able to make more * progress at this position, so try again. Otherwise, even though * we didn't successfully handle a case, we may have installed a * switch into the torus/mesh, so try to install links as well. * Then we'll have another go at the next position. */ if (success) { if (t->debug) OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "Success on fingerprint 0x%03x @ %d %d %d\n", fp, i, j, k); goto again; } else { check_tlinks(t, i, j, k); if (t->debug) OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "Failed on fingerprint 0x%03x @ %d %d %d\n", fp, i, j, k); } out: return; } #define LINK_ERR_STR " direction link required for topology seed configuration since radix == 4! See torus-2QoS.conf(5).\n" #define LINK_ERR2_STR " direction link required for topology seed configuration! See torus-2QoS.conf(5).\n" #define SEED_ERR_STR " direction links for topology seed do not share a common switch! See torus-2QoS.conf(5).\n" static bool verify_setup(struct torus *t, struct fabric *f) { struct coord_dirs *o; struct f_switch *sw; unsigned p, s, n = 0; bool success = false; bool all_sw_present, need_seed = true; if (!(t->x_sz && t->y_sz && t->z_sz)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E20: missing required torus size specification!\n"); goto out; } if (t->osm->subn.min_sw_data_vls < 2) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E48: Too few data VLs to support torus routing " "without credit loops (have switchport %d need 2)\n", (int)t->osm->subn.min_sw_data_vls); goto out; } if (t->osm->subn.min_sw_data_vls < 4) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Warning: Too few data VLs to support torus routing " "with a failed switch without credit loops " "(have switchport %d need 4)\n", (int)t->osm->subn.min_sw_data_vls); if (t->osm->subn.min_sw_data_vls < 8) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Warning: Too few data VLs to support torus routing " "with two QoS levels (have switchport %d need 8)\n", (int)t->osm->subn.min_sw_data_vls); if (t->osm->subn.min_data_vls < 2) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Warning: Too few data VLs to support torus routing " "with two QoS levels (have endport %d need 2)\n", (int)t->osm->subn.min_data_vls); /* * Be sure all the switches in the torus support the port * ordering that might have been configured. */ for (s = 0; s < f->switch_cnt; s++) { sw = f->sw[s]; for (p = 0; p < sw->port_cnt; p++) { if (t->port_order[p] >= sw->port_cnt) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E21: port_order configured using " "port %u, but only %u ports in " "switch w/ GUID 0x%04"PRIx64"\n", t->port_order[p], sw->port_cnt - 1, cl_ntoh64(sw->n_id)); goto out; } } } /* * Unfortunately, there is a problem with non-unique topology for any * torus dimension which has radix four. This problem requires extra * input, in the form of specifying both the positive and negative * coordinate directions from a common switch, for any torus dimension * with radix four (see also build_torus()). * * Do the checking required to ensure that the required information * is present, but more than the needed information is not required. * * So, verify that we learned the coordinate directions correctly for * the fabric. The coordinate direction links get an invalid port * set on their ends when parsed. */ again: all_sw_present = true; o = &t->seed[n]; if (t->x_sz == 4 && !(t->flags & X_MESH)) { if (o->xp_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E22: Positive x" LINK_ERR_STR); goto out; } if (o->xm_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E23: Negative x" LINK_ERR_STR); goto out; } if (o->xp_link.end[0].n_id != o->xm_link.end[0].n_id) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E24: Positive/negative x" SEED_ERR_STR); goto out; } } if (t->y_sz == 4 && !(t->flags & Y_MESH)) { if (o->yp_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E25: Positive y" LINK_ERR_STR); goto out; } if (o->ym_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E26: Negative y" LINK_ERR_STR); goto out; } if (o->yp_link.end[0].n_id != o->ym_link.end[0].n_id) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E27: Positive/negative y" SEED_ERR_STR); goto out; } } if (t->z_sz == 4 && !(t->flags & Z_MESH)) { if (o->zp_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E28: Positive z" LINK_ERR_STR); goto out; } if (o->zm_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E29: Negative z" LINK_ERR_STR); goto out; } if (o->zp_link.end[0].n_id != o->zm_link.end[0].n_id) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2A: Positive/negative z" SEED_ERR_STR); goto out; } } if (t->x_sz > 1) { if (o->xp_link.end[0].port >= 0 && o->xm_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2B: Positive or negative x" LINK_ERR2_STR); goto out; } if (o->xp_link.end[0].port < 0 && !find_f_sw(f, o->xp_link.end[0].n_id)) all_sw_present = false; if (o->xp_link.end[1].port < 0 && !find_f_sw(f, o->xp_link.end[1].n_id)) all_sw_present = false; if (o->xm_link.end[0].port < 0 && !find_f_sw(f, o->xm_link.end[0].n_id)) all_sw_present = false; if (o->xm_link.end[1].port < 0 && !find_f_sw(f, o->xm_link.end[1].n_id)) all_sw_present = false; } if (t->z_sz > 1) { if (o->zp_link.end[0].port >= 0 && o->zm_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2C: Positive or negative z" LINK_ERR2_STR); goto out; } if ((o->xp_link.end[0].port < 0 && o->zp_link.end[0].port < 0 && o->zp_link.end[0].n_id != o->xp_link.end[0].n_id) || (o->xp_link.end[0].port < 0 && o->zm_link.end[0].port < 0 && o->zm_link.end[0].n_id != o->xp_link.end[0].n_id) || (o->xm_link.end[0].port < 0 && o->zp_link.end[0].port < 0 && o->zp_link.end[0].n_id != o->xm_link.end[0].n_id) || (o->xm_link.end[0].port < 0 && o->zm_link.end[0].port < 0 && o->zm_link.end[0].n_id != o->xm_link.end[0].n_id)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2D: x and z" SEED_ERR_STR); goto out; } if (o->zp_link.end[0].port < 0 && !find_f_sw(f, o->zp_link.end[0].n_id)) all_sw_present = false; if (o->zp_link.end[1].port < 0 && !find_f_sw(f, o->zp_link.end[1].n_id)) all_sw_present = false; if (o->zm_link.end[0].port < 0 && !find_f_sw(f, o->zm_link.end[0].n_id)) all_sw_present = false; if (o->zm_link.end[1].port < 0 && !find_f_sw(f, o->zm_link.end[1].n_id)) all_sw_present = false; } if (t->y_sz > 1) { if (o->yp_link.end[0].port >= 0 && o->ym_link.end[0].port >= 0) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2E: Positive or negative y" LINK_ERR2_STR); goto out; } if ((o->xp_link.end[0].port < 0 && o->yp_link.end[0].port < 0 && o->yp_link.end[0].n_id != o->xp_link.end[0].n_id) || (o->xp_link.end[0].port < 0 && o->ym_link.end[0].port < 0 && o->ym_link.end[0].n_id != o->xp_link.end[0].n_id) || (o->xm_link.end[0].port < 0 && o->yp_link.end[0].port < 0 && o->yp_link.end[0].n_id != o->xm_link.end[0].n_id) || (o->xm_link.end[0].port < 0 && o->ym_link.end[0].port < 0 && o->ym_link.end[0].n_id != o->xm_link.end[0].n_id)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E2F: x and y" SEED_ERR_STR); goto out; } if (o->yp_link.end[0].port < 0 && !find_f_sw(f, o->yp_link.end[0].n_id)) all_sw_present = false; if (o->yp_link.end[1].port < 0 && !find_f_sw(f, o->yp_link.end[1].n_id)) all_sw_present = false; if (o->ym_link.end[0].port < 0 && !find_f_sw(f, o->ym_link.end[0].n_id)) all_sw_present = false; if (o->ym_link.end[1].port < 0 && !find_f_sw(f, o->ym_link.end[1].n_id)) all_sw_present = false; } if (all_sw_present && need_seed) { t->seed_idx = n; need_seed = false; } if (++n < t->seed_cnt) goto again; if (need_seed) OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E30: Every configured torus seed has at " "least one switch missing in fabric! See " "torus-2QoS.conf(5) and TORUS TOPOLOGY DISCOVERY " "in torus-2QoS(8)\n"); else success = true; out: return success; } static bool build_torus(struct fabric *f, struct torus *t) { int i, j, k; int im1, jm1, km1; int ip1, jp1, kp1; unsigned nlink; struct coord_dirs *o; struct f_switch *fsw0, *fsw1; struct t_switch ****sw = t->sw; bool success = true; t->link_pool_sz = f->link_cnt; t->link_pool = calloc(1, t->link_pool_sz * sizeof(*t->link_pool)); if (!t->link_pool) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E31: Allocating torus link pool: %s\n", strerror(errno)); goto out; } t->fabric = f; /* * Get things started by locating the up to seven switches that * define the torus "seed", coordinate directions, and datelines. */ o = &t->seed[t->seed_idx]; i = canonicalize(-o->x_dateline, t->x_sz); j = canonicalize(-o->y_dateline, t->y_sz); k = canonicalize(-o->z_dateline, t->z_sz); if (o->xp_link.end[0].port < 0) { ip1 = canonicalize(1 - o->x_dateline, t->x_sz); fsw0 = find_f_sw(f, o->xp_link.end[0].n_id); fsw1 = find_f_sw(f, o->xp_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, ip1, j, k, fsw1) && success; } if (o->xm_link.end[0].port < 0) { im1 = canonicalize(-1 - o->x_dateline, t->x_sz); fsw0 = find_f_sw(f, o->xm_link.end[0].n_id); fsw1 = find_f_sw(f, o->xm_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, im1, j, k, fsw1) && success; } if (o->yp_link.end[0].port < 0) { jp1 = canonicalize(1 - o->y_dateline, t->y_sz); fsw0 = find_f_sw(f, o->yp_link.end[0].n_id); fsw1 = find_f_sw(f, o->yp_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, i, jp1, k, fsw1) && success; } if (o->ym_link.end[0].port < 0) { jm1 = canonicalize(-1 - o->y_dateline, t->y_sz); fsw0 = find_f_sw(f, o->ym_link.end[0].n_id); fsw1 = find_f_sw(f, o->ym_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, i, jm1, k, fsw1) && success; } if (o->zp_link.end[0].port < 0) { kp1 = canonicalize(1 - o->z_dateline, t->z_sz); fsw0 = find_f_sw(f, o->zp_link.end[0].n_id); fsw1 = find_f_sw(f, o->zp_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, i, j, kp1, fsw1) && success; } if (o->zm_link.end[0].port < 0) { km1 = canonicalize(-1 - o->z_dateline, t->z_sz); fsw0 = find_f_sw(f, o->zm_link.end[0].n_id); fsw1 = find_f_sw(f, o->zm_link.end[1].n_id); success = install_tswitch(t, i, j, k, fsw0) && install_tswitch(t, i, j, km1, fsw1) && success; } if (!success) goto out; if (!t->seed_idx) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Using torus seed configured as default " "(seed sw %d,%d,%d GUID 0x%04"PRIx64").\n", i, j, k, cl_ntoh64(sw[i][j][k]->n_id)); else OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Using torus seed configured as backup #%u " "(seed sw %d,%d,%d GUID 0x%04"PRIx64").\n", t->seed_idx, i, j, k, cl_ntoh64(sw[i][j][k]->n_id)); /* * Search the fabric and construct the expected torus topology. * * The algorithm is to consider the "cube" formed by eight switch * locations bounded by the corners i, j, k and i+1, j+1, k+1. * For each such cube look at the topology of the switches already * placed in the torus, and deduce which new switches can be placed * into their proper locations in the torus. Examine each cube * multiple times, until the number of links moved into the torus * topology does not change. */ again: nlink = t->link_cnt; for (k = 0; k < (int)t->z_sz; k++) for (j = 0; j < (int)t->y_sz; j++) for (i = 0; i < (int)t->x_sz; i++) locate_sw(t, i, j, k); if (t->link_cnt != nlink) goto again; /* * Move all other endpoints into torus/mesh. */ for (k = 0; k < (int)t->z_sz; k++) for (j = 0; j < (int)t->y_sz; j++) for (i = 0; i < (int)t->x_sz; i++) if (!link_srcsink(t, i, j, k)) { success = false; goto out; } out: return success; } /* * Returns a count of differences between old and new switches. */ static unsigned tsw_changes(struct t_switch *nsw, struct t_switch *osw) { unsigned p, cnt = 0, port_cnt; struct endpoint *npt, *opt; struct endpoint *rnpt, *ropt; if (nsw && !osw) { cnt++; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "New torus switch %d,%d,%d GUID 0x%04"PRIx64"\n", nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id)); goto out; } if (osw && !nsw) { cnt++; OSM_LOG(&osw->torus->osm->log, OSM_LOG_INFO, "Lost torus switch %d,%d,%d GUID 0x%04"PRIx64"\n", osw->i, osw->j, osw->k, cl_ntoh64(osw->n_id)); goto out; } if (!(nsw && osw)) goto out; if (nsw->n_id != osw->n_id) { cnt++; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "Torus switch %d,%d,%d GUID " "was 0x%04"PRIx64", now 0x%04"PRIx64"\n", nsw->i, nsw->j, nsw->k, cl_ntoh64(osw->n_id), cl_ntoh64(nsw->n_id)); } if (nsw->port_cnt != osw->port_cnt) { cnt++; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "Torus switch %d,%d,%d GUID 0x%04"PRIx64" " "had %d ports, now has %d\n", nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id), osw->port_cnt, nsw->port_cnt); } port_cnt = nsw->port_cnt; if (port_cnt > osw->port_cnt) port_cnt = osw->port_cnt; for (p = 0; p < port_cnt; p++) { npt = nsw->port[p]; opt = osw->port[p]; if (npt && npt->link) { if (&npt->link->end[0] == npt) rnpt = &npt->link->end[1]; else rnpt = &npt->link->end[0]; } else rnpt = NULL; if (opt && opt->link) { if (&opt->link->end[0] == opt) ropt = &opt->link->end[1]; else ropt = &opt->link->end[0]; } else ropt = NULL; if (rnpt && !ropt) { ++cnt; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] " "remote now %s GUID 0x%04"PRIx64"[%d], " "was missing\n", nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id), p, rnpt->type == PASSTHRU ? "sw" : "node", cl_ntoh64(rnpt->n_id), rnpt->port); continue; } if (ropt && !rnpt) { ++cnt; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] " "remote now missing, " "was %s GUID 0x%04"PRIx64"[%d]\n", osw->i, osw->j, osw->k, cl_ntoh64(nsw->n_id), p, ropt->type == PASSTHRU ? "sw" : "node", cl_ntoh64(ropt->n_id), ropt->port); continue; } if (!(rnpt && ropt)) continue; if (rnpt->n_id != ropt->n_id) { ++cnt; OSM_LOG(&nsw->torus->osm->log, OSM_LOG_INFO, "Torus switch %d,%d,%d GUID 0x%04"PRIx64"[%d] " "remote now %s GUID 0x%04"PRIx64"[%d], " "was %s GUID 0x%04"PRIx64"[%d]\n", nsw->i, nsw->j, nsw->k, cl_ntoh64(nsw->n_id), p, rnpt->type == PASSTHRU ? "sw" : "node", cl_ntoh64(rnpt->n_id), rnpt->port, ropt->type == PASSTHRU ? "sw" : "node", cl_ntoh64(ropt->n_id), ropt->port); continue; } } out: return cnt; } static void dump_torus(struct torus *t) { unsigned i, j, k; unsigned x_sz = t->x_sz; unsigned y_sz = t->y_sz; unsigned z_sz = t->z_sz; char path[1024]; FILE *file; snprintf(path, sizeof(path), "%s/%s", t->osm->subn.opt.dump_files_dir, "opensm-torus.dump"); file = fopen(path, "w"); if (!file) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E47: cannot create file \'%s\'\n", path); return; } for (k = 0; k < z_sz; k++) for (j = 0; j < y_sz; j++) for (i = 0; i < x_sz; i++) if (t->sw[i][j][k]) fprintf(file, "switch %u,%u,%u GUID 0x%04" PRIx64 " (%s)\n", i, j, k, cl_ntoh64(t->sw[i][j][k]->n_id), t->sw[i][j][k]->osm_switch->p_node->print_desc); fclose(file); } static void report_torus_changes(struct torus *nt, struct torus *ot) { unsigned cnt = 0; unsigned i, j, k; unsigned x_sz = nt->x_sz; unsigned y_sz = nt->y_sz; unsigned z_sz = nt->z_sz; unsigned max_changes = nt->max_changes; if (OSM_LOG_IS_ACTIVE_V2(&nt->osm->log, OSM_LOG_ROUTING)) dump_torus(nt); if (!ot) return; if (x_sz != ot->x_sz) { cnt++; OSM_LOG(&nt->osm->log, OSM_LOG_INFO, "Torus x radix was %d now %d\n", ot->x_sz, nt->x_sz); if (x_sz > ot->x_sz) x_sz = ot->x_sz; } if (y_sz != ot->y_sz) { cnt++; OSM_LOG(&nt->osm->log, OSM_LOG_INFO, "Torus y radix was %d now %d\n", ot->y_sz, nt->y_sz); if (y_sz > ot->y_sz) y_sz = ot->y_sz; } if (z_sz != ot->z_sz) { cnt++; OSM_LOG(&nt->osm->log, OSM_LOG_INFO, "Torus z radix was %d now %d\n", ot->z_sz, nt->z_sz); if (z_sz > ot->z_sz) z_sz = ot->z_sz; } for (k = 0; k < z_sz; k++) for (j = 0; j < y_sz; j++) for (i = 0; i < x_sz; i++) { cnt += tsw_changes(nt->sw[i][j][k], ot->sw[i][j][k]); /* * Booting a big fabric will cause lots of * changes as hosts come up, so don't spew. * We want to log changes to learn more about * bouncing links, etc, so they can be fixed. */ if (cnt > max_changes) { OSM_LOG(&nt->osm->log, OSM_LOG_INFO, "Too many torus changes; " "stopping reporting early\n"); return; } } } static void rpt_torus_missing(struct torus *t, int i, int j, int k, struct t_switch *sw, int *missing_z) { uint64_t guid_ho; if (!sw) { /* * We can have multiple missing switches without deadlock * if and only if they are adajacent in the Z direction. */ if ((t->switch_cnt + 1) < t->sw_pool_sz) { if (t->sw[i][j][canonicalize(k - 1, t->z_sz)] && t->sw[i][j][canonicalize(k + 1, t->z_sz)]) t->flags |= MSG_DEADLOCK; } /* * There can be only one such Z-column of missing switches. */ if (*missing_z < 0) *missing_z = i + j * t->x_sz; else if (*missing_z != i + j * t->x_sz) t->flags |= MSG_DEADLOCK; OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus switch at %d,%d,%d\n", i, j, k); return; } guid_ho = cl_ntoh64(sw->n_id); if (!(sw->ptgrp[0].port_cnt || (t->x_sz == 1) || ((t->flags & X_MESH) && i == 0))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus -x link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); if (!(sw->ptgrp[1].port_cnt || (t->x_sz == 1) || ((t->flags & X_MESH) && (i + 1) == t->x_sz))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus +x link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); if (!(sw->ptgrp[2].port_cnt || (t->y_sz == 1) || ((t->flags & Y_MESH) && j == 0))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus -y link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); if (!(sw->ptgrp[3].port_cnt || (t->y_sz == 1) || ((t->flags & Y_MESH) && (j + 1) == t->y_sz))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus +y link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); if (!(sw->ptgrp[4].port_cnt || (t->z_sz == 1) || ((t->flags & Z_MESH) && k == 0))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus -z link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); if (!(sw->ptgrp[5].port_cnt || (t->z_sz == 1) || ((t->flags & Z_MESH) && (k + 1) == t->z_sz))) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Missing torus +z link on " "switch %d,%d,%d GUID 0x%04"PRIx64"\n", i, j, k, guid_ho); } /* * Returns true if the torus can be successfully routed, false otherwise. */ static bool routable_torus(struct torus *t, struct fabric *f) { int i, j, k, tmp = -1; unsigned b2g_cnt, g2b_cnt; bool success = true; t->flags &= ~MSG_DEADLOCK; if (t->link_cnt != f->link_cnt || t->switch_cnt != f->switch_cnt) OSM_LOG(&t->osm->log, OSM_LOG_INFO, "Warning: Could not construct torus using all " "known fabric switches and/or links.\n"); for (k = 0; k < (int)t->z_sz; k++) for (j = 0; j < (int)t->y_sz; j++) for (i = 0; i < (int)t->x_sz; i++) rpt_torus_missing(t, i, j, k, t->sw[i][j][k], &tmp); /* * Check for multiple failures that create disjoint regions on a ring. */ for (k = 0; k < (int)t->z_sz; k++) for (j = 0; j < (int)t->y_sz; j++) { b2g_cnt = 0; g2b_cnt = 0; for (i = 0; i < (int)t->x_sz; i++) { if (!t->sw[i][j][k]) continue; if (!t->sw[i][j][k]->ptgrp[0].port_cnt) b2g_cnt++; if (!t->sw[i][j][k]->ptgrp[1].port_cnt) g2b_cnt++; } if (b2g_cnt != g2b_cnt) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E32: strange failures in " "x ring at y=%d z=%d" " b2g_cnt %u g2b_cnt %u\n", j, k, b2g_cnt, g2b_cnt); success = false; } if (b2g_cnt > 1) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E33: disjoint failures in " "x ring at y=%d z=%d\n", j, k); success = false; } } for (i = 0; i < (int)t->x_sz; i++) for (k = 0; k < (int)t->z_sz; k++) { b2g_cnt = 0; g2b_cnt = 0; for (j = 0; j < (int)t->y_sz; j++) { if (!t->sw[i][j][k]) continue; if (!t->sw[i][j][k]->ptgrp[2].port_cnt) b2g_cnt++; if (!t->sw[i][j][k]->ptgrp[3].port_cnt) g2b_cnt++; } if (b2g_cnt != g2b_cnt) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E34: strange failures in " "y ring at x=%d z=%d" " b2g_cnt %u g2b_cnt %u\n", i, k, b2g_cnt, g2b_cnt); success = false; } if (b2g_cnt > 1) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E35: disjoint failures in " "y ring at x=%d z=%d\n", i, k); success = false; } } for (j = 0; j < (int)t->y_sz; j++) for (i = 0; i < (int)t->x_sz; i++) { b2g_cnt = 0; g2b_cnt = 0; for (k = 0; k < (int)t->z_sz; k++) { if (!t->sw[i][j][k]) continue; if (!t->sw[i][j][k]->ptgrp[4].port_cnt) b2g_cnt++; if (!t->sw[i][j][k]->ptgrp[5].port_cnt) g2b_cnt++; } if (b2g_cnt != g2b_cnt) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E36: strange failures in " "z ring at x=%d y=%d" " b2g_cnt %u g2b_cnt %u\n", i, j, b2g_cnt, g2b_cnt); success = false; } if (b2g_cnt > 1) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E37: disjoint failures in " "z ring at x=%d y=%d\n", i, j); success = false; } } if (t->flags & MSG_DEADLOCK) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E38: missing switch topology " "==> message deadlock!\n"); success = false; } return success; } /* * Use this function to re-establish the pointers between a torus endpoint * and an opensm osm_port_t. * * Typically this is only needed when "opensm --ucast-cache" is used, and * a CA link bounces. When the CA port goes away, the osm_port_t object * is destroyed, invalidating the endpoint osm_port_t pointer. When the * link comes back, a new osm_port_t object is created with a NULL priv * member. Thus, when osm_get_torus_sl() is called it is missing the data * needed to do its work. Use this function to fix things up. */ static struct endpoint *osm_port_relink_endpoint(const osm_port_t *osm_port) { guid_t node_guid; uint8_t port_num, r_port_num; struct t_switch *sw; struct endpoint *ep = NULL; osm_switch_t *osm_sw; osm_physp_t *osm_physp; osm_node_t *osm_node, *r_osm_node; /* * We need to find the torus endpoint that has the same GUID as * the osm_port. Rather than search the entire set of endpoints, * we'll try to follow pointers. */ osm_physp = osm_port->p_physp; osm_node = osm_port->p_node; port_num = osm_physp_get_port_num(osm_physp); node_guid = osm_node_get_node_guid(osm_node); /* * Switch management port? */ if (port_num == 0 && osm_node_get_type(osm_node) == IB_NODE_TYPE_SWITCH) { osm_sw = osm_node->sw; if (osm_sw && osm_sw->priv) { sw = osm_sw->priv; if (sw->osm_switch == osm_sw && sw->port[0]->n_id == node_guid) { ep = sw->port[0]; goto relink_priv; } } } /* * CA port? Try other end of link. This should also catch a * router port if it is connected to a switch. */ r_osm_node = osm_node_get_remote_node(osm_node, port_num, &r_port_num); if (!r_osm_node) goto out; osm_sw = r_osm_node->sw; if (!osm_sw) goto out; sw = osm_sw->priv; if (!(sw && sw->osm_switch == osm_sw)) goto out; ep = sw->port[r_port_num]; if (!(ep && ep->link)) goto out; if (ep->link->end[0].n_id == node_guid) { ep = &ep->link->end[0]; goto relink_priv; } if (ep->link->end[1].n_id == node_guid) { ep = &ep->link->end[1]; goto relink_priv; } ep = NULL; goto out; relink_priv: /* FIXME: * Unfortunately, we need to cast away const to rebuild the links * between the torus endpoint and the osm_port_t. * * What is really needed is to check whether pr_rcv_get_path_parms() * needs its port objects to be const. If so, why, and whether * anything can be done about it. */ ((osm_port_t *)osm_port)->priv = ep; ep->osm_port = (osm_port_t *)osm_port; out: return ep; } /* * Computing LFT entries and path SL values: * * For a pristine torus, we compute LFT entries using XYZ DOR, and select * which direction to route on a ring (i.e., the 1-D torus for the coordinate * in question) based on shortest path. We compute the SL to use for the * path based on whether we crossed a dateline (where a ring coordinate * wraps to zero) for each coordinate. * * When there is a link/switch failure, we want to compute LFT entries * to route around the failure, without changing the path SL. I.e., we * want the SL to reach a given destination from a given source to be * independent of the presence or number of failed components in the fabric. * * In order to make this feasible, we will assume that no ring is broken * into disjoint pieces by multiple failures * * We handle failure by attempting to take the long way around any ring * with connectivity interrupted by failed components, unless the path * requires a turn on a failed switch. * * For paths that require a turn on a failed switch, we head towards the * failed switch, then turn when progress is blocked by a failure, using a * turn allowed under XYZ DOR. However, such a path will also require a turn * that is not a legal XYZ DOR turn, so we construct the SL2VL mapping tables * such that XYZ DOR turns use one set of VLs and ZYX DOR turns use a * separate set of VLs. * * Under these rules the algorithm guarantees credit-loop-free routing for a * single failed switch, without any change in path SL values. We can also * guarantee credit-loop-free routing for failures of multiple switches, if * they are adjacent in the last DOR direction. Since we use XYZ-DOR, * that means failed switches at i,j,k and i,j,k+1 will not cause credit * loops. * * These failure routing rules are intended to prevent paths that cross any * coordinate dateline twice (over and back), so we don't need to worry about * any ambiguity over which SL to use for such a case. Also, we cannot have * a ring deadlock when a ring is broken by failure and we route the long * way around, so we don't need to worry about the impact of such routing * on SL choice. */ /* * Functions to set our SL bit encoding for routing/QoS info. Combine the * resuts of these functions with bitwise or to get final SL. * * SL bits 0-2 encode whether we "looped" in a given direction * on the torus on the path from source to destination. * * SL bit 3 encodes the QoS level. We only support two QoS levels. * * Below we assume TORUS_MAX_DIM == 3 and 0 <= coord_dir < TORUS_MAX_DIM. */ static inline unsigned sl_set_use_loop_vl(bool use_loop_vl, unsigned coord_dir) { return (coord_dir < TORUS_MAX_DIM) ? ((unsigned)use_loop_vl << coord_dir) : 0; } static inline unsigned sl_set_qos(unsigned qos) { return (unsigned)(!!qos) << TORUS_MAX_DIM; } /* * Functions to crack our SL bit encoding for routing/QoS info. */ static inline bool sl_get_use_loop_vl(unsigned sl, unsigned coord_dir) { return (coord_dir < TORUS_MAX_DIM) ? (sl >> coord_dir) & 0x1 : false; } static inline unsigned sl_get_qos(unsigned sl) { return (sl >> TORUS_MAX_DIM) & 0x1; } /* * Functions to encode routing/QoS info into VL bits. Combine the resuts of * these functions with bitwise or to get final VL. * * For interswitch links: * VL bit 0 encodes whether we need to leave on the "loop" VL. * * VL bit 1 encodes whether turn is XYZ DOR or ZYX DOR. A 3d mesh/torus * has 6 turn types: x-y, y-z, x-z, y-x, z-y, z-x. The first three are * legal XYZ DOR turns, and the second three are legal ZYX DOR turns. * Straight-through (x-x, y-y, z-z) paths are legal in both DOR variants, * so we'll assign them to XYZ DOR VLs. * * Note that delivery to switch-local ports (i.e. those that source/sink * traffic, rather than forwarding it) cannot cause a deadlock, so that * can also use either XYZ or ZYX DOR. * * VL bit 2 encodes QoS level. * * For end port links: * VL bit 0 encodes QoS level. * * Note that if VL bit encodings are changed here, the available fabric VL * verification in verify_setup() needs to be updated as well. */ static inline unsigned vl_set_loop_vl(bool use_loop_vl) { return use_loop_vl; } static inline unsigned vl_set_qos_vl(unsigned qos) { return (qos & 0x1) << 2; } static inline unsigned vl_set_ca_qos_vl(unsigned qos) { return qos & 0x1; } static inline unsigned vl_set_turn_vl(unsigned in_coord_dir, unsigned out_coord_dir) { unsigned vl = 0; if (in_coord_dir != TORUS_MAX_DIM && out_coord_dir != TORUS_MAX_DIM) vl = (in_coord_dir > out_coord_dir) ? 0x1 << 1 : 0; return vl; } static unsigned sl2vl_entry(struct torus *t, struct t_switch *sw, int input_pt, int output_pt, unsigned sl) { unsigned id, od, vl, data_vls; if (sw && sw->port[input_pt]) id = sw->port[input_pt]->pgrp->port_grp / 2; else id = TORUS_MAX_DIM; if (sw && sw->port[output_pt]) od = sw->port[output_pt]->pgrp->port_grp / 2; else od = TORUS_MAX_DIM; if (sw) data_vls = t->osm->subn.min_sw_data_vls; else data_vls = t->osm->subn.min_data_vls; vl = 0; if (sw && od != TORUS_MAX_DIM) { if (data_vls >= 2) vl |= vl_set_loop_vl(sl_get_use_loop_vl(sl, od)); if (data_vls >= 4) vl |= vl_set_turn_vl(id, od); if (data_vls >= 8) vl |= vl_set_qos_vl(sl_get_qos(sl)); } else { if (data_vls >= 2) vl |= vl_set_ca_qos_vl(sl_get_qos(sl)); } return vl; } static void torus_update_osm_sl2vl(void *context, osm_physp_t *osm_phys_port, uint8_t iport_num, uint8_t oport_num, ib_slvl_table_t *osm_oport_sl2vl) { osm_node_t *node = osm_physp_get_node_ptr(osm_phys_port); struct torus_context *ctx = context; struct t_switch *sw = NULL; int sl, vl; if (node->sw) { sw = node->sw->priv; if (sw && sw->osm_switch != node->sw) { osm_log_t *log = &ctx->osm->log; guid_t guid; guid = osm_node_get_node_guid(node); OSM_LOG(log, OSM_LOG_INFO, "Note: osm_switch (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(guid)); return; } } for (sl = 0; sl < 16; sl++) { vl = sl2vl_entry(ctx->torus, sw, iport_num, oport_num, sl); ib_slvl_table_set(osm_oport_sl2vl, sl, vl); } } static void torus_update_osm_vlarb(void *context, osm_physp_t *osm_phys_port, uint8_t port_num, ib_vl_arb_table_t *block, unsigned block_length, unsigned block_num) { osm_node_t *node = osm_physp_get_node_ptr(osm_phys_port); struct torus_context *ctx = context; struct t_switch *sw = NULL; unsigned i, next; if (node->sw) { sw = node->sw->priv; if (sw && sw->osm_switch != node->sw) { osm_log_t *log = &ctx->osm->log; guid_t guid; guid = osm_node_get_node_guid(node); OSM_LOG(log, OSM_LOG_INFO, "Note: osm_switch (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(guid)); return; } } /* * If osm_phys_port is a switch port that connects to a CA, then * we're using at most VL 0 (for QoS level 0) and VL 1 (for QoS * level 1). We've been passed the VLarb values for a switch * external port, so we need to fix them up to avoid unexpected * results depending on how the switch handles VLarb values for * unprogrammed VLs. * * For inter-switch links torus-2QoS uses VLs 0-3 to implement * QoS level 0, and VLs 4-7 to implement QoS level 1. * * So, leave VL 0 alone, remap VL 4 to VL 1, zero out the rest, * and compress out the zero entries to the end. */ if (!sw || !port_num || !sw->port[port_num] || sw->port[port_num]->pgrp->port_grp != 2 * TORUS_MAX_DIM) return; next = 0; for (i = 0; i < block_length; i++) { switch (block->vl_entry[i].vl) { case 4: block->vl_entry[i].vl = 1; /* fall through */ case 0: block->vl_entry[next].vl = block->vl_entry[i].vl; block->vl_entry[next].weight = block->vl_entry[i].weight; next++; /* * If we didn't update vl_entry[i] in place, * fall through to zero it out. */ if (next > i) break; default: block->vl_entry[i].vl = 0; block->vl_entry[i].weight = 0; break; } } } /* * Computes the path lengths *vl0_len and *vl1_len to get from src * to dst on a ring with count switches. * * *vl0_len is the path length for a direct path; it corresponds to a path * that should be assigned to use VL0 in a switch. *vl1_len is the path * length for a path that wraps aroung the ring, i.e. where the ring index * goes from count to zero or from zero to count. It corresponds to the path * that should be assigned to use VL1 in a switch. */ static void get_pathlen(unsigned src, unsigned dst, unsigned count, unsigned *vl0_len, unsigned *vl1_len) { unsigned s, l; /* assume s < l */ if (dst > src) { s = src; l = dst; } else { s = dst; l = src; } *vl0_len = l - s; *vl1_len = s + count - l; } /* * Returns a positive number if we should take the "positive" ring direction * to reach dst from src, a negative number if we should take the "negative" * ring direction, and 0 if src and dst are the same. The choice is strictly * based on which path is shorter. */ static int ring_dir_idx(unsigned src, unsigned dst, unsigned count) { int r; unsigned vl0_len, vl1_len; if (dst == src) return 0; get_pathlen(src, dst, count, &vl0_len, &vl1_len); if (dst > src) r = vl0_len <= vl1_len ? 1 : -1; else r = vl0_len <= vl1_len ? -1 : 1; return r; } /* * Returns true if the VL1 path should be used to reach src from dst on a * ring, based on which path is shorter. */ static bool use_vl1(unsigned src, unsigned dst, unsigned count) { unsigned vl0_len, vl1_len; get_pathlen(src, dst, count, &vl0_len, &vl1_len); return vl0_len <= vl1_len ? false : true; } /* * Returns the next switch in the ring of switches along coordinate direction * cdir, in the positive ring direction if rdir is positive, and in the * negative ring direction if rdir is negative. * * Returns NULL if rdir is zero, or there is no next switch. */ static struct t_switch *ring_next_sw(struct t_switch *sw, unsigned cdir, int rdir) { unsigned pt_grp, far_end = 0; if (!rdir) return NULL; /* * Recall that links are installed into the torus so that their 1 end * is in the "positive" coordinate direction relative to their 0 end * (see link_tswitches() and connect_tlink()). Recall also that for * interswitch links, all links in a given switch port group have the * same endpoints, so we just need to look at the first link. */ pt_grp = 2 * cdir; if (rdir > 0) { pt_grp++; far_end = 1; } if (!sw->ptgrp[pt_grp].port_cnt) return NULL; return sw->ptgrp[pt_grp].port[0]->link->end[far_end].sw; } /* * Returns a positive number if we should take the "positive" ring direction * to reach dsw from ssw, a negative number if we should take the "negative" * ring direction, and 0 if src and dst are the same, or if dsw is not * reachable from ssw because the path is interrupted by failure. */ static int ring_dir_path(struct torus *t, unsigned cdir, struct t_switch *ssw, struct t_switch *dsw) { int d = 0; struct t_switch *sw; switch (cdir) { case 0: d = ring_dir_idx(ssw->i, dsw->i, t->x_sz); break; case 1: d = ring_dir_idx(ssw->j, dsw->j, t->y_sz); break; case 2: d = ring_dir_idx(ssw->k, dsw->k, t->z_sz); break; default: break; } if (!d) goto out; sw = ssw; while (sw) { sw = ring_next_sw(sw, cdir, d); if (sw == dsw) goto out; } d *= -1; sw = ssw; while (sw) { sw = ring_next_sw(sw, cdir, d); if (sw == dsw) goto out; } d = 0; out: return d; } /* * Returns true, and sets *pt_grp to the port group index to use for the * next hop, if it is possible to make progress from ssw to dsw along the * coordinate direction cdir, taking into account whether there are * interruptions in the path. * * This next hop result can be used without worrying about ring deadlocks - * if we don't choose the shortest path it is because there is a failure in * the ring, which removes the possibilility of a ring deadlock on that ring. */ static bool next_hop_path(struct torus *t, unsigned cdir, struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp) { struct t_switch *tsw = NULL; bool success = false; int d; /* * If the path from ssw to dsw turns, this is the switch where the * turn happens. */ switch (cdir) { case 0: tsw = t->sw[dsw->i][ssw->j][ssw->k]; break; case 1: tsw = t->sw[ssw->i][dsw->j][ssw->k]; break; case 2: tsw = t->sw[ssw->i][ssw->j][dsw->k]; break; default: goto out; } if (tsw) { d = ring_dir_path(t, cdir, ssw, tsw); cdir *= 2; if (d > 0) *pt_grp = cdir + 1; else if (d < 0) *pt_grp = cdir; else goto out; success = true; } out: return success; } /* * Returns true, and sets *pt_grp to the port group index to use for the * next hop, if it is possible to make progress from ssw to dsw along the * coordinate direction cdir. This decision is made strictly on a * shortest-path basis without regard for path availability. */ static bool next_hop_idx(struct torus *t, unsigned cdir, struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp) { int d; unsigned g; bool success = false; switch (cdir) { case 0: d = ring_dir_idx(ssw->i, dsw->i, t->x_sz); break; case 1: d = ring_dir_idx(ssw->j, dsw->j, t->y_sz); break; case 2: d = ring_dir_idx(ssw->k, dsw->k, t->z_sz); break; default: goto out; } cdir *= 2; if (d > 0) g = cdir + 1; else if (d < 0) g = cdir; else goto out; if (!ssw->ptgrp[g].port_cnt) goto out; *pt_grp = g; success = true; out: return success; } static void warn_on_routing(const char *msg, struct t_switch *sw, struct t_switch *dsw) { OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR, "%s from sw 0x%04"PRIx64" (%d,%d,%d) " "to sw 0x%04"PRIx64" (%d,%d,%d)\n", msg, cl_ntoh64(sw->n_id), sw->i, sw->j, sw->k, cl_ntoh64(dsw->n_id), dsw->i, dsw->j, dsw->k); } static bool next_hop_x(struct torus *t, struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp) { if (t->sw[dsw->i][ssw->j][ssw->k]) /* * The next turning switch on this path is available, * so head towards it by the shortest available path. */ return next_hop_path(t, 0, ssw, dsw, pt_grp); else /* * The next turning switch on this path is not * available, so head towards it in the shortest * path direction. */ return next_hop_idx(t, 0, ssw, dsw, pt_grp); } static bool next_hop_y(struct torus *t, struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp) { if (t->sw[ssw->i][dsw->j][ssw->k]) /* * The next turning switch on this path is available, * so head towards it by the shortest available path. */ return next_hop_path(t, 1, ssw, dsw, pt_grp); else /* * The next turning switch on this path is not * available, so head towards it in the shortest * path direction. */ return next_hop_idx(t, 1, ssw, dsw, pt_grp); } static bool next_hop_z(struct torus *t, struct t_switch *ssw, struct t_switch *dsw, unsigned *pt_grp) { return next_hop_path(t, 2, ssw, dsw, pt_grp); } /* * Returns the port number on *sw to use to reach *dsw, or -1 if unable to * route. */ static int lft_port(struct torus *t, struct t_switch *sw, struct t_switch *dsw, bool update_port_cnt, bool ca) { unsigned g, p; struct port_grp *pg; /* * The IBA does not provide a way to preserve path history for * routing decisions and VL assignment, and the only mechanism to * provide global fabric knowledge to the routing engine is via * the four SL bits. This severely constrains the ability to deal * with missing/dead switches. * * Also, if routing a torus with XYZ-DOR, the only way to route * around a missing/dead switch is to introduce a turn that is * illegal under XYZ-DOR. * * But here's what we can do: * * We have a VL bit we use to flag illegal turns, thus putting the * hop directly after an illegal turn on a separate set of VLs. * Unfortunately, since there is no path history, the _second_ * and subsequent hops after an illegal turn use the standard * XYZ-DOR VL set. This is enough to introduce credit loops in * many cases. * * To minimize the number of cases such illegal turns can introduce * credit loops, we try to introduce the illegal turn as late in a * path as possible. * * Define a turning switch as a switch where a path turns from one * coordinate direction onto another. If a turning switch in a path * is missing, construct the LFT entries so that the path progresses * as far as possible on the shortest path to the turning switch. * When progress is not possible, turn onto the next coordinate * direction. * * The next turn after that will be an illegal turn, after which * point the path will continue to use a standard XYZ-DOR path. */ if (dsw->i != sw->i) { if (next_hop_x(t, sw, dsw, &g)) goto done; /* * This path has made as much progress in this direction as * is possible, so turn it now. */ if (dsw->j != sw->j && next_hop_y(t, sw, dsw, &g)) goto done; if (dsw->k != sw->k && next_hop_z(t, sw, dsw, &g)) goto done; warn_on_routing("Error: unable to route", sw, dsw); goto no_route; } else if (dsw->j != sw->j) { if (next_hop_y(t, sw, dsw, &g)) goto done; if (dsw->k != sw->k && next_hop_z(t, sw, dsw, &g)) goto done; warn_on_routing("Error: unable to route", sw, dsw); goto no_route; } else { if (dsw->k == sw->k) warn_on_routing("Warning: bad routing", sw, dsw); if (next_hop_z(t, sw, dsw, &g)) goto done; warn_on_routing("Error: unable to route", sw, dsw); goto no_route; } done: pg = &sw->ptgrp[g]; if (!pg->port_cnt) goto no_route; if (update_port_cnt) { if (ca) p = pg->ca_dlid_cnt++ % pg->port_cnt; else p = pg->sw_dlid_cnt++ % pg->port_cnt; } else { /* * If we're not updating port counts, then we're just running * routes for SL path checking, and it doesn't matter which * of several parallel links we use. Use the first one. */ p = 0; } p = pg->port[p]->port; return p; no_route: /* * We can't get there from here. */ OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E39: routing on sw 0x%04"PRIx64": sending " "traffic for dest sw 0x%04"PRIx64" to port %u\n", cl_ntoh64(sw->n_id), cl_ntoh64(dsw->n_id), OSM_NO_PATH); return -1; } static bool get_lid(struct port_grp *pg, unsigned p, uint16_t *dlid_base, uint8_t *dlid_lmc, bool *ca) { struct endpoint *ep; osm_port_t *osm_port; if (p >= pg->port_cnt) { OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E3A: Port group index %u too large: sw " "0x%04"PRIx64" pt_grp %u pt_grp_cnt %u\n", p, cl_ntoh64(pg->sw->n_id), (unsigned)pg->port_grp, (unsigned)pg->port_cnt); return false; } if (pg->port[p]->type == SRCSINK) { ep = pg->port[p]; if (ca) *ca = false; } else if (pg->port[p]->type == PASSTHRU && pg->port[p]->link->end[1].type == SRCSINK) { /* * If this port is connected via a link to a CA, then we * know link->end[0] is the switch end and link->end[1] is * the CA end; see build_ca_link() and link_srcsink(). */ ep = &pg->port[p]->link->end[1]; if (ca) *ca = true; } else { OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E3B: Switch 0x%04"PRIx64" port %d improperly connected\n", cl_ntoh64(pg->sw->n_id), pg->port[p]->port); return false; } osm_port = ep->osm_port; if (!(osm_port && osm_port->priv == ep)) { OSM_LOG(&pg->sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E3C: ep->osm_port->priv != ep " "for sw 0x%04"PRIx64" port %d\n", cl_ntoh64(((struct t_switch *)(ep->sw))->n_id), ep->port); return false; } *dlid_base = cl_ntoh16(osm_physp_get_base_lid(osm_port->p_physp)); *dlid_lmc = osm_physp_get_lmc(osm_port->p_physp); return true; } static bool torus_lft(struct torus *t, struct t_switch *sw) { bool success = true; int dp; unsigned p, s; uint16_t l, dlid_base; uint8_t dlid_lmc; bool ca; struct port_grp *pgrp; struct t_switch *dsw; osm_switch_t *osm_sw; uint8_t order[IB_NODE_NUM_PORTS_MAX+1]; if (!(sw->osm_switch && sw->osm_switch->priv == sw)) { OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E3D: sw->osm_switch->priv != sw " "for sw 0x%04"PRIx64"\n", cl_ntoh64(sw->n_id)); return false; } osm_sw = sw->osm_switch; memset(osm_sw->new_lft, OSM_NO_PATH, osm_sw->lft_size); for (s = 0; s < t->switch_cnt; s++) { dsw = t->sw_pool[s]; pgrp = &dsw->ptgrp[2 * TORUS_MAX_DIM]; memset(order, IB_INVALID_PORT_NUM, sizeof(order)); for (p = 0; p < pgrp->port_cnt; p++) order[pgrp->port[p]->port] = p; for (p = 0; p < ARRAY_SIZE(order); p++) { uint8_t px = order[t->port_order[p]]; if (px == IB_INVALID_PORT_NUM) continue; if (!get_lid(pgrp, px, &dlid_base, &dlid_lmc, &ca)) return false; if (sw->n_id == dsw->n_id) dp = pgrp->port[px]->port; else dp = lft_port(t, sw, dsw, true, ca); /* * LMC > 0 doesn't really make sense for torus-2QoS. * So, just make sure traffic gets delivered if * non-zero LMC is used. */ if (dp >= 0) for (l = 0; l < (1U << dlid_lmc); l++) osm_sw->new_lft[dlid_base + l] = dp; else success = false; } } return success; } static osm_mtree_node_t *mcast_stree_branch(struct t_switch *sw, osm_switch_t *osm_sw, osm_mgrp_box_t *mgb, unsigned depth, unsigned *port_cnt, unsigned *max_depth) { osm_mtree_node_t *mtn = NULL; osm_mcast_tbl_t *mcast_tbl, *ds_mcast_tbl; osm_node_t *ds_node; struct t_switch *ds_sw; struct port_grp *ptgrp; struct link *link; struct endpoint *port; unsigned g, p; unsigned mcast_fwd_ports = 0, mcast_end_ports = 0; depth++; if (osm_sw->priv != sw) { OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E3E: osm_sw (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(osm_node_get_node_guid(osm_sw->p_node))); goto out; } if (!osm_switch_supports_mcast(osm_sw)) { OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E3F: osm_sw (GUID 0x%04"PRIx64") " "does not support multicast\n", cl_ntoh64(osm_node_get_node_guid(osm_sw->p_node))); goto out; } mtn = osm_mtree_node_new(osm_sw); if (!mtn) { OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E46: Insufficient memory to build multicast tree\n"); goto out; } mcast_tbl = osm_switch_get_mcast_tbl_ptr(osm_sw); /* * Recurse to downstream switches, i.e. those closer to master * spanning tree branch tips. * * Note that if there are multiple ports in this port group, i.e., * multiple parallel links, we can pick any one of them to use for * any individual MLID without causing loops. Pick one based on MLID * for now, until someone turns up evidence we need to be smarter. * * Also, it might be we got called in a window between a switch getting * removed from the fabric, and torus-2QoS getting to rebuild its * fabric representation. If that were to happen, our next hop * osm_switch pointer might be stale. Look it up via opensm's fabric * description to be sure it's not. */ for (g = 0; g < 2 * TORUS_MAX_DIM; g++) { ptgrp = &sw->ptgrp[g]; if (!ptgrp->to_stree_tip) continue; p = mgb->mlid % ptgrp->port_cnt;/* port # in port group */ p = ptgrp->port[p]->port; /* now port # in switch */ ds_node = osm_node_get_remote_node(osm_sw->p_node, p, NULL); ds_sw = ptgrp->to_stree_tip->sw; if (!(ds_node && ds_node->sw && ds_sw->osm_switch == ds_node->sw)) { OSM_LOG(&sw->torus->osm->log, OSM_LOG_ERROR, "ERR 4E40: stale pointer to osm_sw " "(GUID 0x%04"PRIx64")\n", cl_ntoh64(ds_sw->n_id)); continue; } mtn->child_array[p] = mcast_stree_branch(ds_sw, ds_node->sw, mgb, depth, port_cnt, max_depth); if (!mtn->child_array[p]) continue; osm_mcast_tbl_set(mcast_tbl, mgb->mlid, p); mcast_fwd_ports++; /* * Since we forward traffic for this multicast group on this * port, cause the switch on the other end of the link * to forward traffic back to us. Do it now since have at * hand the link used; otherwise it'll be hard to figure out * later, and if we get it wrong we get a MC routing loop. */ link = sw->port[p]->link; ds_mcast_tbl = osm_switch_get_mcast_tbl_ptr(ds_node->sw); if (&link->end[0] == sw->port[p]) osm_mcast_tbl_set(ds_mcast_tbl, mgb->mlid, link->end[1].port); else osm_mcast_tbl_set(ds_mcast_tbl, mgb->mlid, link->end[0].port); } /* * Add any host ports marked as in mcast group into spanning tree. */ ptgrp = &sw->ptgrp[2 * TORUS_MAX_DIM]; for (p = 0; p < ptgrp->port_cnt; p++) { port = ptgrp->port[p]; if (port->tmp) { port->tmp = NULL; mtn->child_array[port->port] = OSM_MTREE_LEAF; osm_mcast_tbl_set(mcast_tbl, mgb->mlid, port->port); mcast_end_ports++; } } if (!(mcast_end_ports || mcast_fwd_ports)) { osm_mtree_destroy(mtn); mtn = NULL; } else if (depth > *max_depth) *max_depth = depth; *port_cnt += mcast_end_ports; out: return mtn; } static osm_port_t *next_mgrp_box_port(osm_mgrp_box_t *mgb, cl_list_item_t **list_iterator, cl_map_item_t **map_iterator) { osm_mgrp_t *mgrp; osm_mcm_port_t *mcm_port; osm_port_t *osm_port = NULL; cl_map_item_t *m_item = *map_iterator; cl_list_item_t *l_item = *list_iterator; next_mgrp: if (!l_item) l_item = cl_qlist_head(&mgb->mgrp_list); if (l_item == cl_qlist_end(&mgb->mgrp_list)) { l_item = NULL; goto out; } mgrp = cl_item_obj(l_item, mgrp, list_item); if (!m_item) m_item = cl_qmap_head(&mgrp->mcm_port_tbl); if (m_item == cl_qmap_end(&mgrp->mcm_port_tbl)) { m_item = NULL; l_item = cl_qlist_next(l_item); goto next_mgrp; } mcm_port = cl_item_obj(m_item, mcm_port, map_item); m_item = cl_qmap_next(m_item); osm_port = mcm_port->port; out: *list_iterator = l_item; *map_iterator = m_item; return osm_port; } static ib_api_status_t torus_mcast_stree(void *context, osm_mgrp_box_t *mgb) { struct torus_context *ctx = context; struct torus *t = ctx->torus; cl_map_item_t *m_item = NULL; cl_list_item_t *l_item = NULL; osm_port_t *osm_port; osm_switch_t *osm_sw; struct endpoint *port; unsigned port_cnt = 0, max_depth = 0; osm_purge_mtree(&ctx->osm->sm, mgb); /* * Build a spanning tree for a multicast group by first marking * the torus endpoints that are participating in the group. * Then do a depth-first search of the torus master spanning * tree to build up the spanning tree specific to this group. * * Since the torus master spanning tree is constructed specifically * to guarantee that multicast will not deadlock against unicast * when they share VLs, we can be sure that any multicast group * spanning tree constructed this way has the same property. */ while ((osm_port = next_mgrp_box_port(mgb, &l_item, &m_item))) { port = osm_port->priv; if (!(port && port->osm_port == osm_port)) { port = osm_port_relink_endpoint(osm_port); if (!port) { guid_t id; id = osm_node_get_node_guid(osm_port->p_node); OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR, "ERR 4E41: osm_port (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(id)); continue; } } /* * If this is a CA port, mark the switch port at the * other end of this port's link. * * By definition, a CA port is connected to end[1] of a link, * and the switch port is end[0]. See build_ca_link() and * link_srcsink(). */ if (port->link) port = &port->link->end[0]; port->tmp = osm_port; } /* * It might be we got called in a window between a switch getting * removed from the fabric, and torus-2QoS getting to rebuild its * fabric representation. If that were to happen, our * master_stree_root->osm_switch pointer might be stale. Look up * the osm_switch by GUID to be sure it's not. * * Also, call into mcast_stree_branch with depth = -1, because * depth at root switch needs to be 0. */ osm_sw = (osm_switch_t *)cl_qmap_get(&ctx->osm->subn.sw_guid_tbl, t->master_stree_root->n_id); if (!(osm_sw && t->master_stree_root->osm_switch == osm_sw)) { OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR, "ERR 4E42: stale pointer to osm_sw (GUID 0x%04"PRIx64")\n", cl_ntoh64(t->master_stree_root->n_id)); return IB_ERROR; } mgb->root = mcast_stree_branch(t->master_stree_root, osm_sw, mgb, -1, &port_cnt, &max_depth); OSM_LOG(&ctx->osm->log, OSM_LOG_VERBOSE, "Configured MLID 0x%X for %u ports, max tree depth = %u\n", mgb->mlid, port_cnt, max_depth); return IB_SUCCESS; } static bool good_xy_ring(struct torus *t, const int x, const int y, const int z) { struct t_switch ****sw = t->sw; bool good_ring = true; int x_tst, y_tst; for (x_tst = 0; x_tst < t->x_sz && good_ring; x_tst++) good_ring = sw[x_tst][y][z]; for (y_tst = 0; y_tst < t->y_sz && good_ring; y_tst++) good_ring = sw[x][y_tst][z]; return good_ring; } static struct t_switch *find_plane_mid(struct torus *t, const int z) { int x, dx, xm = t->x_sz / 2; int y, dy, ym = t->y_sz / 2; struct t_switch ****sw = t->sw; if (good_xy_ring(t, xm, ym, z)) return sw[xm][ym][z]; for (dx = 1, dy = 1; dx <= xm && dy <= ym; dx++, dy++) { x = canonicalize(xm - dx, t->x_sz); y = canonicalize(ym - dy, t->y_sz); if (good_xy_ring(t, x, y, z)) return sw[x][y][z]; x = canonicalize(xm + dx, t->x_sz); y = canonicalize(ym + dy, t->y_sz); if (good_xy_ring(t, x, y, z)) return sw[x][y][z]; } return NULL; } static struct t_switch *find_stree_root(struct torus *t) { int x, y, z, dz, zm = t->z_sz / 2; struct t_switch ****sw = t->sw; struct t_switch *root; bool good_plane; /* * Look for a switch near the "center" (wrt. the datelines) of the * torus, as that will be the most optimum spanning tree root. Use * a search that is not exhaustive, on the theory that this routing * engine isn't useful anyway if too many switches are missing. * * Also, want to pick an x-y plane with no missing switches, so that * the master spanning tree construction algorithm doesn't have to * deal with needing a turn on a missing switch. */ for (dz = 0; dz <= zm; dz++) { z = canonicalize(zm - dz, t->z_sz); good_plane = true; for (y = 0; y < t->y_sz && good_plane; y++) for (x = 0; x < t->x_sz && good_plane; x++) good_plane = sw[x][y][z]; if (good_plane) { root = find_plane_mid(t, z); if (root) goto out; } if (!dz) continue; z = canonicalize(zm + dz, t->z_sz); good_plane = true; for (y = 0; y < t->y_sz && good_plane; y++) for (x = 0; x < t->x_sz && good_plane; x++) good_plane = sw[x][y][z]; if (good_plane) { root = find_plane_mid(t, z); if (root) goto out; } } /* * Note that torus-2QoS can route a torus that is missing an entire * column (switches with x,y constant, for all z values) without * deadlocks. * * if we've reached this point, we must have a column of missing * switches, as routable_torus() would have returned false for * any other configuration of missing switches that made it through * the above. * * So any switch in the mid-z plane will do as the root. */ root = find_plane_mid(t, zm); out: return root; } static bool sw_in_master_stree(struct t_switch *sw) { int g; bool connected; connected = sw == sw->torus->master_stree_root; for (g = 0; g < 2 * TORUS_MAX_DIM; g++) connected = connected || sw->ptgrp[g].to_stree_root; return connected; } static void grow_master_stree_branch(struct t_switch *root, struct t_switch *tip, unsigned to_root_pg, unsigned to_tip_pg) { root->ptgrp[to_tip_pg].to_stree_tip = &tip->ptgrp[to_root_pg]; tip->ptgrp[to_root_pg].to_stree_root = &root->ptgrp[to_tip_pg]; } static void build_master_stree_branch(struct t_switch *branch_root, int cdir) { struct t_switch *sw, *n_sw, *p_sw; unsigned l, idx, cnt, pg, ng; switch (cdir) { case 0: idx = branch_root->i; cnt = branch_root->torus->x_sz; break; case 1: idx = branch_root->j; cnt = branch_root->torus->y_sz; break; case 2: idx = branch_root->k; cnt = branch_root->torus->z_sz; break; default: goto out; } /* * This algorithm intends that a spanning tree branch never crosses * a dateline unless the 1-D ring for which we're building the branch * is interrupted by failure. We need that guarantee to prevent * multicast/unicast credit loops. */ n_sw = branch_root; /* tip of negative cdir branch */ ng = 2 * cdir; /* negative cdir port group index */ p_sw = branch_root; /* tip of positive cdir branch */ pg = 2 * cdir + 1; /* positive cdir port group index */ for (l = idx; n_sw && l >= 1; l--) { sw = ring_next_sw(n_sw, cdir, -1); if (sw && !sw_in_master_stree(sw)) { grow_master_stree_branch(n_sw, sw, pg, ng); n_sw = sw; } else n_sw = NULL; } for (l = idx; p_sw && l < (cnt - 1); l++) { sw = ring_next_sw(p_sw, cdir, 1); if (sw && !sw_in_master_stree(sw)) { grow_master_stree_branch(p_sw, sw, ng, pg); p_sw = sw; } else p_sw = NULL; } if (n_sw && p_sw) goto out; /* * At least one branch couldn't grow to the dateline for this ring. * That means it is acceptable to grow the branch by crossing the * dateline. */ for (l = 0; l < cnt; l++) { if (n_sw) { sw = ring_next_sw(n_sw, cdir, -1); if (sw && !sw_in_master_stree(sw)) { grow_master_stree_branch(n_sw, sw, pg, ng); n_sw = sw; } else n_sw = NULL; } if (p_sw) { sw = ring_next_sw(p_sw, cdir, 1); if (sw && !sw_in_master_stree(sw)) { grow_master_stree_branch(p_sw, sw, ng, pg); p_sw = sw; } else p_sw = NULL; } if (!(n_sw || p_sw)) break; } out: return; } static bool torus_master_stree(struct torus *t) { int i, j, k; bool success = false; struct t_switch *stree_root = find_stree_root(t); if (stree_root) build_master_stree_branch(stree_root, 0); else goto out; k = stree_root->k; for (i = 0; i < t->x_sz; i++) { j = stree_root->j; if (t->sw[i][j][k]) build_master_stree_branch(t->sw[i][j][k], 1); for (j = 0; j < t->y_sz; j++) if (t->sw[i][j][k]) build_master_stree_branch(t->sw[i][j][k], 2); } t->master_stree_root = stree_root; /* * At this point we should have a master spanning tree that contains * every present switch, for all fabrics that torus-2QoS can route * without deadlocks. Make sure this is the case; otherwise warn * and return failure so we get bug reports. */ success = true; for (i = 0; i < t->x_sz; i++) for (j = 0; j < t->y_sz; j++) for (k = 0; k < t->z_sz; k++) { struct t_switch *sw = t->sw[i][j][k]; if (!sw || sw_in_master_stree(sw)) continue; success = false; OSM_LOG(&t->osm->log, OSM_LOG_ERROR, "ERR 4E43: sw 0x%04"PRIx64" (%d,%d,%d) not in " "torus multicast master spanning tree\n", cl_ntoh64(sw->n_id), i, j, k); } out: return success; } int route_torus(struct torus *t) { int s; bool success = true; for (s = 0; s < (int)t->switch_cnt; s++) success = torus_lft(t, t->sw_pool[s]) && success; success = success && torus_master_stree(t); return success ? 0 : -1; } uint8_t torus_path_sl(void *context, uint8_t path_sl_hint, const ib_net16_t slid, const ib_net16_t dlid) { struct torus_context *ctx = context; osm_opensm_t *p_osm = ctx->osm; osm_log_t *log = &p_osm->log; osm_port_t *osm_sport, *osm_dport; struct endpoint *sport, *dport; struct t_switch *ssw, *dsw; struct torus *t; guid_t guid; unsigned sl = 0; osm_sport = osm_get_port_by_lid(&p_osm->subn, slid); if (!osm_sport) goto out; osm_dport = osm_get_port_by_lid(&p_osm->subn, dlid); if (!osm_dport) goto out; sport = osm_sport->priv; if (!(sport && sport->osm_port == osm_sport)) { sport = osm_port_relink_endpoint(osm_sport); if (!sport) { guid = osm_node_get_node_guid(osm_sport->p_node); OSM_LOG(log, OSM_LOG_INFO, "Note: osm_sport (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(guid)); goto out; } } dport = osm_dport->priv; if (!(dport && dport->osm_port == osm_dport)) { dport = osm_port_relink_endpoint(osm_dport); if (!dport) { guid = osm_node_get_node_guid(osm_dport->p_node); OSM_LOG(log, OSM_LOG_INFO, "Note: osm_dport (GUID 0x%04"PRIx64") " "not in torus fabric description\n", cl_ntoh64(guid)); goto out; } } /* * We're only supposed to be called for CA ports, and maybe * switch management ports. */ if (sport->type != SRCSINK) { guid = osm_node_get_node_guid(osm_sport->p_node); OSM_LOG(log, OSM_LOG_INFO, "Error: osm_sport (GUID 0x%04"PRIx64") " "not a data src/sink port\n", cl_ntoh64(guid)); goto out; } if (dport->type != SRCSINK) { guid = osm_node_get_node_guid(osm_dport->p_node); OSM_LOG(log, OSM_LOG_INFO, "Error: osm_dport (GUID 0x%04"PRIx64") " "not a data src/sink port\n", cl_ntoh64(guid)); goto out; } /* * By definition, a CA port is connected to end[1] of a link, and * the switch port is end[0]. See build_ca_link() and link_srcsink(). */ if (sport->link) { ssw = sport->link->end[0].sw; } else { ssw = sport->sw; } if (dport->link) dsw = dport->link->end[0].sw; else dsw = dport->sw; t = ssw->torus; sl = sl_set_use_loop_vl(use_vl1(ssw->i, dsw->i, t->x_sz), 0); sl |= sl_set_use_loop_vl(use_vl1(ssw->j, dsw->j, t->y_sz), 1); sl |= sl_set_use_loop_vl(use_vl1(ssw->k, dsw->k, t->z_sz), 2); sl |= sl_set_qos(sl_get_qos(path_sl_hint)); out: return sl; } static void sum_vlarb_weights(const char *vlarb_str, unsigned total_weight[IB_MAX_NUM_VLS]) { unsigned i = 0, v, vl = 0; char *end; while (*vlarb_str && i++ < 2 * IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK) { v = strtoul(vlarb_str, &end, 0); if (*end) end++; vlarb_str = end; if (i & 0x1) vl = v & 0xf; else total_weight[vl] += v & 0xff; } } static int uniform_vlarb_weight_value(unsigned *weight, unsigned count) { int i, v = weight[0]; for (i = 1; i < count; i++) { if (v != weight[i]) return -1; } return v; } static void check_vlarb_config(const char *vlarb_str, bool is_default, const char *str, const char *pri, osm_log_t *log) { unsigned total_weight[IB_MAX_NUM_VLS] = {0,}; sum_vlarb_weights(vlarb_str, total_weight); if (!(uniform_vlarb_weight_value(&total_weight[0], 4) >= 0 && uniform_vlarb_weight_value(&total_weight[4], 4) >= 0)) OSM_LOG(log, OSM_LOG_INFO, "Warning: torus-2QoS requires same VLarb weights for " "VLs 0-3; also for VLs 4-7: not true for %s " "%s_vlarb_%s\n", (is_default ? "default" : "configured"), str, pri); } /* * Use this to check the qos_config for switch external ports. */ static void check_qos_swe_config(osm_qos_options_t *opt, osm_qos_options_t *def, osm_log_t *log) { const char *vlarb_str, *tstr; bool is_default; unsigned max_vls; max_vls = def->max_vls; if (opt->max_vls > 0) max_vls = opt->max_vls; if (max_vls > 0 && max_vls < 8) OSM_LOG(log, OSM_LOG_INFO, "Warning: full torus-2QoS functionality not available " "for configured %s_max_vls = %d\n", (opt->max_vls > 0 ? "qos_swe" : "qos"), opt->max_vls); vlarb_str = opt->vlarb_high; is_default = false; tstr = "qos_swe"; if (!vlarb_str) { vlarb_str = def->vlarb_high; tstr = "qos"; } if (!vlarb_str) { vlarb_str = OSM_DEFAULT_QOS_VLARB_HIGH; is_default = true; } check_vlarb_config(vlarb_str, is_default, tstr, "high", log); vlarb_str = opt->vlarb_low; is_default = false; tstr = "qos_swe"; if (!vlarb_str) { vlarb_str = def->vlarb_low; tstr = "qos"; } if (!vlarb_str) { vlarb_str = OSM_DEFAULT_QOS_VLARB_LOW; is_default = true; } check_vlarb_config(vlarb_str, is_default, tstr, "low", log); if (opt->sl2vl) OSM_LOG(log, OSM_LOG_INFO, "Warning: torus-2QoS must override configured " "qos_swe_sl2vl to generate deadlock-free routes\n"); } static void check_ep_vlarb_config(const char *vlarb_str, bool is_default, bool is_specific, const char *str, const char *pri, osm_log_t *log) { unsigned i, total_weight[IB_MAX_NUM_VLS] = {0,}; int val = 0; sum_vlarb_weights(vlarb_str, total_weight); for (i = 2; i < 8; i++) { val += total_weight[i]; } if (!val) return; if (is_specific) OSM_LOG(log, OSM_LOG_INFO, "Warning: torus-2QoS recommends 0 VLarb weights" " for VLs 2-7 on endpoint links; not true for " " configured %s_vlarb_%s\n", str, pri); else OSM_LOG(log, OSM_LOG_INFO, "Warning: torus-2QoS recommends 0 VLarb weights " "for VLs 2-7 on endpoint links; not true for %s " "qos_vlarb_%s values used for %s_vlarb_%s\n", (is_default ? "default" : "configured"), pri, str, pri); } /* * Use this to check the qos_config for endports */ static void check_qos_ep_config(osm_qos_options_t *opt, osm_qos_options_t *def, const char *str, osm_log_t *log) { const char *vlarb_str; bool is_default, is_specific; unsigned max_vls; max_vls = def->max_vls; if (opt->max_vls > 0) max_vls = opt->max_vls; if (max_vls > 0 && max_vls < 2) OSM_LOG(log, OSM_LOG_INFO, "Warning: full torus-2QoS functionality not available " "for configured %s_max_vls = %d\n", (opt->max_vls > 0 ? str : "qos"), opt->max_vls); vlarb_str = opt->vlarb_high; is_default = false; is_specific = true; if (!vlarb_str) { vlarb_str = def->vlarb_high; is_specific = false; } if (!vlarb_str) { vlarb_str = OSM_DEFAULT_QOS_VLARB_HIGH; is_default = true; } check_ep_vlarb_config(vlarb_str, is_default, is_specific, str, "high", log); vlarb_str = opt->vlarb_low; is_default = false; is_specific = true; if (!vlarb_str) { vlarb_str = def->vlarb_low; is_specific = false; } if (!vlarb_str) { vlarb_str = OSM_DEFAULT_QOS_VLARB_LOW; is_default = true; } check_ep_vlarb_config(vlarb_str, is_default, is_specific, str, "low", log); if (opt->sl2vl) OSM_LOG(log, OSM_LOG_INFO, "Warning: torus-2QoS must override configured " "%s_sl2vl to generate deadlock-free routes\n", str); } static int torus_build_lfts(void *context) { int status = -1; struct torus_context *ctx = context; struct fabric *fabric; struct torus *torus; if (!ctx->osm->subn.opt.qos) { OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR, "ERR 4E44: Routing engine list contains torus-2QoS. " "Enable QoS for correct operation " "(-Q or 'qos TRUE' in opensm.conf).\n"); return status; } fabric = &ctx->fabric; teardown_fabric(fabric); torus = calloc(1, sizeof(*torus)); if (!torus) { OSM_LOG(&ctx->osm->log, OSM_LOG_ERROR, "ERR 4E45: allocating torus: %s\n", strerror(errno)); goto out; } torus->osm = ctx->osm; fabric->osm = ctx->osm; if (!parse_config(ctx->osm->subn.opt.torus_conf_file, fabric, torus)) goto out; if (!capture_fabric(fabric)) goto out; OSM_LOG(&torus->osm->log, OSM_LOG_INFO, "Found fabric w/ %d links, %d switches, %d CA ports, " "minimum data VLs: endport %d, switchport %d\n", (int)fabric->link_cnt, (int)fabric->switch_cnt, (int)fabric->ca_cnt, (int)ctx->osm->subn.min_data_vls, (int)ctx->osm->subn.min_sw_data_vls); if (!verify_setup(torus, fabric)) goto out; OSM_LOG(&torus->osm->log, OSM_LOG_INFO, "Looking for %d x %d x %d %s\n", (int)torus->x_sz, (int)torus->y_sz, (int)torus->z_sz, (ALL_MESH(torus->flags) ? "mesh" : "torus")); if (!build_torus(fabric, torus)) { OSM_LOG(&torus->osm->log, OSM_LOG_ERROR, "ERR 4E57: " "build_torus finished with errors\n"); goto out; } OSM_LOG(&torus->osm->log, OSM_LOG_INFO, "Built %d x %d x %d %s w/ %d links, %d switches, %d CA ports\n", (int)torus->x_sz, (int)torus->y_sz, (int)torus->z_sz, (ALL_MESH(torus->flags) ? "mesh" : "torus"), (int)torus->link_cnt, (int)torus->switch_cnt, (int)torus->ca_cnt); diagnose_fabric(fabric); /* * Since we found some sort of torus fabric, report on any topology * changes vs. the last torus we found. */ if (torus->flags & NOTIFY_CHANGES) report_torus_changes(torus, ctx->torus); if (routable_torus(torus, fabric)) status = route_torus(torus); out: if (status) { /* bad torus!! */ if (torus) teardown_torus(torus); } else { osm_subn_opt_t *opt = &torus->osm->subn.opt; osm_log_t *log = &torus->osm->log; if (ctx->torus) teardown_torus(ctx->torus); ctx->torus = torus; check_qos_swe_config(&opt->qos_swe_options, &opt->qos_options, log); check_qos_ep_config(&opt->qos_ca_options, &opt->qos_options, "qos_ca", log); check_qos_ep_config(&opt->qos_sw0_options, &opt->qos_options, "qos_sw0", log); check_qos_ep_config(&opt->qos_rtr_options, &opt->qos_options, "qos_rtr", log); } teardown_fabric(fabric); return status; } int osm_ucast_torus2QoS_setup(struct osm_routing_engine *r, osm_opensm_t *osm) { struct torus_context *ctx; ctx = torus_context_create(osm); if (!ctx) return -1; r->context = ctx; r->ucast_build_fwd_tables = torus_build_lfts; r->build_lid_matrices = ucast_dummy_build_lid_matrices; r->update_sl2vl = torus_update_osm_sl2vl; r->update_vlarb = torus_update_osm_vlarb; r->path_sl = torus_path_sl; r->mcast_build_stree = torus_mcast_stree; r->destroy = torus_context_delete; return 0; } opensm-3.3.20/opensm/osm_ucast_dnup.c0000644000205000001450000003377612104655725014527 00000000000000/* * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007,2009 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2009 Battelle Memorial Institue. 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 Up Down Algorithm using ranking & Min Hop * Calculation functions */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_DNUP_C #include #include #include /* //////////////////////////// */ /* Local types */ /* //////////////////////////// */ /* direction */ typedef enum dnup_switch_dir { UP = 0, DOWN, EQUAL } dnup_switch_dir_t; /* dnup structure */ typedef struct dnup { osm_opensm_t *p_osm; } dnup_t; struct dnup_node { cl_list_item_t list; osm_switch_t *sw; dnup_switch_dir_t dir; unsigned rank; unsigned visited; }; /* This function returns direction based on rank and guid info of current & remote ports */ static dnup_switch_dir_t dnup_get_dir(unsigned cur_rank, unsigned rem_rank) { /* HACK: comes to solve root nodes connection, in a classic subnet root nodes do not connect directly, but in case they are we assign to root node an UP direction to allow DNUP to discover the subnet correctly (and not from the point of view of the last root node). */ if (!cur_rank && !rem_rank) return EQUAL; if (cur_rank < rem_rank) return DOWN; else if (cur_rank > rem_rank) return UP; else return EQUAL; } /********************************************************************** * This function does the bfs of min hop table calculation by guid index * as a starting point. **********************************************************************/ static int dnup_bfs_by_node(IN osm_log_t * p_log, IN osm_subn_t * p_subn, IN osm_switch_t * p_sw, IN uint8_t prune_weight, OUT uint8_t * max_hops) { uint8_t pn, pn_rem; cl_qlist_t list; uint16_t lid; struct dnup_node *u; dnup_switch_dir_t next_dir, current_dir; OSM_LOG_ENTER(p_log); lid = osm_node_get_base_lid(p_sw->p_node, 0); lid = cl_ntoh16(lid); osm_switch_set_hops(p_sw, lid, 0, 0); OSM_LOG(p_log, OSM_LOG_DEBUG, "Starting from switch - port GUID 0x%" PRIx64 " lid %u\n", cl_ntoh64(p_sw->p_node->node_info.port_guid), lid); u = p_sw->priv; u->dir = DOWN; /* Update list with the new element */ cl_qlist_init(&list); cl_qlist_insert_tail(&list, &u->list); /* BFS the list till no next element */ while (!cl_is_qlist_empty(&list)) { u = (struct dnup_node *)cl_qlist_remove_head(&list); u->visited = 0; /* cleanup */ current_dir = u->dir; /* Go over all ports of the switch and find unvisited remote nodes */ for (pn = 1; pn < u->sw->num_ports; pn++) { osm_node_t *p_remote_node; struct dnup_node *rem_u; uint8_t current_min_hop, remote_min_hop, set_hop_return_value; osm_switch_t *p_remote_sw; p_remote_node = osm_node_get_remote_node(u->sw->p_node, pn, &pn_rem); /* If no remote node OR remote node is not a SWITCH continue to next pn */ if (!p_remote_node || !p_remote_node->sw) continue; /* Fetch remote guid only after validation of remote node */ p_remote_sw = p_remote_node->sw; rem_u = p_remote_sw->priv; /* Decide which direction to mark it (UP/DOWN) */ next_dir = dnup_get_dir(u->rank, rem_u->rank); /* Set MinHop value for the current lid */ current_min_hop = osm_switch_get_least_hops(u->sw, lid); /* Check hop count if better insert into list && update the remote node Min Hop Table */ remote_min_hop = osm_switch_get_hop_count(p_remote_sw, lid, pn_rem); /* Check if this is a legal step : the only illegal step is going from UP to DOWN */ if ((current_dir == UP) && (next_dir == DOWN)) { OSM_LOG(p_log, OSM_LOG_DEBUG, "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(u->sw->p_node)), cl_ntoh64(osm_node_get_node_guid(p_remote_node))); /* Illegal step. If prune_weight is set, allow it with an * additional weight */ if(prune_weight) { current_min_hop+=prune_weight; if(current_min_hop >= 64) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AE02: Too many hops on subnet," " can't relax illegal Dn/Up transition."); osm_switch_set_hops(p_remote_sw, lid, pn_rem, OSM_NO_PATH); } } else { continue; } } if (current_min_hop + 1 < remote_min_hop) { set_hop_return_value = osm_switch_set_hops(p_remote_sw, lid, pn_rem, current_min_hop + 1); if(max_hops && current_min_hop + 1 > *max_hops) { *max_hops = current_min_hop + 1; } if (set_hop_return_value) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AE01: " "Invalid value returned from set min hop is: %d\n", set_hop_return_value); } /* Check if remote port has already been visited */ if (!rem_u->visited) { /* Insert dnup_switch item into the list */ rem_u->dir = next_dir; rem_u->visited = 1; cl_qlist_insert_tail(&list, &rem_u->list); } } } } OSM_LOG_EXIT(p_log); return 0; } /* NOTE : PLS check if we need to decide that the first */ /* rank is a SWITCH for BFS purpose */ static int dnup_subn_rank(IN dnup_t * p_dnup) { osm_switch_t *p_sw; osm_physp_t *p_physp, *p_remote_physp; cl_qlist_t list; cl_map_item_t *item; struct dnup_node *u, *remote_u; uint8_t num_ports, port_num; osm_log_t *p_log = &p_dnup->p_osm->log; unsigned max_rank = 0; OSM_LOG_ENTER(p_log); cl_qlist_init(&list); /* add all node level switches to the list */ for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; u = p_sw->priv; if (u->rank == 0) cl_qlist_insert_tail(&list, &u->list); } /* BFS the list till it's empty */ while (!cl_is_qlist_empty(&list)) { u = (struct dnup_node *)cl_qlist_remove_head(&list); /* Go over all remote nodes and rank them (if not already visited) */ p_sw = u->sw; num_ports = p_sw->num_ports; OSM_LOG(p_log, OSM_LOG_DEBUG, "Handling switch GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); for (port_num = 1; port_num < num_ports; port_num++) { ib_net64_t port_guid; /* Current port fetched in order to get remote side */ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num); if (!p_physp) continue; p_remote_physp = p_physp->p_remote_physp; /* make sure that all the following occur on p_remote_physp: 1. The port isn't NULL 2. It is a switch */ if (p_remote_physp && p_remote_physp->p_node->sw) { remote_u = p_remote_physp->p_node->sw->priv; port_guid = p_remote_physp->port_guid; if (remote_u->rank > u->rank + 1) { remote_u->rank = u->rank + 1; max_rank = remote_u->rank; cl_qlist_insert_tail(&list, &remote_u->list); OSM_LOG(p_log, OSM_LOG_DEBUG, "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid), remote_u->rank); } } } } /* Print Summary of ranking */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Subnet ranking completed. Max Node Rank = %d\n", max_rank); OSM_LOG_EXIT(p_log); return 0; } static int dnup_set_min_hop_table(IN dnup_t * p_dnup) { osm_subn_t *p_subn = &p_dnup->p_osm->subn; osm_log_t *p_log = &p_dnup->p_osm->log; osm_switch_t *p_sw; struct dnup_node *u; cl_map_item_t *item; uint8_t max_hops = 0; OSM_LOG_ENTER(p_log); /* Go over all the switches in the subnet - for each init their Min Hop Table */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "Init Min Hop Table of all switches [\n"); for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; /* Clear Min Hop Table */ osm_switch_clear_hops(p_sw); } OSM_LOG(p_log, OSM_LOG_VERBOSE, "Init Min Hop Table of all switches ]\n"); /* Now do the BFS for each port in the subnet */ OSM_LOG(p_log, OSM_LOG_VERBOSE, "BFS through all port guids in the subnet [\n"); for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; dnup_bfs_by_node(p_log, p_subn, p_sw, 0, &max_hops); } if(p_subn->opt.connect_roots) { /*This is probably not necessary, by I am more comfortable * clearing any possible side effects from the previous * dnup routing pass */ for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; osm_switch_clear_hops(p_sw); u = (struct dnup_node *) p_sw->priv; u->visited = 0; } for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; dnup_bfs_by_node(p_log, p_subn, p_sw, max_hops + 1, NULL); } } OSM_LOG(p_log, OSM_LOG_VERBOSE, "BFS through all port guids in the subnet ]\n"); /* Cleanup */ OSM_LOG_EXIT(p_log); return 0; } static int dnup_build_lid_matrices(IN dnup_t * p_dnup) { int status; OSM_LOG_ENTER(&p_dnup->p_osm->log); OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_VERBOSE, "Ranking all port guids in the list\n"); /* Check if it's not a switched subnet */ if (cl_is_qmap_empty(&p_dnup->p_osm->subn.sw_guid_tbl)) { OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_ERROR, "ERR AEOB: " "This is not a switched subnet, cannot perform DNUP algorithm\n"); status = -1; goto _exit; } /* Rank the subnet switches */ dnup_subn_rank(p_dnup); /* After multiple ranking need to set Min Hop Table by DnUp algorithm */ OSM_LOG(&p_dnup->p_osm->log, OSM_LOG_VERBOSE, "Setting all switches' Min Hop Table\n"); status = dnup_set_min_hop_table(p_dnup); _exit: OSM_LOG_EXIT(&p_dnup->p_osm->log); return status; } static struct dnup_node *create_dnup_node(osm_switch_t * sw) { struct dnup_node *u; u = malloc(sizeof(*u)); if (!u) return NULL; memset(u, 0, sizeof(*u)); u->sw = sw; u->rank = 0xffffffff; return u; } static void delete_dnup_node(struct dnup_node *u) { u->sw->priv = NULL; free(u); } /* DNUP callback function */ static int dnup_lid_matrices(void *ctx) { dnup_t *p_dnup = ctx; cl_map_item_t *item; osm_switch_t *p_sw; int ret = 0; int num_leafs = 0; uint8_t pn, pn_rem; OSM_LOG_ENTER(&p_dnup->p_osm->log); for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; p_sw->priv = create_dnup_node(p_sw); if (!p_sw->priv) { OSM_LOG(&(p_dnup->p_osm->log), OSM_LOG_ERROR, "ERR AE0C: " "cannot create dnup node\n"); OSM_LOG_EXIT(&p_dnup->p_osm->log); return -1; } } /* First setup node level nodes */ for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *)item; for (pn = 0; pn < p_sw->num_ports; pn++) { osm_node_t *p_remote_node; p_remote_node = osm_node_get_remote_node(p_sw->p_node, pn, &pn_rem); if(p_remote_node && !p_remote_node->sw) { struct dnup_node *u = p_sw->priv; u->rank = 0; OSM_LOG(&(p_dnup->p_osm->log), OSM_LOG_VERBOSE, "(%s) rank 0 leaf switch\n", p_sw->p_node->print_desc); num_leafs++; break; } } } if(num_leafs == 0) { OSM_LOG(&(p_dnup->p_osm->log), OSM_LOG_ERROR, "ERR AE0D: No leaf switches found, DnUp routing failed\n"); OSM_LOG_EXIT(&p_dnup->p_osm->log); return -1; } ret = dnup_build_lid_matrices(p_dnup); for (item = cl_qmap_head(&p_dnup->p_osm->subn.sw_guid_tbl); item != cl_qmap_end(&p_dnup->p_osm->subn.sw_guid_tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; delete_dnup_node(p_sw->priv); } OSM_LOG_EXIT(&p_dnup->p_osm->log); return ret; } static void dnup_delete(void *context) { free(context); } int osm_ucast_dnup_setup(struct osm_routing_engine *r, osm_opensm_t *osm) { dnup_t *dnup; OSM_LOG_ENTER(&osm->log); dnup = malloc(sizeof(dnup_t)); if (!dnup) return -1; memset(dnup, 0, sizeof(dnup_t)); dnup->p_osm = osm; r->context = dnup; r->destroy = dnup_delete; r->build_lid_matrices = dnup_lid_matrices; OSM_LOG_EXIT(&osm->log); return 0; } opensm-3.3.20/opensm/osm_ucast_dfsssp.c0000644000205000001450000024405412607730031015044 00000000000000/* * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009-2015 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved. * Copyright (C) 2012-2013 Tokyo Institute of Technology. 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 OpenSM (deadlock-free) single-source-shortest-path routing * (with dijkstra algorithm) */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_UCAST_DFSSSP_C #include #include #include #include #include /* "infinity" for dijkstra */ #define INF 0x7FFFFFFF enum { UNDISCOVERED = 0, DISCOVERED }; enum { UNKNOWN = 0, GRAY, BLACK, }; typedef struct link { uint64_t guid; /* guid of the neighbor behind the link */ uint32_t from; /* base_index in the adjazenz list (start of the link) */ uint8_t from_port; /* port on the base_side (needed for weight update to identify the correct link for multigraphs) */ uint32_t to; /* index of the neighbor in the adjazenz list (end of the link) */ uint8_t to_port; /* port on the side of the neighbor (needed for the LFT) */ uint64_t weight; /* link weight */ struct link *next; } link_t; typedef struct vertex { /* informations of the fabric */ uint64_t guid; uint16_t lid; /* for lft filling */ uint32_t num_hca; /* numbers of Hca/LIDs on the switch, for weight calculation */ link_t *links; uint8_t hops; /* for dijkstra routing */ link_t *used_link; /* link between the vertex discovered before and this vertex */ uint64_t distance; /* distance from source to this vertex */ uint8_t state; /* for the binary heap */ uint32_t heap_id; /* for LFT writing and debug */ osm_switch_t *sw; /* selfpointer */ boolean_t dropped; /* indicate dropped switches (w/ ucast cache) */ } vertex_t; typedef struct binary_heap { uint32_t size; /* size of the heap */ vertex_t **nodes; /* array with pointers to elements of the adj_list */ } binary_heap_t; typedef struct vltable { uint64_t num_lids; /* size of the lids array */ uint16_t *lids; /* sorted array of all lids in the subnet */ uint8_t *vls; /* matrix form assignment lid X lid -> virtual lane */ } vltable_t; typedef struct cdg_link { struct cdg_node *node; uint32_t num_pairs; /* number of src->dest pairs incremented in path adding step */ uint32_t max_len; /* length of the srcdest array */ uint32_t removed; /* number of pairs removed in path deletion step */ uint32_t *srcdest_pairs; struct cdg_link *next; } cdg_link_t; /* struct for a node of a binary tree with additional parent pointer */ typedef struct cdg_node { uint64_t channelID; /* unique key consist of src lid + port + dest lid + port */ cdg_link_t *linklist; /* edges to adjazent nodes */ uint8_t status; /* node status in cycle search to avoid recursive function */ uint8_t visited; /* needed to traverse the binary tree */ struct cdg_node *pre; /* to save the path in cycle detection algorithm */ struct cdg_node *left, *right, *parent; } cdg_node_t; typedef struct dfsssp_context { osm_routing_engine_type_t routing_type; osm_ucast_mgr_t *p_mgr; vertex_t *adj_list; uint32_t adj_list_size; vltable_t *srcdest2vl_table; uint8_t *vl_split_count; } dfsssp_context_t; /**************** set initial values for structs ********************** **********************************************************************/ static inline void set_default_link(link_t * link) { link->guid = 0; link->from = 0; link->from_port = 0; link->to = 0; link->to_port = 0; link->weight = 0; link->next = NULL; } static inline void set_default_vertex(vertex_t * vertex) { vertex->guid = 0; vertex->lid = 0; vertex->num_hca = 0; vertex->links = NULL; vertex->hops = 0; vertex->used_link = NULL; vertex->distance = 0; vertex->state = UNDISCOVERED; vertex->heap_id = 0; vertex->sw = NULL; vertex->dropped = FALSE; } static inline void set_default_cdg_node(cdg_node_t * node) { node->channelID = 0; node->linklist = NULL; node->status = UNKNOWN; node->visited = 0; node->pre = NULL; node->left = NULL; node->right = NULL; node->parent = NULL; } /********************************************************************** **********************************************************************/ /************ helper functions for heap in dijkstra ******************* **********************************************************************/ /* returns true if element 1 is smaller than element 2 */ static inline uint32_t heap_smaller(binary_heap_t * heap, uint32_t i, uint32_t j) { return (heap->nodes[i]->distance < heap->nodes[j]->distance) ? 1 : 0; } /* swap two elements */ static void heap_exchange(binary_heap_t * heap, uint32_t i, uint32_t j) { uint32_t tmp_heap_id = 0; vertex_t *tmp_node = NULL; /* 1. swap the heap_id */ tmp_heap_id = heap->nodes[i]->heap_id; heap->nodes[i]->heap_id = heap->nodes[j]->heap_id; heap->nodes[j]->heap_id = tmp_heap_id; /* 2. swap pointers */ tmp_node = heap->nodes[i]; heap->nodes[i] = heap->nodes[j]; heap->nodes[j] = tmp_node; } /* changes position of element with parent until children are bigger */ static uint32_t heap_up(binary_heap_t * heap, uint32_t i) { uint32_t curr = i, father = 0; if (curr > 0) { father = (curr - 1) >> 1; while (heap_smaller(heap, curr, father)) { heap_exchange(heap, curr, father); /* try to go up when we arent already root */ curr = father; if (curr > 0) father = (curr - 1) >> 1; } } return curr; } /* changes position of element with children until parent is smaller */ static uint32_t heap_down(binary_heap_t * heap, uint32_t i) { uint32_t curr = i; uint32_t son1 = 0, son2 = 0, smaller_son = 0; uint32_t exchanged = 0; do { son1 = ((curr + 1) << 1) - 1; son2 = (curr + 1) << 1; exchanged = 0; /* exchange with smaller son */ if (son1 < heap->size && son2 < heap->size) { if (heap_smaller(heap, son1, son2)) smaller_son = son1; else smaller_son = son2; } else if (son1 < heap->size) { /* only one son */ smaller_son = son1; } else { /* finished */ break; } /* only exchange when smaller */ if (heap_smaller(heap, smaller_son, curr)) { heap_exchange(heap, curr, smaller_son); exchanged = 1; curr = smaller_son; } } while (exchanged); return curr; } /* reheapify element */ static inline void heap_heapify(binary_heap_t * heap, uint32_t i) { heap_down(heap, heap_up(heap, i)); } /* creates heap for graph */ static int heap_create(vertex_t * adj_list, uint32_t adj_list_size, binary_heap_t ** binheap) { binary_heap_t *heap = NULL; uint32_t i = 0; /* allocate the memory for the heap object */ heap = (binary_heap_t *) malloc(sizeof(binary_heap_t)); if (!heap) return 1; /* the heap size is equivalent to the size of the adj_list */ heap->size = adj_list_size; /* allocate the pointer array, fill with the pointers to the elements of the adj_list and set the initial heap_id */ heap->nodes = (vertex_t **) malloc(heap->size * sizeof(vertex_t *)); if (!heap->nodes) { free(heap); return 1; } for (i = 0; i < heap->size; i++) { heap->nodes[i] = &adj_list[i]; heap->nodes[i]->heap_id = i; } /* sort elements */ for (i = heap->size; i > 0; i--) heap_down(heap, i - 1); *binheap = heap; return 0; } /* returns current minimum and removes it from heap */ static vertex_t *heap_getmin(binary_heap_t * heap) { vertex_t *min = NULL; if (heap->size > 0) min = heap->nodes[0]; if (min == NULL) return min; if (heap->size > 0) { if (heap->size > 1) { heap_exchange(heap, 0, heap->size - 1); heap->size--; heap_down(heap, 0); } else { heap->size--; } } return min; } /* cleanup heap */ static void heap_free(binary_heap_t * heap) { if (heap) { if (heap->nodes) { free(heap->nodes); heap->nodes = NULL; } free(heap); } } /********************************************************************** **********************************************************************/ /************ helper functions to save src/dest X vl combination ****** **********************************************************************/ /* compare function of two lids for stdlib qsort */ static int cmp_lids(const void *l1, const void *l2) { ib_net16_t lid1 = *((ib_net16_t *) l1), lid2 = *((ib_net16_t *) l2); if (lid1 < lid2) return -1; else if (lid1 > lid2) return 1; else return 0; } /* use stdlib to sort the lid array */ static inline void vltable_sort_lids(vltable_t * vltable) { qsort(vltable->lids, vltable->num_lids, sizeof(ib_net16_t), cmp_lids); } /* use stdlib to get index of key in lid array; return -1 if lid isn't found in lids array */ static inline int64_t vltable_get_lidindex(ib_net16_t * key, vltable_t * vltable) { ib_net16_t *found_lid = NULL; found_lid = (ib_net16_t *) bsearch(key, vltable->lids, vltable->num_lids, sizeof(ib_net16_t), cmp_lids); if (found_lid) return found_lid - vltable->lids; else return -1; } /* get virtual lane from src lid X dest lid combination; return -1 for invalid lids */ static int32_t vltable_get_vl(vltable_t * vltable, ib_net16_t slid, ib_net16_t dlid) { int64_t ind1 = vltable_get_lidindex(&slid, vltable); int64_t ind2 = vltable_get_lidindex(&dlid, vltable); if (ind1 > -1 && ind2 > -1) return (int32_t) (vltable-> vls[ind1 + ind2 * vltable->num_lids]); else return -1; } /* set a virtual lane in the matrix */ static inline void vltable_insert(vltable_t * vltable, ib_net16_t slid, ib_net16_t dlid, uint8_t vl) { int64_t ind1 = vltable_get_lidindex(&slid, vltable); int64_t ind2 = vltable_get_lidindex(&dlid, vltable); if (ind1 > -1 && ind2 > -1) vltable->vls[ind1 + ind2 * vltable->num_lids] = vl; } /* change a number of lanes from lane xy to lane yz */ static void vltable_change_vl(vltable_t * vltable, uint8_t from, uint8_t to, uint64_t count) { uint64_t set = 0, stop = 0; uint64_t ind1 = 0, ind2 = 0; for (ind1 = 0; ind1 < vltable->num_lids; ind1++) { for (ind2 = 0; ind2 < vltable->num_lids; ind2++) { if (set == count) { stop = 1; break; } if (ind1 != ind2) { if (vltable-> vls[ind1 + ind2 * vltable->num_lids] == from) { vltable->vls[ind1 + ind2 * vltable->num_lids] = to; set++; } } } if (stop) break; } } static void vltable_print(osm_ucast_mgr_t * p_mgr, vltable_t * vltable) { uint64_t ind1 = 0, ind2 = 0; for (ind1 = 0; ind1 < vltable->num_lids; ind1++) { for (ind2 = 0; ind2 < vltable->num_lids; ind2++) { if (ind1 != ind2) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " route from src_lid=%" PRIu16 " to dest_lid=%" PRIu16 " on vl=%" PRIu8 "\n", cl_ntoh16(vltable->lids[ind1]), cl_ntoh16(vltable->lids[ind2]), vltable->vls[ind1 + ind2 * vltable->num_lids]); } } } } static void vltable_dealloc(vltable_t ** vltable) { if (*vltable) { if ((*vltable)->lids) free((*vltable)->lids); if ((*vltable)->vls) free((*vltable)->vls); free(*vltable); *vltable = NULL; } } static int vltable_alloc(vltable_t ** vltable, uint64_t size) { /* allocate VL table and indexing array */ *vltable = (vltable_t *) malloc(sizeof(vltable_t)); if (!(*vltable)) goto ERROR; (*vltable)->num_lids = size; (*vltable)->lids = (ib_net16_t *) malloc(size * sizeof(ib_net16_t)); if (!((*vltable)->lids)) goto ERROR; (*vltable)->vls = (uint8_t *) malloc(size * size * sizeof(uint8_t)); if (!((*vltable)->vls)) goto ERROR; memset((*vltable)->vls, OSM_DEFAULT_SL, size * size); return 0; ERROR: vltable_dealloc(vltable); return 1; } /********************************************************************** **********************************************************************/ /************ helper functions to save/manage the channel dep. graph ** **********************************************************************/ /* update the srcdest array; realloc array (double the size) if size is not large enough */ static void set_next_srcdest_pair(cdg_link_t * link, uint32_t srcdest) { uint32_t new_size = 0, start_size = 2; uint32_t *tmp = NULL, *tmp2 = NULL; if (link->num_pairs == 0) { link->srcdest_pairs = (uint32_t *) malloc(start_size * sizeof(uint32_t)); link->srcdest_pairs[link->num_pairs] = srcdest; link->max_len = start_size; link->removed = 0; } else if (link->num_pairs == link->max_len) { new_size = link->max_len << 1; tmp = (uint32_t *) malloc(new_size * sizeof(uint32_t)); tmp = memcpy(tmp, link->srcdest_pairs, link->max_len * sizeof(uint32_t)); tmp2 = link->srcdest_pairs; link->srcdest_pairs = tmp; link->srcdest_pairs[link->num_pairs] = srcdest; free(tmp2); link->max_len = new_size; } else { link->srcdest_pairs[link->num_pairs] = srcdest; } link->num_pairs++; } static inline uint32_t get_next_srcdest_pair(cdg_link_t * link, uint32_t index) { return link->srcdest_pairs[index]; } /* traverse binary tree to find a node */ static cdg_node_t *cdg_search(cdg_node_t * root, uint64_t channelID) { while (root) { if (channelID < root->channelID) root = root->left; else if (channelID > root->channelID) root = root->right; else if (channelID == root->channelID) return root; } return NULL; } /* insert new node into the binary tree */ static void cdg_insert(cdg_node_t ** root, cdg_node_t * new_node) { cdg_node_t *current = *root; if (!current) { current = new_node; *root = current; return; } while (current) { if (new_node->channelID < current->channelID) { if (current->left) { current = current->left; } else { current->left = new_node; new_node->parent = current; break; } } else if (new_node->channelID > current->channelID) { if (current->right) { current = current->right; } else { current->right = new_node; new_node->parent = current; break; } } else if (new_node->channelID == current->channelID) { /* not really possible, maybe programming error */ break; } } } static void cdg_node_dealloc(cdg_node_t * node) { cdg_link_t *link = node->linklist, *tmp = NULL; /* dealloc linklist */ while (link) { tmp = link; link = link->next; if (tmp->num_pairs) free(tmp->srcdest_pairs); free(tmp); } /* dealloc node */ free(node); } static void cdg_dealloc(cdg_node_t ** root) { cdg_node_t *current = *root; while (current) { if (current->left) { current = current->left; } else if (current->right) { current = current->right; } else { if (current->parent == NULL) { cdg_node_dealloc(current); *root = NULL; break; } if (current->parent->left == current) { current = current->parent; cdg_node_dealloc(current->left); current->left = NULL; } else if (current->parent->right == current) { current = current->parent; cdg_node_dealloc(current->right); current->right = NULL; } } } } /* search for a edge in the cdg which should be removed to break a cycle */ static cdg_link_t *get_weakest_link_in_cycle(cdg_node_t * cycle) { cdg_node_t *current = cycle, *node_with_weakest_link = NULL; cdg_link_t *link = NULL, *weakest_link = NULL; link = current->linklist; while (link) { if (link->node->status == GRAY) { weakest_link = link; node_with_weakest_link = current; current = link->node; break; } link = link->next; } while (1) { current->status = UNKNOWN; link = current->linklist; while (link) { if (link->node->status == GRAY) { if ((link->num_pairs - link->removed) < (weakest_link->num_pairs - weakest_link->removed)) { weakest_link = link; node_with_weakest_link = current; } current = link->node; break; } link = link->next; } /* if complete cycle is traversed */ if (current == cycle) { current->status = UNKNOWN; break; } } if (node_with_weakest_link->linklist == weakest_link) { node_with_weakest_link->linklist = weakest_link->next; } else { link = node_with_weakest_link->linklist; while (link) { if (link->next == weakest_link) { link->next = weakest_link->next; break; } link = link->next; } } return weakest_link; } /* search for nodes in the cdg not yet reached in the cycle search process; (some nodes are unreachable, e.g. a node is a source or the cdg has not connected parts) */ static cdg_node_t *get_next_cdg_node(cdg_node_t * root) { cdg_node_t *current = root, *res = NULL; while (current) { current->visited = 1; if (current->status == UNKNOWN) { res = current; break; } if (current->left && !current->left->visited) { current = current->left; } else if (current->right && !current->right->visited) { current = current->right; } else { if (current->left) current->left->visited = 0; if (current->right) current->right->visited = 0; if (current->parent == NULL) break; else current = current->parent; } } /* Clean up */ while (current) { current->visited = 0; if (current->left) current->left->visited = 0; if (current->right) current->right->visited = 0; current = current->parent; } return res; } /* make a DFS on the cdg to check for a cycle */ static cdg_node_t *search_cycle_in_channel_dep_graph(cdg_node_t * cdg, cdg_node_t * start_node) { cdg_node_t *cycle = NULL; cdg_node_t *current = start_node, *next_node = NULL, *tmp = NULL; cdg_link_t *link = NULL; while (current) { current->status = GRAY; link = current->linklist; next_node = NULL; while (link) { if (link->node->status == UNKNOWN) { next_node = link->node; break; } if (link->node->status == GRAY) { cycle = link->node; goto Exit; } link = link->next; } if (next_node) { next_node->pre = current; current = next_node; } else { /* found a sink in the graph, go to last node */ current->status = BLACK; /* srcdest_pairs of this node aren't relevant, free the allocated memory */ link = current->linklist; while (link) { if (link->num_pairs) free(link->srcdest_pairs); link->srcdest_pairs = NULL; link->num_pairs = 0; link->removed = 0; link = link->next; } if (current->pre) { tmp = current; current = current->pre; tmp->pre = NULL; } else { /* search for other subgraphs in cdg */ current = get_next_cdg_node(cdg); if (!current) break; /* all relevant nodes traversed, no more cycles found */ } } } Exit: return cycle; } /* calculate the path from source to destination port; new channels are added directly to the cdg */ static int update_channel_dep_graph(cdg_node_t ** cdg_root, osm_port_t * src_port, uint16_t slid, osm_port_t * dest_port, uint16_t dlid) { osm_node_t *local_node = NULL, *remote_node = NULL; uint16_t local_lid = 0, remote_lid = 0; uint32_t srcdest = 0; uint8_t local_port = 0, remote_port = 0; uint64_t channelID = 0; cdg_node_t *channel_head = NULL, *channel = NULL, *last_channel = NULL; cdg_link_t *linklist = NULL; /* set the identifier for the src/dest pair to save this on each edge of the cdg */ srcdest = (((uint32_t) slid) << 16) + ((uint32_t) dlid); channel_head = (cdg_node_t *) malloc(sizeof(cdg_node_t)); if (!channel_head) goto ERROR; set_default_cdg_node(channel_head); last_channel = channel_head; /* if src is a Hca, then the channel from Hca to switch would be a source in the graph sources can't be part of a cycle -> skip this channel */ remote_node = osm_node_get_remote_node(src_port->p_node, src_port->p_physp->port_num, &remote_port); while (remote_node && remote_node->sw) { local_node = remote_node; local_port = local_node->sw->new_lft[dlid]; local_lid = cl_ntoh16(osm_node_get_base_lid(local_node, 0)); /* each port belonging to a switch has lmc==0 -> get_base_lid is fine (local/remote port in this function are always part of a switch) */ remote_node = osm_node_get_remote_node(local_node, local_port, &remote_port); /* if remote_node is a Hca, then the last channel from switch to Hca would be a sink in the cdg -> skip */ if (!remote_node || !remote_node->sw) break; remote_lid = cl_ntoh16(osm_node_get_base_lid(remote_node, 0)); channelID = (((uint64_t) local_lid) << 48) + (((uint64_t) local_port) << 32) + (((uint64_t) remote_lid) << 16) + ((uint64_t) remote_port); channel = cdg_search(*cdg_root, channelID); if (channel) { /* check whether last channel has connection to this channel, i.e. subpath already exists in cdg */ linklist = last_channel->linklist; while (linklist && linklist->node != channel && linklist->next) linklist = linklist->next; /* if there is no connection, add one */ if (linklist) { if (linklist->node == channel) { set_next_srcdest_pair(linklist, srcdest); } else { linklist->next = (cdg_link_t *) malloc(sizeof(cdg_link_t)); if (!linklist->next) goto ERROR; linklist = linklist->next; linklist->node = channel; linklist->num_pairs = 0; linklist->srcdest_pairs = NULL; set_next_srcdest_pair(linklist, srcdest); linklist->next = NULL; } } else { /* either this is the first channel of the path, or the last channel was a new channel, or last channel was a sink */ last_channel->linklist = (cdg_link_t *) malloc(sizeof(cdg_link_t)); if (!last_channel->linklist) goto ERROR; last_channel->linklist->node = channel; last_channel->linklist->num_pairs = 0; last_channel->linklist->srcdest_pairs = NULL; set_next_srcdest_pair(last_channel->linklist, srcdest); last_channel->linklist->next = NULL; } } else { /* create new channel */ channel = (cdg_node_t *) malloc(sizeof(cdg_node_t)); if (!channel) goto ERROR; set_default_cdg_node(channel); channel->channelID = channelID; cdg_insert(cdg_root, channel); /* go to end of link list of last channel */ linklist = last_channel->linklist; while (linklist && linklist->next) linklist = linklist->next; if (linklist) { /* update last link of an existing channel */ linklist->next = (cdg_link_t *) malloc(sizeof(cdg_link_t)); if (!linklist->next) goto ERROR; linklist = linklist->next; linklist->node = channel; linklist->num_pairs = 0; linklist->srcdest_pairs = NULL; set_next_srcdest_pair(linklist, srcdest); linklist->next = NULL; } else { /* either this is the first channel of the path, or the last channel was a new channel, or last channel was a sink */ last_channel->linklist = (cdg_link_t *) malloc(sizeof(cdg_link_t)); if (!last_channel->linklist) goto ERROR; last_channel->linklist->node = channel; last_channel->linklist->num_pairs = 0; last_channel->linklist->srcdest_pairs = NULL; set_next_srcdest_pair(last_channel->linklist, srcdest); last_channel->linklist->next = NULL; } } last_channel = channel; } if (channel_head->linklist) { if (channel_head->linklist->srcdest_pairs) free(channel_head->linklist->srcdest_pairs); free(channel_head->linklist); } free(channel_head); return 0; ERROR: /* cleanup data and exit */ if (channel_head) { if (channel_head->linklist) free(channel_head->linklist); free(channel_head); } return 1; } /* calculate the path from source to destination port; the links in the cdg representing this path are decremented to simulate the removal */ static int remove_path_from_cdg(cdg_node_t ** cdg_root, osm_port_t * src_port, uint16_t slid, osm_port_t * dest_port, uint16_t dlid) { osm_node_t *local_node = NULL, *remote_node = NULL; uint16_t local_lid = 0, remote_lid = 0; uint8_t local_port = 0, remote_port = 0; uint64_t channelID = 0; cdg_node_t *channel_head = NULL, *channel = NULL, *last_channel = NULL; cdg_link_t *linklist = NULL; channel_head = (cdg_node_t *) malloc(sizeof(cdg_node_t)); if (!channel_head) goto ERROR; set_default_cdg_node(channel_head); last_channel = channel_head; /* if src is a Hca, then the channel from Hca to switch would be a source in the graph sources can't be part of a cycle -> skip this channel */ remote_node = osm_node_get_remote_node(src_port->p_node, src_port->p_physp->port_num, &remote_port); while (remote_node && remote_node->sw) { local_node = remote_node; local_port = local_node->sw->new_lft[dlid]; local_lid = cl_ntoh16(osm_node_get_base_lid(local_node, 0)); remote_node = osm_node_get_remote_node(local_node, local_port, &remote_port); /* if remote_node is a Hca, then the last channel from switch to Hca would be a sink in the cdg -> skip */ if (!remote_node || !remote_node->sw) break; remote_lid = cl_ntoh16(osm_node_get_base_lid(remote_node, 0)); channelID = (((uint64_t) local_lid) << 48) + (((uint64_t) local_port) << 32) + (((uint64_t) remote_lid) << 16) + ((uint64_t) remote_port); channel = cdg_search(*cdg_root, channelID); if (channel) { /* check whether last channel has connection to this channel, i.e. subpath already exists in cdg */ linklist = last_channel->linklist; while (linklist && linklist->node != channel && linklist->next) linklist = linklist->next; /* remove the srcdest from the link */ if (linklist) { if (linklist->node == channel) { linklist->removed++; } else { /* may happen if the link is missing (thru cycle detect algorithm) */ } } else { /* may happen if the link is missing (thru cycle detect algorithm or last_channel==channel_head (dummy channel)) */ } } else { /* must be an error, channels for the path are added before, so a missing channel would be a corrupt data structure */ goto ERROR; } last_channel = channel; } if (channel_head->linklist) free(channel_head->linklist); free(channel_head); return 0; ERROR: /* cleanup data and exit */ if (channel_head) { if (channel_head->linklist) free(channel_head->linklist); free(channel_head); } return 1; } /********************************************************************** **********************************************************************/ /************ helper functions to generate an ordered list of ports *** ************ (functions copied from osm_ucast_mgr.c and modified) **** **********************************************************************/ static void add_sw_endports_to_order_list(osm_switch_t * sw, osm_ucast_mgr_t * m, cl_qmap_t * guid_tbl, boolean_t add_guids) { osm_port_t *port; uint64_t port_guid; osm_physp_t *p; int i; boolean_t found; for (i = 1; i < sw->num_ports; i++) { p = osm_node_get_physp_ptr(sw->p_node, i); if (p && p->p_remote_physp && !p->p_remote_physp->p_node->sw) { port_guid = p->p_remote_physp->port_guid; port = osm_get_port_by_guid(m->p_subn, port_guid); if (!port) continue; if (!cl_is_qmap_empty(guid_tbl)) { found = (cl_qmap_get(guid_tbl, port_guid) != cl_qmap_end(guid_tbl)); if ((add_guids && !found) || (!add_guids && found)) continue; } if (!cl_is_item_in_qlist(&m->port_order_list, &port->list_item)) cl_qlist_insert_tail(&m->port_order_list, &port->list_item); else OSM_LOG(m->p_log, OSM_LOG_INFO, "WRN AD37: guid 0x%016" PRIx64 " already in list\n", port_guid); } } } static void add_guid_to_order_list(uint64_t guid, osm_ucast_mgr_t * m) { osm_port_t *port = osm_get_port_by_guid(m->p_subn, cl_hton64(guid)); if (!port) { OSM_LOG(m->p_log, OSM_LOG_DEBUG, "port guid not found: 0x%016" PRIx64 "\n", guid); } if (!cl_is_item_in_qlist(&m->port_order_list, &port->list_item)) cl_qlist_insert_tail(&m->port_order_list, &port->list_item); else OSM_LOG(m->p_log, OSM_LOG_INFO, "WRN AD38: guid 0x%016" PRIx64 " already in list\n", guid); } /* compare function of #Hca attached to a switch for stdlib qsort */ static int cmp_num_hca(const void * l1, const void * l2) { vertex_t *sw1 = *((vertex_t **) l1); vertex_t *sw2 = *((vertex_t **) l2); uint32_t num_hca1 = 0, num_hca2 = 0; if (sw1) num_hca1 = sw1->num_hca; if (sw2) num_hca2 = sw2->num_hca; if (num_hca1 > num_hca2) return -1; else if (num_hca1 < num_hca2) return 1; else return 0; } /* use stdlib to sort the switch array depending on num_hca */ static inline void sw_list_sort_by_num_hca(vertex_t ** sw_list, uint32_t sw_list_size) { qsort(sw_list, sw_list_size, sizeof(vertex_t *), cmp_num_hca); } /********************************************************************** **********************************************************************/ /************ helper functions to manage a map of CN and I/O guids **** **********************************************************************/ static int add_guid_to_map(void * cxt, uint64_t guid, char * p) { cl_qmap_t *map = cxt; name_map_item_t *item; item = malloc(sizeof(*item)); if (!item) return -1; item->guid = cl_hton64(guid); /* internal: network byte order */ item->name = NULL; /* name isn't needed */ cl_qmap_insert(map, item->guid, &item->item); return 0; } static void destroy_guid_map(cl_qmap_t * guid_tbl) { name_map_item_t *p_guid = NULL, *p_next_guid = NULL; p_next_guid = (name_map_item_t *) cl_qmap_head(guid_tbl); while (p_next_guid != (name_map_item_t *) cl_qmap_end(guid_tbl)) { p_guid = p_next_guid; p_next_guid = (name_map_item_t *) cl_qmap_next(&p_guid->item); free(p_guid); } cl_qmap_remove_all(guid_tbl); } /********************************************************************** **********************************************************************/ static void dfsssp_print_graph(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list, uint32_t size) { uint32_t i = 0, c = 0; link_t *link = NULL; /* index 0 is for the source in dijkstra -> ignore */ for (i = 1; i < size; i++) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "adj_list[%" PRIu32 "]:\n", i); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " guid = 0x%" PRIx64 " lid = %" PRIu16 " (%s)\n", adj_list[i].guid, adj_list[i].lid, adj_list[i].sw->p_node->print_desc); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " num_hca = %" PRIu32 "\n", adj_list[i].num_hca); c = 1; for (link = adj_list[i].links; link != NULL; link = link->next, c++) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " link[%" PRIu32 "]:\n", c); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " to guid = 0x%" PRIx64 " (%s) port %" PRIu8 "\n", link->guid, adj_list[link->to].sw->p_node->print_desc, link->to_port); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " weight on this link = %" PRIu64 "\n", link->weight); } } } /* predefine, to use this in next function */ static void dfsssp_context_destroy(void *context); /* traverse subnet to gather information about the connected switches */ static int dfsssp_build_graph(void *context) { dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context; osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) (dfsssp_ctx->p_mgr); cl_qmap_t *port_tbl = &p_mgr->p_subn->port_guid_tbl; /* 1 management port per switch + 1 or 2 ports for each Hca */ osm_port_t *p_port = NULL; cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl; cl_map_item_t *item = NULL; osm_switch_t *sw = NULL; osm_node_t *remote_node = NULL; uint8_t port = 0, remote_port = 0; uint32_t i = 0, j = 0; uint64_t total_num_hca = 0; vertex_t *adj_list = NULL; osm_physp_t *p_physp = NULL; link_t *link = NULL, *head = NULL; uint32_t num_sw = 0, adj_list_size = 0; uint8_t lmc = 0; OSM_LOG_ENTER(p_mgr->p_log); OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Building graph for df-/sssp routing\n"); /* if this pointer isn't NULL, this is a reroute step; old context will be destroyed (adj_list and srcdest2vl_table) */ if (dfsssp_ctx->adj_list) dfsssp_context_destroy(context); num_sw = cl_qmap_count(sw_tbl); adj_list_size = num_sw + 1; /* allocate an adjazenz list (array), 0. element is reserved for the source (Hca) in the routing algo, others are switches */ adj_list = (vertex_t *) malloc(adj_list_size * sizeof(vertex_t)); if (!adj_list) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD02: cannot allocate memory for adj_list\n"); goto ERROR; } for (i = 0; i < adj_list_size; i++) set_default_vertex(&adj_list[i]); dfsssp_ctx->adj_list = adj_list; dfsssp_ctx->adj_list_size = adj_list_size; /* count the total number of Hca / LIDs (for lmc>0) in the fabric; even include base/enhanced switch port 0; base SP0 will have lmc=0 */ for (item = cl_qmap_head(port_tbl); item != cl_qmap_end(port_tbl); item = cl_qmap_next(item)) { p_port = (osm_port_t *) item; if (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_CA || osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH) { lmc = osm_port_get_lmc(p_port); total_num_hca += (1 << lmc); } } i = 1; /* fill adj_list -> start with index 1 */ for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl); item = cl_qmap_next(item), i++) { sw = (osm_switch_t *) item; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing switch with GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(sw->p_node))); adj_list[i].guid = cl_ntoh64(osm_node_get_node_guid(sw->p_node)); adj_list[i].lid = cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0)); adj_list[i].sw = sw; link = (link_t *) malloc(sizeof(link_t)); if (!link) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD03: cannot allocate memory for a link\n"); dfsssp_context_destroy(context); goto ERROR; } head = link; head->next = NULL; /* add SP0 to number of CA connected to a switch */ lmc = osm_node_get_lmc(sw->p_node, 0); adj_list[i].num_hca += (1 << lmc); /* iterate over all ports in the switch, start with port 1 (port 0 is a management port) */ for (port = 1; port < sw->num_ports; port++) { /* get the node behind the port */ remote_node = osm_node_get_remote_node(sw->p_node, port, &remote_port); /* if there is no remote node on this port or it's the same switch -> try next port */ if (!remote_node || remote_node->sw == sw) continue; /* make sure the link is healthy */ p_physp = osm_node_get_physp_ptr(sw->p_node, port); if (!p_physp || !osm_link_is_healthy(p_physp)) continue; /* if there is a Hca connected -> count and cycle */ if (!remote_node->sw) { lmc = osm_node_get_lmc(remote_node, (uint32_t)remote_port); adj_list[i].num_hca += (1 << lmc); continue; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 ", port %" PRIu8 ", remote port %" PRIu8 "\n", cl_ntoh64(osm_node_get_node_guid(sw->p_node)), cl_ntoh64(osm_node_get_node_guid(remote_node)), port, remote_port); link->next = (link_t *) malloc(sizeof(link_t)); if (!link->next) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD08: cannot allocate memory for a link\n"); dfsssp_context_destroy(context); while (head) { link = head; head = head->next; free(link); } goto ERROR; } link = link->next; set_default_link(link); link->guid = cl_ntoh64(osm_node_get_node_guid(remote_node)); link->from = i; link->from_port = port; link->to_port = remote_port; link->weight = total_num_hca * total_num_hca; /* initialize with P^2 to force shortest paths */ } adj_list[i].links = head->next; free(head); } /* connect the links with it's second adjacent node in the list */ for (i = 1; i < adj_list_size; i++) { link = adj_list[i].links; while (link) { for (j = 1; j < adj_list_size; j++) { if (link->guid == adj_list[j].guid) { link->to = j; break; } } link = link->next; } } /* print the discovered graph */ if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) dfsssp_print_graph(p_mgr, adj_list, adj_list_size); OSM_LOG_EXIT(p_mgr->p_log); return 0; ERROR: return -1; } static void print_routes(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list, uint32_t adj_list_size, osm_port_t * port) { uint32_t i = 0, j = 0; for (i = 1; i < adj_list_size; i++) { if (adj_list[i].state == DISCOVERED) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Route from 0x%" PRIx64 " (%s) to 0x%" PRIx64 " (%s):\n", adj_list[i].guid, adj_list[i].sw->p_node->print_desc, cl_ntoh64(osm_node_get_node_guid(port->p_node)), port->p_node->print_desc); j = i; while (adj_list[j].used_link) { if (j > 0) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " 0x%" PRIx64 " (%s) routes thru port %" PRIu8 "\n", adj_list[j].guid, adj_list[j].sw->p_node-> print_desc, adj_list[j].used_link->to_port); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " 0x%" PRIx64 " (%s) routes thru port %" PRIu8 "\n", adj_list[j].guid, port->p_node->print_desc, adj_list[j].used_link->to_port); } j = adj_list[j].used_link->from; } } } } /* dijkstra step from one source to all switches in the df-/sssp graph */ static int dijkstra(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list, uint32_t adj_list_size, osm_port_t * port, uint16_t lid) { uint32_t i = 0, j = 0, index = 0; osm_node_t *remote_node = NULL; uint8_t remote_port = 0; vertex_t *current = NULL; link_t *link = NULL; uint64_t guid = 0; binary_heap_t *heap = NULL; int err = 0; OSM_LOG_ENTER(p_mgr->p_log); /* reset all switches for new round with a new source for dijkstra */ for (i = 1; i < adj_list_size; i++) { adj_list[i].hops = 0; adj_list[i].used_link = NULL; adj_list[i].distance = INF; adj_list[i].state = UNDISCOVERED; } /* if behind port is a Hca -> set adj_list[0] */ if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_CA) { /* save old link to prevent many mallocs after set_default_... */ link = adj_list[0].links; /* initialize adj_list[0] (the source for the routing, a Hca) */ set_default_vertex(&adj_list[0]); adj_list[0].guid = cl_ntoh64(osm_node_get_node_guid(port->p_node)); adj_list[0].lid = lid; index = 0; /* write saved link back to new adj_list[0] */ adj_list[0].links = link; /* initialize link to neighbor for adj_list[0]; make sure the link is healthy */ if (port->p_physp && osm_link_is_healthy(port->p_physp)) { remote_node = osm_node_get_remote_node(port->p_node, port->p_physp->port_num, &remote_port); /* if there is no remote node on this port or it's the same Hca -> ignore */ if (remote_node && (osm_node_get_type(remote_node) == IB_NODE_TYPE_SWITCH)) { if (!(adj_list[0].links)) { adj_list[0].links = (link_t *) malloc(sizeof(link_t)); if (!(adj_list[0].links)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD07: cannot allocate memory for a link\n"); return 1; } } set_default_link(adj_list[0].links); adj_list[0].links->guid = cl_ntoh64(osm_node_get_node_guid (remote_node)); adj_list[0].links->from_port = port->p_physp->port_num; adj_list[0].links->to_port = remote_port; adj_list[0].links->weight = 1; for (j = 1; j < adj_list_size; j++) { if (adj_list[0].links->guid == adj_list[j].guid) { adj_list[0].links->to = j; break; } } } } /* if behind port is a switch -> search switch in adj_list */ } else { /* reset adj_list[0], if links=NULL reset was done before, then skip */ if (adj_list[0].links) { free(adj_list[0].links); set_default_vertex(&adj_list[0]); } /* search for the switch which is the source in this round */ guid = cl_ntoh64(osm_node_get_node_guid(port->p_node)); for (i = 1; i < adj_list_size; i++) { if (guid == adj_list[i].guid) { index = i; break; } } } /* source in dijkstra */ adj_list[index].distance = 0; adj_list[index].state = DISCOVERED; adj_list[index].hops = 0; /* the source has hop count = 0 */ /* create a heap to find (efficient) the node with the smallest distance */ if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_CA) err = heap_create(adj_list, adj_list_size, &heap); else err = heap_create(&adj_list[1], adj_list_size - 1, &heap); if (err) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD09: cannot allocate memory for heap or heap->node in heap_create(...)\n"); return err; } current = heap_getmin(heap); while (current) { current->state = DISCOVERED; if (current->used_link) /* increment the number of hops to the source for each new node */ current->hops = adj_list[current->used_link->from].hops + 1; /* add/update nodes which aren't discovered but accessible */ for (link = current->links; link != NULL; link = link->next) { if ((adj_list[link->to].state != DISCOVERED) && (current->distance + link->weight < adj_list[link->to].distance)) { adj_list[link->to].used_link = link; adj_list[link->to].distance = current->distance + link->weight; heap_heapify(heap, adj_list[link->to].heap_id); } } current = heap_getmin(heap); } /* destroy the heap */ heap_free(heap); heap = NULL; OSM_LOG_EXIT(p_mgr->p_log); return 0; } /* update the linear forwarding tables of all switches with the informations from the last dijsktra step */ static int update_lft(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list, uint32_t adj_list_size, osm_port_t * p_port, uint16_t lid) { uint32_t i = 0; uint8_t port = 0; uint8_t hops = 0; osm_switch_t *p_sw = NULL; boolean_t is_ignored_by_port_prof = FALSE; osm_physp_t *p = NULL; cl_status_t ret; OSM_LOG_ENTER(p_mgr->p_log); for (i = 1; i < adj_list_size; i++) { /* if no route goes thru this switch -> cycle */ if (!(adj_list[i].used_link)) continue; p_sw = adj_list[i].sw; hops = adj_list[i].hops; port = adj_list[i].used_link->to_port; /* the used_link is the link that was used in dijkstra to reach this node, so the to_port is the local port on this node */ if (port == OSM_NO_PATH) { /* if clause shouldn't be possible in this routing, but who cares */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD06: No path to get to LID %" PRIu16 " from switch 0x%" PRIx64 "\n", lid, cl_ntoh64(osm_node_get_node_guid (p_sw->p_node))); /* do not try to overwrite the ppro of non existing port ... */ is_ignored_by_port_prof = TRUE; return 1; } else { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Routing LID %" PRIu16 " to port %" PRIu8 " for switch 0x%" PRIx64 "\n", lid, port, cl_ntoh64(osm_node_get_node_guid (p_sw->p_node))); p = osm_node_get_physp_ptr(p_sw->p_node, port); if (!p) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD0A: Physical port %d of Node GUID 0x%" PRIx64 "not found\n", port, cl_ntoh64(osm_node_get_node_guid(p_sw->p_node))); return 1; } /* we would like to optionally ignore this port in equalization as in the case of the Mellanox Anafa Internal PCI TCA port */ is_ignored_by_port_prof = p->is_prof_ignored; /* We also would ignore this route if the target lid is of a switch and the port_profile_switch_node is not TRUE */ if (!p_mgr->p_subn->opt.port_profile_switch_nodes) is_ignored_by_port_prof |= (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH); } /* to support lmc > 0 the functions alloc_ports_priv, free_ports_priv, find_and_add_remote_sys from minhop aren't needed cause osm_switch_recommend_path is implicitly calculated for each LID pair thru dijkstra; for each port the dijkstra algorithm calculates (max_lid_ho - min_lid_ho)-times maybe disjoint routes to spread the bandwidth -> diffent routes for one port and lmc>0 */ /* set port in LFT */ p_sw->new_lft[lid] = port; if (!is_ignored_by_port_prof) { /* update the number of path routing thru this port */ osm_switch_count_path(p_sw, port); } /* set the hop count from this switch to the lid */ ret = osm_switch_set_hops(p_sw, lid, port, hops); if (ret != CL_SUCCESS) OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD05: cannot set hops for LID %" PRIu16 " at switch 0x%" PRIx64 "\n", lid, cl_ntoh64(osm_node_get_node_guid (p_sw->p_node))); } OSM_LOG_EXIT(p_mgr->p_log); return 0; } /* the function updates the multicast group membership information similar to create_mgrp_switch_map (osm_mcast_mgr.c) => with it we can identify if a switch needs to be processed or not in update_mcft */ static void update_mgrp_membership(cl_qlist_t * port_list) { osm_mcast_work_obj_t *wobj = NULL; osm_port_t *port = NULL; osm_switch_t *sw = NULL; cl_list_item_t *i = NULL; for (i = cl_qlist_head(port_list); i != cl_qlist_end(port_list); i = cl_qlist_next(i)) { wobj = cl_item_obj(i, wobj, list_item); port = wobj->p_port; if (port->p_node->sw) { sw = port->p_node->sw; sw->is_mc_member = 1; } else { sw = port->p_physp->p_remote_physp->p_node->sw; sw->num_of_mcm++; } } } /* reset is_mc_member and num_of_mcm for future computations */ static void reset_mgrp_membership(vertex_t * adj_list, uint32_t adj_list_size) { uint32_t i = 0; for (i = 1; i < adj_list_size; i++) { if (adj_list[i].dropped) continue; adj_list[i].sw->is_mc_member = 0; adj_list[i].sw->num_of_mcm = 0; } } /* update the multicast forwarding tables of all switches with the informations from the previous dijsktra step for the current mlid */ static int update_mcft(osm_sm_t * p_sm, vertex_t * adj_list, uint32_t adj_list_size, uint16_t mlid_ho, cl_qmap_t * port_map, osm_switch_t * root_sw) { uint32_t i = 0; uint8_t port = 0, remote_port = 0; uint8_t upstream_port = 0, downstream_port = 0; ib_net64_t guid = 0; osm_switch_t *p_sw = NULL; osm_node_t *remote_node = NULL; osm_physp_t *p_physp = NULL; osm_mcast_tbl_t *p_tbl = NULL; vertex_t *curr_adj = NULL; OSM_LOG_ENTER(p_sm->p_log); for (i = 1; i < adj_list_size; i++) { if (adj_list[i].dropped) continue; p_sw = adj_list[i].sw; OSM_LOG(p_sm->p_log, OSM_LOG_VERBOSE, "Processing switch 0x%016" PRIx64 " (%s) for MLID 0x%X\n", cl_ntoh64(adj_list[i].guid), p_sw->p_node->print_desc, mlid_ho); /* if a) the switch does not support mcast or b) no ports of this switch are part or the mcast group then cycle */ if (osm_switch_supports_mcast(p_sw) == FALSE || (p_sw->num_of_mcm == 0 && !(p_sw->is_mc_member))) continue; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); /* add all ports of this sw to the mcast table, if they are part of the mcast grp */ if (p_sw->is_mc_member) osm_mcast_tbl_set(p_tbl, mlid_ho, 0); for (port = 1; port < p_sw->num_ports; port++) { /* get the node behind the port */ remote_node = osm_node_get_remote_node(p_sw->p_node, port, &remote_port); /* check if connected and its not the same switch */ if (!remote_node || remote_node->sw == p_sw) continue; /* make sure the link is healthy */ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port); if (!p_physp || !osm_link_is_healthy(p_physp)) continue; /* we don't add upstream ports in this step */ if (osm_node_get_type(remote_node) != IB_NODE_TYPE_CA) continue; guid = osm_physp_get_port_guid(osm_node_get_physp_ptr( remote_node, remote_port)); if (cl_qmap_get(port_map, guid) != cl_qmap_end(port_map)) osm_mcast_tbl_set(p_tbl, mlid_ho, port); } /* now we have to add the upstream port of 'this' switch and the downstream port of the next switch to the mcast table until we reach the root_sw */ curr_adj = &adj_list[i]; while (curr_adj->sw != root_sw) { /* the used_link is the link that was used in dijkstra to reach this node, so the to_port is the local (upstream) port on curr_adj->sw */ upstream_port = curr_adj->used_link->to_port; osm_mcast_tbl_set(p_tbl, mlid_ho, upstream_port); /* now we go one step in direction root_sw and add the downstream port for the spanning tree */ downstream_port = curr_adj->used_link->from_port; p_tbl = osm_switch_get_mcast_tbl_ptr( adj_list[curr_adj->used_link->from].sw); osm_mcast_tbl_set(p_tbl, mlid_ho, downstream_port); curr_adj = &adj_list[curr_adj->used_link->from]; } } OSM_LOG_EXIT(p_sm->p_log); return 0; } /* increment the edge weights of the df-/sssp graph which represent the number of paths on this link */ static void update_weights(osm_ucast_mgr_t * p_mgr, vertex_t * adj_list, uint32_t adj_list_size) { uint32_t i = 0, j = 0; uint32_t additional_weight = 0; OSM_LOG_ENTER(p_mgr->p_log); for (i = 1; i < adj_list_size; i++) { /* if no route goes thru this switch -> cycle */ if (!(adj_list[i].used_link)) continue; additional_weight = adj_list[i].num_hca; j = i; while (adj_list[j].used_link) { /* update the link from pre to this node */ adj_list[j].used_link->weight += additional_weight; j = adj_list[j].used_link->from; } } OSM_LOG_EXIT(p_mgr->p_log); } /* get the largest number of virtual lanes which is supported by all switches in the subnet */ static uint8_t get_avail_vl_in_subn(osm_ucast_mgr_t * p_mgr) { uint32_t i = 0; uint8_t vls_avail = 0xFF, port_vls_avail = 0; cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl; cl_map_item_t *item = NULL; osm_switch_t *sw = NULL; /* traverse all switches to get the number of available virtual lanes in the subnet */ for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl); item = cl_qmap_next(item)) { sw = (osm_switch_t *) item; /* ignore management port 0 */ for (i = 1; i < osm_node_get_num_physp(sw->p_node); i++) { osm_physp_t *p_physp = osm_node_get_physp_ptr(sw->p_node, i); if (p_physp && p_physp->p_remote_physp) { port_vls_avail = ib_port_info_get_op_vls(&p_physp-> port_info); if (port_vls_avail && port_vls_avail < vls_avail) vls_avail = port_vls_avail; } } } /* ib_port_info_get_op_vls gives values 1 ... 5 (s. IBAS 14.2.5.6) */ vls_avail = 1 << (vls_avail - 1); /* set boundaries (s. IBAS 3.5.7) */ if (vls_avail > 15) vls_avail = 15; if (vls_avail < 1) vls_avail = 1; return vls_avail; } /* search for cycles in the channel dependency graph to identify possible deadlocks in the network; assign new virtual lanes to some paths to break the deadlocks */ static int dfsssp_remove_deadlocks(dfsssp_context_t * dfsssp_ctx) { osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr; cl_qlist_t *port_tbl = &p_mgr->port_order_list; /* 1 management port per switch + 1 or 2 ports for each Hca */ cl_list_item_t *item1 = NULL, *item2 = NULL; osm_port_t *src_port = NULL, *dest_port = NULL; uint32_t i = 0, j = 0, err = 0; uint8_t vl = 0, test_vl = 0, vl_avail = 0, vl_needed = 1; double most_avg_paths = 0.0; cdg_node_t **cdg = NULL, *start_here = NULL, *cycle = NULL; cdg_link_t *weakest_link = NULL; uint32_t srcdest = 0; vltable_t *srcdest2vl_table = NULL; uint8_t lmc = 0; uint16_t slid = 0, dlid = 0, min_lid_ho = 0, max_lid_ho = 0, min_lid_ho2 = 0, max_lid_ho2 = 0;; uint64_t *paths_per_vl = NULL; uint64_t from = 0, to = 0, count = 0; uint8_t *split_count = NULL; uint8_t ntype = 0; OSM_LOG_ENTER(p_mgr->p_log); OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Assign each src/dest pair a Virtual Lanes, to remove deadlocks in the routing\n"); vl_avail = get_avail_vl_in_subn(p_mgr); OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "Virtual Lanes available: %" PRIu8 "\n", vl_avail); paths_per_vl = (uint64_t *) malloc(vl_avail * sizeof(uint64_t)); if (!paths_per_vl) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD22: cannot allocate memory for paths_per_vl\n"); return 1; } memset(paths_per_vl, 0, vl_avail * sizeof(uint64_t)); cdg = (cdg_node_t **) malloc(vl_avail * sizeof(cdg_node_t *)); if (!cdg) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD23: cannot allocate memory for cdg\n"); free(paths_per_vl); return 1; } for (i = 0; i < vl_avail; i++) cdg[i] = NULL; count = 0; /* count all ports (also multiple LIDs) of type CA or SP0 for size of VL table */ for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl); item1 = cl_qlist_next(item1)) { dest_port = (osm_port_t *)cl_item_obj(item1, dest_port, list_item); ntype = osm_node_get_type(dest_port->p_node); if (ntype == IB_NODE_TYPE_CA || ntype == IB_NODE_TYPE_SWITCH) { /* only SP0 with SLtoVLMapping support will be processed */ if (ntype == IB_NODE_TYPE_SWITCH && !(dest_port->p_physp->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) continue; lmc = osm_port_get_lmc(dest_port); count += (1 << lmc); } } /* allocate VL table and indexing array */ err = vltable_alloc(&srcdest2vl_table, count); if (err) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD26: cannot allocate memory for srcdest2vl_table\n"); goto ERROR; } i = 0; /* fill lids into indexing array */ for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl); item1 = cl_qlist_next(item1)) { dest_port = (osm_port_t *)cl_item_obj(item1, dest_port, list_item); ntype = osm_node_get_type(dest_port->p_node); if (ntype == IB_NODE_TYPE_CA || ntype == IB_NODE_TYPE_SWITCH) { /* only SP0 with SLtoVLMapping support will be processed */ if (ntype == IB_NODE_TYPE_SWITCH && !(dest_port->p_physp->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) continue; osm_port_get_lid_range_ho(dest_port, &min_lid_ho, &max_lid_ho); for (dlid = min_lid_ho; dlid <= max_lid_ho; dlid++, i++) srcdest2vl_table->lids[i] = cl_hton16(dlid); } } /* sort lids */ vltable_sort_lids(srcdest2vl_table); test_vl = 0; /* fill cdg[0] with routes from each src/dest port combination for all Hca/SP0 in the subnet */ for (item1 = cl_qlist_head(port_tbl); item1 != cl_qlist_end(port_tbl); item1 = cl_qlist_next(item1)) { dest_port = (osm_port_t *)cl_item_obj(item1, dest_port, list_item); ntype = osm_node_get_type(dest_port->p_node); if ((ntype != IB_NODE_TYPE_CA && ntype != IB_NODE_TYPE_SWITCH) || !(dest_port->p_physp->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) continue; for (item2 = cl_qlist_head(port_tbl); item2 != cl_qlist_end(port_tbl); item2 = cl_qlist_next(item2)) { src_port = (osm_port_t *)cl_item_obj(item2, src_port, list_item); ntype = osm_node_get_type(src_port->p_node); if ((ntype != IB_NODE_TYPE_CA && ntype != IB_NODE_TYPE_SWITCH) || !(src_port->p_physp->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP)) continue; if (src_port != dest_port) { /* iterate over LIDs of src and dest port */ osm_port_get_lid_range_ho(src_port, &min_lid_ho, &max_lid_ho); for (slid = min_lid_ho; slid <= max_lid_ho; slid++) { osm_port_get_lid_range_ho (dest_port, &min_lid_ho2, &max_lid_ho2); for (dlid = min_lid_ho2; dlid <= max_lid_ho2; dlid++) { /* try to add the path to cdg[0] */ err = update_channel_dep_graph (&(cdg[test_vl]), src_port, slid, dest_port, dlid); if (err) { OSM_LOG(p_mgr-> p_log, OSM_LOG_ERROR, "ERR AD14: cannot allocate memory for cdg node or link in update_channel_dep_graph(...)\n"); goto ERROR; } /* add the combination / corresponding virtual lane to the VL table */ vltable_insert (srcdest2vl_table, cl_hton16(slid), cl_hton16(dlid), test_vl); paths_per_vl[test_vl]++; } } } } } dfsssp_ctx->srcdest2vl_table = srcdest2vl_table; /* test all cdg for cycles and break the cycles by moving paths on the weakest link to the next cdg */ for (test_vl = 0; test_vl < vl_avail - 1; test_vl++) { start_here = cdg[test_vl]; while (start_here) { cycle = search_cycle_in_channel_dep_graph(cdg[test_vl], start_here); if (cycle) { vl_needed = test_vl + 2; /* calc weakest link n cycle */ weakest_link = get_weakest_link_in_cycle(cycle); if (!weakest_link) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD27: something went wrong in get_weakest_link_in_cycle(...)\n"); err = 1; goto ERROR; } paths_per_vl[test_vl] -= weakest_link->num_pairs; paths_per_vl[test_vl + 1] += weakest_link->num_pairs; /* move all paths on this link to the next cdg */ for (i = 0; i < weakest_link->num_pairs; i++) { srcdest = get_next_srcdest_pair(weakest_link, i); slid = (uint16_t) (srcdest >> 16); dlid = (uint16_t) ((srcdest << 16) >> 16); /* only move if not moved in a previous step */ if (test_vl != (uint8_t) vltable_get_vl(srcdest2vl_table, cl_hton16(slid), cl_hton16(dlid))) { /* this path has been moved before -> don't count */ paths_per_vl[test_vl]++; paths_per_vl[test_vl + 1]--; continue; } src_port = osm_get_port_by_lid(p_mgr->p_subn, cl_hton16 (slid)); dest_port = osm_get_port_by_lid(p_mgr->p_subn, cl_hton16 (dlid)); /* remove path from current cdg / vl */ err = remove_path_from_cdg(& (cdg[test_vl]), src_port, slid, dest_port, dlid); if (err) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD44: something went wrong in remove_path_from_cdg(...)\n"); goto ERROR; } /* add path to next cdg / vl */ err = update_channel_dep_graph(& (cdg [test_vl + 1]), src_port, slid, dest_port, dlid); if (err) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD14: cannot allocate memory for cdg node or link in update_channel_dep_graph(...)\n"); goto ERROR; } vltable_insert(srcdest2vl_table, cl_hton16(slid), cl_hton16(dlid), test_vl + 1); } if (weakest_link->num_pairs) free(weakest_link->srcdest_pairs); if (weakest_link) free(weakest_link); } start_here = cycle; } } /* test the last avail cdg for a cycle; if there is one, than vl_needed > vl_avail */ start_here = cdg[vl_avail - 1]; if (start_here) { cycle = search_cycle_in_channel_dep_graph(cdg[vl_avail - 1], start_here); if (cycle) { vl_needed = vl_avail + 1; } } OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "Virtual Lanes needed: %" PRIu8 "\n", vl_needed); if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_INFO)) { OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "Paths per VL (before balancing):\n"); for (i = 0; i < vl_avail; i++) OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, " %" PRIu32 ". lane: %" PRIu64 "\n", i, paths_per_vl[i]); } OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Balancing the paths on the available Virtual Lanes\n"); /* optimal balancing virtual lanes, under condition: no additional cycle checks; sl/vl != 0 might be assigned to loopback packets (i.e. slid/dlid on the same port for lmc>0), but thats no problem, see IBAS 10.2.2.3 */ split_count = (uint8_t *) calloc(vl_avail, sizeof(uint8_t)); if (!split_count) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD24: cannot allocate memory for split_count, skip balancing\n"); err = 1; goto ERROR; } /* initial state: paths for VLs won't be separated */ for (i = 0; i < ((vl_needed < vl_avail) ? vl_needed : vl_avail); i++) split_count[i] = 1; dfsssp_ctx->vl_split_count = split_count; /* balancing is necessary if we have empty VLs */ if (vl_needed < vl_avail) { /* split paths of VLs until we find an equal distribution */ for (i = vl_needed; i < vl_avail; i++) { /* find VL with most paths in it */ vl = 0; most_avg_paths = 0.0; for (test_vl = 0; test_vl < vl_needed; test_vl++) { if (most_avg_paths < ((double)paths_per_vl[test_vl] / split_count[test_vl])) { vl = test_vl; most_avg_paths = (double)paths_per_vl[test_vl] / split_count[test_vl]; } } split_count[vl]++; } /* change the VL assignment depending on split_count for all VLs except VL 0 */ for (from = vl_needed - 1; from > 0; from--) { /* how much space needed for others? */ to = 0; for (i = 0; i < from; i++) to += split_count[i]; count = paths_per_vl[from]; vltable_change_vl(srcdest2vl_table, from, to, count); /* change also the information within the split_count array; this is important for fast calculation later */ split_count[to] = split_count[from]; split_count[from] = 0; paths_per_vl[to] = paths_per_vl[from]; paths_per_vl[from] = 0; } } else if (vl_needed > vl_avail) { /* routing not possible, a further development would be the LASH-TOR approach (update: LASH-TOR isn't possible, there is a mistake in the theory) */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD25: Not enough VLs available (avail=%d, needed=%d); Stopping dfsssp routing!\n", vl_avail, vl_needed); err = 1; goto ERROR; } /* else { no balancing } */ if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Virtual Lanes per src/dest combination after balancing:\n"); vltable_print(p_mgr, srcdest2vl_table); } if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_INFO)) { OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "Approx. #paths per VL (after balancing):\n"); j = 0; count = 1; /* to prevent div. by 0 */ for (i = 0; i < vl_avail; i++) { if (split_count[i] > 0) { j = i; count = split_count[i]; } OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, " %" PRIu32 ". lane: %" PRIu64 "\n", i, paths_per_vl[j] / count); } } free(paths_per_vl); /* deallocate channel dependency graphs */ for (i = 0; i < vl_avail; i++) cdg_dealloc(&cdg[i]); free(cdg); OSM_LOG_EXIT(p_mgr->p_log); return 0; ERROR: free(paths_per_vl); for (i = 0; i < vl_avail; i++) cdg_dealloc(&cdg[i]); free(cdg); vltable_dealloc(&srcdest2vl_table); dfsssp_ctx->srcdest2vl_table = NULL; return err; } /* meta function which calls subfunctions for dijkstra, update lft and weights, (and remove deadlocks) to calculate the routing for the subnet */ static int dfsssp_do_dijkstra_routing(void *context) { dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context; osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr; vertex_t *adj_list = (vertex_t *) dfsssp_ctx->adj_list; uint32_t adj_list_size = dfsssp_ctx->adj_list_size; vertex_t **sw_list = NULL; uint32_t sw_list_size = 0; uint64_t guid = 0; cl_qlist_t *qlist = NULL; cl_list_item_t *qlist_item = NULL; cl_qmap_t *sw_tbl = &p_mgr->p_subn->sw_guid_tbl; cl_qmap_t cn_tbl, io_tbl, *p_mixed_tbl = NULL; cl_map_item_t *item = NULL; osm_switch_t *sw = NULL; osm_port_t *port = NULL; uint32_t i = 0, err = 0; uint16_t lid = 0, min_lid_ho = 0, max_lid_ho = 0; uint8_t lmc = 0; boolean_t cn_nodes_provided = FALSE, io_nodes_provided = FALSE; OSM_LOG_ENTER(p_mgr->p_log); OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Calculating shortest path from all Hca/switches to all\n"); cl_qmap_init(&cn_tbl); cl_qmap_init(&io_tbl); p_mixed_tbl = &cn_tbl; cl_qlist_init(&p_mgr->port_order_list); /* reset the new_lft for each switch */ for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl); item = cl_qmap_next(item)) { sw = (osm_switch_t *) item; /* initialize LIDs in buffer to invalid port number */ memset(sw->new_lft, OSM_NO_PATH, sw->max_lid_ho + 1); /* initialize LFT and hop count for bsp0/esp0 of the switch */ min_lid_ho = cl_ntoh16(osm_node_get_base_lid(sw->p_node, 0)); lmc = osm_node_get_lmc(sw->p_node, 0); for (i = min_lid_ho; i < min_lid_ho + (1 << lmc); i++) { /* for each switch the port to the 'self'lid is the management port 0 */ sw->new_lft[i] = 0; /* the hop count to the 'self'lid is 0 for each switch */ osm_switch_set_hops(sw, i, 0, 0); } } /* we need an intermediate array of pointers to switches in adj_list; this array will be sorted in respect to num_hca (descending) */ sw_list_size = adj_list_size - 1; sw_list = (vertex_t **)malloc(sw_list_size * sizeof(vertex_t *)); if (!sw_list) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD29: cannot allocate memory for sw_list in dfsssp_do_dijkstra_routing\n"); goto ERROR; } memset(sw_list, 0, sw_list_size * sizeof(vertex_t *)); /* fill the array with references to the 'real' sw in adj_list */ for (i = 0; i < sw_list_size; i++) sw_list[i] = &(adj_list[i + 1]); /* sort the sw_list in descending order */ sw_list_sort_by_num_hca(sw_list, sw_list_size); /* parse compute node guid file, if provided by the user */ if (p_mgr->p_subn->opt.cn_guid_file) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Parsing compute nodes from file %s\n", p_mgr->p_subn->opt.cn_guid_file); if (parse_node_map(p_mgr->p_subn->opt.cn_guid_file, add_guid_to_map, &cn_tbl)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD33: Problem parsing compute node guid file\n"); goto ERROR; } if (cl_is_qmap_empty(&cn_tbl)) OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "WRN AD34: compute node guids file contains no valid guids\n"); else cn_nodes_provided = TRUE; } /* parse I/O guid file, if provided by the user */ if (p_mgr->p_subn->opt.io_guid_file) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Parsing I/O nodes from file %s\n", p_mgr->p_subn->opt.io_guid_file); if (parse_node_map(p_mgr->p_subn->opt.io_guid_file, add_guid_to_map, &io_tbl)) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD35: Problem parsing I/O guid file\n"); goto ERROR; } if (cl_is_qmap_empty(&io_tbl)) OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "WRN AD36: I/O node guids file contains no valid guids\n"); else io_nodes_provided = TRUE; } /* if we mix Hca/Tca/SP0 during the dijkstra routing, we might end up in rare cases with a bad balancing for Hca<->Hca connections, i.e. some inter-switch links get oversubscribed with paths; therefore: add Hca ports first to ensure good Hca<->Hca balancing */ if (cn_nodes_provided) { for (i = 0; i < adj_list_size - 1; i++) { if (sw_list[i] && sw_list[i]->sw) { sw = (osm_switch_t *)(sw_list[i]->sw); add_sw_endports_to_order_list(sw, p_mgr, &cn_tbl, TRUE); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD30: corrupted sw_list array in dfsssp_do_dijkstra_routing\n"); goto ERROR; } } } /* then: add Tca ports to ensure good Hca->Tca balancing and separate paths towards I/O nodes on the same switch (if possible) */ if (io_nodes_provided) { for (i = 0; i < adj_list_size - 1; i++) { if (sw_list[i] && sw_list[i]->sw) { sw = (osm_switch_t *)(sw_list[i]->sw); add_sw_endports_to_order_list(sw, p_mgr, &io_tbl, TRUE); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD32: corrupted sw_list array in dfsssp_do_dijkstra_routing\n"); goto ERROR; } } } /* then: add anything else, such as administration nodes, ... */ if (cn_nodes_provided && io_nodes_provided) { cl_qmap_merge(&cn_tbl, &io_tbl); } else if (io_nodes_provided) { p_mixed_tbl = &io_tbl; } for (i = 0; i < adj_list_size - 1; i++) { if (sw_list[i] && sw_list[i]->sw) { sw = (osm_switch_t *)(sw_list[i]->sw); add_sw_endports_to_order_list(sw, p_mgr, p_mixed_tbl, FALSE); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD39: corrupted sw_list array in dfsssp_do_dijkstra_routing\n"); goto ERROR; } } /* last: add SP0 afterwards which have lower priority for balancing */ for (i = 0; i < sw_list_size; i++) { if (sw_list[i] && sw_list[i]->sw) { sw = (osm_switch_t *)(sw_list[i]->sw); guid = cl_ntoh64(osm_node_get_node_guid(sw->p_node)); add_guid_to_order_list(guid, p_mgr); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD31: corrupted sw_list array in dfsssp_do_dijkstra_routing\n"); goto ERROR; } } /* the intermediate array lived long enough */ free(sw_list); sw_list = NULL; /* same is true for the compute node and I/O guid map */ destroy_guid_map(&cn_tbl); cn_nodes_provided = FALSE; destroy_guid_map(&io_tbl); io_nodes_provided = FALSE; /* do the routing for the each Hca in the subnet and each switch in the subnet (to add the routes to base/enhanced SP0) */ qlist = &p_mgr->port_order_list; for (qlist_item = cl_qlist_head(qlist); qlist_item != cl_qlist_end(qlist); qlist_item = cl_qlist_next(qlist_item)) { port = (osm_port_t *)cl_item_obj(qlist_item, port, list_item); /* calculate shortest path with dijkstra from node to all switches/Hca */ if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_CA) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing Hca with GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid (port->p_node))); } else if (osm_node_get_type(port->p_node) == IB_NODE_TYPE_SWITCH) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Processing switch with GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid (port->p_node))); } else { /* we don't handle routers, in case they show up */ continue; } /* distribute the LID range across the ports that can reach those LIDs to have disjoint paths for one destination port with lmc>0; for switches with bsp0: min=max; with esp0: max>min if lmc>0 */ osm_port_get_lid_range_ho(port, &min_lid_ho, &max_lid_ho); for (lid = min_lid_ho; lid <= max_lid_ho; lid++) { /* do dijkstra from this Hca/LID/SP0 to each switch */ err = dijkstra(p_mgr, adj_list, adj_list_size, port, lid); if (err) goto ERROR; if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) print_routes(p_mgr, adj_list, adj_list_size, port); /* make an update for the linear forwarding tables of the switches */ err = update_lft(p_mgr, adj_list, adj_list_size, port, lid); if (err) goto ERROR; /* add weights for calculated routes to adjust the weights for the next cycle */ update_weights(p_mgr, adj_list, adj_list_size); if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) dfsssp_print_graph(p_mgr, adj_list, adj_list_size); } } /* try deadlock removal only for the dfsssp routing (not for the sssp case, which is a subset of the dfsssp algorithm) */ if (dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_DFSSSP) { /* remove potential deadlocks by assigning different virtual lanes to src/dest paths and balance the lanes */ err = dfsssp_remove_deadlocks(dfsssp_ctx); if (err) goto ERROR; } else if (dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_SSSP) { OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "SSSP routing specified -> skipping deadlock removal thru dfsssp_remove_deadlocks(...)\n"); } else { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD28: wrong routing engine specified in dfsssp_ctx\n"); goto ERROR; } /* list not needed after the dijkstra steps and deadlock removal */ cl_qlist_remove_all(&p_mgr->port_order_list); /* print the new_lft for each switch after routing is done */ if (OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) { for (item = cl_qmap_head(sw_tbl); item != cl_qmap_end(sw_tbl); item = cl_qmap_next(item)) { sw = (osm_switch_t *) item; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Summary of the (new) LFT for switch 0x%" PRIx64 " (%s):\n", cl_ntoh64(osm_node_get_node_guid(sw->p_node)), sw->p_node->print_desc); for (i = 0; i < sw->max_lid_ho + 1; i++) if (sw->new_lft[i] != OSM_NO_PATH) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, " for LID=%" PRIu32 " use port=%" PRIu8 "\n", i, sw->new_lft[i]); } } } OSM_LOG_EXIT(p_mgr->p_log); return 0; ERROR: if (!cl_is_qlist_empty(&p_mgr->port_order_list)) cl_qlist_remove_all(&p_mgr->port_order_list); if (cn_nodes_provided) destroy_guid_map(&cn_tbl); if (io_nodes_provided) destroy_guid_map(&io_tbl); if (sw_list) free(sw_list); return -1; } /* meta function which calls subfunctions for finding the optimal switch for the spanning tree, performing a dijkstra step with this sw as root, and calculating the mcast table for MLID */ static ib_api_status_t dfsssp_do_mcast_routing(void * context, osm_mgrp_box_t * mbox) { dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context; osm_ucast_mgr_t *p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr; osm_sm_t *sm = (osm_sm_t *) p_mgr->sm; vertex_t *adj_list = (vertex_t *) dfsssp_ctx->adj_list; uint32_t adj_list_size = dfsssp_ctx->adj_list_size; cl_qlist_t mcastgrp_port_list; cl_qmap_t mcastgrp_port_map; osm_switch_t *root_sw = NULL, *p_sw = NULL; osm_port_t *port = NULL; ib_net16_t lid = 0; uint32_t err = 0, num_ports = 0, i = 0; ib_net64_t guid = 0; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(sm->p_log); /* using the ucast cache feature with dfsssp might mean that a leaf sw got removed (and got back) without calling dfsssp_build_graph and therefore the adj_list (and pointers to osm's internal switches) could be outdated (here we have no knowledge if it has happened, so unfortunately a check is necessary... still better than rebuilding adj_list every time we arrive here) */ if (p_mgr->p_subn->opt.use_ucast_cache && p_mgr->cache_valid) { for (i = 1; i < adj_list_size; i++) { guid = cl_hton64(adj_list[i].guid); p_sw = osm_get_switch_by_guid(p_mgr->p_subn, guid); if (p_sw) { /* check if switch came back from the dead */ if (adj_list[i].dropped) adj_list[i].dropped = FALSE; /* verify that sw object has not been moved (this can happen for a leaf switch, if it was dropped and came back later without a rerouting), otherwise we have to update dfsssp's internal switch list with the new sw pointer */ if (p_sw == adj_list[i].sw) continue; else adj_list[i].sw = p_sw; } else { /* if a switch from adj_list is not in the sw_guid_tbl anymore, then the only reason is that it was a leaf switch and opensm dropped it without calling a rerouting -> calling dijkstra is no problem, since it is a leaf and different from root_sw -> only update_mcft and reset_mgrp_membership need to be aware of these dropped switches */ if (!adj_list[i].dropped) adj_list[i].dropped = TRUE; } } } /* create a map and a list of all ports which are member in the mcast group; map for searching elements and list for iteration */ if (osm_mcast_make_port_list_and_map(&mcastgrp_port_list, &mcastgrp_port_map, mbox)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD50: " "Insufficient memory to make port list\n"); status = IB_ERROR; goto Exit; } num_ports = cl_qlist_count(&mcastgrp_port_list); if (num_ports < 2) { OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "MLID 0x%X has %u members - nothing to do\n", mbox->mlid, num_ports); goto Exit; } /* find the root switch for the spanning tree, which has the smallest hops count to all LIDs in the mcast group */ root_sw = osm_mcast_mgr_find_root_switch(sm, &mcastgrp_port_list); if (!root_sw) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD51: " "Unable to locate a suitable switch for group 0x%X\n", mbox->mlid); status = IB_ERROR; goto Exit; } /* a) start one dijkstra step from the root switch to generate a spanning tree b) this might be a bit of an overkill to span the whole network, if there are only a few ports in the mcast group, but its only one dijkstra step for each mcast group and we did many steps before in the ucast routing for each LID in the subnet; c) we can use the subnet structure from the ucast routing, and don't even have to reset the link weights (=> therefore the mcast spanning tree will use less 'growded' links in the network) d) the mcast dfsssp algorithm will not change the link weights */ lid = osm_node_get_base_lid(root_sw->p_node, 0); port = osm_get_port_by_lid(sm->p_subn, lid); err = dijkstra(p_mgr, adj_list, adj_list_size, port, lid); if (err) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD52: " "Dijkstra step for mcast failed for group 0x%X\n", mbox->mlid); status = IB_ERROR; goto Exit; } /* set mcast group membership again for update_mcft (unfortunately: osm_mcast_mgr_find_root_switch resets it) */ update_mgrp_membership(&mcastgrp_port_list); /* update the mcast forwarding tables of the switches */ err = update_mcft(sm, adj_list, adj_list_size, mbox->mlid, &mcastgrp_port_map, root_sw); if (err) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR AD53: " "Update of mcast forwarding tables failed for group 0x%X\n", mbox->mlid); status = IB_ERROR; goto Exit; } Exit: reset_mgrp_membership(adj_list, adj_list_size); osm_mcast_drop_port_list(&mcastgrp_port_list); OSM_LOG_EXIT(sm->p_log); return status; } /* called from extern in QP creation process to gain the the service level and the virtual lane respectively for a pair */ static uint8_t get_dfsssp_sl(void *context, uint8_t hint_for_default_sl, const ib_net16_t slid, const ib_net16_t dlid) { dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context; osm_port_t *src_port, *dest_port; vltable_t *srcdest2vl_table = NULL; uint8_t *vl_split_count = NULL; osm_ucast_mgr_t *p_mgr = NULL; int32_t res = 0; if (dfsssp_ctx && dfsssp_ctx->routing_type == OSM_ROUTING_ENGINE_TYPE_DFSSSP) { p_mgr = (osm_ucast_mgr_t *) dfsssp_ctx->p_mgr; srcdest2vl_table = (vltable_t *) (dfsssp_ctx->srcdest2vl_table); vl_split_count = (uint8_t *) (dfsssp_ctx->vl_split_count); } else return hint_for_default_sl; src_port = osm_get_port_by_lid(p_mgr->p_subn, slid); if (!src_port) return hint_for_default_sl; dest_port = osm_get_port_by_lid(p_mgr->p_subn, dlid); if (!dest_port) return hint_for_default_sl; if (!srcdest2vl_table) return hint_for_default_sl; res = vltable_get_vl(srcdest2vl_table, slid, dlid); /* we will randomly distribute the traffic over multiple VLs if necessary for good balancing; therefore vl_split_count provides the number of VLs to use for certain traffic */ if (res > -1) { if (vl_split_count[res] > 1) return (uint8_t) (res + rand()%(vl_split_count[res])); else return (uint8_t) res; } else return hint_for_default_sl; } static dfsssp_context_t *dfsssp_context_create(osm_opensm_t * p_osm, osm_routing_engine_type_t routing_type) { dfsssp_context_t *dfsssp_ctx = NULL; /* allocate memory */ dfsssp_ctx = (dfsssp_context_t *) malloc(sizeof(dfsssp_context_t)); if (dfsssp_ctx) { /* set initial values */ dfsssp_ctx->routing_type = routing_type; dfsssp_ctx->p_mgr = (osm_ucast_mgr_t *) & (p_osm->sm.ucast_mgr); dfsssp_ctx->adj_list = NULL; dfsssp_ctx->adj_list_size = 0; dfsssp_ctx->srcdest2vl_table = NULL; dfsssp_ctx->vl_split_count = NULL; } else { OSM_LOG(p_osm->sm.ucast_mgr.p_log, OSM_LOG_ERROR, "ERR AD04: cannot allocate memory for dfsssp_ctx in dfsssp_context_create\n"); return NULL; } return dfsssp_ctx; } static void dfsssp_context_destroy(void *context) { dfsssp_context_t *dfsssp_ctx = (dfsssp_context_t *) context; vertex_t *adj_list = (vertex_t *) (dfsssp_ctx->adj_list); uint32_t i = 0; link_t *link = NULL, *tmp = NULL; /* free adj_list */ for (i = 0; i < dfsssp_ctx->adj_list_size; i++) { link = adj_list[i].links; while (link) { tmp = link; link = link->next; free(tmp); } } free(adj_list); dfsssp_ctx->adj_list = NULL; dfsssp_ctx->adj_list_size = 0; /* free srcdest2vl table and the split count information table (can be done, because dfsssp_context_destroy is called after osm_get_dfsssp_sl) */ vltable_dealloc(&(dfsssp_ctx->srcdest2vl_table)); dfsssp_ctx->srcdest2vl_table = NULL; if (dfsssp_ctx->vl_split_count) { free(dfsssp_ctx->vl_split_count); dfsssp_ctx->vl_split_count = NULL; } } static void delete(void *context) { if (!context) return; dfsssp_context_destroy(context); free(context); } int osm_ucast_dfsssp_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm) { /* create context container and add ucast management object */ dfsssp_context_t *dfsssp_context = dfsssp_context_create(p_osm, OSM_ROUTING_ENGINE_TYPE_DFSSSP); if (!dfsssp_context) { return 1; /* alloc failed -> skip this routing */ } /* reset function pointers to dfsssp routines */ r->context = (void *)dfsssp_context; r->build_lid_matrices = dfsssp_build_graph; r->ucast_build_fwd_tables = dfsssp_do_dijkstra_routing; r->mcast_build_stree = dfsssp_do_mcast_routing; r->path_sl = get_dfsssp_sl; r->destroy = delete; /* we initialize with the current time to achieve a 'good' randomized assignment in get_dfsssp_sl(...) */ srand(time(NULL)); return 0; } int osm_ucast_sssp_setup(struct osm_routing_engine *r, osm_opensm_t * p_osm) { /* create context container and add ucast management object */ dfsssp_context_t *dfsssp_context = dfsssp_context_create(p_osm, OSM_ROUTING_ENGINE_TYPE_SSSP); if (!dfsssp_context) { return 1; /* alloc failed -> skip this routing */ } /* reset function pointers to sssp routines */ r->context = (void *)dfsssp_context; r->build_lid_matrices = dfsssp_build_graph; r->ucast_build_fwd_tables = dfsssp_do_dijkstra_routing; r->mcast_build_stree = dfsssp_do_mcast_routing; r->destroy = delete; return 0; } opensm-3.3.20/opensm/osm_vl15intf.c0000644000205000001450000002653112342616674014025 00000000000000/* * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2010 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 osm_vl15_t. * This object represents the VL15 Interface object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #define FILE_ID OSM_FILE_VL15INTF_C #include #include #include #include #include static void vl15_send_mad(osm_vl15_t * p_vl, osm_madw_t * p_madw) { ib_api_status_t status; boolean_t resp_expected = p_madw->resp_expected; ib_smp_t * p_smp; ib_net16_t attr_id; uint8_t method; p_smp = osm_madw_get_smp_ptr(p_madw); method = p_smp->method; attr_id = p_smp->attr_id; /* Non-response-expected mads are not throttled on the wire since we can have no confirmation that they arrived at their destination. */ if (resp_expected) /* Note that other threads may not see the response MAD arrive before send() even returns. In that case, the wire count would temporarily go negative. To avoid this confusion, preincrement the counts on the assumption that send() will succeed. */ cl_atomic_inc(&p_vl->p_stats->qp0_mads_outstanding_on_wire); else cl_atomic_inc(&p_vl->p_stats->qp0_unicasts_sent); cl_atomic_inc(&p_vl->p_stats->qp0_mads_sent); status = osm_vendor_send(osm_madw_get_bind_handle(p_madw), p_madw, p_madw->resp_expected); if (status == IB_SUCCESS) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs on wire, %u outstanding, " "%u unicasts sent, %u total sent\n", p_vl->p_stats->qp0_mads_outstanding_on_wire, p_vl->p_stats->qp0_mads_outstanding, p_vl->p_stats->qp0_unicasts_sent, p_vl->p_stats->qp0_mads_sent); return; } OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E03: " "MAD send failed (%s)\n", ib_get_err_str(status)); /* The MAD was never successfully sent, so fix up the pre-incremented count values. */ /* Decrement qp0_mads_sent that were incremented in the code above. qp0_mads_outstanding will be decremented by send error callback (called by osm_vendor_send() */ cl_atomic_dec(&p_vl->p_stats->qp0_mads_sent); if (!resp_expected) { cl_atomic_dec(&p_vl->p_stats->qp0_unicasts_sent); return; } /* need to cause heavy-sweep if resp_expected MAD sending failed */ OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E04: " "%s method failed for attribute 0x%X (%s)\n", method == IB_MAD_METHOD_SET ? "SET" : "GET", cl_ntoh16(attr_id), ib_get_sm_attr_str(attr_id)); p_vl->p_subn->subnet_initialization_error = TRUE; } static void vl15_poller(IN void *p_ptr) { ib_api_status_t status; osm_madw_t *p_madw; osm_vl15_t *p_vl = p_ptr; cl_qlist_t *p_fifo; int32_t max_smps = p_vl->max_wire_smps; int32_t max_smps2 = p_vl->max_wire_smps2; OSM_LOG_ENTER(p_vl->p_log); if (p_vl->thread_state == OSM_THREAD_STATE_NONE) p_vl->thread_state = OSM_THREAD_STATE_RUN; while (p_vl->thread_state == OSM_THREAD_STATE_RUN) { /* Start servicing the FIFOs by pulling off MAD wrappers and passing them to the transport interface. There are lots of corner cases here so tread carefully. The unicast FIFO has priority, since somebody is waiting for a timely response. */ cl_spinlock_acquire(&p_vl->lock); if (cl_qlist_count(&p_vl->ufifo) != 0) p_fifo = &p_vl->ufifo; else p_fifo = &p_vl->rfifo; p_madw = (osm_madw_t *) cl_qlist_remove_head(p_fifo); cl_spinlock_release(&p_vl->lock); if (p_madw != (osm_madw_t *) cl_qlist_end(p_fifo)) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Servicing p_madw = %p\n", p_madw); if (OSM_LOG_IS_ACTIVE_V2(p_vl->p_log, OSM_LOG_FRAMES)) osm_dump_dr_smp_v2(p_vl->p_log, osm_madw_get_smp_ptr(p_madw), FILE_ID, OSM_LOG_FRAMES); vl15_send_mad(p_vl, p_madw); } else /* The VL15 FIFO is empty, so we have nothing left to do. */ status = cl_event_wait_on(&p_vl->signal, EVENT_NO_TIMEOUT, TRUE); while (p_vl->p_stats->qp0_mads_outstanding_on_wire >= max_smps && p_vl->thread_state == OSM_THREAD_STATE_RUN) { status = cl_event_wait_on(&p_vl->signal, p_vl->max_smps_timeout, TRUE); if (status == CL_TIMEOUT) { if (max_smps < max_smps2) max_smps++; break; } else if (status != CL_SUCCESS) { OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E02: " "Event wait failed (%s)\n", CL_STATUS_MSG(status)); break; } max_smps = p_vl->max_wire_smps; } } /* since we abort immediately when the state != OSM_THREAD_STATE_RUN we might have some mads on the queues. After the thread exits the vl15 destroy routine should put these mads back... */ OSM_LOG_EXIT(p_vl->p_log); } void osm_vl15_construct(IN osm_vl15_t * p_vl) { memset(p_vl, 0, sizeof(*p_vl)); p_vl->state = OSM_VL15_STATE_INIT; p_vl->thread_state = OSM_THREAD_STATE_NONE; cl_event_construct(&p_vl->signal); cl_spinlock_construct(&p_vl->lock); cl_qlist_init(&p_vl->rfifo); cl_qlist_init(&p_vl->ufifo); cl_thread_construct(&p_vl->poller); } void osm_vl15_destroy(IN osm_vl15_t * p_vl, IN struct osm_mad_pool *p_pool) { osm_madw_t *p_madw; OSM_LOG_ENTER(p_vl->p_log); /* Signal our threads that we're leaving. */ p_vl->thread_state = OSM_THREAD_STATE_EXIT; /* Don't trigger unless event has been initialized. Destroy the thread before we tear down the other objects. */ if (p_vl->state != OSM_VL15_STATE_INIT) cl_event_signal(&p_vl->signal); cl_thread_destroy(&p_vl->poller); /* Return the outstanding messages to the pool */ cl_spinlock_acquire(&p_vl->lock); while (!cl_is_qlist_empty(&p_vl->rfifo)) { p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo); osm_mad_pool_put(p_pool, p_madw); } while (!cl_is_qlist_empty(&p_vl->ufifo)) { p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo); osm_mad_pool_put(p_pool, p_madw); } cl_spinlock_release(&p_vl->lock); cl_event_destroy(&p_vl->signal); p_vl->state = OSM_VL15_STATE_INIT; cl_spinlock_destroy(&p_vl->lock); OSM_LOG_EXIT(p_vl->p_log); } ib_api_status_t osm_vl15_init(IN osm_vl15_t * p_vl, IN osm_vendor_t * p_vend, IN osm_log_t * p_log, IN osm_stats_t * p_stats, IN osm_subn_t * p_subn, IN int32_t max_wire_smps, IN int32_t max_wire_smps2, IN uint32_t max_smps_timeout) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); p_vl->p_vend = p_vend; p_vl->p_log = p_log; p_vl->p_stats = p_stats; p_vl->p_subn = p_subn; p_vl->max_wire_smps = max_wire_smps; p_vl->max_wire_smps2 = max_wire_smps2; p_vl->max_smps_timeout = max_wire_smps < max_wire_smps2 ? max_smps_timeout : EVENT_NO_TIMEOUT; status = cl_event_init(&p_vl->signal, FALSE); if (status != IB_SUCCESS) goto Exit; p_vl->state = OSM_VL15_STATE_READY; status = cl_spinlock_init(&p_vl->lock); if (status != IB_SUCCESS) goto Exit; /* Initialize the thread after all other dependent objects have been initialized. */ status = cl_thread_init(&p_vl->poller, vl15_poller, p_vl, "opensm poller"); Exit: OSM_LOG_EXIT(p_log); return status; } void osm_vl15_poll(IN osm_vl15_t * p_vl) { OSM_LOG_ENTER(p_vl->p_log); CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY); /* If we have room for more VL15 MADs on the wire, then signal the poller thread. This is not an airtight check, since the poller thread could be just about to send another MAD as we signal the event here. To cover this rare case, the poller thread checks for a spurious wake-up. */ if (p_vl->p_stats->qp0_mads_outstanding_on_wire < (int32_t) p_vl->max_wire_smps) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Signalling poller thread\n"); cl_event_signal(&p_vl->signal); } OSM_LOG_EXIT(p_vl->p_log); } void osm_vl15_post(IN osm_vl15_t * p_vl, IN osm_madw_t * p_madw) { OSM_LOG_ENTER(p_vl->p_log); CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY); OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Posting p_madw = %p\n", p_madw); /* Determine in which fifo to place the pending madw. */ cl_spinlock_acquire(&p_vl->lock); if (p_madw->resp_expected == TRUE) { cl_qlist_insert_tail(&p_vl->rfifo, &p_madw->list_item); osm_stats_inc_qp0_outstanding(p_vl->p_stats); } else cl_qlist_insert_tail(&p_vl->ufifo, &p_madw->list_item); cl_spinlock_release(&p_vl->lock); OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs on wire, %u QP0 MADs outstanding\n", p_vl->p_stats->qp0_mads_outstanding_on_wire, p_vl->p_stats->qp0_mads_outstanding); osm_vl15_poll(p_vl); OSM_LOG_EXIT(p_vl->p_log); } void osm_vl15_shutdown(IN osm_vl15_t * p_vl, IN osm_mad_pool_t * p_mad_pool) { osm_madw_t *p_madw; OSM_LOG_ENTER(p_vl->p_log); /* we only should get here after the VL15 interface was initialized */ CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY); /* grab a lock on the object */ cl_spinlock_acquire(&p_vl->lock); /* go over all outstanding MADs and retire their transactions */ /* first we handle the list of response MADs */ p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo); while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->ufifo)) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Releasing Response p_madw = %p\n", p_madw); osm_mad_pool_put(p_mad_pool, p_madw); p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo); } /* Request MADs we send out */ p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo); while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->rfifo)) { OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Releasing Request p_madw = %p\n", p_madw); osm_mad_pool_put(p_mad_pool, p_madw); osm_stats_dec_qp0_outstanding(p_vl->p_stats); p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo); } /* free the lock */ cl_spinlock_release(&p_vl->lock); OSM_LOG_EXIT(p_vl->p_log); } opensm-3.3.20/opensm/osm_vl_arb_rcv.c0000644000205000001450000001152612273221507014460 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2010 HNR Consulting. All rights reserved. * Copyright (c) 2010 Sun Microsystems, Inc. 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 osm_vla_rcv_t. * This object represents the Vl Arbitration Receiver object. * This object is part of the opensm family of objects. */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_VL_ARB_RCV_C #include #include #include #include #include #include /* * WE ONLY RECEIVE GET or SET responses */ void osm_vla_rcv_process(IN void *context, IN void *data) { osm_sm_t *sm = context; osm_madw_t *p_madw = data; ib_vl_arb_table_t *p_vla_tbl; ib_smp_t *p_smp; osm_port_t *p_port; osm_physp_t *p_physp; osm_node_t *p_node; osm_vla_context_t *p_context; ib_net64_t port_guid; ib_net64_t node_guid; uint8_t port_num, block_num; CL_ASSERT(sm); OSM_LOG_ENTER(sm->p_log); CL_ASSERT(p_madw); p_smp = osm_madw_get_smp_ptr(p_madw); p_context = osm_madw_get_vla_context_ptr(p_madw); p_vla_tbl = ib_smp_get_payload_ptr(p_smp); port_guid = p_context->port_guid; node_guid = p_context->node_guid; CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_VL_ARBITRATION); if (ib_smp_get_status(p_smp)) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "MAD status 0x%x received\n", cl_ntoh16(ib_smp_get_status(p_smp))); goto Exit2; } cl_plock_excl_acquire(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3F06: " "No port object for port with GUID 0x%" PRIx64 "\n\t\t\t\tfor parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); goto Exit; } p_node = p_port->p_node; CL_ASSERT(p_node); block_num = (uint8_t) (cl_ntoh32(p_smp->attr_mod) >> 16); /* in case of a non switch node the attr modifier should be ignored */ if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { port_num = (uint8_t) (cl_ntoh32(p_smp->attr_mod) & 0x000000FF); p_physp = osm_node_get_physp_ptr(p_node, port_num); } else { p_physp = p_port->p_physp; port_num = p_physp->port_num; } /* We do not care if this is a result of a set or get - all we want is to update the subnet. */ OSM_LOG(sm->p_log, OSM_LOG_VERBOSE, "Got GetResp(VLArb) block:%u port_num %u with GUID 0x%" PRIx64 " for parent node GUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n", block_num, port_num, cl_ntoh64(port_guid), cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id)); /* Determine if we encountered a new Physical Port. If so, Ignore it. */ if (!p_physp) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "Got invalid port number %u\n", port_num); goto Exit; } if ((block_num < 1) || (block_num > 4)) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "Got invalid block number 0x%X\n", block_num); goto Exit; } osm_dump_vl_arb_table_v2(sm->p_log, port_guid, block_num, port_num, p_vla_tbl, FILE_ID, OSM_LOG_DEBUG); osm_physp_set_vla_tbl(p_physp, p_vla_tbl, block_num); Exit: cl_plock_release(sm->p_lock); Exit2: OSM_LOG_EXIT(sm->p_log); } opensm-3.3.20/opensm/st.c0000644000205000001450000002733212104655725012121 00000000000000/* * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 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. * */ /* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_ST_C #include typedef struct st_table_entry st_table_entry; struct st_table_entry { unsigned int hash; st_data_t key; st_data_t record; st_table_entry *next; }; #define ST_DEFAULT_MAX_DENSITY 5 #define ST_DEFAULT_INIT_TABLE_SIZE 11 /* * DEFAULT_MAX_DENSITY is the default for the largest we allow the * average number of items per bin before increasing the number of * bins * * DEFAULT_INIT_TABLE_SIZE is the default for the number of bins * allocated initially * */ static int numcmp(void *, void *); static st_ptr_t numhash(void *); static struct st_hash_type type_numhash = { numcmp, numhash, }; /* extern int strcmp(const char *, const char *); */ static int strhash(const char *); static inline st_ptr_t st_strhash(void *key) { return strhash((const char *)key); } static inline int st_strcmp(void *key1, void *key2) { return strcmp((const char *)key1, (const char *)key2); } static struct st_hash_type type_strhash = { st_strcmp, st_strhash }; #define xmalloc malloc #define xcalloc calloc #define xrealloc realloc #define xfree free static void rehash(st_table *); #define alloc(type) (type*)xmalloc(sizeof(type)) #define Calloc(n,s) (char*)xcalloc((n), (s)) #define EQUAL(table,x,y) ((x)==(y) || (*table->type->compare)(((void*)x),((void *)y)) == 0) #define do_hash(key,table) (unsigned int)(*(table)->type->hash)(((void*)key)) #define do_hash_bin(key,table) (do_hash(key, table)%(table)->num_bins) /* * MINSIZE is the minimum size of a dictionary. */ #define MINSIZE 8 /* Table of prime numbers 2^n+a, 2<=n<=30. */ static long primes[] = { 8 + 3, 16 + 3, 32 + 5, 64 + 3, 128 + 3, 256 + 27, 512 + 9, 1024 + 9, 2048 + 5, 4096 + 3, 8192 + 27, 16384 + 43, 32768 + 3, 65536 + 45, 131072 + 29, 262144 + 3, 524288 + 21, 1048576 + 7, 2097152 + 17, 4194304 + 15, 8388608 + 9, 16777216 + 43, 33554432 + 35, 67108864 + 15, 134217728 + 29, 268435456 + 3, 536870912 + 11, 1073741824 + 85, 0 }; static int new_size(int size) { int i; #if 0 for (i = 3; i < 31; i++) { if ((1 << i) > size) return 1 << i; } return -1; #else int newsize; for (i = 0, newsize = MINSIZE; i < sizeof(primes) / sizeof(primes[0]); i++, newsize <<= 1) { if (newsize > size) return primes[i]; } /* Ran out of polynomials */ return 0; /* should raise exception */ #endif } #ifdef HASH_LOG static int collision = 0; static int init_st = 0; static void stat_col() { FILE *f = fopen("/var/log/osm_st_col", "w"); fprintf(f, "collision: %d\n", collision); fclose(f); } #endif st_table *st_init_table_with_size(type, size) struct st_hash_type *type; size_t size; { st_table *tbl; #ifdef HASH_LOG if (init_st == 0) { init_st = 1; atexit(stat_col); } #endif size = new_size(size); /* round up to prime number */ if (!size) return NULL; tbl = alloc(st_table); tbl->type = type; tbl->num_entries = 0; tbl->num_bins = size; tbl->bins = (st_table_entry **) Calloc(size, sizeof(st_table_entry *)); return tbl; } st_table *st_init_table(type) struct st_hash_type *type; { return st_init_table_with_size(type, 0); } st_table *st_init_numtable(void) { return st_init_table(&type_numhash); } st_table *st_init_numtable_with_size(size) size_t size; { return st_init_table_with_size(&type_numhash, size); } st_table *st_init_strtable(void) { return st_init_table(&type_strhash); } st_table *st_init_strtable_with_size(size) size_t size; { return st_init_table_with_size(&type_strhash, size); } void st_free_table(table) st_table *table; { register st_table_entry *ptr, *next; int i; for (i = 0; i < table->num_bins; i++) { ptr = table->bins[i]; while (ptr != 0) { next = ptr->next; free(ptr); ptr = next; } } free(table->bins); free(table); } #define PTR_NOT_EQUAL(table, ptr, hash_val, key) \ ((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key))) #ifdef HASH_LOG #define COLLISION collision++ #else #define COLLISION #endif #define FIND_ENTRY(table, ptr, hash_val, bin_pos) do {\ bin_pos = hash_val%(table)->num_bins;\ ptr = (table)->bins[bin_pos];\ if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) \ {\ COLLISION;\ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\ ptr = ptr->next;\ }\ ptr = ptr->next;\ }\ } while (0) int st_lookup(table, key, value) st_table *table; register st_data_t key; st_data_t *value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); if (ptr == 0) { return 0; } else { if (value != 0) *value = ptr->record; return 1; } } #define ADD_DIRECT(table, key, value, hash_val, bin_pos)\ do {\ st_table_entry *entry;\ if (table->num_entries/(table->num_bins) > ST_DEFAULT_MAX_DENSITY) \ {\ rehash(table);\ bin_pos = hash_val % table->num_bins;\ }\ \ entry = alloc(st_table_entry);\ \ entry->hash = hash_val;\ entry->key = key;\ entry->record = value;\ entry->next = table->bins[bin_pos];\ table->bins[bin_pos] = entry;\ table->num_entries++;\ } while (0); int st_insert(table, key, value) register st_table *table; register st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; register st_table_entry *ptr; hash_val = do_hash(key, table); FIND_ENTRY(table, ptr, hash_val, bin_pos); if (ptr == 0) { ADD_DIRECT(table, key, value, hash_val, bin_pos); return 0; } else { ptr->record = value; return 1; } } void st_add_direct(table, key, value) st_table *table; st_data_t key; st_data_t value; { unsigned int hash_val, bin_pos; hash_val = do_hash(key, table); bin_pos = hash_val % table->num_bins; ADD_DIRECT(table, key, value, hash_val, bin_pos); } static void rehash(table) register st_table *table; { register st_table_entry *ptr, *next, **new_bins; int i, old_num_bins = table->num_bins, new_num_bins; unsigned int hash_val; new_num_bins = new_size(old_num_bins + 1); if (!new_num_bins) return; new_bins = (st_table_entry **) Calloc(new_num_bins, sizeof(st_table_entry *)); for (i = 0; i < old_num_bins; i++) { ptr = table->bins[i]; while (ptr != 0) { next = ptr->next; hash_val = ptr->hash % new_num_bins; ptr->next = new_bins[hash_val]; new_bins[hash_val] = ptr; ptr = next; } } free(table->bins); table->num_bins = new_num_bins; table->bins = new_bins; } st_table *st_copy(old_table) st_table *old_table; { st_table *new_table; st_table_entry *ptr, *entry; size_t i, num_bins = old_table->num_bins; new_table = alloc(st_table); if (new_table == 0) { return 0; } *new_table = *old_table; new_table->bins = (st_table_entry **) Calloc(num_bins, sizeof(st_table_entry *)); if (new_table->bins == 0) { free(new_table); return 0; } for (i = 0; i < num_bins; i++) { new_table->bins[i] = 0; ptr = old_table->bins[i]; while (ptr != 0) { entry = alloc(st_table_entry); if (entry == 0) { free(new_table->bins); free(new_table); return 0; } *entry = *ptr; entry->next = new_table->bins[i]; new_table->bins[i] = entry; ptr = ptr->next; } } return new_table; } int st_delete(table, key, value) register st_table *table; register st_data_t *key; st_data_t *value; { unsigned int hash_val; st_table_entry *tmp; register st_table_entry *ptr; hash_val = do_hash_bin(*key, table); ptr = table->bins[hash_val]; if (ptr == 0) { if (value != 0) *value = 0; return 0; } if (EQUAL(table, *key, ptr->key)) { table->bins[hash_val] = ptr->next; table->num_entries--; if (value != 0) *value = ptr->record; *key = ptr->key; free(ptr); return 1; } for (; ptr->next != 0; ptr = ptr->next) { if (EQUAL(table, ptr->next->key, *key)) { tmp = ptr->next; ptr->next = ptr->next->next; table->num_entries--; if (value != 0) *value = tmp->record; *key = tmp->key; free(tmp); return 1; } } return 0; } int st_delete_safe(table, key, value, never) register st_table *table; register st_data_t *key; st_data_t *value; st_data_t never; { unsigned int hash_val; register st_table_entry *ptr; hash_val = do_hash_bin(*key, table); ptr = table->bins[hash_val]; if (ptr == 0) { if (value != 0) *value = 0; return 0; } for (; ptr != 0; ptr = ptr->next) { if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) { table->num_entries--; *key = ptr->key; if (value != 0) *value = ptr->record; ptr->key = ptr->record = never; return 1; } } return 0; } static int delete_never(st_data_t key, st_data_t value, st_data_t never) { if (value == never) return ST_DELETE; return ST_CONTINUE; } void st_cleanup_safe(table, never) st_table *table; st_data_t never; { int num_entries = table->num_entries; st_foreach(table, delete_never, never); table->num_entries = num_entries; } void st_foreach(table, func, arg) st_table *table; int (*func) (st_data_t key, st_data_t val, st_data_t arg); st_data_t arg; { st_table_entry *ptr, *last, *tmp; enum st_retval retval; int i; for (i = 0; i < table->num_bins; i++) { last = 0; for (ptr = table->bins[i]; ptr != 0;) { retval = (*func) (ptr->key, ptr->record, arg); switch (retval) { case ST_CONTINUE: last = ptr; ptr = ptr->next; break; case ST_STOP: return; case ST_DELETE: tmp = ptr; if (last == 0) { table->bins[i] = ptr->next; } else { last->next = ptr->next; } ptr = ptr->next; free(tmp); table->num_entries--; } } } } static int strhash(string) register const char *string; { register int c; #ifdef HASH_ELFHASH register unsigned int h = 0, g; while ((c = *string++) != '\0') { h = (h << 4) + c; if (g = h & 0xF0000000) h ^= g >> 24; h &= ~g; } return h; #elif HASH_PERL register int val = 0; while ((c = *string++) != '\0') { val = val * 33 + c; } return val + (val >> 5); #else register int val = 0; while ((c = *string++) != '\0') { val = val * 997 + c; } return val + (val >> 5); #endif } static int numcmp(x, y) void *x, *y; { return (st_ptr_t) x != (st_ptr_t) y; } static st_ptr_t numhash(n) void *n; { return (st_ptr_t) n; } opensm-3.3.20/opensm/osm_perfmgr.c0000644000205000001450000017625412443047246014022 00000000000000/* * Copyright (c) 2007 The Regents of the University of California. * Copyright (c) 2007-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. All rights reserved. * Copyright (c) 2013 Lawrence Livermore National Security. All rights reserved. * Copyright (c) 2011-2014 Mellanox Technologies LTD. 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 osm_perfmgr_t. * This object implements an IBA performance manager. * * Author: * Ira Weiny, LLNL */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef ENABLE_OSM_PERF_MGR #include #include #include #include #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_PERFMGR_C #include #include #include #include #include #include #define PERFMGR_INITIAL_TID_VALUE 0xcafe #ifdef ENABLE_OSM_PERF_MGR_PROFILE struct { double fastest_us; double slowest_us; double avg_us; uint64_t num; } perfmgr_mad_stats = { fastest_us: DBL_MAX, slowest_us: DBL_MIN, avg_us: 0, num:0}; /* diff must be something which can fit in a susecond_t */ static inline void update_mad_stats(struct timeval *diff) { double new = (diff->tv_sec * 1000000) + diff->tv_usec; if (new < perfmgr_mad_stats.fastest_us) perfmgr_mad_stats.fastest_us = new; if (new > perfmgr_mad_stats.slowest_us) perfmgr_mad_stats.slowest_us = new; perfmgr_mad_stats.avg_us = ((perfmgr_mad_stats.avg_us * perfmgr_mad_stats.num) + new) / (perfmgr_mad_stats.num + 1); perfmgr_mad_stats.num++; } static inline void clear_mad_stats(void) { perfmgr_mad_stats.fastest_us = DBL_MAX; perfmgr_mad_stats.slowest_us = DBL_MIN; perfmgr_mad_stats.avg_us = 0; perfmgr_mad_stats.num = 0; } /* after and diff can be the same struct */ static inline void diff_time(struct timeval *before, struct timeval *after, struct timeval *diff) { struct timeval tmp = *after; if (tmp.tv_usec < before->tv_usec) { tmp.tv_sec--; tmp.tv_usec += 1000000; } diff->tv_sec = tmp.tv_sec - before->tv_sec; diff->tv_usec = tmp.tv_usec - before->tv_usec; } #endif /********************************************************************** * Internal helper functions **********************************************************************/ static void init_monitored_nodes(osm_perfmgr_t * pm) { cl_qmap_init(&pm->monitored_map); pm->remove_list = NULL; cl_event_construct(&pm->sig_query); cl_event_init(&pm->sig_query, FALSE); } static void mark_for_removal(osm_perfmgr_t * pm, monitored_node_t * node) { if (pm->remove_list) { node->next = pm->remove_list; pm->remove_list = node; } else { node->next = NULL; pm->remove_list = node; } } static void remove_marked_nodes(osm_perfmgr_t * pm) { while (pm->remove_list) { monitored_node_t *next = pm->remove_list->next; int port; cl_qmap_remove_item(&pm->monitored_map, (cl_map_item_t *) (pm->remove_list)); if (pm->rm_nodes) perfmgr_db_delete_entry(pm->db, pm->remove_list->guid); else perfmgr_db_mark_active(pm->db, pm->remove_list->guid, FALSE); if (pm->remove_list->name) free(pm->remove_list->name); for (port = pm->remove_list->esp0 ? 0 : 1; port < pm->remove_list->num_ports; port++) { if (pm->remove_list->port[port].remote_name) free(pm->remove_list->port[port].remote_name); } free(pm->remove_list); pm->remove_list = next; } } static inline void decrement_outstanding_queries(osm_perfmgr_t * pm) { cl_atomic_dec(&pm->outstanding_queries); if (!pm->outstanding_queries) { cl_spinlock_acquire(&pm->lock); if (pm->sweep_state == PERFMGR_SWEEP_POST_PROCESSING) { pm->sweep_state = PERFMGR_SWEEP_SLEEP; OSM_LOG(pm->log, OSM_LOG_INFO, "PM sweep state exiting Post Processing\n"); } cl_spinlock_release(&pm->lock); } cl_event_signal(&pm->sig_query); } /********************************************************************** * Receive the MAD from the vendor layer and post it for processing by * the dispatcher **********************************************************************/ static void perfmgr_mad_recv_callback(osm_madw_t * p_madw, void *bind_context, osm_madw_t * p_req_madw) { osm_perfmgr_t *pm = (osm_perfmgr_t *) bind_context; OSM_LOG_ENTER(pm->log); CL_ASSERT(p_madw); CL_ASSERT(p_req_madw != NULL); osm_madw_copy_context(p_madw, p_req_madw); osm_mad_pool_put(pm->mad_pool, p_req_madw); decrement_outstanding_queries(pm); /* post this message for later processing. */ if (cl_disp_post(pm->pc_disp_h, OSM_MSG_MAD_PORT_COUNTERS, p_madw, NULL, NULL) != CL_SUCCESS) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5401: " "PerfMgr Dispatcher post failed\n"); osm_mad_pool_put(pm->mad_pool, p_madw); } OSM_LOG_EXIT(pm->log); } /********************************************************************** * Process MAD send errors **********************************************************************/ static void perfmgr_mad_send_err_callback(void *bind_context, osm_madw_t * p_madw) { osm_perfmgr_t *pm = (osm_perfmgr_t *) bind_context; osm_madw_context_t *context = &p_madw->context; uint64_t node_guid = context->perfmgr_context.node_guid; uint8_t port = context->perfmgr_context.port; cl_map_item_t *p_node; monitored_node_t *p_mon_node; ib_net16_t orig_lid; OSM_LOG_ENTER(pm->log); /* * get the monitored node struct to have the printable name * for log messages */ if ((p_node = cl_qmap_get(&pm->monitored_map, node_guid)) == cl_qmap_end(&pm->monitored_map)) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5415: GUID 0x%016" PRIx64 " not found in monitored map\n", node_guid); goto Exit; } p_mon_node = (monitored_node_t *) p_node; OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5402: %s (0x%" PRIx64 ") port %u LID %u TID 0x%" PRIx64 "\n", p_mon_node->name, p_mon_node->guid, port, cl_ntoh16(p_madw->mad_addr.dest_lid), cl_ntoh64(p_madw->p_mad->trans_id)); if (pm->subn->opt.perfmgr_redir && p_madw->status == IB_TIMEOUT) { /* First, find the node in the monitored map */ cl_plock_acquire(&pm->osm->lock); /* Now, validate port number */ if (port >= p_mon_node->num_ports) { cl_plock_release(&pm->osm->lock); OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5416: " "Invalid port num %u for %s (GUID 0x%016" PRIx64 ") num ports %u\n", port, p_mon_node->name, p_mon_node->guid, p_mon_node->num_ports); goto Exit; } /* Clear redirection info for this port except orig_lid */ orig_lid = p_mon_node->port[port].orig_lid; memset(&p_mon_node->port[port], 0, sizeof(monitored_port_t)); p_mon_node->port[port].orig_lid = orig_lid; p_mon_node->port[port].valid = TRUE; cl_plock_release(&pm->osm->lock); } Exit: osm_mad_pool_put(pm->mad_pool, p_madw); decrement_outstanding_queries(pm); OSM_LOG_EXIT(pm->log); } /********************************************************************** * Bind the PerfMgr to the vendor layer for MAD sends/receives **********************************************************************/ ib_api_status_t osm_perfmgr_bind(osm_perfmgr_t * pm, ib_net64_t port_guid) { osm_bind_info_t bind_info; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(pm->log); if (pm->bind_handle != OSM_BIND_INVALID_HANDLE) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5403: Multiple binds not allowed\n"); status = IB_ERROR; goto Exit; } bind_info.port_guid = pm->port_guid = port_guid; bind_info.mad_class = IB_MCLASS_PERF; bind_info.class_version = 1; bind_info.is_responder = FALSE; bind_info.is_report_processor = FALSE; bind_info.is_trap_processor = FALSE; bind_info.recv_q_size = OSM_PM_DEFAULT_QP1_RCV_SIZE; bind_info.send_q_size = OSM_PM_DEFAULT_QP1_SEND_SIZE; bind_info.timeout = pm->subn->opt.transaction_timeout; bind_info.retries = pm->subn->opt.transaction_retries; OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); pm->bind_handle = osm_vendor_bind(pm->vendor, &bind_info, pm->mad_pool, perfmgr_mad_recv_callback, perfmgr_mad_send_err_callback, pm); if (pm->bind_handle == OSM_BIND_INVALID_HANDLE) { status = IB_ERROR; OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5404: Vendor specific bind failed (%s)\n", ib_get_err_str(status)); } Exit: OSM_LOG_EXIT(pm->log); return status; } /********************************************************************** * Unbind the PerfMgr from the vendor layer for MAD sends/receives **********************************************************************/ static void perfmgr_mad_unbind(osm_perfmgr_t * pm) { OSM_LOG_ENTER(pm->log); if (pm->bind_handle == OSM_BIND_INVALID_HANDLE) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5405: No previous bind\n"); goto Exit; } osm_vendor_unbind(pm->bind_handle); Exit: OSM_LOG_EXIT(pm->log); } /********************************************************************** * Given a monitored node and a port, return the qp **********************************************************************/ static ib_net32_t get_qp(monitored_node_t * mon_node, uint8_t port) { ib_net32_t qp = IB_QP1; if (mon_node && mon_node->num_ports && port < mon_node->num_ports && mon_node->port[port].redirection && mon_node->port[port].qp) qp = mon_node->port[port].qp; return qp; } static ib_net16_t get_base_lid(osm_node_t * p_node, uint8_t port) { switch (p_node->node_info.node_type) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: return osm_node_get_base_lid(p_node, port); case IB_NODE_TYPE_SWITCH: return osm_node_get_base_lid(p_node, 0); default: return 0; } } /********************************************************************** * Given a node, a port, and an optional monitored node, * return the lid appropriate to query that port **********************************************************************/ static ib_net16_t get_lid(osm_node_t * p_node, uint8_t port, monitored_node_t * mon_node) { if (mon_node && mon_node->num_ports && port < mon_node->num_ports && mon_node->port[port].lid) return mon_node->port[port].lid; return get_base_lid(p_node, port); } /********************************************************************** * Build a Performance Management class MAD **********************************************************************/ static osm_madw_t *perfmgr_build_mad(osm_perfmgr_t * perfmgr, ib_net16_t dest_lid, uint8_t sl, ib_net32_t dest_qp, uint16_t pkey_ix, uint8_t mad_method, ib_net16_t attr_id, osm_madw_context_t * p_context, ib_perfmgt_mad_t ** p_pm_mad) { ib_perfmgt_mad_t *pm_mad = NULL; osm_madw_t *p_madw = NULL; OSM_LOG_ENTER(perfmgr->log); p_madw = osm_mad_pool_get(perfmgr->mad_pool, perfmgr->bind_handle, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) return NULL; pm_mad = osm_madw_get_perfmgt_mad_ptr(p_madw); /* build the mad */ pm_mad->header.base_ver = 1; pm_mad->header.mgmt_class = IB_MCLASS_PERF; pm_mad->header.class_ver = 1; pm_mad->header.method = mad_method; pm_mad->header.status = 0; pm_mad->header.class_spec = 0; pm_mad->header.trans_id = cl_hton64((uint64_t) cl_atomic_inc(&perfmgr->trans_id) & (uint64_t) (0xFFFFFFFF)); if (perfmgr->trans_id == 0) pm_mad->header.trans_id = cl_hton64((uint64_t) cl_atomic_inc(&perfmgr->trans_id) & (uint64_t) (0xFFFFFFFF)); pm_mad->header.attr_id = attr_id; pm_mad->header.resv = 0; pm_mad->header.attr_mod = 0; p_madw->mad_addr.dest_lid = dest_lid; p_madw->mad_addr.addr_type.gsi.remote_qp = dest_qp; p_madw->mad_addr.addr_type.gsi.remote_qkey = cl_hton32(IB_QP1_WELL_KNOWN_Q_KEY); p_madw->mad_addr.addr_type.gsi.pkey_ix = pkey_ix; p_madw->mad_addr.addr_type.gsi.service_level = sl; p_madw->mad_addr.addr_type.gsi.global_route = FALSE; p_madw->resp_expected = TRUE; if (p_context) p_madw->context = *p_context; if (p_pm_mad) *p_pm_mad = pm_mad; OSM_LOG_EXIT(perfmgr->log); return (p_madw); } /********************************************************************** * Send a Performance Management class MAD **********************************************************************/ static ib_api_status_t perfmgr_send_mad(osm_perfmgr_t *perfmgr, osm_madw_t * const p_madw) { cl_status_t sts; ib_api_status_t status = osm_vendor_send(perfmgr->bind_handle, p_madw, TRUE); if (status == IB_SUCCESS) { /* pause thread if there are too many outstanding requests */ cl_atomic_inc(&(perfmgr->outstanding_queries)); while (perfmgr->outstanding_queries > (int32_t)perfmgr->max_outstanding_queries) { cl_spinlock_acquire(&perfmgr->lock); if (perfmgr->sweep_state == PERFMGR_SWEEP_SLEEP) { perfmgr->sweep_state = PERFMGR_SWEEP_POST_PROCESSING; OSM_LOG(perfmgr->log, OSM_LOG_INFO, "PM sweep state going into Post Processing\n"); } else if (perfmgr->sweep_state == PERFMGR_SWEEP_ACTIVE) perfmgr->sweep_state = PERFMGR_SWEEP_SUSPENDED; cl_spinlock_release(&perfmgr->lock); wait: sts = cl_event_wait_on(&perfmgr->sig_query, EVENT_NO_TIMEOUT, TRUE); if (sts != CL_SUCCESS) goto wait; cl_spinlock_acquire(&perfmgr->lock); if (perfmgr->sweep_state == PERFMGR_SWEEP_SUSPENDED) perfmgr->sweep_state = PERFMGR_SWEEP_ACTIVE; cl_spinlock_release(&perfmgr->lock); } } return (status); } /********************************************************************** * Form and send the PortCounters MAD for a single port **********************************************************************/ static ib_api_status_t perfmgr_send_pc_mad(osm_perfmgr_t * perfmgr, ib_net16_t dest_lid, ib_net32_t dest_qp, uint16_t pkey_ix, uint8_t port, uint8_t mad_method, uint16_t counter_select, uint8_t counter_select2, osm_madw_context_t * p_context, uint8_t sl) { ib_api_status_t status = IB_SUCCESS; ib_port_counters_t *port_counter = NULL; ib_perfmgt_mad_t *pm_mad = NULL; osm_madw_t *p_madw = NULL; OSM_LOG_ENTER(perfmgr->log); p_context->perfmgr_context.mad_attr_id = IB_MAD_ATTR_PORT_CNTRS; p_madw = perfmgr_build_mad(perfmgr, dest_lid, sl, dest_qp, pkey_ix, mad_method, IB_MAD_ATTR_PORT_CNTRS, p_context, &pm_mad); if (p_madw == NULL) return IB_INSUFFICIENT_MEMORY; port_counter = (ib_port_counters_t *) & pm_mad->data; memset(port_counter, 0, sizeof(*port_counter)); port_counter->port_select = port; port_counter->counter_select = cl_hton16(counter_select); port_counter->counter_select2 = counter_select2; status = perfmgr_send_mad(perfmgr, p_madw); OSM_LOG_EXIT(perfmgr->log); return status; } /********************************************************************** * sweep the node_guid_tbl and collect the node guids to be tracked **********************************************************************/ static void collect_guids(cl_map_item_t * p_map_item, void *context) { osm_node_t *node = (osm_node_t *) p_map_item; uint64_t node_guid = cl_ntoh64(node->node_info.node_guid); osm_perfmgr_t *pm = (osm_perfmgr_t *) context; monitored_node_t *mon_node = NULL; uint32_t num_ports; int port; OSM_LOG_ENTER(pm->log); if (cl_qmap_get(&pm->monitored_map, node_guid) == cl_qmap_end(&pm->monitored_map)) { if (pm->ignore_cas && (node->node_info.node_type == IB_NODE_TYPE_CA)) goto Exit; /* if not already in map add it */ num_ports = osm_node_get_num_physp(node); mon_node = malloc(sizeof(*mon_node) + sizeof(monitored_port_t) * num_ports); if (!mon_node) { OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 5406: " "malloc failed: not handling node %s" "(GUID 0x%" PRIx64 ")\n", node->print_desc, node_guid); goto Exit; } memset(mon_node, 0, sizeof(*mon_node) + sizeof(monitored_port_t) * num_ports); mon_node->guid = node_guid; mon_node->name = strdup(node->print_desc); mon_node->num_ports = num_ports; mon_node->node_type = node->node_info.node_type; /* check for enhanced switch port 0 */ mon_node->esp0 = (node->sw && ib_switch_info_is_enhanced_port0(&node->sw-> switch_info)); for (port = mon_node->esp0 ? 0 : 1; port < num_ports; port++) { monitored_port_t *mon_port = &mon_node->port[port]; osm_physp_t *p_physp = &node->physp_table[port]; osm_physp_t *p_remote_physp = p_physp->p_remote_physp; mon_port->orig_lid = 0; mon_port->valid = FALSE; if (osm_physp_is_valid(p_physp)) { mon_port->orig_lid = get_base_lid(node, port); mon_port->valid = TRUE; } mon_port->remote_valid = FALSE; mon_port->remote_name = NULL; if (p_remote_physp && osm_physp_is_valid(p_remote_physp)) { osm_node_t *p_remote_node = p_remote_physp->p_node; mon_port->remote_valid = TRUE; mon_port->remote_guid = p_remote_node->node_info.node_guid; mon_port->remote_name = strdup(p_remote_node->print_desc); mon_port->remote_port = p_remote_physp->port_num; } } cl_qmap_insert(&pm->monitored_map, node_guid, (cl_map_item_t *) mon_node); } Exit: OSM_LOG_EXIT(pm->log); } /********************************************************************** * Form and send the ClassPortInfo MAD for a single port **********************************************************************/ static ib_api_status_t perfmgr_send_cpi_mad(osm_perfmgr_t * pm, ib_net16_t dest_lid, ib_net32_t dest_qp, uint16_t pkey_ix, uint8_t port, osm_madw_context_t * p_context, uint8_t sl) { ib_api_status_t status = IB_SUCCESS; osm_madw_t *p_madw = NULL; OSM_LOG_ENTER(pm->log); p_context->perfmgr_context.mad_attr_id = IB_MAD_ATTR_CLASS_PORT_INFO; p_madw = perfmgr_build_mad(pm, dest_lid, sl, dest_qp, pkey_ix, IB_MAD_METHOD_GET, IB_MAD_ATTR_CLASS_PORT_INFO, p_context, NULL); if (p_madw == NULL) return IB_INSUFFICIENT_MEMORY; status = perfmgr_send_mad(pm, p_madw); OSM_LOG_EXIT(pm->log); return status; } /********************************************************************** * return if some form of PortCountersExtended (PCE || PCE NoIETF) are supported **********************************************************************/ static inline boolean_t pce_supported(monitored_node_t *mon_node, uint8_t port) { monitored_port_t *mon_port = &(mon_node->port[port]); return (mon_port->cpi_valid && (mon_port->cap_mask & IB_PM_EXT_WIDTH_SUPPORTED || mon_port->cap_mask & IB_PM_EXT_WIDTH_NOIETF_SUP)); } /********************************************************************** * return if CapMask.PortCountersXmitWaitSupported is set **********************************************************************/ static inline boolean_t xmit_wait_supported(monitored_node_t *mon_node, uint8_t port) { monitored_port_t *mon_port = &(mon_node->port[port]); return (mon_port->cpi_valid && (mon_port->cap_mask & IB_PM_PC_XMIT_WAIT_SUP)); } /********************************************************************** * return if "full" PortCountersExtended (IETF) is indicated **********************************************************************/ static inline boolean_t ietf_supported(monitored_node_t *mon_node, uint8_t port) { monitored_port_t *mon_port = &(mon_node->port[port]); return (mon_port->cpi_valid && (mon_port->cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)); } /********************************************************************** * Form and send the PortCountersExtended MAD for a single port **********************************************************************/ static ib_api_status_t perfmgr_send_pce_mad(osm_perfmgr_t * perfmgr, ib_net16_t dest_lid, ib_net32_t dest_qp, uint16_t pkey_ix, uint8_t port, uint8_t mad_method, osm_madw_context_t * p_context, uint8_t sl) { ib_api_status_t status = IB_SUCCESS; ib_port_counters_ext_t *port_counter_ext = NULL; ib_perfmgt_mad_t *pm_mad = NULL; osm_madw_t *p_madw = NULL; OSM_LOG_ENTER(perfmgr->log); p_context->perfmgr_context.mad_attr_id = IB_MAD_ATTR_PORT_CNTRS_EXT; p_madw = perfmgr_build_mad(perfmgr, dest_lid, sl, dest_qp, pkey_ix, mad_method, IB_MAD_ATTR_PORT_CNTRS_EXT, p_context, &pm_mad); if (p_madw == NULL) return IB_INSUFFICIENT_MEMORY; port_counter_ext = (ib_port_counters_ext_t *) & pm_mad->data; memset(port_counter_ext, 0, sizeof(*port_counter_ext)); port_counter_ext->port_select = port; port_counter_ext->counter_select = cl_hton16(0x00FF); status = perfmgr_send_mad(perfmgr, p_madw); OSM_LOG_EXIT(perfmgr->log); return status; } /********************************************************************** * query the Port Counters of all the nodes in the subnet **********************************************************************/ static void perfmgr_query_counters(cl_map_item_t * p_map_item, void *context) { ib_api_status_t status = IB_SUCCESS; osm_perfmgr_t *pm = context; osm_node_t *node = NULL; monitored_node_t *mon_node = (monitored_node_t *) p_map_item; osm_madw_context_t mad_context; uint64_t node_guid = 0; ib_net32_t remote_qp; uint8_t port, num_ports = 0; OSM_LOG_ENTER(pm->log); cl_plock_acquire(&pm->osm->lock); node = osm_get_node_by_guid(pm->subn, cl_hton64(mon_node->guid)); if (!node) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5407: Node \"%s\" (guid 0x%" PRIx64 ") no longer exists so removing from PerfMgr monitoring\n", mon_node->name, mon_node->guid); mark_for_removal(pm, mon_node); goto Exit; } num_ports = osm_node_get_num_physp(node); node_guid = cl_ntoh64(node->node_info.node_guid); /* make sure there is a database object ready to store this info */ if (perfmgr_db_create_entry(pm->db, node_guid, mon_node->esp0, num_ports, node->print_desc) != PERFMGR_EVENT_DB_SUCCESS) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5408: DB create entry failed for 0x%" PRIx64 " (%s) : %s\n", node_guid, node->print_desc, strerror(errno)); goto Exit; } perfmgr_db_mark_active(pm->db, node_guid, TRUE); /* issue the query for each port */ for (port = mon_node->esp0 ? 0 : 1; port < num_ports; port++) { ib_net16_t lid; if (!osm_node_get_physp_ptr(node, port)) continue; if (!mon_node->port[port].valid) continue; lid = get_lid(node, port, mon_node); if (lid == 0) { OSM_LOG(pm->log, OSM_LOG_DEBUG, "WARN: node 0x%" PRIx64 " port %d (%s): port out of range, skipping\n", cl_ntoh64(node->node_info.node_guid), port, node->print_desc); continue; } remote_qp = get_qp(mon_node, port); mad_context.perfmgr_context.node_guid = node_guid; mad_context.perfmgr_context.port = port; mad_context.perfmgr_context.mad_method = IB_MAD_METHOD_GET; if (pm->query_cpi && !mon_node->port[port].cpi_valid) { status = perfmgr_send_cpi_mad(pm, lid, remote_qp, mon_node->port[port].pkey_ix, port, &mad_context, 0); /* FIXME SL != 0 */ if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5410: " "Failed to issue ClassPortInfo query " "for node 0x%" PRIx64 " port %d (%s)\n", node->node_info.node_guid, port, node->print_desc); if (mon_node->node_type == IB_NODE_TYPE_SWITCH) goto Exit; /* only need to issue 1 CPI query for switches */ } else { #ifdef ENABLE_OSM_PERF_MGR_PROFILE gettimeofday(&mad_context.perfmgr_context.query_start, NULL); #endif OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Getting stats for node 0x%" PRIx64 " port %d (lid %u) (%s)\n", node_guid, port, cl_ntoh16(lid), node->print_desc); status = perfmgr_send_pc_mad(pm, lid, remote_qp, mon_node->port[port].pkey_ix, port, IB_MAD_METHOD_GET, 0xffff, 1, &mad_context, 0); /* FIXME SL != 0 */ if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5409: " "Failed to issue port counter query for node 0x%" PRIx64 " port %d (%s)\n", node->node_info.node_guid, port, node->print_desc); if (pce_supported(mon_node, port)) { #if ENABLE_OSM_PERF_MGR_PROFILE gettimeofday(&mad_context.perfmgr_context.query_start, NULL); #endif status = perfmgr_send_pce_mad(pm, lid, remote_qp, mon_node->port[port].pkey_ix, port, IB_MAD_METHOD_GET, &mad_context, 0); /* FIXME SL != 0 */ if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5417: Failed to issue " "port counter query for " "node 0x%" PRIx64 " port " "%d (%s)\n", node->node_info.node_guid, port, node->print_desc); } } } Exit: cl_plock_release(&pm->osm->lock); OSM_LOG_EXIT(pm->log); } /********************************************************************** * Discovery stuff * This code should not be here, but merged with main OpenSM **********************************************************************/ extern int wait_for_pending_transactions(osm_stats_t * stats); extern void osm_drop_mgr_process(IN osm_sm_t * sm); static int sweep_hop_1(osm_sm_t * sm) { ib_api_status_t status = IB_SUCCESS; osm_madw_context_t context; osm_node_t *p_node; osm_port_t *p_port; osm_dr_path_t hop_1_path; ib_net64_t port_guid; uint8_t port_num; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; uint8_t num_ports; osm_physp_t *p_ext_physp; port_guid = sm->p_subn->sm_port_guid; p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5481: No SM port object\n"); return -1; } p_node = p_port->p_node; port_num = ib_node_info_get_local_port_num(&p_node->node_info); OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Probing hop 1 on local port %u\n", port_num); memset(path_array, 0, sizeof(path_array)); /* the hop_1 operations depend on the type of our node. * Currently - legal nodes that can host SM are SW and CA */ switch (osm_node_get_type(p_node)) { case IB_NODE_TYPE_CA: case IB_NODE_TYPE_ROUTER: memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, 1, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5482: " "Request for NodeInfo failed\n"); break; case IB_NODE_TYPE_SWITCH: /* Need to go over all the ports of the switch, and send a node_info * from them. This doesn't include the port 0 of the switch, which * hosts the SM. * Note: We'll send another switchInfo on port 0, since if no ports * are connected, we still want to get some response, and have the * subnet come up. */ num_ports = osm_node_get_num_physp(p_node); for (port_num = 0; port_num < num_ports; port_num++) { /* go through the port only if the port is not DOWN */ p_ext_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_ext_physp || ib_port_info_get_port_state (&p_ext_physp->port_info) <= IB_LINK_DOWN) continue; memset(&context, 0, sizeof(context)); context.ni_context.node_guid = osm_node_get_node_guid(p_node); context.ni_context.port_num = port_num; path_array[1] = port_num; osm_dr_path_init(&hop_1_path, 1, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, &context); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5484: " "Request for NodeInfo failed\n"); } break; default: OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5483: Unknown node type %d\n", osm_node_get_type(p_node)); } return status; } static unsigned is_sm_port_down(osm_sm_t * sm) { ib_net64_t port_guid; osm_port_t *p_port; port_guid = sm->p_subn->sm_port_guid; if (port_guid == 0) return 1; CL_PLOCK_ACQUIRE(sm->p_lock); p_port = osm_get_port_by_guid(sm->p_subn, port_guid); if (!p_port) { CL_PLOCK_RELEASE(sm->p_lock); OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5485: " "SM port with GUID:%016" PRIx64 " is unknown\n", cl_ntoh64(port_guid)); return 1; } CL_PLOCK_RELEASE(sm->p_lock); if (p_port->p_node->sw && !ib_switch_info_is_enhanced_port0(&p_port->p_node->sw->switch_info)) return 0; /* base SP0 */ return osm_physp_get_port_state(p_port->p_physp) == IB_LINK_DOWN; } static int sweep_hop_0(osm_sm_t * sm) { ib_api_status_t status; osm_dr_path_t dr_path; osm_bind_handle_t h_bind; uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX]; memset(path_array, 0, sizeof(path_array)); h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl); if (h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "No bound ports\n"); return -1; } osm_dr_path_init(&dr_path, 0, path_array); CL_PLOCK_ACQUIRE(sm->p_lock); status = osm_req_get(sm, &dr_path, IB_MAD_ATTR_NODE_INFO, 0, TRUE, 0, CL_DISP_MSGID_NONE, NULL); CL_PLOCK_RELEASE(sm->p_lock); if (status != IB_SUCCESS) OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 5486: Request for NodeInfo failed\n"); return status; } static void reset_node_count(cl_map_item_t * p_map_item, void *cxt) { osm_node_t *p_node = (osm_node_t *) p_map_item; p_node->discovery_count = 0; memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size); } static void reset_port_count(cl_map_item_t * p_map_item, void *cxt) { osm_port_t *p_port = (osm_port_t *) p_map_item; p_port->discovery_count = 0; } static void reset_switch_count(cl_map_item_t * p_map_item, void *cxt) { osm_switch_t *p_sw = (osm_switch_t *) p_map_item; p_sw->need_update = 0; } static int perfmgr_discovery(osm_opensm_t * osm) { int ret; CL_PLOCK_ACQUIRE(&osm->lock); cl_qmap_apply_func(&osm->subn.node_guid_tbl, reset_node_count, NULL); cl_qmap_apply_func(&osm->subn.port_guid_tbl, reset_port_count, NULL); cl_qmap_apply_func(&osm->subn.sw_guid_tbl, reset_switch_count, NULL); CL_PLOCK_RELEASE(&osm->lock); osm->subn.in_sweep_hop_0 = TRUE; ret = sweep_hop_0(&osm->sm); if (ret) goto _exit; if (wait_for_pending_transactions(&osm->stats)) goto _exit; if (is_sm_port_down(&osm->sm)) { OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "SM port is down\n"); goto _drop; } osm->subn.in_sweep_hop_0 = FALSE; ret = sweep_hop_1(&osm->sm); if (ret) goto _exit; if (wait_for_pending_transactions(&osm->stats)) goto _exit; _drop: osm_drop_mgr_process(&osm->sm); _exit: return ret; } /********************************************************************** * Main PerfMgr processor - query the performance counters **********************************************************************/ void osm_perfmgr_process(osm_perfmgr_t * pm) { #ifdef ENABLE_OSM_PERF_MGR_PROFILE struct timeval before, after; #endif if (pm->state != PERFMGR_STATE_ENABLED) return; cl_spinlock_acquire(&pm->lock); if (pm->sweep_state == PERFMGR_SWEEP_ACTIVE || pm->sweep_state == PERFMGR_SWEEP_SUSPENDED || pm->sweep_state == PERFMGR_SWEEP_POST_PROCESSING) { cl_spinlock_release(&pm->lock); OSM_LOG(pm->log, OSM_LOG_INFO, "PM sweep state %d, skipping sweep\n", pm->sweep_state); return; } pm->sweep_state = PERFMGR_SWEEP_ACTIVE; cl_spinlock_release(&pm->lock); if (pm->subn->sm_state == IB_SMINFO_STATE_STANDBY || pm->subn->sm_state == IB_SMINFO_STATE_NOTACTIVE) perfmgr_discovery(pm->subn->p_osm); /* if redirection enabled, determine local port */ if (pm->subn->opt.perfmgr_redir && pm->local_port == -1) { osm_node_t *p_node; osm_port_t *p_port; CL_PLOCK_ACQUIRE(pm->sm->p_lock); p_port = osm_get_port_by_guid(pm->subn, pm->port_guid); if (p_port) { p_node = p_port->p_node; CL_ASSERT(p_node); pm->local_port = ib_node_info_get_local_port_num(&p_node->node_info); } else OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5487: No PerfMgr port object for " "port GUID 0x%" PRIx64 "\n", cl_ntoh64(pm->port_guid)); CL_PLOCK_RELEASE(pm->sm->p_lock); } #ifdef ENABLE_OSM_PERF_MGR_PROFILE gettimeofday(&before, NULL); #endif /* With the global lock held, collect the node guids */ /* FIXME we should be able to track SA notices * and not have to sweep the node_guid_tbl each pass */ OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Gathering PerfMgr stats\n"); cl_plock_acquire(&pm->osm->lock); cl_qmap_apply_func(&pm->subn->node_guid_tbl, collect_guids, pm); cl_plock_release(&pm->osm->lock); /* then for each node query their counters */ cl_qmap_apply_func(&pm->monitored_map, perfmgr_query_counters, pm); /* clean out any nodes found to be removed during the sweep */ remove_marked_nodes(pm); #ifdef ENABLE_OSM_PERF_MGR_PROFILE gettimeofday(&after, NULL); diff_time(&before, &after, &after); osm_log_v2(pm->log, OSM_LOG_INFO, FILE_ID, "PerfMgr total sweep time : %ld.%06ld s\n" " fastest mad : %g us\n" " slowest mad : %g us\n" " average mad : %g us\n", after.tv_sec, after.tv_usec, perfmgr_mad_stats.fastest_us, perfmgr_mad_stats.slowest_us, perfmgr_mad_stats.avg_us); clear_mad_stats(); #endif cl_spinlock_acquire(&pm->lock); pm->sweep_state = PERFMGR_SWEEP_SLEEP; cl_spinlock_release(&pm->lock); } /********************************************************************** * PerfMgr timer - loop continuously and signal SM to run PerfMgr * processor if enabled **********************************************************************/ static void perfmgr_sweep(void *arg) { osm_perfmgr_t *pm = arg; osm_sm_signal(pm->sm, OSM_SIGNAL_PERFMGR_SWEEP); cl_timer_start(&pm->sweep_timer, pm->sweep_time_s * 1000); } void osm_perfmgr_shutdown(osm_perfmgr_t * pm) { OSM_LOG_ENTER(pm->log); cl_timer_stop(&pm->sweep_timer); cl_disp_unregister(pm->pc_disp_h); perfmgr_mad_unbind(pm); OSM_LOG_EXIT(pm->log); } void osm_perfmgr_destroy(osm_perfmgr_t * pm) { OSM_LOG_ENTER(pm->log); perfmgr_db_destroy(pm->db); cl_timer_destroy(&pm->sweep_timer); OSM_LOG_EXIT(pm->log); } /********************************************************************** * Detect if someone else on the network could have cleared the counters * without us knowing. This is easy to detect because the counters never * wrap but are "sticky". * * The one time this will not work is if the port is getting errors fast * enough to have the reading overtake the previous reading. In this case, * counters will be missed. **********************************************************************/ static void perfmgr_check_oob_clear(osm_perfmgr_t * pm, monitored_node_t * mon_node, uint8_t port, perfmgr_db_err_reading_t * cr) { perfmgr_db_err_reading_t prev_err; if (perfmgr_db_get_prev_err(pm->db, mon_node->guid, port, &prev_err) != PERFMGR_EVENT_DB_SUCCESS) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Failed to find previous " "error reading for %s (guid 0x%" PRIx64 ") port %u\n", mon_node->name, mon_node->guid, port); return; } OSM_LOG(pm->log, OSM_LOG_DEBUG, "Errors vs previous node %s (0x%" PRIx64 ") port %u\n" "SE: %"PRIu64" ?< %"PRIu64"\n" "LE: %"PRIu64" ?< %"PRIu64"\n" "LD: %"PRIu64" ?< %"PRIu64"\n" "RE: %"PRIu64" ?< %"PRIu64"\n" "RPE: %"PRIu64" ?< %"PRIu64"\n" "SRE: %"PRIu64" ?< %"PRIu64"\n" "XD: %"PRIu64" ?< %"PRIu64"\n" "XCE: %"PRIu64" ?< %"PRIu64"\n" "RCE: %"PRIu64" ?< %"PRIu64"\n" "LI: %"PRIu64" ?< %"PRIu64"\n" "BO: %"PRIu64" ?< %"PRIu64"\n" "VL15: %"PRIu64" ?< %"PRIu64"\n" "XW: %"PRIu64" ?< %"PRIu64"\n" , mon_node->name, mon_node->guid, port, cr->symbol_err_cnt, prev_err.symbol_err_cnt, cr->link_err_recover, prev_err.link_err_recover, cr->link_downed, prev_err.link_downed, cr->rcv_err, prev_err.rcv_err, cr->rcv_rem_phys_err, prev_err.rcv_rem_phys_err, cr->rcv_switch_relay_err, prev_err.rcv_switch_relay_err, cr->xmit_discards, prev_err.xmit_discards, cr->xmit_constraint_err, prev_err.xmit_constraint_err, cr->rcv_constraint_err, prev_err.rcv_constraint_err, cr->link_integrity, prev_err.link_integrity, cr->buffer_overrun, prev_err.buffer_overrun, cr->vl15_dropped, prev_err.vl15_dropped, cr->xmit_wait, prev_err.xmit_wait); if (cr->symbol_err_cnt < prev_err.symbol_err_cnt || cr->link_err_recover < prev_err.link_err_recover || cr->link_downed < prev_err.link_downed || cr->rcv_err < prev_err.rcv_err || cr->rcv_rem_phys_err < prev_err.rcv_rem_phys_err || cr->rcv_switch_relay_err < prev_err.rcv_switch_relay_err || cr->xmit_discards < prev_err.xmit_discards || cr->xmit_constraint_err < prev_err.xmit_constraint_err || cr->rcv_constraint_err < prev_err.rcv_constraint_err || cr->link_integrity < prev_err.link_integrity || cr->buffer_overrun < prev_err.buffer_overrun || cr->vl15_dropped < prev_err.vl15_dropped || cr->xmit_wait < prev_err.xmit_wait) { OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 540A: " "Detected an out of band error clear " "on %s (0x%" PRIx64 ") port %u\n", mon_node->name, mon_node->guid, port); perfmgr_db_clear_prev_err(pm->db, mon_node->guid, port); } } /********************************************************************** * Return 1 if the value is "close" to overflowing * "close" is defined at 25% for now **********************************************************************/ static int counter_overflow_4(uint8_t val) { return (val >= 10); } static int counter_overflow_8(uint8_t val) { return (val >= (UINT8_MAX - (UINT8_MAX / 4))); } static int counter_overflow_16(ib_net16_t val) { return (cl_ntoh16(val) >= (UINT16_MAX - (UINT16_MAX / 4))); } static int counter_overflow_32(ib_net32_t val) { return (cl_ntoh32(val) >= (UINT32_MAX - (UINT32_MAX / 4))); } static int counter_overflow_64(ib_net64_t val) { return (cl_ntoh64(val) >= (UINT64_MAX - (UINT64_MAX / 4))); } /********************************************************************** * Check if the port counters have overflowed and if so issue a clear * MAD to the port **********************************************************************/ static void perfmgr_check_overflow(osm_perfmgr_t * pm, monitored_node_t * mon_node, int16_t pkey_ix, uint8_t port, ib_port_counters_t * pc, boolean_t xmit_wait_sup) { osm_madw_context_t mad_context; ib_api_status_t status; ib_net32_t remote_qp; uint16_t counter_select; uint8_t counter_select2; OSM_LOG_ENTER(pm->log); if (counter_overflow_16(pc->symbol_err_cnt) || counter_overflow_8(pc->link_err_recover) || counter_overflow_8(pc->link_downed) || counter_overflow_16(pc->rcv_err) || counter_overflow_16(pc->rcv_rem_phys_err) || counter_overflow_16(pc->rcv_switch_relay_err) || counter_overflow_16(pc->xmit_discards) || counter_overflow_8(pc->xmit_constraint_err) || counter_overflow_8(pc->rcv_constraint_err) || counter_overflow_4(PC_LINK_INT(pc->link_int_buffer_overrun)) || counter_overflow_4(PC_BUF_OVERRUN(pc->link_int_buffer_overrun)) || counter_overflow_16(pc->vl15_dropped) || (xmit_wait_sup && counter_overflow_32(pc->xmit_wait)) || (!pce_supported(mon_node, port) && (counter_overflow_32(pc->xmit_data) || counter_overflow_32(pc->rcv_data) || counter_overflow_32(pc->xmit_pkts) || counter_overflow_32(pc->rcv_pkts)))) { osm_node_t *p_node = NULL; ib_net16_t lid = 0; if (!mon_node->port[port].valid) goto Exit; osm_log_v2(pm->log, OSM_LOG_VERBOSE, FILE_ID, "PerfMgr: Counter overflow: %s (0x%" PRIx64 ") port %d; clearing counters\n", mon_node->name, mon_node->guid, port); cl_plock_acquire(&pm->osm->lock); p_node = osm_get_node_by_guid(pm->subn, cl_hton64(mon_node->guid)); lid = get_lid(p_node, port, mon_node); cl_plock_release(&pm->osm->lock); if (lid == 0) { OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 540C: " "Failed to clear counters for %s (0x%" PRIx64 ") port %d; failed to get lid\n", mon_node->name, mon_node->guid, port); goto Exit; } remote_qp = get_qp(NULL, port); mad_context.perfmgr_context.node_guid = mon_node->guid; mad_context.perfmgr_context.port = port; mad_context.perfmgr_context.mad_method = IB_MAD_METHOD_SET; /* apparently some HW uses the same counters for the 32 and 64 * bit versions and a clear of them in the PortCounters * attribute also clears the ExtendedPortCounters equivalant * counters */ if (pce_supported(mon_node, port)) counter_select = 0x0fff; else counter_select = 0xffff; if (xmit_wait_sup) counter_select2 = 1; else counter_select2 = 0; status = perfmgr_send_pc_mad(pm, lid, remote_qp, pkey_ix, port, IB_MAD_METHOD_SET, counter_select, counter_select2, &mad_context, 0); /* FIXME SL != 0 */ if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 5411: " "Failed to send clear counters MAD for %s (0x%" PRIx64 ") port %d\n", mon_node->name, mon_node->guid, port); perfmgr_db_clear_prev_err(pm->db, mon_node->guid, port); if (!pce_supported(mon_node, port)) perfmgr_db_clear_prev_dc(pm->db, mon_node->guid, port); } Exit: OSM_LOG_EXIT(pm->log); } /********************************************************************** * Check if the port counters have overflowed and if so issue a clear * MAD to the port **********************************************************************/ static void perfmgr_check_pce_overflow(osm_perfmgr_t * pm, monitored_node_t * mon_node, int16_t pkey_ix, uint8_t port, ib_port_counters_ext_t * pc) { osm_madw_context_t mad_context; ib_api_status_t status; ib_net32_t remote_qp; OSM_LOG_ENTER(pm->log); if (counter_overflow_64(pc->xmit_data) || counter_overflow_64(pc->rcv_data) || counter_overflow_64(pc->xmit_pkts) || counter_overflow_64(pc->rcv_pkts) || (ietf_supported(mon_node, port) && (counter_overflow_64(pc->unicast_xmit_pkts) || counter_overflow_64(pc->unicast_rcv_pkts) || counter_overflow_64(pc->multicast_xmit_pkts) || counter_overflow_64(pc->multicast_rcv_pkts)))) { osm_node_t *p_node = NULL; ib_net16_t lid = 0; if (!mon_node->port[port].valid) goto Exit; osm_log(pm->log, OSM_LOG_VERBOSE, "PerfMgr: PortCountersExtended overflow: %s (0x%" PRIx64 ") port %d; clearing counters\n", mon_node->name, mon_node->guid, port); cl_plock_acquire(&pm->osm->lock); p_node = osm_get_node_by_guid(pm->subn, cl_hton64(mon_node->guid)); lid = get_lid(p_node, port, mon_node); cl_plock_release(&pm->osm->lock); if (lid == 0) { OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 5418: " "Failed to clear counters for %s (0x%" PRIx64 ") port %d; failed to get lid\n", mon_node->name, mon_node->guid, port); goto Exit; } remote_qp = get_qp(NULL, port); mad_context.perfmgr_context.node_guid = mon_node->guid; mad_context.perfmgr_context.port = port; mad_context.perfmgr_context.mad_method = IB_MAD_METHOD_SET; /* clear port counters */ status = perfmgr_send_pce_mad(pm, lid, remote_qp, pkey_ix, port, IB_MAD_METHOD_SET, &mad_context, 0); /* FIXME SL != 0 */ if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 5419: " "Failed to send clear counters MAD for %s (0x%" PRIx64 ") port %d\n", mon_node->name, mon_node->guid, port); perfmgr_db_clear_prev_dc(pm->db, mon_node->guid, port); } Exit: OSM_LOG_EXIT(pm->log); } /********************************************************************** * Check values for logging of errors **********************************************************************/ static void perfmgr_log_errors(osm_perfmgr_t * pm, monitored_node_t * mon_node, uint8_t port, perfmgr_db_err_reading_t * reading) { perfmgr_db_err_reading_t prev_read; perfmgr_db_err_t err = perfmgr_db_get_prev_err(pm->db, mon_node->guid, port, &prev_read); uint64_t cur, prev; if (err != PERFMGR_EVENT_DB_SUCCESS) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Failed to find previous " "reading for %s (0x%" PRIx64 ") port %u\n", mon_node->name, mon_node->guid, port); return; } #define LOG_ERR_CNT(errname, errnum, counter_name) \ if (reading->counter_name > prev_read.counter_name) { \ if (mon_node->port[port].remote_valid == TRUE) \ OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR %s: " \ "%s : %" PRIu64 " : node " \ "\"%s\" (NodeGUID: 0x%" PRIx64 ") : port %u " \ "connected to \"%s\" (NodeGUID: 0x%" PRIx64 ") : port %u\n", \ errnum, errname, \ reading->counter_name - prev_read.counter_name, \ mon_node->name, mon_node->guid, port, \ mon_node->port[port].remote_name, \ mon_node->port[port].remote_guid, \ mon_node->port[port].remote_port); \ else \ OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR %s: " \ "%s : %" PRIu64 " : node " \ "\"%s\" (NodeGUID: 0x%" PRIx64 ") : port %u\n", \ errnum, errname, \ reading->counter_name - prev_read.counter_name, \ mon_node->name, mon_node->guid, port); \ } LOG_ERR_CNT("SymbolErrorCounter", "5431", symbol_err_cnt); LOG_ERR_CNT("LinkErrorRecoveryCounter", "5432", link_err_recover); LOG_ERR_CNT("LinkDownedCounter", "5433", link_downed); LOG_ERR_CNT("PortRcvErrors", "5434", rcv_err); LOG_ERR_CNT("PortRcvRemotePhysicalErrors", "5435", rcv_rem_phys_err); LOG_ERR_CNT("PortRcvSwitchRelayErrors", "5436", rcv_switch_relay_err); LOG_ERR_CNT("PortXmitDiscards", "5437", xmit_discards); LOG_ERR_CNT("PortXmitConstraintErrors", "5438", xmit_constraint_err); LOG_ERR_CNT("PortRcvConstraintErrors", "5439", rcv_constraint_err); LOG_ERR_CNT("LocalLinkIntegrityErrors", "543A", link_integrity); LOG_ERR_CNT("ExcessiveBufferOverrunErrors", "543B", buffer_overrun); LOG_ERR_CNT("VL15Dropped", "543C", vl15_dropped); cur = reading->xmit_wait; prev = prev_read.xmit_wait; if (pm->xmit_wait_log && cur > prev && (cur - prev) >= pm->xmit_wait_threshold) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 543D: XmitWait : %" PRIu64 " : node \"%s\" (NodeGUID: 0x%" PRIx64 ") : port %u\n", cur - prev, mon_node->name, mon_node->guid, port); } } static int16_t validate_redir_pkey(osm_perfmgr_t *pm, ib_net16_t pkey) { int16_t pkey_ix = -1; osm_port_t *p_port; osm_pkey_tbl_t *p_pkey_tbl; ib_net16_t *p_orig_pkey; uint16_t block; uint8_t index; OSM_LOG_ENTER(pm->log); CL_PLOCK_ACQUIRE(pm->sm->p_lock); p_port = osm_get_port_by_guid(pm->subn, pm->port_guid); if (!p_port) { CL_PLOCK_RELEASE(pm->sm->p_lock); OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 541E: No PerfMgr port object\n"); goto Exit; } if (p_port->p_physp && osm_physp_is_valid(p_port->p_physp)) { p_pkey_tbl = &p_port->p_physp->pkeys; if (!p_pkey_tbl) { CL_PLOCK_RELEASE(pm->sm->p_lock); OSM_LOG(pm->log, OSM_LOG_VERBOSE, "No PKey table found for PerfMgr port\n"); goto Exit; } p_orig_pkey = cl_map_get(&p_pkey_tbl->keys, ib_pkey_get_base(pkey)); if (!p_orig_pkey) { CL_PLOCK_RELEASE(pm->sm->p_lock); OSM_LOG(pm->log, OSM_LOG_VERBOSE, "PKey 0x%x not found for PerfMgr port\n", cl_ntoh16(pkey)); goto Exit; } if (osm_pkey_tbl_get_block_and_idx(p_pkey_tbl, p_orig_pkey, &block, &index) == IB_SUCCESS) { CL_PLOCK_RELEASE(pm->sm->p_lock); pkey_ix = block * IB_NUM_PKEY_ELEMENTS_IN_BLOCK + index; } else { CL_PLOCK_RELEASE(pm->sm->p_lock); OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 541F: Failed to obtain P_Key 0x%04x " "block and index for PerfMgr port\n", cl_ntoh16(pkey)); } } else { CL_PLOCK_RELEASE(pm->sm->p_lock); OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5420: Local PerfMgt port physp invalid\n"); } Exit: OSM_LOG_EXIT(pm->log); return pkey_ix; } static boolean_t handle_redirect(osm_perfmgr_t *pm, ib_class_port_info_t *cpi, monitored_node_t *p_mon_node, uint8_t port, osm_madw_context_t *mad_context) { char gid_str[INET6_ADDRSTRLEN]; ib_api_status_t status; boolean_t valid = TRUE; int16_t pkey_ix = 0; uint8_t mad_method; OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Redirection to LID %u GID %s QP 0x%x received\n", cl_ntoh16(cpi->redir_lid), inet_ntop(AF_INET6, cpi->redir_gid.raw, gid_str, sizeof gid_str), cl_ntoh32(cpi->redir_qp)); if (!pm->subn->opt.perfmgr_redir) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Redirection requested but disabled\n"); valid = FALSE; } /* valid redirection ? */ if (cpi->redir_lid == 0) { if (!ib_gid_is_notzero(&cpi->redir_gid)) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Invalid redirection " "(both redirect LID and GID are zero)\n"); valid = FALSE; } } if (cpi->redir_qp == 0) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Invalid RedirectQP\n"); valid = FALSE; } if (cpi->redir_pkey == 0) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Invalid RedirectP_Key\n"); valid = FALSE; } if (cpi->redir_qkey != IB_QP1_WELL_KNOWN_Q_KEY) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Invalid RedirectQ_Key\n"); valid = FALSE; } pkey_ix = validate_redir_pkey(pm, cpi->redir_pkey); if (pkey_ix == -1) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Index for Pkey 0x%x not found\n", cl_ntoh16(cpi->redir_pkey)); valid = FALSE; } if (cpi->redir_lid == 0) { /* GID redirection: get PathRecord information */ OSM_LOG(pm->log, OSM_LOG_VERBOSE, "GID redirection not currently supported\n"); goto Exit; } if (!valid) goto Exit; /* LID redirection support (easier than GID redirection) */ cl_plock_acquire(&pm->osm->lock); p_mon_node->port[port].redirection = TRUE; p_mon_node->port[port].valid = valid; memcpy(&p_mon_node->port[port].gid, &cpi->redir_gid, sizeof(ib_gid_t)); p_mon_node->port[port].lid = cpi->redir_lid; p_mon_node->port[port].qp = cpi->redir_qp; p_mon_node->port[port].pkey = cpi->redir_pkey; if (pkey_ix != -1) p_mon_node->port[port].pkey_ix = pkey_ix; cl_plock_release(&pm->osm->lock); /* either */ if (pm->query_cpi) { /* issue a CPI query to the redirected location */ mad_method = IB_MAD_METHOD_GET; p_mon_node->port[port].cpi_valid = FALSE; status = perfmgr_send_cpi_mad(pm, cpi->redir_lid, cpi->redir_qp, pkey_ix, port, mad_context, 0); /* FIXME SL != 0 */ } else { /* reissue the original query to the redirected location */ uint8_t counter_select2; if (xmit_wait_supported(p_mon_node, port)) counter_select2 = 1; else counter_select2 = 0; mad_method = mad_context->perfmgr_context.mad_method; if (mad_context->perfmgr_context.mad_attr_id == IB_MAD_ATTR_PORT_CNTRS) { status = perfmgr_send_pc_mad(pm, cpi->redir_lid, cpi->redir_qp, pkey_ix, port, mad_method, 0xffff, counter_select2, mad_context, 0); /* FIXME SL != 0 */ } else { status = perfmgr_send_pce_mad(pm, cpi->redir_lid, cpi->redir_qp, pkey_ix, port, mad_method, mad_context, 0); /* FIXME SL != 0 */ } } if (status != IB_SUCCESS) OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5414: " "Failed to send redirected MAD " "with method 0x%x for node %s " "(NodeGuid 0x%" PRIx64 ") port %d\n", mad_method, p_mon_node->name, p_mon_node->guid, port); Exit: return (valid); } /********************************************************************** * Detect if someone else on the network could have cleared the counters * without us knowing. This is easy to detect because the counters never * wrap but are "sticky" PortCountersExtended version. * * The one time this will not work is if the port is getting errors fast * enough to have the reading overtake the previous reading. In this case, * counters will be missed. **********************************************************************/ static void perfmgr_check_data_cnt_oob_clear(osm_perfmgr_t * pm, monitored_node_t * mon_node, uint8_t port, perfmgr_db_data_cnt_reading_t * dc) { perfmgr_db_data_cnt_reading_t prev_dc; if (perfmgr_db_get_prev_dc(pm->db, mon_node->guid, port, &prev_dc) != PERFMGR_EVENT_DB_SUCCESS) { OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Failed to find previous data count " "reading for %s (0x%" PRIx64 ") port %u\n", mon_node->name, mon_node->guid, port); return; } OSM_LOG(pm->log, OSM_LOG_DEBUG, "Data vs previous node %s (0x%" PRIx64 ") port %u\n" "TX: %"PRIu64" ?< %"PRIu64"\n" "RX: %"PRIu64" ?< %"PRIu64"\n" "TXP: %"PRIu64" ?< %"PRIu64"\n" "RXP: %"PRIu64" ?< %"PRIu64"\n" "UTXP: %"PRIu64" ?< %"PRIu64"\n" "URXP: %"PRIu64" ?< %"PRIu64"\n" "MTXP: %"PRIu64" ?< %"PRIu64"\n" "MRXP: %"PRIu64" ?< %"PRIu64"\n" , mon_node->name, mon_node->guid, port, dc->xmit_data, prev_dc.xmit_data, dc->rcv_data, prev_dc.rcv_data, dc->xmit_pkts, prev_dc.xmit_pkts, dc->rcv_pkts, prev_dc.rcv_pkts, dc->unicast_xmit_pkts, prev_dc.unicast_xmit_pkts, dc->unicast_rcv_pkts, prev_dc.unicast_rcv_pkts, dc->multicast_xmit_pkts, prev_dc.multicast_xmit_pkts, dc->multicast_rcv_pkts, prev_dc.multicast_rcv_pkts); if (dc->xmit_data < prev_dc.xmit_data || dc->rcv_data < prev_dc.rcv_data || dc->xmit_pkts < prev_dc.xmit_pkts || dc->rcv_pkts < prev_dc.rcv_pkts || (ietf_supported(mon_node, port) && (dc->unicast_xmit_pkts < prev_dc.unicast_xmit_pkts || dc->unicast_rcv_pkts < prev_dc.unicast_rcv_pkts || dc->multicast_xmit_pkts < prev_dc.multicast_xmit_pkts || dc->multicast_rcv_pkts < prev_dc.multicast_rcv_pkts))) { OSM_LOG(pm->log, OSM_LOG_ERROR, "PerfMgr: ERR 540B: Detected an out of band data counter " "clear on node %s (0x%" PRIx64 ") port %u\n", mon_node->name, mon_node->guid, port); perfmgr_db_clear_prev_dc(pm->db, mon_node->guid, port); } } /********************************************************************** * The dispatcher uses a thread pool which will call this function when * there is a thread available to process the mad received on the wire **********************************************************************/ static void pc_recv_process(void *context, void *data) { osm_perfmgr_t *pm = context; osm_madw_t *p_madw = data; osm_madw_context_t *mad_context = &p_madw->context; ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw); uint64_t node_guid = mad_context->perfmgr_context.node_guid; uint8_t port = mad_context->perfmgr_context.port; perfmgr_db_err_reading_t err_reading; perfmgr_db_data_cnt_reading_t data_reading; cl_map_item_t *p_node; monitored_node_t *p_mon_node; ib_class_port_info_t *cpi = NULL; OSM_LOG_ENTER(pm->log); /* * get the monitored node struct to have the printable name * for log messages */ if ((p_node = cl_qmap_get(&pm->monitored_map, node_guid)) == cl_qmap_end(&pm->monitored_map)) { OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5412: GUID 0x%016" PRIx64 " not found in monitored map\n", node_guid); goto Exit; } p_mon_node = (monitored_node_t *) p_node; OSM_LOG(pm->log, OSM_LOG_VERBOSE, "Processing received MAD status 0x%x context 0x%" PRIx64 " port %u\n", cl_ntoh16(p_mad->status), node_guid, port); CL_ASSERT(p_mad->attr_id == IB_MAD_ATTR_PORT_CNTRS || p_mad->attr_id == IB_MAD_ATTR_PORT_CNTRS_EXT || p_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO); cl_plock_acquire(&pm->osm->lock); /* validate port number */ if (port >= p_mon_node->num_ports) { cl_plock_release(&pm->osm->lock); OSM_LOG(pm->log, OSM_LOG_ERROR, "ERR 5413: " "Invalid port num %d for GUID 0x%016" PRIx64 " num ports %d\n", port, node_guid, p_mon_node->num_ports); goto Exit; } cl_plock_release(&pm->osm->lock); /* capture CLASS_PORT_INFO data */ if (p_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO) { boolean_t cpi_valid = TRUE; cpi = (ib_class_port_info_t *) & (osm_madw_get_perfmgt_mad_ptr(p_madw)->data); /* Response could be redirection (IBM eHCA PMA does this) */ if (p_mad->status & IB_MAD_STATUS_REDIRECT) cpi_valid = handle_redirect(pm, cpi, p_mon_node, port, mad_context); if (pm->query_cpi && cpi_valid) { cl_plock_acquire(&pm->osm->lock); if (p_mon_node->node_type == IB_NODE_TYPE_SWITCH) { int i; for (i = p_mon_node->esp0 ? 0 : 1; i < p_mon_node->num_ports; i++) { p_mon_node->port[i].cap_mask = cpi->cap_mask; p_mon_node->port[i].cpi_valid = cpi_valid; } } else { p_mon_node->port[port].cap_mask = cpi->cap_mask; p_mon_node->port[port].cpi_valid = cpi_valid; } cl_plock_release(&pm->osm->lock); } goto Exit; } if (p_mad->attr_id == IB_MAD_ATTR_PORT_CNTRS_EXT) { ib_port_counters_ext_t *ext_wire_read = (ib_port_counters_ext_t *) &osm_madw_get_perfmgt_mad_ptr(p_madw)->data; /* convert wire data to perfmgr data counter reading */ perfmgr_db_fill_data_cnt_read_pce(ext_wire_read, &data_reading, ietf_supported(p_mon_node, port)); /* add counter */ if (mad_context->perfmgr_context.mad_method == IB_MAD_METHOD_GET) { /* detect an out of band clear on the port */ perfmgr_check_data_cnt_oob_clear(pm, p_mon_node, port, &data_reading); perfmgr_db_add_dc_reading(pm->db, node_guid, port, &data_reading, ietf_supported(p_mon_node, port)); } else { perfmgr_db_clear_prev_dc(pm->db, node_guid, port); } perfmgr_check_pce_overflow(pm, p_mon_node, p_mon_node->port[port].pkey_ix, port, ext_wire_read); } else { boolean_t pce_sup = pce_supported(p_mon_node, port); boolean_t xmit_wait_sup = xmit_wait_supported(p_mon_node, port); ib_port_counters_t *wire_read = (ib_port_counters_t *) &osm_madw_get_perfmgt_mad_ptr(p_madw)->data; perfmgr_db_fill_err_read(wire_read, &err_reading, xmit_wait_sup); if (!pce_sup) perfmgr_db_fill_data_cnt_read_pc(wire_read, &data_reading); if (mad_context->perfmgr_context.mad_method == IB_MAD_METHOD_GET) { /* detect an out of band clear on the port */ perfmgr_check_oob_clear(pm, p_mon_node, port, &err_reading); if (!pce_sup) perfmgr_check_data_cnt_oob_clear(pm, p_mon_node, port, &data_reading); /* log errors from this reading */ if (pm->subn->opt.perfmgr_log_errors) perfmgr_log_errors(pm, p_mon_node, port, &err_reading); perfmgr_db_add_err_reading(pm->db, node_guid, port, &err_reading); if (!pce_sup) perfmgr_db_add_dc_reading(pm->db, node_guid, port, &data_reading, 0); } else { perfmgr_db_clear_prev_err(pm->db, node_guid, port); if (!pce_sup) perfmgr_db_clear_prev_dc(pm->db, node_guid, port); } perfmgr_check_overflow(pm, p_mon_node, p_mon_node->port[port].pkey_ix, port, wire_read, xmit_wait_sup); } #ifdef ENABLE_OSM_PERF_MGR_PROFILE do { struct timeval proc_time; gettimeofday(&proc_time, NULL); diff_time(&p_madw->context.perfmgr_context.query_start, &proc_time, &proc_time); update_mad_stats(&proc_time); } while (0); #endif Exit: osm_mad_pool_put(pm->mad_pool, p_madw); OSM_LOG_EXIT(pm->log); } /********************************************************************** * Initialize the PerfMgr object **********************************************************************/ ib_api_status_t osm_perfmgr_init(osm_perfmgr_t * pm, osm_opensm_t * osm, const osm_subn_opt_t * p_opt) { ib_api_status_t status; OSM_LOG_ENTER(&osm->log); OSM_LOG(&osm->log, OSM_LOG_VERBOSE, "Initializing PerfMgr\n"); memset(pm, 0, sizeof(*pm)); pm->subn = &osm->subn; pm->sm = &osm->sm; pm->log = &osm->log; pm->mad_pool = &osm->mad_pool; pm->vendor = osm->p_vendor; pm->trans_id = PERFMGR_INITIAL_TID_VALUE; pm->state = p_opt->perfmgr ? PERFMGR_STATE_ENABLED : PERFMGR_STATE_DISABLE; pm->sweep_state = PERFMGR_SWEEP_SLEEP; cl_spinlock_init(&pm->lock); pm->sweep_time_s = p_opt->perfmgr_sweep_time_s; pm->max_outstanding_queries = p_opt->perfmgr_max_outstanding_queries; pm->ignore_cas = p_opt->perfmgr_ignore_cas; pm->osm = osm; pm->local_port = -1; status = cl_timer_init(&pm->sweep_timer, perfmgr_sweep, pm); if (status != IB_SUCCESS) goto Exit; status = IB_INSUFFICIENT_RESOURCES; pm->db = perfmgr_db_construct(pm); if (!pm->db) { pm->state = PERFMGR_STATE_NO_DB; goto Exit; } pm->pc_disp_h = cl_disp_register(&osm->disp, OSM_MSG_MAD_PORT_COUNTERS, pc_recv_process, pm); if (pm->pc_disp_h == CL_DISP_INVALID_HANDLE) { perfmgr_db_destroy(pm->db); goto Exit; } init_monitored_nodes(pm); if (pm->state == PERFMGR_STATE_ENABLED) cl_timer_start(&pm->sweep_timer, pm->sweep_time_s * 1000); pm->rm_nodes = p_opt->perfmgr_rm_nodes; pm->query_cpi = p_opt->perfmgr_query_cpi; pm->xmit_wait_log = p_opt->perfmgr_xmit_wait_log; pm->xmit_wait_threshold = p_opt->perfmgr_xmit_wait_threshold; status = IB_SUCCESS; Exit: OSM_LOG_EXIT(pm->log); return status; } /********************************************************************** * Clear the counters from the db **********************************************************************/ void osm_perfmgr_clear_counters(osm_perfmgr_t * pm) { /** * FIXME todo issue clear on the fabric? */ perfmgr_db_clear_counters(pm->db); osm_log_v2(pm->log, OSM_LOG_INFO, FILE_ID, "PerfMgr counters cleared\n"); } /******************************************************************* * Dump the DB information to the file specified *******************************************************************/ void osm_perfmgr_dump_counters(osm_perfmgr_t * pm, perfmgr_db_dump_t dump_type) { char path[256]; char *file_name; if (pm->subn->opt.event_db_dump_file) file_name = pm->subn->opt.event_db_dump_file; else { snprintf(path, sizeof(path), "%s/%s", pm->subn->opt.dump_files_dir, OSM_PERFMGR_DEFAULT_DUMP_FILE); file_name = path; } if (perfmgr_db_dump(pm->db, file_name, dump_type) != 0) OSM_LOG(pm->log, OSM_LOG_ERROR, "Failed to dump file %s : %s", file_name, strerror(errno)); } /******************************************************************* * Print the DB information to the fp specified *******************************************************************/ void osm_perfmgr_print_counters(osm_perfmgr_t * pm, char *nodename, FILE * fp, char *port, int err_only) { if (nodename) { char *end = NULL; uint64_t guid = strtoull(nodename, &end, 0); if (nodename + strlen(nodename) != end) perfmgr_db_print_by_name(pm->db, nodename, fp, port, err_only); else perfmgr_db_print_by_guid(pm->db, guid, fp, port, err_only); } else perfmgr_db_print_all(pm->db, fp, err_only); } void osm_perfmgr_update_nodename(osm_perfmgr_t *pm, uint64_t node_guid, char *nodename) { if (pm->db) perfmgr_db_update_name(pm->db, node_guid, nodename); } #endif /* ENABLE_OSM_PERF_MGR */ opensm-3.3.20/opensm/osm_perfmgr_db.c0000644000205000001450000010344212331106741014444 00000000000000/* * Copyright (c) 2008-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 The Regents of the University of California. * Copyright (c) 2009 HNR Consulting. 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef ENABLE_OSM_PERF_MGR #include #include #include #include #include #include #define FILE_ID OSM_FILE_PERFMGR_DB_C #include #include #include static void free_node(db_node_t * node); /** ========================================================================= */ perfmgr_db_t *perfmgr_db_construct(osm_perfmgr_t *perfmgr) { perfmgr_db_t *db = malloc(sizeof(*db)); if (!db) return NULL; cl_qmap_init(&db->pc_data); cl_plock_construct(&db->lock); cl_plock_init(&db->lock); db->perfmgr = perfmgr; return db; } /** ========================================================================= */ void perfmgr_db_destroy(perfmgr_db_t * db) { cl_map_item_t *item, *next_item; if (db) { item = cl_qmap_head(&db->pc_data); while (item != cl_qmap_end(&db->pc_data)) { next_item = cl_qmap_next(item); free_node((db_node_t *)item); item = next_item; } cl_plock_destroy(&db->lock); free(db); } } /********************************************************************** * Internal call db->lock should be held when calling **********************************************************************/ static inline db_node_t *get(perfmgr_db_t * db, uint64_t guid) { cl_map_item_t *rc = cl_qmap_get(&db->pc_data, guid); const cl_map_item_t *end = cl_qmap_end(&db->pc_data); if (rc == end) return NULL; return (db_node_t *) rc; } static inline perfmgr_db_err_t bad_node_port(db_node_t * node, uint8_t port) { if (!node) return PERFMGR_EVENT_DB_GUIDNOTFOUND; if (port >= node->num_ports || (!node->esp0 && port == 0)) return PERFMGR_EVENT_DB_PORTNOTFOUND; return PERFMGR_EVENT_DB_SUCCESS; } static inline void mark_port_valid(db_node_t * node, uint8_t port) { node->ports[port].valid = TRUE; } /** ========================================================================= */ static db_node_t *malloc_node(uint64_t guid, boolean_t esp0, uint8_t num_ports, char *name) { int i = 0; time_t cur_time = 0; db_node_t *rc = malloc(sizeof(*rc)); if (!rc) return NULL; rc->ports = calloc(num_ports, sizeof(db_port_t)); if (!rc->ports) goto free_rc; rc->num_ports = num_ports; rc->node_guid = guid; rc->esp0 = esp0; cur_time = time(NULL); for (i = 0; i < num_ports; i++) { rc->ports[i].last_reset = cur_time; rc->ports[i].err_previous.time = cur_time; rc->ports[i].dc_previous.time = cur_time; rc->ports[i].valid = FALSE; } snprintf(rc->node_name, sizeof(rc->node_name), "%s", name); rc->active = FALSE; return rc; free_rc: free(rc); return NULL; } /** ========================================================================= */ static void free_node(db_node_t * node) { if (!node) return; if (node->ports) free(node->ports); free(node); } /* insert nodes to the database */ static perfmgr_db_err_t insert(perfmgr_db_t * db, db_node_t * node) { cl_map_item_t *rc = cl_qmap_insert(&db->pc_data, node->node_guid, (cl_map_item_t *) node); if ((void *)rc != (void *)node) return PERFMGR_EVENT_DB_FAIL; return PERFMGR_EVENT_DB_SUCCESS; } perfmgr_db_err_t perfmgr_db_create_entry(perfmgr_db_t * db, uint64_t guid, boolean_t esp0, uint8_t num_ports, char *name) { perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_excl_acquire(&db->lock); if (!get(db, guid)) { db_node_t *pc_node = malloc_node(guid, esp0, num_ports, name); if (!pc_node) { rc = PERFMGR_EVENT_DB_NOMEM; goto Exit; } if (insert(db, pc_node)) { free_node(pc_node); rc = PERFMGR_EVENT_DB_FAIL; goto Exit; } } Exit: cl_plock_release(&db->lock); return rc; } perfmgr_db_err_t perfmgr_db_update_name(perfmgr_db_t * db, uint64_t node_guid, char *name) { db_node_t *node = NULL; cl_plock_excl_acquire(&db->lock); node = get(db, node_guid); if (node) snprintf(node->node_name, sizeof(node->node_name), "%s", name); cl_plock_release(&db->lock); return (PERFMGR_EVENT_DB_SUCCESS); } perfmgr_db_err_t perfmgr_db_delete_entry(perfmgr_db_t * db, uint64_t guid) { cl_map_item_t * rc = cl_qmap_remove(&db->pc_data, guid); if (rc == cl_qmap_end(&db->pc_data)) return(PERFMGR_EVENT_DB_GUIDNOTFOUND); db_node_t *pc_node = (db_node_t *)rc; free_node(pc_node); return(PERFMGR_EVENT_DB_SUCCESS); } perfmgr_db_err_t perfmgr_db_delete_inactive(perfmgr_db_t * db, unsigned *cnt) { perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; int i = 0; int num = 0; uint64_t * guid_list = NULL; cl_map_item_t * p_map_item = cl_qmap_head(&db->pc_data); if (p_map_item == cl_qmap_end(&db->pc_data)) { rc = PERFMGR_EVENT_DB_SUCCESS; goto Done; } while (p_map_item != cl_qmap_end(&db->pc_data)) { db_node_t *n = (db_node_t *)p_map_item; if (n->active == FALSE) { guid_list = realloc(guid_list, sizeof(*guid_list) * (num+1)); if (!guid_list) { num = 0; rc = PERFMGR_EVENT_DB_NOMEM; goto Done; } guid_list[num] = n->node_guid; num++; } p_map_item = cl_qmap_next(p_map_item); } for (i = 0 ; i < num; i++) perfmgr_db_delete_entry(db, guid_list[i]); free(guid_list); Done: if (cnt) *cnt = num; return(rc); } perfmgr_db_err_t perfmgr_db_mark_active(perfmgr_db_t *db, uint64_t guid, boolean_t active) { db_node_t *node = NULL; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if (node) node->active = active; cl_plock_release(&db->lock); return (PERFMGR_EVENT_DB_SUCCESS); } /********************************************************************** * Dump a reading vs the previous reading to stdout **********************************************************************/ static inline void debug_dump_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num, db_port_t * port, perfmgr_db_err_reading_t * cur) { osm_log_t *log = db->perfmgr->log; if (!OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_DEBUG)) return; /* optimize this a bit */ osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "GUID 0x%" PRIx64 " Port %u:\n", guid, port_num); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "sym %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->symbol_err_cnt, port->err_previous.symbol_err_cnt, port->err_total.symbol_err_cnt); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "ler %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->link_err_recover, port->err_previous.link_err_recover, port->err_total.link_err_recover); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "ld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->link_downed, port->err_previous.link_downed, port->err_total.link_downed); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "re %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_err, port->err_previous.rcv_err, port->err_total.rcv_err); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "rrp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_rem_phys_err, port->err_previous.rcv_rem_phys_err, port->err_total.rcv_rem_phys_err); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "rsr %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_switch_relay_err, port->err_previous.rcv_switch_relay_err, port->err_total.rcv_switch_relay_err); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->xmit_discards, port->err_previous.xmit_discards, port->err_total.xmit_discards); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "xce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->xmit_constraint_err, port->err_previous.xmit_constraint_err, port->err_total.xmit_constraint_err); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "rce %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_constraint_err, port->err_previous.rcv_constraint_err, port->err_total.rcv_constraint_err); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "li %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->link_integrity, port->err_previous.link_integrity, port->err_total.link_integrity); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "bo %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->buffer_overrun, port->err_previous.buffer_overrun, port->err_total.buffer_overrun); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "vld %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->vl15_dropped, port->err_previous.vl15_dropped, port->err_total.vl15_dropped); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "xw %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->xmit_wait, port->err_previous.xmit_wait, port->err_total.xmit_wait); } /********************************************************************** * perfmgr_db_err_reading_t functions **********************************************************************/ perfmgr_db_err_t perfmgr_db_add_err_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_err_reading_t * reading) { db_port_t *p_port = NULL; db_node_t *node = NULL; perfmgr_db_err_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; osm_epi_pe_event_t epi_pe_data; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; mark_port_valid(node, port); p_port = &(node->ports[port]); previous = &(node->ports[port].err_previous); debug_dump_err_reading(db, guid, port, p_port, reading); epi_pe_data.time_diff_s = (reading->time - previous->time); osm_epi_create_port_id(&epi_pe_data.port_id, guid, port, node->node_name); /* calculate changes from previous reading */ epi_pe_data.symbol_err_cnt = (reading->symbol_err_cnt - previous->symbol_err_cnt); p_port->err_total.symbol_err_cnt += epi_pe_data.symbol_err_cnt; epi_pe_data.link_err_recover = (reading->link_err_recover - previous->link_err_recover); p_port->err_total.link_err_recover += epi_pe_data.link_err_recover; epi_pe_data.link_downed = (reading->link_downed - previous->link_downed); p_port->err_total.link_downed += epi_pe_data.link_downed; epi_pe_data.rcv_err = (reading->rcv_err - previous->rcv_err); p_port->err_total.rcv_err += epi_pe_data.rcv_err; epi_pe_data.rcv_rem_phys_err = (reading->rcv_rem_phys_err - previous->rcv_rem_phys_err); p_port->err_total.rcv_rem_phys_err += epi_pe_data.rcv_rem_phys_err; epi_pe_data.rcv_switch_relay_err = (reading->rcv_switch_relay_err - previous->rcv_switch_relay_err); p_port->err_total.rcv_switch_relay_err += epi_pe_data.rcv_switch_relay_err; epi_pe_data.xmit_discards = (reading->xmit_discards - previous->xmit_discards); p_port->err_total.xmit_discards += epi_pe_data.xmit_discards; epi_pe_data.xmit_constraint_err = (reading->xmit_constraint_err - previous->xmit_constraint_err); p_port->err_total.xmit_constraint_err += epi_pe_data.xmit_constraint_err; epi_pe_data.rcv_constraint_err = (reading->rcv_constraint_err - previous->rcv_constraint_err); p_port->err_total.rcv_constraint_err += epi_pe_data.rcv_constraint_err; epi_pe_data.link_integrity = (reading->link_integrity - previous->link_integrity); p_port->err_total.link_integrity += epi_pe_data.link_integrity; epi_pe_data.buffer_overrun = (reading->buffer_overrun - previous->buffer_overrun); p_port->err_total.buffer_overrun += epi_pe_data.buffer_overrun; epi_pe_data.vl15_dropped = (reading->vl15_dropped - previous->vl15_dropped); p_port->err_total.vl15_dropped += epi_pe_data.vl15_dropped; epi_pe_data.xmit_wait = (reading->xmit_wait - previous->xmit_wait); p_port->err_total.xmit_wait += epi_pe_data.xmit_wait; p_port->err_previous = *reading; /* mark the time this total was updated */ p_port->err_total.time = reading->time; osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_ERRORS, &epi_pe_data); Exit: cl_plock_release(&db->lock); return rc; } perfmgr_db_err_t perfmgr_db_get_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_err_reading_t * reading) { db_node_t *node = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; *reading = node->ports[port].err_previous; Exit: cl_plock_release(&db->lock); return rc; } perfmgr_db_err_t perfmgr_db_clear_prev_err(perfmgr_db_t * db, uint64_t guid, uint8_t port) { db_node_t *node = NULL; perfmgr_db_err_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; previous = &(node->ports[port].err_previous); memset(previous, 0, sizeof(*previous)); node->ports[port].err_previous.time = time(NULL); Exit: cl_plock_release(&db->lock); return rc; } static inline void debug_dump_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port_num, db_port_t * port, perfmgr_db_data_cnt_reading_t * cur) { osm_log_t *log = db->perfmgr->log; if (!OSM_LOG_IS_ACTIVE_V2(log, OSM_LOG_DEBUG)) return; osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "xd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->xmit_data, port->dc_previous.xmit_data, port->dc_total.xmit_data); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "rd %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_data, port->dc_previous.rcv_data, port->dc_total.rcv_data); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "xp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->xmit_pkts, port->dc_previous.xmit_pkts, port->dc_total.xmit_pkts); osm_log_v2(log, OSM_LOG_DEBUG, FILE_ID, "rp %" PRIu64 " <-- %" PRIu64 " (%" PRIu64 ")\n", cur->rcv_pkts, port->dc_previous.rcv_pkts, port->dc_total.rcv_pkts); } /********************************************************************** * perfmgr_db_data_cnt_reading_t functions **********************************************************************/ perfmgr_db_err_t perfmgr_db_add_dc_reading(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_data_cnt_reading_t * reading, int ietf_sup) { db_port_t *p_port = NULL; db_node_t *node = NULL; perfmgr_db_data_cnt_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; osm_epi_dc_event_t epi_dc_data; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; mark_port_valid(node, port); p_port = &node->ports[port]; previous = &node->ports[port].dc_previous; debug_dump_dc_reading(db, guid, port, p_port, reading); epi_dc_data.time_diff_s = reading->time - previous->time; osm_epi_create_port_id(&epi_dc_data.port_id, guid, port, node->node_name); /* calculate changes from previous reading */ epi_dc_data.xmit_data = reading->xmit_data - previous->xmit_data; p_port->dc_total.xmit_data += epi_dc_data.xmit_data; epi_dc_data.rcv_data = reading->rcv_data - previous->rcv_data; p_port->dc_total.rcv_data += epi_dc_data.rcv_data; epi_dc_data.xmit_pkts = reading->xmit_pkts - previous->xmit_pkts; p_port->dc_total.xmit_pkts += epi_dc_data.xmit_pkts; epi_dc_data.rcv_pkts = reading->rcv_pkts - previous->rcv_pkts; p_port->dc_total.rcv_pkts += epi_dc_data.rcv_pkts; if (ietf_sup) { epi_dc_data.unicast_xmit_pkts = reading->unicast_xmit_pkts - previous->unicast_xmit_pkts; p_port->dc_total.unicast_xmit_pkts += epi_dc_data.unicast_xmit_pkts; epi_dc_data.unicast_rcv_pkts = reading->unicast_rcv_pkts - previous->unicast_rcv_pkts; p_port->dc_total.unicast_rcv_pkts += epi_dc_data.unicast_rcv_pkts; epi_dc_data.multicast_xmit_pkts = reading->multicast_xmit_pkts - previous->multicast_xmit_pkts; p_port->dc_total.multicast_xmit_pkts += epi_dc_data.multicast_xmit_pkts; epi_dc_data.multicast_rcv_pkts = reading->multicast_rcv_pkts - previous->multicast_rcv_pkts; p_port->dc_total.multicast_rcv_pkts += epi_dc_data.multicast_rcv_pkts; } p_port->dc_previous = *reading; /* mark the time this total was updated */ p_port->dc_total.time = reading->time; osm_opensm_report_event(db->perfmgr->osm, OSM_EVENT_ID_PORT_DATA_COUNTERS, &epi_dc_data); Exit: cl_plock_release(&db->lock); return rc; } perfmgr_db_err_t perfmgr_db_get_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port, perfmgr_db_data_cnt_reading_t * reading) { db_node_t *node = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; *reading = node->ports[port].dc_previous; Exit: cl_plock_release(&db->lock); return rc; } perfmgr_db_err_t perfmgr_db_clear_prev_dc(perfmgr_db_t * db, uint64_t guid, uint8_t port) { db_node_t *node = NULL; perfmgr_db_data_cnt_reading_t *previous = NULL; perfmgr_db_err_t rc = PERFMGR_EVENT_DB_SUCCESS; cl_plock_excl_acquire(&db->lock); node = get(db, guid); if ((rc = bad_node_port(node, port)) != PERFMGR_EVENT_DB_SUCCESS) goto Exit; previous = &node->ports[port].dc_previous; memset(previous, 0, sizeof(*previous)); node->ports[port].dc_previous.time = time(NULL); Exit: cl_plock_release(&db->lock); return rc; } static void clear_counters(cl_map_item_t * const p_map_item, void *context) { db_node_t *node = (db_node_t *) p_map_item; int i = 0; time_t ts = time(NULL); for (i = 0; i < node->num_ports; i++) { node->ports[i].err_total.symbol_err_cnt = 0; node->ports[i].err_total.link_err_recover = 0; node->ports[i].err_total.link_downed = 0; node->ports[i].err_total.rcv_err = 0; node->ports[i].err_total.rcv_rem_phys_err = 0; node->ports[i].err_total.rcv_switch_relay_err = 0; node->ports[i].err_total.xmit_discards = 0; node->ports[i].err_total.xmit_constraint_err = 0; node->ports[i].err_total.rcv_constraint_err = 0; node->ports[i].err_total.link_integrity = 0; node->ports[i].err_total.buffer_overrun = 0; node->ports[i].err_total.vl15_dropped = 0; node->ports[i].err_total.xmit_wait = 0; node->ports[i].err_total.time = ts; node->ports[i].dc_total.xmit_data = 0; node->ports[i].dc_total.rcv_data = 0; node->ports[i].dc_total.xmit_pkts = 0; node->ports[i].dc_total.rcv_pkts = 0; node->ports[i].dc_total.unicast_xmit_pkts = 0; node->ports[i].dc_total.unicast_rcv_pkts = 0; node->ports[i].dc_total.multicast_xmit_pkts = 0; node->ports[i].dc_total.multicast_rcv_pkts = 0; node->ports[i].dc_total.time = ts; node->ports[i].last_reset = ts; } } /********************************************************************** * Clear all the counters from the db **********************************************************************/ void perfmgr_db_clear_counters(perfmgr_db_t * db) { cl_plock_excl_acquire(&db->lock); cl_qmap_apply_func(&db->pc_data, clear_counters, (void *)db); cl_plock_release(&db->lock); #if 0 if (db->db_impl->clear_counters) db->db_impl->clear_counters(db->db_data); #endif } /********************************************************************** * Output a tab delimited output of the port counters **********************************************************************/ static void dump_node_mr(db_node_t * node, FILE * fp) { int i = 0; fprintf(fp, "\nName\tGUID\tActive\tPort\tLast Reset\t" "Last Error Update\tLast Data Update\t" "%s\t%s\t" "%s\t%s\t%s\t%s\t%s\t%s\t%s\t" "%s\t%s\t%s\t%s\t%s\t%s\t%s\t" "%s\t%s\t%s\t%s\t%s\n", "symbol_err_cnt", "link_err_recover", "link_downed", "rcv_err", "rcv_rem_phys_err", "rcv_switch_relay_err", "xmit_discards", "xmit_constraint_err", "rcv_constraint_err", "link_int_err", "buf_overrun_err", "vl15_dropped", "xmit_wait", "xmit_data", "rcv_data", "xmit_pkts", "rcv_pkts", "unicast_xmit_pkts", "unicast_rcv_pkts", "multicast_xmit_pkts", "multicast_rcv_pkts"); for (i = (node->esp0) ? 0 : 1; i < node->num_ports; i++) { char lr[128]; char *last_reset = ctime_r(&node->ports[i].last_reset, lr); char leu[128]; char *last_err_update = ctime_r(&node->ports[i].err_total.time, leu); char ldu[128]; char *last_data_update = ctime_r(&node->ports[i].dc_total.time, ldu); if (!node->ports[i].valid) continue; last_reset[strlen(last_reset) - 1] = '\0'; /* remove \n */ last_err_update[strlen(last_err_update) - 1] = '\0'; /* remove \n */ last_data_update[strlen(last_data_update) - 1] = '\0'; /* remove \n */ fprintf(fp, "%s\t0x%" PRIx64 "\t%s\t%d\t%s\t%s\t%s\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t" "%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\n", node->node_name, node->node_guid, node->active ? "TRUE" : "FALSE", i, last_reset, last_err_update, last_data_update, node->ports[i].err_total.symbol_err_cnt, node->ports[i].err_total.link_err_recover, node->ports[i].err_total.link_downed, node->ports[i].err_total.rcv_err, node->ports[i].err_total.rcv_rem_phys_err, node->ports[i].err_total.rcv_switch_relay_err, node->ports[i].err_total.xmit_discards, node->ports[i].err_total.xmit_constraint_err, node->ports[i].err_total.rcv_constraint_err, node->ports[i].err_total.link_integrity, node->ports[i].err_total.buffer_overrun, node->ports[i].err_total.vl15_dropped, node->ports[i].err_total.xmit_wait, node->ports[i].dc_total.xmit_data, node->ports[i].dc_total.rcv_data, node->ports[i].dc_total.xmit_pkts, node->ports[i].dc_total.rcv_pkts, node->ports[i].dc_total.unicast_xmit_pkts, node->ports[i].dc_total.unicast_rcv_pkts, node->ports[i].dc_total.multicast_xmit_pkts, node->ports[i].dc_total.multicast_rcv_pkts); } } static void dump_hr_dc(FILE *fp, uint64_t val64, int data) { const char *unit = ""; uint64_t tmp = val64; float val = 0.0; int ui = 0; uint64_t div = 1; tmp /= 1024; while (tmp) { ui++; tmp /= 1024; div *= 1024; } val = (float)(val64); if (data) { val *= 4; if (val/div > 1024) { ui++; div *= 1024; } } val /= div; switch (ui) { case 1: unit = "K"; break; case 2: unit = "M"; break; case 3: unit = "G"; break; case 4: unit = "T"; break; case 5: unit = "P"; break; case 6: unit = "E"; break; } fprintf(fp, " (%5.3f%s%s)\n", val, unit, data ? "B" : ""); } /********************************************************************** * Output a human readable output of the port counters **********************************************************************/ static void dump_node_hr(db_node_t * node, FILE * fp, char *port, int err_only) { int i = (node->esp0) ? 0 : 1; int num_ports = node->num_ports; if (port) { char *end = NULL; int p = strtoul(port, &end, 0); if (port + strlen(port) == end && p >= i && p < num_ports) { i = p; num_ports = p+1; } else { fprintf(fp, "Warning: \"%s\" is not a valid port\n", port); } } for (/* set above */; i < num_ports; i++) { char lr[128]; char *last_reset = ctime_r(&node->ports[i].last_reset, lr); char leu[128]; char *last_err_update = ctime_r(&node->ports[i].err_total.time, leu); char ldu[128]; char *last_data_update = ctime_r(&node->ports[i].dc_total.time, ldu); if (!node->ports[i].valid) continue; last_reset[strlen(last_reset) - 1] = '\0'; /* remove \n */ last_err_update[strlen(last_err_update) - 1] = '\0'; /* remove \n */ last_data_update[strlen(last_data_update) - 1] = '\0'; /* remove \n */ perfmgr_db_err_reading_t *err = &node->ports[i].err_total; if (err_only && err->symbol_err_cnt == 0 && err->link_err_recover == 0 && err->link_downed == 0 && err->rcv_err == 0 && err->rcv_rem_phys_err == 0 && err->rcv_switch_relay_err == 0 && err->xmit_discards == 0 && err->xmit_constraint_err == 0 && err->rcv_constraint_err == 0 && err->link_integrity == 0 && err->buffer_overrun == 0 && err->vl15_dropped == 0 && err->xmit_wait == 0) continue; fprintf(fp, "\"%s\" 0x%" PRIx64 " active %s port %d\n" " Last Reset : %s\n" " Last Error Update : %s\n", node->node_name, node->node_guid, node->active ? "TRUE":"FALSE", i, last_reset, last_err_update); if (!err_only || err->symbol_err_cnt != 0) fprintf(fp, " symbol_err_cnt : %" PRIu64 "\n", err->symbol_err_cnt); if (!err_only || err->link_err_recover != 0) fprintf(fp, " link_err_recover : %" PRIu64 "\n", err->link_err_recover); if (!err_only || err->link_downed != 0) fprintf(fp, " link_downed : %" PRIu64 "\n", err->link_downed); if (!err_only || err->rcv_err != 0) fprintf(fp, " rcv_err : %" PRIu64 "\n", err->rcv_err); if (!err_only || err->rcv_rem_phys_err != 0) fprintf(fp, " rcv_rem_phys_err : %" PRIu64 "\n", err->rcv_rem_phys_err); if (!err_only || err->rcv_switch_relay_err != 0) fprintf(fp, " rcv_switch_relay_err : %" PRIu64 "\n", err->rcv_switch_relay_err); if (!err_only || err->xmit_discards != 0) fprintf(fp, " xmit_discards : %" PRIu64 "\n", err->xmit_discards); if (!err_only || err->xmit_constraint_err != 0) fprintf(fp, " xmit_constraint_err : %" PRIu64 "\n", err->xmit_constraint_err); if (!err_only || err->rcv_constraint_err != 0) fprintf(fp, " rcv_constraint_err : %" PRIu64 "\n", err->rcv_constraint_err); if (!err_only || err->link_integrity != 0) fprintf(fp, " link_integrity_err : %" PRIu64 "\n", err->link_integrity); if (!err_only || err->buffer_overrun != 0) fprintf(fp, " buf_overrun_err : %" PRIu64 "\n", err->buffer_overrun); if (!err_only || err->vl15_dropped != 0) fprintf(fp, " vl15_dropped : %" PRIu64 "\n", err->vl15_dropped); if (!err_only || err->xmit_wait != 0) fprintf(fp, " xmit_wait : %" PRIu64 "\n", err->xmit_wait); if (err_only) continue; fprintf(fp, " Last Data Update : %s\n", last_data_update); fprintf(fp, " xmit_data : %" PRIu64, node->ports[i].dc_total.xmit_data); dump_hr_dc(fp, node->ports[i].dc_total.xmit_data, 1); fprintf(fp, " rcv_data : %" PRIu64, node->ports[i].dc_total.rcv_data); dump_hr_dc(fp, node->ports[i].dc_total.rcv_data, 1); fprintf(fp, " xmit_pkts : %" PRIu64, node->ports[i].dc_total.xmit_pkts); dump_hr_dc(fp, node->ports[i].dc_total.xmit_pkts, 0); fprintf(fp, " rcv_pkts : %" PRIu64, node->ports[i].dc_total.rcv_pkts); dump_hr_dc(fp, node->ports[i].dc_total.rcv_pkts, 0); fprintf(fp, " unicast_xmit_pkts : %" PRIu64, node->ports[i].dc_total.unicast_xmit_pkts); dump_hr_dc(fp, node->ports[i].dc_total.unicast_xmit_pkts, 0); fprintf(fp, " unicast_rcv_pkts : %" PRIu64, node->ports[i].dc_total.unicast_rcv_pkts); dump_hr_dc(fp, node->ports[i].dc_total.unicast_rcv_pkts, 0); fprintf(fp, " multicast_xmit_pkts : %" PRIu64, node->ports[i].dc_total.multicast_xmit_pkts); dump_hr_dc(fp, node->ports[i].dc_total.multicast_xmit_pkts, 0); fprintf(fp, " multicast_rcv_pkts : %" PRIu64, node->ports[i].dc_total.multicast_rcv_pkts); dump_hr_dc(fp, node->ports[i].dc_total.multicast_rcv_pkts, 0); } } /* Define a context for the __db_dump callback */ typedef struct { FILE *fp; perfmgr_db_dump_t dump_type; } dump_context_t; static void db_dump(cl_map_item_t * const p_map_item, void *context) { db_node_t *node = (db_node_t *) p_map_item; dump_context_t *c = (dump_context_t *) context; FILE *fp = c->fp; switch (c->dump_type) { case PERFMGR_EVENT_DB_DUMP_MR: dump_node_mr(node, fp); break; case PERFMGR_EVENT_DB_DUMP_HR: default: dump_node_hr(node, fp, NULL, 0); break; } } /********************************************************************** * print all node data to fp **********************************************************************/ void perfmgr_db_print_all(perfmgr_db_t * db, FILE *fp, int err_only) { cl_map_item_t *item; db_node_t *node; cl_plock_acquire(&db->lock); item = cl_qmap_head(&db->pc_data); while (item != cl_qmap_end(&db->pc_data)) { node = (db_node_t *)item; dump_node_hr(node, fp, NULL, err_only); item = cl_qmap_next(item); } cl_plock_release(&db->lock); } /********************************************************************** * print node data to fp **********************************************************************/ void perfmgr_db_print_by_name(perfmgr_db_t * db, char *nodename, FILE *fp, char *port, int err_only) { cl_map_item_t *item; db_node_t *node; cl_plock_acquire(&db->lock); /* find the node */ item = cl_qmap_head(&db->pc_data); while (item != cl_qmap_end(&db->pc_data)) { node = (db_node_t *)item; if (strcmp(node->node_name, nodename) == 0) { dump_node_hr(node, fp, port, err_only); goto done; } item = cl_qmap_next(item); } fprintf(fp, "Node %s not found...\n", nodename); done: cl_plock_release(&db->lock); } /********************************************************************** * print node data to fp **********************************************************************/ void perfmgr_db_print_by_guid(perfmgr_db_t * db, uint64_t nodeguid, FILE *fp, char *port, int err_only) { cl_map_item_t *node; cl_plock_acquire(&db->lock); node = cl_qmap_get(&db->pc_data, nodeguid); if (node != cl_qmap_end(&db->pc_data)) dump_node_hr((db_node_t *)node, fp, port, err_only); else fprintf(fp, "Node 0x%" PRIx64 " not found...\n", nodeguid); cl_plock_release(&db->lock); } /********************************************************************** * dump the data to the file "file" **********************************************************************/ perfmgr_db_err_t perfmgr_db_dump(perfmgr_db_t * db, char *file, perfmgr_db_dump_t dump_type) { dump_context_t context; context.fp = fopen(file, "w+"); if (!context.fp) return PERFMGR_EVENT_DB_FAIL; context.dump_type = dump_type; cl_plock_acquire(&db->lock); cl_qmap_apply_func(&db->pc_data, db_dump, (void *)&context); cl_plock_release(&db->lock); fclose(context.fp); return PERFMGR_EVENT_DB_SUCCESS; } /********************************************************************** * Fill in the various DB objects from their wire counter parts **********************************************************************/ void perfmgr_db_fill_err_read(ib_port_counters_t * wire_read, perfmgr_db_err_reading_t * reading, boolean_t xmit_wait_sup) { reading->symbol_err_cnt = cl_ntoh16(wire_read->symbol_err_cnt); reading->link_err_recover = wire_read->link_err_recover; reading->link_downed = wire_read->link_downed; reading->rcv_err = cl_ntoh16(wire_read->rcv_err); reading->rcv_rem_phys_err = cl_ntoh16(wire_read->rcv_rem_phys_err); reading->rcv_switch_relay_err = cl_ntoh16(wire_read->rcv_switch_relay_err); reading->xmit_discards = cl_ntoh16(wire_read->xmit_discards); reading->xmit_constraint_err = wire_read->xmit_constraint_err; reading->rcv_constraint_err = wire_read->rcv_constraint_err; reading->link_integrity = PC_LINK_INT(wire_read->link_int_buffer_overrun); reading->buffer_overrun = PC_BUF_OVERRUN(wire_read->link_int_buffer_overrun); reading->vl15_dropped = cl_ntoh16(wire_read->vl15_dropped); if (xmit_wait_sup) reading->xmit_wait = cl_ntoh32(wire_read->xmit_wait); else reading->xmit_wait = 0; reading->time = time(NULL); } void perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read, perfmgr_db_data_cnt_reading_t * reading) { reading->xmit_data = cl_ntoh32(wire_read->xmit_data); reading->rcv_data = cl_ntoh32(wire_read->rcv_data); reading->xmit_pkts = cl_ntoh32(wire_read->xmit_pkts); reading->rcv_pkts = cl_ntoh32(wire_read->rcv_pkts); reading->unicast_xmit_pkts = 0; reading->unicast_rcv_pkts = 0; reading->multicast_xmit_pkts = 0; reading->multicast_rcv_pkts = 0; reading->time = time(NULL); } void perfmgr_db_fill_data_cnt_read_pce(ib_port_counters_ext_t * wire_read, perfmgr_db_data_cnt_reading_t * reading, int ietf_sup) { reading->xmit_data = cl_ntoh64(wire_read->xmit_data); reading->rcv_data = cl_ntoh64(wire_read->rcv_data); reading->xmit_pkts = cl_ntoh64(wire_read->xmit_pkts); reading->rcv_pkts = cl_ntoh64(wire_read->rcv_pkts); if (ietf_sup) { reading->unicast_xmit_pkts = cl_ntoh64(wire_read->unicast_xmit_pkts); reading->unicast_rcv_pkts = cl_ntoh64(wire_read->unicast_rcv_pkts); reading->multicast_xmit_pkts = cl_ntoh64(wire_read->multicast_xmit_pkts); reading->multicast_rcv_pkts = cl_ntoh64(wire_read->multicast_rcv_pkts); } reading->time = time(NULL); } #endif /* ENABLE_OSM_PERF_MGR */ opensm-3.3.20/opensm/osm_event_plugin.c0000644000205000001450000001026112104655724015040 00000000000000/* * Copyright (c) 2008-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 The Regents of the University of California. * * 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. * */ /****h* OpenSM Event plugin interface * DESCRIPTION * Database interface to record subnet events * * Implementations of this object _MUST_ be thread safe. * * AUTHOR * Ira Weiny, LLNL * *********/ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #define FILE_ID OSM_FILE_EVENT_PLUGIN_C #include #include #if defined(PATH_MAX) #define OSM_PATH_MAX (PATH_MAX + 1) #elif defined (_POSIX_PATH_MAX) #define OSM_PATH_MAX (_POSIX_PATH_MAX + 1) #else #define OSM_PATH_MAX 256 #endif /** * functions */ osm_epi_plugin_t *osm_epi_construct(osm_opensm_t *osm, char *plugin_name) { char lib_name[OSM_PATH_MAX]; struct old_if { unsigned ver; } *old_impl; osm_epi_plugin_t *rc = NULL; if (!plugin_name || !*plugin_name) return NULL; /* find the plugin */ snprintf(lib_name, sizeof(lib_name), "lib%s.so", plugin_name); rc = malloc(sizeof(*rc)); if (!rc) return NULL; rc->handle = dlopen(lib_name, RTLD_LAZY); if (!rc->handle) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "Failed to open event plugin \"%s\" : \"%s\"\n", lib_name, dlerror()); goto DLOPENFAIL; } rc->impl = (osm_event_plugin_t *) dlsym(rc->handle, OSM_EVENT_PLUGIN_IMPL_NAME); if (!rc->impl) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "Failed to find \"%s\" symbol in \"%s\" : \"%s\"\n", OSM_EVENT_PLUGIN_IMPL_NAME, lib_name, dlerror()); goto Exit; } /* check for old interface */ old_impl = (struct old_if *) rc->impl; if (old_impl->ver == OSM_ORIG_EVENT_PLUGIN_INTERFACE_VER) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "Error loading plugin: " "\'%s\' contains a depricated interface version %d\n" " Please recompile with the new interface.\n", plugin_name, old_impl->ver); goto Exit; } /* Check the version to make sure this module will work with us */ if (strcmp(rc->impl->osm_version, osm->osm_version)) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "Error loading plugin" " \'%s\': OpenSM version mismatch - plugin was built" " against %s version of OpenSM. Skip loading.\n", plugin_name, rc->impl->osm_version); goto Exit; } if (!rc->impl->create) { OSM_LOG(&osm->log, OSM_LOG_ERROR, "Error loading plugin \'%s\': no create() method.\n", plugin_name); goto Exit; } rc->plugin_data = rc->impl->create(osm); if (!rc->plugin_data) goto Exit; rc->plugin_name = strdup(plugin_name); return rc; Exit: dlclose(rc->handle); DLOPENFAIL: free(rc); return NULL; } void osm_epi_destroy(osm_epi_plugin_t * plugin) { if (plugin) { if (plugin->impl->delete) plugin->impl->delete(plugin->plugin_data); dlclose(plugin->handle); free(plugin->plugin_name); free(plugin); } } opensm-3.3.20/opensm/osm_dump.c0000644000205000001450000005274012600531614013306 00000000000000/* * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2015 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: * Various OpenSM dumpers */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_DUMP_C #include #include #include #include #include #include #include static void dump_ucast_path_distribution(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node; osm_node_t *p_remote_node; uint8_t i; uint8_t num_ports; uint32_t num_paths; ib_net64_t remote_guid_ho; osm_switch_t *p_sw = (osm_switch_t *) item; p_node = p_sw->p_node; num_ports = p_sw->num_ports; fprintf(file, "dump_ucast_path_distribution: Switch 0x%" PRIx64 "\n" "Port : Path Count Through Port", cl_ntoh64(osm_node_get_node_guid(p_node))); for (i = 0; i < num_ports; i++) { num_paths = osm_switch_path_count_get(p_sw, i); fprintf(file, "\n %03u : %u", i, num_paths); if (i == 0) { fprintf(file, " (switch management port)"); continue; } p_remote_node = osm_node_get_remote_node(p_node, i, NULL); if (p_remote_node == NULL) continue; remote_guid_ho = cl_ntoh64(osm_node_get_node_guid(p_remote_node)); switch (osm_node_get_type(p_remote_node)) { case IB_NODE_TYPE_SWITCH: fprintf(file, " (link to switch"); break; case IB_NODE_TYPE_ROUTER: fprintf(file, " (link to router"); break; case IB_NODE_TYPE_CA: fprintf(file, " (link to CA"); break; default: fprintf(file, " (link to unknown node type"); break; } fprintf(file, " 0x%" PRIx64 ")", remote_guid_ho); } fprintf(file, "\n"); } static void dump_ucast_routes(cl_map_item_t * item, FILE * file, void *cxt) { const osm_node_t *p_node; osm_port_t *p_port; uint8_t port_num; uint8_t num_hops; uint8_t best_hops; uint8_t best_port; uint16_t max_lid_ho; uint16_t lid_ho, base_lid; boolean_t direct_route_exists = FALSE; boolean_t dor; osm_switch_t *p_sw = (osm_switch_t *) item; osm_opensm_t *p_osm = cxt; p_node = p_sw->p_node; max_lid_ho = p_sw->max_lid_ho; fprintf(file, "dump_ucast_routes: " "Switch 0x%016" PRIx64 "\nLID : Port : Hops : Optimal\n", cl_ntoh64(osm_node_get_node_guid(p_node))); dor = (p_osm->routing_engine_used && p_osm->routing_engine_used->type == OSM_ROUTING_ENGINE_TYPE_DOR); for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++) { fprintf(file, "0x%04X : ", lid_ho); p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid_ho); if (!p_port) { fprintf(file, "UNREACHABLE\n"); continue; } port_num = osm_switch_get_port_by_lid(p_sw, lid_ho, OSM_NEW_LFT); if (port_num == OSM_NO_PATH) { /* This may occur if there are 'holes' in the existing LID assignments. Running SM with --reassign_lids will reassign and compress the LID range. The subnet should work fine either way. */ fprintf(file, "UNREACHABLE\n"); continue; } /* Switches can lie about which port routes a given lid due to a recent reconfiguration of the subnet. Therefore, ensure that the hop count is better than OSM_NO_PATH. */ if (p_port->p_node->sw) { /* Target LID is switch. Get its base lid and check hop count for this base LID only. */ base_lid = osm_node_get_base_lid(p_port->p_node, 0); base_lid = cl_ntoh16(base_lid); num_hops = osm_switch_get_hop_count(p_sw, base_lid, port_num); } else { /* Target LID is not switch (CA or router). Check if we have route to this target from current switch. */ num_hops = osm_switch_get_hop_count(p_sw, lid_ho, port_num); if (num_hops != OSM_NO_PATH) { direct_route_exists = TRUE; base_lid = lid_ho; } else { osm_physp_t *p_physp = p_port->p_physp; if (!p_physp || !p_physp->p_remote_physp || !p_physp->p_remote_physp->p_node->sw) num_hops = OSM_NO_PATH; else { base_lid = osm_node_get_base_lid(p_physp-> p_remote_physp-> p_node, 0); base_lid = cl_ntoh16(base_lid); num_hops = p_physp->p_remote_physp->p_node-> sw == p_sw ? 0 : osm_switch_get_hop_count(p_sw, base_lid, port_num); } } } if (num_hops == OSM_NO_PATH) { fprintf(file, "%03u : HOPS UNKNOWN\n", port_num); continue; } best_hops = osm_switch_get_least_hops(p_sw, base_lid); if (!p_port->p_node->sw && !direct_route_exists) { best_hops++; num_hops++; } fprintf(file, "%03u : %02u : ", port_num, num_hops); if (best_hops == num_hops) fprintf(file, "yes"); else { /* No LMC Optimization */ best_port = osm_switch_recommend_path(p_sw, p_port, lid_ho, 1, TRUE, FALSE, dor, p_osm->subn.opt.port_shifting, p_osm->subn.opt.scatter_ports, OSM_NEW_LFT); fprintf(file, "No %u hop path possible via port %u!", best_hops, best_port); } fprintf(file, "\n"); } } static void dump_mcast_routes(cl_map_item_t * item, FILE * file, void *cxt) { osm_switch_t *p_sw = (osm_switch_t *) item; osm_mcast_tbl_t *p_tbl; int16_t mlid_ho = 0; int16_t mlid_start_ho; uint8_t position = 0; int16_t block_num = 0; boolean_t first_mlid; boolean_t first_port; const osm_node_t *p_node; uint16_t i, j; uint16_t mask_entry; char sw_hdr[256]; char mlid_hdr[32]; p_node = p_sw->p_node; p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw); sprintf(sw_hdr, "\nSwitch 0x%016" PRIx64 "\nLID : Out Port(s)\n", cl_ntoh64(osm_node_get_node_guid(p_node))); first_mlid = TRUE; while (block_num <= p_tbl->max_block_in_use) { mlid_start_ho = (uint16_t) (block_num * IB_MCAST_BLOCK_SIZE); for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++) { mlid_ho = mlid_start_ho + i; position = 0; first_port = TRUE; sprintf(mlid_hdr, "0x%04X :", mlid_ho + IB_LID_MCAST_START_HO); while (position <= p_tbl->max_position) { mask_entry = cl_ntoh16((*p_tbl-> p_mask_tbl)[mlid_ho][position]); if (mask_entry == 0) { position++; continue; } for (j = 0; j < 16; j++) { if ((1 << j) & mask_entry) { if (first_mlid) { fprintf(file, "%s", sw_hdr); first_mlid = FALSE; } if (first_port) { fprintf(file, "%s", mlid_hdr); first_port = FALSE; } fprintf(file, " 0x%03X ", j + (position * 16)); } } position++; } if (first_port == FALSE) fprintf(file, "\n"); } block_num++; } } static void dump_lid_matrix(cl_map_item_t * item, FILE * file, void *cxt) { osm_switch_t *p_sw = (osm_switch_t *) item; osm_opensm_t *p_osm = cxt; osm_node_t *p_node = p_sw->p_node; unsigned max_lid = p_sw->max_lid_ho; unsigned max_port = p_sw->num_ports; uint16_t lid; uint8_t port; fprintf(file, "Switch: guid 0x%016" PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node))); for (lid = 1; lid <= max_lid; lid++) { osm_port_t *p_port; if (osm_switch_get_least_hops(p_sw, lid) == OSM_NO_PATH) continue; fprintf(file, "0x%04x:", lid); for (port = 0; port < max_port; port++) fprintf(file, " %02x", osm_switch_get_hop_count(p_sw, lid, port)); p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid); if (p_port) fprintf(file, " # portguid 0x%016" PRIx64, cl_ntoh64(osm_port_get_guid(p_port))); fprintf(file, "\n"); } } static void dump_ucast_lfts(cl_map_item_t * item, FILE * file, void *cxt) { osm_switch_t *p_sw = (osm_switch_t *) item; osm_opensm_t *p_osm = cxt; osm_node_t *p_node = p_sw->p_node; unsigned max_lid = p_sw->max_lid_ho; unsigned max_port = p_sw->num_ports; uint16_t lid; uint8_t port; fprintf(file, "Unicast lids [0-%u] of switch Lid %u guid 0x%016" PRIx64 " (\'%s\'):\n", max_lid, cl_ntoh16(osm_node_get_base_lid(p_node, 0)), cl_ntoh64(osm_node_get_node_guid(p_node)), p_node->print_desc); for (lid = 0; lid <= max_lid; lid++) { osm_port_t *p_port; port = osm_switch_get_port_by_lid(p_sw, lid, OSM_NEW_LFT); if (port >= max_port) continue; fprintf(file, "0x%04x %03u # ", lid, port); p_port = osm_get_port_by_lid_ho(&p_osm->subn, lid); if (p_port) { p_node = p_port->p_node; fprintf(file, "%s portguid 0x%016" PRIx64 ": \'%s\'", ib_get_node_type_str(osm_node_get_type(p_node)), cl_ntoh64(osm_port_get_guid(p_port)), p_node->print_desc); } else fprintf(file, "unknown node and type"); fprintf(file, "\n"); } fprintf(file, "%u lids dumped\n", max_lid); } static void dump_topology_node(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node = (osm_node_t *) item; uint32_t cPort; osm_node_t *p_nbnode; osm_physp_t *p_physp, *p_default_physp, *p_rphysp; uint8_t link_speed_act; const char *link_speed_act_str; if (!p_node->node_info.num_ports) return; for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) { uint8_t port_state; p_physp = osm_node_get_physp_ptr(p_node, cPort); if (!p_physp) continue; p_rphysp = p_physp->p_remote_physp; if (!p_rphysp) continue; CL_ASSERT(cPort == p_physp->port_num); if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) p_default_physp = osm_node_get_physp_ptr(p_node, 0); else p_default_physp = p_physp; fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64 " VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ? "SW" : p_node->node_info.node_type == IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type == IB_NODE_TYPE_ROUTER ? "Rt" : "**", p_default_physp->port_info.base_lid == p_default_physp->port_info. master_sm_base_lid ? "-SM" : "", p_node->node_info.num_ports, cl_ntoh64(p_node->node_info.sys_guid), cl_ntoh64(p_node->node_info.node_guid), cl_ntoh64(p_physp->port_guid), cl_ntoh32(ib_node_info_get_vendor_id (&p_node->node_info)), cl_ntoh16(p_node->node_info.device_id), cl_ntoh32(p_node->node_info.revision), p_node->print_desc, cl_ntoh16(p_default_physp->port_info.base_lid), cPort); p_nbnode = p_rphysp->p_node; if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH) p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0); else p_default_physp = p_rphysp; fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64 " NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64 " VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ", p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ? "SW" : p_nbnode->node_info.node_type == IB_NODE_TYPE_CA ? "CA" : p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ? "Rt" : "**", p_default_physp->port_info.base_lid == p_default_physp->port_info. master_sm_base_lid ? "-SM" : "", p_nbnode->node_info.num_ports, cl_ntoh64(p_nbnode->node_info.sys_guid), cl_ntoh64(p_nbnode->node_info.node_guid), cl_ntoh64(p_rphysp->port_guid), cl_ntoh32(ib_node_info_get_vendor_id (&p_nbnode->node_info)), cl_ntoh32(p_nbnode->node_info.device_id), cl_ntoh32(p_nbnode->node_info.revision), p_nbnode->print_desc, cl_ntoh16(p_default_physp->port_info.base_lid), p_rphysp->port_num); port_state = ib_port_info_get_port_state(&p_physp->port_info); link_speed_act = ib_port_info_get_link_speed_active(&p_physp->port_info); if (link_speed_act == IB_LINK_SPEED_ACTIVE_2_5) link_speed_act_str = "2.5"; else if (link_speed_act == IB_LINK_SPEED_ACTIVE_5) link_speed_act_str = "5"; else if (link_speed_act == IB_LINK_SPEED_ACTIVE_10) link_speed_act_str = "10"; else link_speed_act_str = "??"; if (p_physp->ext_port_info.link_speed_active & FDR10) link_speed_act_str = "FDR10"; if (p_default_physp->port_info.capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) { link_speed_act = ib_port_info_get_link_speed_ext_active(&p_physp->port_info); if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_14) link_speed_act_str = "14"; else if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_25) link_speed_act_str = "25"; else if (link_speed_act != IB_LINK_SPEED_EXT_ACTIVE_NONE) link_speed_act_str = "??"; } fprintf(file, "PHY=%s LOG=%s SPD=%s\n", p_physp->port_info.link_width_active == 1 ? "1x" : p_physp->port_info.link_width_active == 2 ? "4x" : p_physp->port_info.link_width_active == 4 ? "8x" : p_physp->port_info.link_width_active == 8 ? "12x" : "??", port_state == IB_LINK_ACTIVE ? "ACT" : port_state == IB_LINK_ARMED ? "ARM" : port_state == IB_LINK_INIT ? "INI" : "DWN", link_speed_act_str); } } static void dump_sl2vl_tbl(cl_map_item_t * item, FILE * file, void *cxt) { osm_port_t *p_port = (osm_port_t *) item; osm_node_t *p_node = p_port->p_node; uint32_t in_port, out_port, num_ports = p_node->node_info.num_ports; ib_net16_t base_lid = osm_port_get_base_lid(p_port); osm_physp_t *p_physp; ib_slvl_table_t *p_tbl; int i, n; char buf[1024]; const char * header_line = "#in out : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"; const char * separator_line = "#--------------------------------------------------------"; if (!num_ports) return; fprintf(file, "%s 0x%016" PRIx64 ", base LID %d, " "\"%s\"\n%s\n%s\n", ib_get_node_type_str(p_node->node_info.node_type), cl_ntoh64(p_port->guid), cl_ntoh16(base_lid), p_node->print_desc, header_line, separator_line); if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH) { for (out_port = 0; out_port <= num_ports; out_port++){ p_physp = osm_node_get_physp_ptr(p_node, out_port); /* no need to print SL2VL table for port that is down */ if (!p_physp || !p_physp->p_remote_physp) continue; for (in_port = 0; in_port <= num_ports; in_port++) { p_tbl = osm_physp_get_slvl_tbl(p_physp, in_port); for (i = 0, n = 0; i < 16; i++) n += sprintf(buf + n, " %-2d", ib_slvl_table_get(p_tbl, i)); fprintf(file, "%-3d %-3d :%s\n", in_port, out_port, buf); } } } else { p_physp = p_port->p_physp; p_tbl = osm_physp_get_slvl_tbl(p_physp, 0); for (i = 0, n = 0; i < 16; i++) n += sprintf(buf + n, " %-2d", ib_slvl_table_get(p_tbl, i)); fprintf(file, "%-3d %-3d :%s\n", 0, 0, buf); } fprintf(file, "%s\n\n", separator_line); } static void print_node_report(cl_map_item_t * item, FILE * file, void *cxt) { osm_node_t *p_node = (osm_node_t *) item; osm_opensm_t *osm = cxt; const osm_physp_t *p_physp, *p_remote_physp; const ib_port_info_t *p_pi; uint8_t port_num; uint32_t num_ports; uint8_t node_type; node_type = osm_node_get_type(p_node); num_ports = osm_node_get_num_physp(p_node); port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1; for (; port_num < num_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) continue; fprintf(file, "%-11s : %s : %02X :", osm_get_manufacturer_str(cl_ntoh64 (osm_node_get_node_guid (p_node))), osm_get_node_type_str_fixed_width(node_type), port_num); p_pi = &p_physp->port_info; /* * Port state is not defined for base switch port 0 */ if (port_num == 0 && ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) fprintf(file, " :"); else fprintf(file, " %s :", osm_get_port_state_str_fixed_width (ib_port_info_get_port_state(p_pi))); /* * LID values are only meaningful in select cases. */ if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0) || node_type != IB_NODE_TYPE_SWITCH)) fprintf(file, " %04X : %01X :", cl_ntoh16(p_pi->base_lid), ib_port_info_get_lmc(p_pi)); else fprintf(file, " : :"); if (port_num == 0 && ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE) fprintf(file, " : : "); else fprintf(file, " %s : %s : %s ", osm_get_mtu_str (ib_port_info_get_neighbor_mtu(p_pi)), osm_get_lwa_str(p_pi->link_width_active), osm_get_lsa_str (ib_port_info_get_link_speed_active(p_pi), ib_port_info_get_link_speed_ext_active(p_pi), ib_port_info_get_port_state(p_pi), p_physp->ext_port_info.link_speed_active & FDR10)); if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid) fprintf(file, "* %016" PRIx64 " *", cl_ntoh64(osm_physp_get_port_guid(p_physp))); else fprintf(file, ": %016" PRIx64 " :", cl_ntoh64(osm_physp_get_port_guid(p_physp))); if (port_num && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) { p_remote_physp = osm_physp_get_remote(p_physp); if (p_remote_physp) fprintf(file, " %016" PRIx64 " (%02X)", cl_ntoh64(osm_physp_get_port_guid (p_remote_physp)), osm_physp_get_port_num(p_remote_physp)); else fprintf(file, " UNKNOWN"); } fprintf(file, "\n"); } fprintf(file, "------------------------------------------------------" "------------------------------------------------\n"); } struct dump_context { osm_opensm_t *p_osm; FILE *file; void (*func) (cl_map_item_t *, FILE *, void *); void *cxt; }; static void dump_item(cl_map_item_t * item, void *cxt) { ((struct dump_context *)cxt)->func(item, ((struct dump_context *)cxt)->file, ((struct dump_context *)cxt)->cxt); } static void dump_qmap(FILE * file, cl_qmap_t * map, void (*func) (cl_map_item_t *, FILE *, void *), void *cxt) { struct dump_context dump_context; dump_context.file = file; dump_context.func = func; dump_context.cxt = cxt; cl_qmap_apply_func(map, dump_item, &dump_context); } void osm_dump_qmap_to_file(osm_opensm_t * p_osm, const char *file_name, cl_qmap_t * map, void (*func) (cl_map_item_t *, FILE *, void *), void *cxt) { char path[1024]; FILE *file; snprintf(path, sizeof(path), "%s/%s", p_osm->subn.opt.dump_files_dir, file_name); file = fopen(path, "w"); if (!file) { OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "cannot create file \'%s\': %s\n", path, strerror(errno)); return; } dump_qmap(file, map, func, cxt); fclose(file); } static void print_report(osm_opensm_t * osm, FILE * file) { fprintf(file, "\n===================================================" "====================================================\n" "Vendor : Ty : # : Sta : LID : LMC : MTU : LWA :" " LSA : Port GUID : Neighbor Port (Port #)\n"); dump_qmap(stdout, &osm->subn.node_guid_tbl, print_node_report, osm); } void osm_dump_mcast_routes(osm_opensm_t * osm) { if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_ROUTING)) /* multicast routes */ osm_dump_qmap_to_file(osm, "opensm.mcfdbs", &osm->subn.sw_guid_tbl, dump_mcast_routes, osm); } void osm_dump_all(osm_opensm_t * osm) { if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_ROUTING)) { /* unicast routes */ osm_dump_qmap_to_file(osm, "opensm-lid-matrix.dump", &osm->subn.sw_guid_tbl, dump_lid_matrix, osm); osm_dump_qmap_to_file(osm, "opensm-lfts.dump", &osm->subn.sw_guid_tbl, dump_ucast_lfts, osm); if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_DEBUG)) dump_qmap(stdout, &osm->subn.sw_guid_tbl, dump_ucast_path_distribution, osm); /* An attempt to get osm_switch_recommend_path to report the same routes that a sweep would assign. */ if (osm->subn.opt.scatter_ports) srandom(osm->subn.opt.scatter_ports); osm_dump_qmap_to_file(osm, "opensm.fdbs", &osm->subn.sw_guid_tbl, dump_ucast_routes, osm); /* multicast routes */ osm_dump_qmap_to_file(osm, "opensm.mcfdbs", &osm->subn.sw_guid_tbl, dump_mcast_routes, osm); /* SL2VL tables */ if (osm->subn.opt.qos || (osm->routing_engine_used && osm->routing_engine_used->update_sl2vl)) osm_dump_qmap_to_file(osm, "opensm-sl2vl.dump", &osm->subn.port_guid_tbl, dump_sl2vl_tbl, osm); } osm_dump_qmap_to_file(osm, "opensm-subnet.lst", &osm->subn.node_guid_tbl, dump_topology_node, osm); if (OSM_LOG_IS_ACTIVE_V2(&osm->log, OSM_LOG_VERBOSE)) print_report(osm, stdout); } opensm-3.3.20/opensm/osm_ucast_cache.c0000644000205000001450000007274512571601203014611 00000000000000/* * Copyright (c) 2008-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2008-2009 Mellanox Technologies LTD. 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 OpenSM Cached Unicast Routing * * Environment: * Linux User Mode * */ #if HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_UCAST_CACHE_C #include #include #include #include #include #include typedef struct cache_port { boolean_t is_leaf; uint16_t remote_lid_ho; } cache_port_t; typedef struct cache_switch { cl_map_item_t map_item; boolean_t dropped; uint16_t max_lid_ho; uint16_t num_hops; uint8_t **hops; uint8_t *lft; uint8_t num_ports; cache_port_t ports[0]; } cache_switch_t; static uint16_t cache_sw_get_base_lid_ho(cache_switch_t * p_sw) { return p_sw->ports[0].remote_lid_ho; } static boolean_t cache_sw_is_leaf(cache_switch_t * p_sw) { return p_sw->ports[0].is_leaf; } static void cache_sw_set_leaf(cache_switch_t * p_sw) { p_sw->ports[0].is_leaf = TRUE; } static cache_switch_t *cache_sw_new(uint16_t lid_ho, unsigned num_ports) { cache_switch_t *p_cache_sw = malloc(sizeof(cache_switch_t) + num_ports * sizeof(cache_port_t)); if (!p_cache_sw) return NULL; memset(p_cache_sw, 0, sizeof(*p_cache_sw) + num_ports * sizeof(cache_port_t)); p_cache_sw->num_ports = num_ports; /* port[0] fields represent this switch details - lid and type */ p_cache_sw->ports[0].remote_lid_ho = lid_ho; p_cache_sw->ports[0].is_leaf = FALSE; return p_cache_sw; } static void cache_sw_destroy(cache_switch_t * p_sw) { unsigned i; if (!p_sw) return; if (p_sw->lft) free(p_sw->lft); if (p_sw->hops) { for (i = 0; i < p_sw->num_hops; i++) if (p_sw->hops[i]) free(p_sw->hops[i]); free(p_sw->hops); } free(p_sw); } static cache_switch_t *cache_get_sw(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho) { cache_switch_t *p_cache_sw = (cache_switch_t *) cl_qmap_get(&p_mgr->cache_sw_tbl, lid_ho); if (p_cache_sw == (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) p_cache_sw = NULL; return p_cache_sw; } static void cache_add_sw_link(osm_ucast_mgr_t * p_mgr, osm_physp_t *p, uint16_t remote_lid_ho, boolean_t is_ca) { cache_switch_t *p_cache_sw; uint16_t lid_ho = cl_ntoh16(osm_node_get_base_lid(p->p_node, 0)); OSM_LOG_ENTER(p_mgr->p_log); if (!lid_ho || !remote_lid_ho || !p->port_num) goto Exit; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Caching switch port: lid %u [port %u] -> lid %u (%s)\n", lid_ho, p->port_num, remote_lid_ho, (is_ca) ? "CA/RTR" : "SW"); p_cache_sw = cache_get_sw(p_mgr, lid_ho); if (!p_cache_sw) { p_cache_sw = cache_sw_new(lid_ho, p->p_node->sw->num_ports); if (!p_cache_sw) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD01: Out of memory - cache is invalid\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } cl_qmap_insert(&p_mgr->cache_sw_tbl, lid_ho, &p_cache_sw->map_item); } if (p->port_num >= p_cache_sw->num_ports) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD02: Wrong switch? - cache is invalid\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (is_ca) cache_sw_set_leaf(p_cache_sw); if (p_cache_sw->ports[p->port_num].remote_lid_ho == 0) { /* cache this link only if it hasn't been already cached */ p_cache_sw->ports[p->port_num].remote_lid_ho = remote_lid_ho; p_cache_sw->ports[p->port_num].is_leaf = is_ca; } Exit: OSM_LOG_EXIT(p_mgr->p_log); } static void cache_cleanup_switches(osm_ucast_mgr_t * p_mgr) { cache_switch_t *p_sw; cache_switch_t *p_next_sw; unsigned port_num; boolean_t found_port; if (!p_mgr->cache_valid) return; p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl); while (p_next_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) { p_sw = p_next_sw; p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item); found_port = FALSE; for (port_num = 1; port_num < p_sw->num_ports; port_num++) if (p_sw->ports[port_num].remote_lid_ho) found_port = TRUE; if (!found_port) { cl_qmap_remove_item(&p_mgr->cache_sw_tbl, &p_sw->map_item); cache_sw_destroy(p_sw); } } } static void cache_check_link_change(osm_ucast_mgr_t * p_mgr, osm_physp_t * p_physp_1, osm_physp_t * p_physp_2) { OSM_LOG_ENTER(p_mgr->p_log); CL_ASSERT(p_physp_1 && p_physp_2); if (!p_mgr->cache_valid) goto Exit; if (!p_physp_1->p_remote_physp && !p_physp_2->p_remote_physp) /* both ports were down - new link */ goto Exit; /* unicast cache cannot tolerate any link location change */ if ((p_physp_1->p_remote_physp && p_physp_1->p_remote_physp->p_remote_physp) || (p_physp_2->p_remote_physp && p_physp_2->p_remote_physp->p_remote_physp)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Link location change discovered\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } Exit: OSM_LOG_EXIT(p_mgr->p_log); } static void cache_remove_port(osm_ucast_mgr_t * p_mgr, uint16_t lid_ho, uint8_t port_num, uint16_t remote_lid_ho, boolean_t is_ca) { cache_switch_t *p_cache_sw; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; p_cache_sw = cache_get_sw(p_mgr, lid_ho); if (!p_cache_sw) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Found uncached switch/link (lid %u, port %u)\n", lid_ho, port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (port_num >= p_cache_sw->num_ports || !p_cache_sw->ports[port_num].remote_lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Found uncached switch link (lid %u, port %u)\n", lid_ho, port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (p_cache_sw->ports[port_num].remote_lid_ho != remote_lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote lid change on switch lid %u, port %u " "(was %u, now %u)\n", lid_ho, port_num, p_cache_sw->ports[port_num].remote_lid_ho, remote_lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if ((p_cache_sw->ports[port_num].is_leaf && !is_ca) || (!p_cache_sw->ports[port_num].is_leaf && is_ca)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote node type change on switch lid %u, port %u\n", lid_ho, port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New link from lid %u, port %u to lid %u - " "found in cache\n", lid_ho, port_num, remote_lid_ho); /* the new link was cached - clean it from the cache */ p_cache_sw->ports[port_num].remote_lid_ho = 0; p_cache_sw->ports[port_num].is_leaf = FALSE; Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* cache_remove_port() */ static void cache_restore_ucast_info(osm_ucast_mgr_t * p_mgr, cache_switch_t * p_cache_sw, osm_switch_t * p_sw) { if (!p_mgr->cache_valid) return; /* when seting unicast info, the cached port should have all the required info */ CL_ASSERT(p_cache_sw->max_lid_ho && p_cache_sw->lft && p_cache_sw->num_hops && p_cache_sw->hops); p_sw->max_lid_ho = p_cache_sw->max_lid_ho; if (p_sw->new_lft) free(p_sw->new_lft); p_sw->new_lft = p_cache_sw->lft; p_cache_sw->lft = NULL; p_sw->num_hops = p_cache_sw->num_hops; p_cache_sw->num_hops = 0; if (p_sw->hops) free(p_sw->hops); p_sw->hops = p_cache_sw->hops; p_cache_sw->hops = NULL; p_sw->need_update = 2; } static void ucast_cache_dump(osm_ucast_mgr_t * p_mgr) { cache_switch_t *p_sw; unsigned i; OSM_LOG_ENTER(p_mgr->p_log); if (!OSM_LOG_IS_ACTIVE_V2(p_mgr->p_log, OSM_LOG_DEBUG)) goto Exit; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dumping missing nodes/links as logged by unicast cache:\n"); for (p_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl); p_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl); p_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "\t Switch lid %u %s%s\n", cache_sw_get_base_lid_ho(p_sw), (cache_sw_is_leaf(p_sw)) ? "[leaf switch] " : "", (p_sw->dropped) ? "[whole switch missing]" : ""); for (i = 1; i < p_sw->num_ports; i++) if (p_sw->ports[i].remote_lid_ho > 0) OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "\t - port %u -> lid %u %s\n", i, p_sw->ports[i].remote_lid_ho, (p_sw->ports[i].is_leaf) ? "[remote node is leaf]" : ""); } Exit: OSM_LOG_EXIT(p_mgr->p_log); } void osm_ucast_cache_invalidate(osm_ucast_mgr_t * p_mgr) { cache_switch_t *p_sw; cache_switch_t *p_next_sw; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; p_mgr->cache_valid = FALSE; p_next_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl); while (p_next_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl)) { p_sw = p_next_sw; p_next_sw = (cache_switch_t *) cl_qmap_next(&p_sw->map_item); cache_sw_destroy(p_sw); } cl_qmap_remove_all(&p_mgr->cache_sw_tbl); OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Unicast Cache invalidated\n"); Exit: OSM_LOG_EXIT(p_mgr->p_log); } static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr) { cache_switch_t *p_cache_sw; cache_switch_t *p_remote_cache_sw; unsigned port_num; unsigned max_ports; uint8_t remote_node_type; uint16_t lid_ho; uint16_t remote_lid_ho; osm_switch_t *p_sw; osm_switch_t *p_remote_sw; osm_node_t *p_node; osm_physp_t *p_physp; osm_physp_t *p_remote_physp; osm_port_t *p_remote_port; cl_qmap_t *p_sw_tbl; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; /* If there are no switches in the subnet, we are done */ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl; if (cl_qmap_count(p_sw_tbl) == 0) { osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * Scan all the physical switch ports in the subnet. * If the port need_update flag is on, check whether * it's just some node/port reset or a cached topology * change. Otherwise the cache is invalid. */ for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl); p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl); p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) { p_node = p_sw->p_node; lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0)); p_cache_sw = cache_get_sw(p_mgr, lid_ho); max_ports = osm_node_get_num_physp(p_node); /* skip port 0 */ for (port_num = 1; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !p_physp->p_remote_physp || !osm_physp_link_exists(p_physp, p_physp->p_remote_physp)) /* no valid link */ continue; /* * While scanning all the physical ports in the subnet, * mark corresponding leaf switches in the cache. */ if (p_cache_sw && !p_cache_sw->dropped && !cache_sw_is_leaf(p_cache_sw) && p_physp->p_remote_physp->p_node && osm_node_get_type(p_physp->p_remote_physp-> p_node) != IB_NODE_TYPE_SWITCH) cache_sw_set_leaf(p_cache_sw); if (!p_physp->need_update) continue; OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Checking switch lid %u, port %u\n", lid_ho, port_num); p_remote_physp = osm_physp_get_remote(p_physp); remote_node_type = osm_node_get_type(p_remote_physp->p_node); if (remote_node_type == IB_NODE_TYPE_SWITCH) remote_lid_ho = cl_ntoh16(osm_node_get_base_lid (p_remote_physp->p_node, 0)); else remote_lid_ho = cl_ntoh16(osm_node_get_base_lid (p_remote_physp->p_node, osm_physp_get_port_num (p_remote_physp))); if (!p_cache_sw || port_num >= p_cache_sw->num_ports || !p_cache_sw->ports[port_num].remote_lid_ho) { /* * There is some uncached change on the port. * In general, the reasons might be as follows: * - switch reset * - port reset (or port down/up) * - quick connection location change * - new link (or new switch) * * First two reasons allow cache usage, while * the last two reasons should invalidate cache. * * In case of quick connection location change, * cache would have been invalidated by * osm_ucast_cache_check_new_link() function. * * In case of new link between two known nodes, * cache also would have been invalidated by * osm_ucast_cache_check_new_link() function. * * Another reason is cached link between two * known switches went back. In this case the * osm_ucast_cache_check_new_link() function would * clear both sides of the link from the cache * during the discovery process, so effectively * this would be equivalent to port reset. * * So three possible reasons remain: * - switch reset * - port reset (or port down/up) * - link of a new switch * * To validate cache, we need to check only the * third reason - link of a new node/switch: * - If this is the local switch that is new, * then it should have (p_sw->need_update == 2). * - If the remote node is switch and it's new, * then it also should have * (p_sw->need_update == 2). * - If the remote node is CA/RTR and it's new, * then its port should have is_new flag on. */ if (p_sw->need_update == 2) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New switch found (lid %u)\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (remote_node_type == IB_NODE_TYPE_SWITCH) { p_remote_sw = p_remote_physp->p_node->sw; if (p_remote_sw->need_update == 2) { /* this could also be case of switch coming back with an additional link that it didn't have before */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New switch/link found (lid %u)\n", remote_lid_ho); osm_ucast_cache_invalidate (p_mgr); goto Exit; } } else { /* * Remote node is CA/RTR. * Get p_port of the remote node and * check its p_port->is_new flag. */ p_remote_port = osm_get_port_by_guid(p_mgr->p_subn, osm_physp_get_port_guid (p_remote_physp)); if (!p_remote_port) { OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD04: No port was found for " "port GUID 0x%" PRIx64 "\n", cl_ntoh64(osm_physp_get_port_guid (p_remote_physp))); osm_ucast_cache_invalidate (p_mgr); goto Exit; } if (p_remote_port->is_new) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "New CA/RTR found (lid %u)\n", remote_lid_ho); osm_ucast_cache_invalidate (p_mgr); goto Exit; } } } else { /* * The change on the port is cached. * In general, the reasons might be as follows: * - link between two known nodes went back * - one or more nodes went back, causing all * the links to reappear * * If it was link that went back, then this case * would have been taken care of during the * discovery by osm_ucast_cache_check_new_link(), * so it's some node that went back. */ if ((p_cache_sw->ports[port_num].is_leaf && remote_node_type == IB_NODE_TYPE_SWITCH) || (!p_cache_sw->ports[port_num].is_leaf && remote_node_type != IB_NODE_TYPE_SWITCH)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote node type change on switch lid %u, port %u\n", lid_ho, port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (p_cache_sw->ports[port_num].remote_lid_ho != remote_lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Remote lid change on switch lid %u, port %u" "(was %u, now %u)\n", lid_ho, port_num, p_cache_sw->ports[port_num]. remote_lid_ho, remote_lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * We don't care who is the node that has * reappeared in the subnet (local or remote). * What's important that the cached link matches * the real fabrics link. * Just clean it from cache. */ p_cache_sw->ports[port_num].remote_lid_ho = 0; p_cache_sw->ports[port_num].is_leaf = FALSE; if (p_cache_sw->dropped) { cache_restore_ucast_info(p_mgr, p_cache_sw, p_sw); p_cache_sw->dropped = FALSE; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Restored link from cache: lid %u, port %u to lid %u\n", lid_ho, port_num, remote_lid_ho); } } } /* Remove all the cached switches that have all their ports restored */ cache_cleanup_switches(p_mgr); /* * Done scanning all the physical switch ports in the subnet. * Now we need to check the other side: * Scan all the cached switches and their ports: * - If the cached switch is missing in the subnet * (dropped flag is on), check that it's a leaf switch. * If it's not a leaf, the cache is invalid, because * cache can tolerate only leaf switch removal. * - If the cached switch exists in fabric, check all * its cached ports. These cached ports represent * missing link in the fabric. * The missing links that can be tolerated are: * + link to missing CA/RTR * + link to missing leaf switch */ for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl); p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl); p_cache_sw = (cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) { if (p_cache_sw->dropped) { if (!cache_sw_is_leaf(p_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Missing non-leaf switch (lid %u)\n", cache_sw_get_base_lid_ho(p_cache_sw)); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Missing leaf switch (lid %u) - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw)); continue; } for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) { if (!p_cache_sw->ports[port_num].remote_lid_ho) continue; if (p_cache_sw->ports[port_num].is_leaf) { CL_ASSERT(cache_sw_is_leaf(p_cache_sw)); OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to CA/RTR - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); continue; } p_remote_cache_sw = cache_get_sw(p_mgr, p_cache_sw-> ports[port_num]. remote_lid_ho); if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to existing switch\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if (!cache_sw_is_leaf(p_remote_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing link to non-leaf switch\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* * At this point we know that the missing link is to * a leaf switch. However, one case deserves a special * treatment. If there was a link between two leaf * switches, then missing leaf switch might break * routing. It is possible that there are routes * that use leaf switches to get from switch to switch * and not just to get to the CAs behind the leaf switch. */ if (cache_sw_is_leaf(p_cache_sw) && cache_sw_is_leaf(p_remote_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing leaf-2-leaf link\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Switch lid %u, port %u: missing remote leaf switch - " "continuing validation\n", cache_sw_get_base_lid_ho(p_cache_sw), port_num); } } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n"); ucast_cache_dump(p_mgr); Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_validate() */ void osm_ucast_cache_check_new_link(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node_1, uint8_t port_num_1, osm_node_t * p_node_2, uint8_t port_num_2) { uint16_t lid_ho_1; uint16_t lid_ho_2; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; cache_check_link_change(p_mgr, osm_node_get_physp_ptr(p_node_1, port_num_1), osm_node_get_physp_ptr(p_node_2, port_num_2)); if (!p_mgr->cache_valid) goto Exit; if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH && osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Found CA-2-CA link\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* for code simplicity, we want the first node to be switch */ if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) { osm_node_t *tmp_node = p_node_1; uint8_t tmp_port_num = port_num_1; p_node_1 = p_node_2; port_num_1 = port_num_2; p_node_2 = tmp_node; port_num_2 = tmp_port_num; } lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0)); if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0)); else lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, port_num_2)); if (!lid_ho_1 || !lid_ho_2) { /* * No lid assigned, which means that one of the nodes is new. * Need to wait for lid manager to process this node. * The switches and their links will be checked later when * the whole cache validity will be verified. */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Link port %u <-> %u reveals new node - cache will " "be validated later\n", port_num_1, port_num_2); goto Exit; } cache_remove_port(p_mgr, lid_ho_1, port_num_1, lid_ho_2, (osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH)); /* if node_2 is a switch, the link should be cleaned from its cache */ if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) cache_remove_port(p_mgr, lid_ho_2, port_num_2, lid_ho_1, FALSE); Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_check_new_link() */ void osm_ucast_cache_add_link(osm_ucast_mgr_t * p_mgr, osm_physp_t * p_physp1, osm_physp_t * p_physp2) { osm_node_t *p_node_1 = p_physp1->p_node, *p_node_2 = p_physp2->p_node; uint16_t lid_ho_1, lid_ho_2; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH && osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropping CA-2-CA link\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } if ((osm_node_get_type(p_node_1) == IB_NODE_TYPE_SWITCH && !osm_node_get_physp_ptr(p_node_1, 0)) || (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH && !osm_node_get_physp_ptr(p_node_2, 0))) { /* we're caching a link when one of the nodes has already been dropped and cached */ OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Port %u <-> port %u: port0 on one of the nodes " "has already been dropped and cached\n", p_physp1->port_num, p_physp2->port_num); goto Exit; } /* One of the nodes is switch. Just for code simplicity, make sure that it's the first node. */ if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) { osm_physp_t *tmp = p_physp1; p_physp1 = p_physp2; p_physp2 = tmp; p_node_1 = p_physp1->p_node; p_node_2 = p_physp2->p_node; } if (!p_node_1->sw) { /* something is wrong - we'd better not use cache */ osm_ucast_cache_invalidate(p_mgr); goto Exit; } lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0)); if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) { if (!p_node_2->sw) { /* something is wrong - we'd better not use cache */ osm_ucast_cache_invalidate(p_mgr); goto Exit; } lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0)); /* lost switch-2-switch link - cache both sides */ cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, FALSE); cache_add_sw_link(p_mgr, p_physp2, lid_ho_1, FALSE); } else { lid_ho_2 = cl_ntoh16(osm_physp_get_base_lid(p_physp2)); /* lost link to CA/RTR - cache only switch side */ cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, TRUE); } Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_add_link() */ void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node) { uint16_t lid_ho; uint8_t max_ports; uint8_t port_num; osm_physp_t *p_physp; cache_switch_t *p_cache_sw; OSM_LOG_ENTER(p_mgr->p_log); if (!p_mgr->cache_valid) goto Exit; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0)); if (!lid_ho) { OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE, "Skip caching. Switch dropped before " "it gets a valid lid.\n"); osm_ucast_cache_invalidate(p_mgr); goto Exit; } OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Caching dropped switch lid %u\n", lid_ho); if (!p_node->sw) { /* something is wrong - forget about cache */ OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR AD03: no switch info for node lid %u - " "clearing cache\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* unlink (add to cache) all the ports of this switch */ max_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !p_physp->p_remote_physp) continue; osm_ucast_cache_add_link(p_mgr, p_physp, p_physp->p_remote_physp); } /* * All the ports have been dropped (cached). * If one of the ports was connected to CA/RTR, * then the cached switch would be marked as leaf. * If it isn't, then the dropped switch isn't a leaf, * and cache can't handle it. */ p_cache_sw = cache_get_sw(p_mgr, lid_ho); /* p_cache_sw could be NULL if it has no remote phys ports */ if (!p_cache_sw || !cache_sw_is_leaf(p_cache_sw)) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropped non-leaf switch (lid %u)\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } p_cache_sw->dropped = TRUE; if (!p_node->sw->num_hops || !p_node->sw->hops) { OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "No LID matrices for switch lid %u\n", lid_ho); osm_ucast_cache_invalidate(p_mgr); goto Exit; } /* lid matrices */ p_cache_sw->num_hops = p_node->sw->num_hops; p_node->sw->num_hops = 0; p_cache_sw->hops = p_node->sw->hops; p_node->sw->hops = NULL; /* linear forwarding table */ if (p_node->sw->new_lft) { /* LFT buffer exists - we use it, because it is more updated than the switch's LFT */ p_cache_sw->lft = p_node->sw->new_lft; p_node->sw->new_lft = NULL; } else { /* no LFT buffer, so we use the switch's LFT */ p_cache_sw->lft = p_node->sw->lft; p_node->sw->lft = NULL; p_node->sw->lft_size = 0; } p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho; } else { /* dropping CA/RTR: add to cache all the ports of this node */ max_ports = osm_node_get_num_physp(p_node); for (port_num = 1; port_num < max_ports; port_num++) { p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp || !p_physp->p_remote_physp) continue; CL_ASSERT(osm_node_get_type (p_physp->p_remote_physp->p_node) == IB_NODE_TYPE_SWITCH); osm_ucast_cache_add_link(p_mgr, p_physp->p_remote_physp, p_physp); } } Exit: OSM_LOG_EXIT(p_mgr->p_log); } /* osm_ucast_cache_add_node() */ int osm_ucast_cache_process(osm_ucast_mgr_t * p_mgr) { cl_qmap_t *tbl = &p_mgr->p_subn->sw_guid_tbl; cl_map_item_t *item; osm_switch_t *p_sw; uint16_t lft_size; if (!p_mgr->p_subn->opt.use_ucast_cache) return 1; ucast_cache_validate(p_mgr); if (!p_mgr->cache_valid) return 1; OSM_LOG(p_mgr->p_log, OSM_LOG_INFO, "Configuring switch tables using cached routing\n"); for (item = cl_qmap_head(tbl); item != cl_qmap_end(tbl); item = cl_qmap_next(item)) { p_sw = (osm_switch_t *) item; CL_ASSERT(p_sw->new_lft); if (!p_sw->lft) { lft_size = (p_sw->max_lid_ho / IB_SMP_DATA_SIZE + 1) * IB_SMP_DATA_SIZE; p_sw->lft = malloc(lft_size); if (!p_sw->lft) return IB_INSUFFICIENT_MEMORY; p_sw->lft_size = lft_size; memset(p_sw->lft, OSM_NO_PATH, p_sw->lft_size); } } osm_ucast_mgr_set_fwd_tables(p_mgr); return 0; } opensm-3.3.20/opensm/osm_qos_parser_y.y0000644000205000001450000035665412314013127015104 00000000000000%{ /* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 HNR Consulting. 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: * Grammar of OSM QoS parser. * * Environment: * Linux User Mode * * Author: * Yevgeny Kliteynik, Mellanox */ #include #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_QOS_PARSER_Y_Y #include #include #define OSM_QOS_POLICY_MAX_LINE_LEN 1024*10 #define OSM_QOS_POLICY_SL2VL_TABLE_LEN IB_MAX_NUM_VLS #define OSM_QOS_POLICY_MAX_VL_NUM IB_MAX_NUM_VLS #define OSM_QOS_POLICY_MAX_RATE IB_MAX_RATE #define OSM_QOS_POLICY_MIN_RATE IB_MIN_RATE #define OSM_QOS_POLICY_MAX_MTU IB_MAX_MTU #define OSM_QOS_POLICY_MIN_MTU IB_MIN_MTU typedef struct tmp_parser_struct_t_ { char str[OSM_QOS_POLICY_MAX_LINE_LEN]; uint64_t num_pair[2]; cl_list_t str_list; cl_list_t num_list; cl_list_t num_pair_list; } tmp_parser_struct_t; static void __parser_tmp_struct_init(); static void __parser_tmp_struct_reset(); static void __parser_tmp_struct_destroy(); static char * __parser_strip_white(char * str); static void __parser_str2uint64(uint64_t * p_val, char * str); static void __parser_port_group_start(); static int __parser_port_group_end(); static void __parser_sl2vl_scope_start(); static int __parser_sl2vl_scope_end(); static void __parser_vlarb_scope_start(); static int __parser_vlarb_scope_end(); static void __parser_qos_level_start(); static int __parser_qos_level_end(); static void __parser_match_rule_start(); static int __parser_match_rule_end(); static void __parser_ulp_match_rule_start(); static int __parser_ulp_match_rule_end(); static void __pkey_rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len); static void __rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len); static void __merge_rangearr( uint64_t ** range_arr_1, unsigned range_len_1, uint64_t ** range_arr_2, unsigned range_len_2, uint64_t ** * p_arr, unsigned * p_arr_len ); static void __parser_add_port_to_port_map( cl_qmap_t * p_map, osm_physp_t * p_physp); static void __parser_add_guid_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len); static void __parser_add_pkey_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len); static void __parser_add_partition_list_to_port_map( cl_qmap_t * p_map, cl_list_t * p_list); static void __parser_add_map_to_port_map( cl_qmap_t * p_dmap, cl_map_t * p_smap); static int __validate_pkeys( uint64_t ** range_arr, unsigned range_len, boolean_t is_ipoib); static void __setup_simple_qos_levels(); static void __clear_simple_qos_levels(); static void __setup_ulp_match_rules(); static void __process_ulp_match_rules(); static void yyerror(const char *format, ...); extern char * yytext; extern int yylex (void); extern FILE * yyin; extern int errno; extern void yyrestart(FILE *input_file); int yyparse(); #define RESET_BUFFER __parser_tmp_struct_reset() tmp_parser_struct_t tmp_parser_struct; int column_num; int line_num; osm_qos_policy_t * p_qos_policy = NULL; osm_qos_port_group_t * p_current_port_group = NULL; osm_qos_sl2vl_scope_t * p_current_sl2vl_scope = NULL; osm_qos_vlarb_scope_t * p_current_vlarb_scope = NULL; osm_qos_level_t * p_current_qos_level = NULL; osm_qos_match_rule_t * p_current_qos_match_rule = NULL; osm_log_t * p_qos_parser_osm_log; /* 16 Simple QoS Levels - one for each SL */ static osm_qos_level_t osm_qos_policy_simple_qos_levels[16]; /* Default Simple QoS Level */ osm_qos_level_t __default_simple_qos_level; /* * List of match rules that will be generated by the * qos-ulp section. These rules are concatenated to * the end of the usual matching rules list at the * end of parsing. */ static cl_list_t __ulp_match_rules; /***************************************************/ %} %token TK_NUMBER %token TK_DASH %token TK_DOTDOT %token TK_COMMA %token TK_ASTERISK %token TK_TEXT %token TK_QOS_ULPS_START %token TK_QOS_ULPS_END %token TK_PORT_GROUPS_START %token TK_PORT_GROUPS_END %token TK_PORT_GROUP_START %token TK_PORT_GROUP_END %token TK_QOS_SETUP_START %token TK_QOS_SETUP_END %token TK_VLARB_TABLES_START %token TK_VLARB_TABLES_END %token TK_VLARB_SCOPE_START %token TK_VLARB_SCOPE_END %token TK_SL2VL_TABLES_START %token TK_SL2VL_TABLES_END %token TK_SL2VL_SCOPE_START %token TK_SL2VL_SCOPE_END %token TK_QOS_LEVELS_START %token TK_QOS_LEVELS_END %token TK_QOS_LEVEL_START %token TK_QOS_LEVEL_END %token TK_QOS_MATCH_RULES_START %token TK_QOS_MATCH_RULES_END %token TK_QOS_MATCH_RULE_START %token TK_QOS_MATCH_RULE_END %token TK_NAME %token TK_USE %token TK_PORT_GUID %token TK_PORT_NAME %token TK_PARTITION %token TK_NODE_TYPE %token TK_GROUP %token TK_ACROSS %token TK_VLARB_HIGH %token TK_VLARB_LOW %token TK_VLARB_HIGH_LIMIT %token TK_TO %token TK_FROM %token TK_ACROSS_TO %token TK_ACROSS_FROM %token TK_SL2VL_TABLE %token TK_SL %token TK_MTU_LIMIT %token TK_RATE_LIMIT %token TK_PACKET_LIFE %token TK_PATH_BITS %token TK_QOS_CLASS %token TK_SOURCE %token TK_DESTINATION %token TK_SERVICE_ID %token TK_QOS_LEVEL_NAME %token TK_PKEY %token TK_NODE_TYPE_ROUTER %token TK_NODE_TYPE_CA %token TK_NODE_TYPE_SWITCH %token TK_NODE_TYPE_SELF %token TK_NODE_TYPE_ALL %token TK_ULP_DEFAULT %token TK_ULP_ANY_SERVICE_ID %token TK_ULP_ANY_PKEY %token TK_ULP_ANY_TARGET_PORT_GUID %token TK_ULP_ANY_SOURCE_PORT_GUID %token TK_ULP_ANY_SOURCE_TARGET_PORT_GUID %token TK_ULP_SDP_DEFAULT %token TK_ULP_SDP_PORT %token TK_ULP_RDS_DEFAULT %token TK_ULP_RDS_PORT %token TK_ULP_ISER_DEFAULT %token TK_ULP_ISER_PORT %token TK_ULP_SRP_GUID %token TK_ULP_IPOIB_DEFAULT %token TK_ULP_IPOIB_PKEY %start head %% head: qos_policy_entries ; qos_policy_entries: /* empty */ | qos_policy_entries qos_policy_entry ; qos_policy_entry: qos_ulps_section | port_groups_section | qos_setup_section | qos_levels_section | qos_match_rules_section ; /* * Parsing qos-ulps: * ------------------- * qos-ulps * default : 0 #default SL * sdp, port-num 30000 : 1 #SL for SDP when destination port is 30000 * sdp, port-num 10000-20000 : 2 * sdp : 0 #default SL for SDP * srp, target-port-guid 0x1234 : 2 * rds, port-num 25000 : 2 #SL for RDS when destination port is 25000 * rds, : 0 #default SL for RDS * iser, port-num 900 : 5 #SL for iSER where target port is 900 * iser : 4 #default SL for iSER * ipoib, pkey 0x0001 : 5 #SL for IPoIB on partition with pkey 0x0001 * ipoib : 6 #default IPoIB partition - pkey=0x7FFF * any, service-id 0x6234 : 2 * any, pkey 0x0ABC : 3 * any, target-port-guid 0x0ABC-0xFFFFF : 6 * any, source-port-guid 0x1234 : 7 * any, source-target-port-guid 0x5678 : 8 * end-qos-ulps */ qos_ulps_section: TK_QOS_ULPS_START qos_ulps TK_QOS_ULPS_END ; qos_ulps: qos_ulp | qos_ulps qos_ulp ; /* * Parsing port groups: * ------------------- * port-groups * port-group * name: Storage * use: our SRP storage targets * port-guid: 0x1000000000000001,0x1000000000000002 * ... * port-name: vs1 HCA-1/P1 * port-name: node_description/P2 * ... * pkey: 0x00FF-0x0FFF * ... * partition: Part1 * ... * node-type: ROUTER,CA,SWITCH,SELF,ALL * ... * end-port-group * port-group * ... * end-port-group * end-port-groups */ port_groups_section: TK_PORT_GROUPS_START port_groups TK_PORT_GROUPS_END ; port_groups: port_group | port_groups port_group ; port_group: port_group_start port_group_entries port_group_end ; port_group_start: TK_PORT_GROUP_START { __parser_port_group_start(); } ; port_group_end: TK_PORT_GROUP_END { if ( __parser_port_group_end() ) return 1; } ; port_group_entries: /* empty */ | port_group_entries port_group_entry ; port_group_entry: port_group_name | port_group_use | port_group_port_guid | port_group_port_name | port_group_pkey | port_group_partition | port_group_node_type ; /* * Parsing qos setup: * ----------------- * qos-setup * vlarb-tables * vlarb-scope * ... * end-vlarb-scope * vlarb-scope * ... * end-vlarb-scope * end-vlarb-tables * sl2vl-tables * sl2vl-scope * ... * end-sl2vl-scope * sl2vl-scope * ... * end-sl2vl-scope * end-sl2vl-tables * end-qos-setup */ qos_setup_section: TK_QOS_SETUP_START qos_setup_items TK_QOS_SETUP_END ; qos_setup_items: /* empty */ | qos_setup_items vlarb_tables | qos_setup_items sl2vl_tables ; /* Parsing vlarb-tables */ vlarb_tables: TK_VLARB_TABLES_START vlarb_scope_items TK_VLARB_TABLES_END ; vlarb_scope_items: /* empty */ | vlarb_scope_items vlarb_scope ; vlarb_scope: vlarb_scope_start vlarb_scope_entries vlarb_scope_end ; vlarb_scope_start: TK_VLARB_SCOPE_START { __parser_vlarb_scope_start(); } ; vlarb_scope_end: TK_VLARB_SCOPE_END { if ( __parser_vlarb_scope_end() ) return 1; } ; vlarb_scope_entries:/* empty */ | vlarb_scope_entries vlarb_scope_entry ; /* * vlarb-scope * group: Storage * ... * across: Storage * ... * vlarb-high: 0:255,1:127,2:63,3:31,4:15,5:7,6:3,7:1 * vlarb-low: 8:255,9:127,10:63,11:31,12:15,13:7,14:3 * vl-high-limit: 10 * end-vlarb-scope */ vlarb_scope_entry: vlarb_scope_group | vlarb_scope_across | vlarb_scope_vlarb_high | vlarb_scope_vlarb_low | vlarb_scope_vlarb_high_limit ; /* Parsing sl2vl-tables */ sl2vl_tables: TK_SL2VL_TABLES_START sl2vl_scope_items TK_SL2VL_TABLES_END ; sl2vl_scope_items: /* empty */ | sl2vl_scope_items sl2vl_scope ; sl2vl_scope: sl2vl_scope_start sl2vl_scope_entries sl2vl_scope_end ; sl2vl_scope_start: TK_SL2VL_SCOPE_START { __parser_sl2vl_scope_start(); } ; sl2vl_scope_end: TK_SL2VL_SCOPE_END { if ( __parser_sl2vl_scope_end() ) return 1; } ; sl2vl_scope_entries:/* empty */ | sl2vl_scope_entries sl2vl_scope_entry ; /* * sl2vl-scope * group: Part1 * ... * from: * * ... * to: * * ... * across-to: Storage2 * ... * across-from: Storage1 * ... * sl2vl-table: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7 * end-sl2vl-scope */ sl2vl_scope_entry: sl2vl_scope_group | sl2vl_scope_across | sl2vl_scope_across_from | sl2vl_scope_across_to | sl2vl_scope_from | sl2vl_scope_to | sl2vl_scope_sl2vl_table ; /* * Parsing qos-levels: * ------------------ * qos-levels * qos-level * name: qos_level_1 * use: for the lowest priority communication * sl: 15 * mtu-limit: 1 * rate-limit: 1 * packet-life: 12 * path-bits: 2,4,8-32 * pkey: 0x00FF-0x0FFF * end-qos-level * ... * qos-level * end-qos-level * end-qos-levels */ qos_levels_section: TK_QOS_LEVELS_START qos_levels TK_QOS_LEVELS_END ; qos_levels: /* empty */ | qos_levels qos_level ; qos_level: qos_level_start qos_level_entries qos_level_end ; qos_level_start: TK_QOS_LEVEL_START { __parser_qos_level_start(); } ; qos_level_end: TK_QOS_LEVEL_END { if ( __parser_qos_level_end() ) return 1; } ; qos_level_entries: /* empty */ | qos_level_entries qos_level_entry ; qos_level_entry: qos_level_name | qos_level_use | qos_level_sl | qos_level_mtu_limit | qos_level_rate_limit | qos_level_packet_life | qos_level_path_bits | qos_level_pkey ; /* * Parsing qos-match-rules: * ----------------------- * qos-match-rules * qos-match-rule * use: low latency by class 7-9 or 11 and bla bla * qos-class: 7-9,11 * qos-level-name: default * source: Storage * destination: Storage * service-id: 22,4719-5000 * pkey: 0x00FF-0x0FFF * end-qos-match-rule * qos-match-rule * ... * end-qos-match-rule * end-qos-match-rules */ qos_match_rules_section: TK_QOS_MATCH_RULES_START qos_match_rules TK_QOS_MATCH_RULES_END ; qos_match_rules: /* empty */ | qos_match_rules qos_match_rule ; qos_match_rule: qos_match_rule_start qos_match_rule_entries qos_match_rule_end ; qos_match_rule_start: TK_QOS_MATCH_RULE_START { __parser_match_rule_start(); } ; qos_match_rule_end: TK_QOS_MATCH_RULE_END { if ( __parser_match_rule_end() ) return 1; } ; qos_match_rule_entries: /* empty */ | qos_match_rule_entries qos_match_rule_entry ; qos_match_rule_entry: qos_match_rule_use | qos_match_rule_qos_class | qos_match_rule_qos_level_name | qos_match_rule_source | qos_match_rule_destination | qos_match_rule_service_id | qos_match_rule_pkey ; /* * Parsing qos-ulps: * ----------------- * default * sdp * sdp with port-num * rds * rds with port-num * srp with target-port-guid * iser * iser with port-num * ipoib * ipoib with pkey * any with service-id * any with pkey * any with target-port-guid * any with source-port-guid * any with source-target-port-guid */ qos_ulp: TK_ULP_DEFAULT single_number { /* parsing default ulp rule: "default: num" */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_tmp_num > 15) { yyerror("illegal SL value"); return 1; } __default_simple_qos_level.sl = (uint8_t)(*p_tmp_num); __default_simple_qos_level.sl_set = TRUE; free(p_tmp_num); cl_list_remove_all(&tmp_parser_struct.num_list); } | qos_ulp_type_any_service list_of_ranges TK_DOTDOT { /* "any, service-id ... : sl" - one instance of list of ranges */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have service ids"); return 1; } /* get all the service id ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } qos_ulp_sl | qos_ulp_type_any_pkey list_of_ranges TK_DOTDOT { /* "any, pkey ... : sl" - one instance of list of ranges */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have pkeys"); return 1; } /* get all the pkey ranges */ __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } qos_ulp_sl | qos_ulp_type_any_target_port_guid list_of_ranges TK_DOTDOT { /* any, target-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } qos_ulp_sl | qos_ulp_type_any_source_port_guid list_of_ranges TK_DOTDOT { /* any, source-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Sources_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the source groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->source_group_list, p_current_port_group); __parser_port_group_end(); } qos_ulp_sl | qos_ulp_type_any_source_target_port_guid list_of_ranges TK_DOTDOT { /* any, source-target-port-guid ... : sl */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_ULP_Sources_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the source and destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->source_group_list, p_current_port_group); cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } qos_ulp_sl | qos_ulp_type_sdp_default { /* "sdp : sl" - default SL for SDP */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; range_arr[0][1] = OSM_QOS_POLICY_ULP_SDP_SERVICE_ID + 0xFFFF; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } qos_ulp_sl | qos_ulp_type_sdp_port list_of_ranges TK_DOTDOT { /* sdp with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("SDP ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_SDP_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } qos_ulp_sl | qos_ulp_type_rds_default { /* "rds : sl" - default SL for RDS */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = OSM_QOS_POLICY_ULP_RDS_SERVICE_ID + OSM_QOS_POLICY_ULP_RDS_PORT; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } qos_ulp_sl | qos_ulp_type_rds_port list_of_ranges TK_DOTDOT { /* rds with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("RDS ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_RDS_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } qos_ulp_sl | qos_ulp_type_iser_default { /* "iSER : sl" - default SL for iSER */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = OSM_QOS_POLICY_ULP_ISER_SERVICE_ID + OSM_QOS_POLICY_ULP_ISER_PORT; p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = 1; } qos_ulp_sl | qos_ulp_type_iser_port list_of_ranges TK_DOTDOT { /* iser with port numbers */ uint64_t ** range_arr; unsigned range_len; unsigned i; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("iSER ULP rule doesn't have port numbers"); return 1; } /* get all the port ranges */ __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* now translate these port numbers into service ids */ for (i = 0; i < range_len; i++) { if (range_arr[i][0] > 0xFFFF || range_arr[i][1] > 0xFFFF) { yyerror("SDP port number out of range"); free(range_arr); return 1; } range_arr[i][0] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID; range_arr[i][1] += OSM_QOS_POLICY_ULP_ISER_SERVICE_ID; } p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } qos_ulp_sl | qos_ulp_type_srp_guid list_of_ranges TK_DOTDOT { /* srp with target guids - this rule is similar to writing 'any' ulp with target port guids */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("SRP ULP rule doesn't have port guids"); return 1; } /* create a new port group with these ports */ __parser_port_group_start(); p_current_port_group->name = strdup("_SRP_Targets_"); p_current_port_group->use = strdup("Generated from ULP rules"); __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); /* add this port group to the destination groups of the current match rule */ cl_list_insert_tail(&p_current_qos_match_rule->destination_group_list, p_current_port_group); __parser_port_group_end(); } qos_ulp_sl | qos_ulp_type_ipoib_default { /* ipoib w/o any pkeys (default pkey) */ uint64_t ** range_arr = (uint64_t **)malloc(sizeof(uint64_t *)); range_arr[0] = (uint64_t *)malloc(2*sizeof(uint64_t)); range_arr[0][0] = range_arr[0][1] = 0x7fff; /* * Although we know that the default partition exists, * we still need to validate it by checking that it has * at least two full members. Otherwise IPoIB won't work. */ if (__validate_pkeys(range_arr, 1, TRUE)) return 1; p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = 1; } qos_ulp_sl | qos_ulp_type_ipoib_pkey list_of_ranges TK_DOTDOT { /* ipoib with pkeys */ uint64_t ** range_arr; unsigned range_len; if (!cl_list_count(&tmp_parser_struct.num_pair_list)) { yyerror("IPoIB ULP rule doesn't have pkeys"); return 1; } /* get all the pkey ranges */ __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); /* * Validate pkeys. * For IPoIB pkeys the validation is strict. * If some problem would be found, parsing will * be aborted with a proper error messages. */ if (__validate_pkeys(range_arr, range_len, TRUE)) { free(range_arr); return 1; } p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } qos_ulp_sl ; qos_ulp_type_any_service: TK_ULP_ANY_SERVICE_ID { __parser_ulp_match_rule_start(); }; qos_ulp_type_any_pkey: TK_ULP_ANY_PKEY { __parser_ulp_match_rule_start(); }; qos_ulp_type_any_target_port_guid: TK_ULP_ANY_TARGET_PORT_GUID { __parser_ulp_match_rule_start(); }; qos_ulp_type_any_source_port_guid: TK_ULP_ANY_SOURCE_PORT_GUID { __parser_ulp_match_rule_start(); }; qos_ulp_type_any_source_target_port_guid: TK_ULP_ANY_SOURCE_TARGET_PORT_GUID { __parser_ulp_match_rule_start(); }; qos_ulp_type_sdp_default: TK_ULP_SDP_DEFAULT { __parser_ulp_match_rule_start(); }; qos_ulp_type_sdp_port: TK_ULP_SDP_PORT { __parser_ulp_match_rule_start(); }; qos_ulp_type_rds_default: TK_ULP_RDS_DEFAULT { __parser_ulp_match_rule_start(); }; qos_ulp_type_rds_port: TK_ULP_RDS_PORT { __parser_ulp_match_rule_start(); }; qos_ulp_type_iser_default: TK_ULP_ISER_DEFAULT { __parser_ulp_match_rule_start(); }; qos_ulp_type_iser_port: TK_ULP_ISER_PORT { __parser_ulp_match_rule_start(); }; qos_ulp_type_srp_guid: TK_ULP_SRP_GUID { __parser_ulp_match_rule_start(); }; qos_ulp_type_ipoib_default: TK_ULP_IPOIB_DEFAULT { __parser_ulp_match_rule_start(); }; qos_ulp_type_ipoib_pkey: TK_ULP_IPOIB_PKEY { __parser_ulp_match_rule_start(); }; qos_ulp_sl: single_number { /* get the SL for ULP rules */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; uint8_t sl; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_tmp_num > 15) { yyerror("illegal SL value"); return 1; } sl = (uint8_t)(*p_tmp_num); free(p_tmp_num); cl_list_remove_all(&tmp_parser_struct.num_list); p_current_qos_match_rule->p_qos_level = &osm_qos_policy_simple_qos_levels[sl]; p_current_qos_match_rule->qos_level_name = strdup(osm_qos_policy_simple_qos_levels[sl].name); if (__parser_ulp_match_rule_end()) return 1; } ; /* * port_group_entry values: * port_group_name * port_group_use * port_group_port_guid * port_group_port_name * port_group_pkey * port_group_partition * port_group_node_type */ port_group_name: port_group_name_start single_string { /* 'name' of 'port-group' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_port_group->name) { yyerror("port-group has multiple 'name' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_port_group->name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; port_group_name_start: TK_NAME { RESET_BUFFER; } ; port_group_use: port_group_use_start single_string { /* 'use' of 'port-group' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_port_group->use) { yyerror("port-group has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_port_group->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; port_group_use_start: TK_USE { RESET_BUFFER; } ; port_group_port_name: port_group_port_name_start string_list { /* 'port-name' in 'port-group' - any num of instances */ cl_list_iterator_t list_iterator; osm_node_t * p_node; osm_physp_t * p_physp; unsigned port_num; char * tmp_str; char * port_str; /* parsing port name strings */ for (list_iterator = cl_list_head(&tmp_parser_struct.str_list); list_iterator != cl_list_end(&tmp_parser_struct.str_list); list_iterator = cl_list_next(list_iterator)) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { /* last slash in port name string is a separator between node name and port number */ port_str = strrchr(tmp_str, '/'); if (!port_str || (strlen(port_str) < 3) || (port_str[1] != 'p' && port_str[1] != 'P')) { yyerror("'%s' - illegal port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } if (!(port_num = strtoul(&port_str[2],NULL,0))) { yyerror( "'%s' - illegal port number in port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } /* separate node name from port number */ port_str[0] = '\0'; if (st_lookup(p_qos_policy->p_node_hash, (st_data_t)tmp_str, (void *)&p_node)) { /* we found the node, now get the right port */ p_physp = osm_node_get_physp_ptr(p_node, port_num); if (!p_physp) { yyerror( "'%s' - port number out of range in port name", tmp_str); free(tmp_str); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } /* we found the port, now add it to guid table */ __parser_add_port_to_port_map(&p_current_port_group->port_map, p_physp); } free(tmp_str); } } cl_list_remove_all(&tmp_parser_struct.str_list); } ; port_group_port_name_start: TK_PORT_NAME { RESET_BUFFER; } ; port_group_port_guid: port_group_port_guid_start list_of_ranges { /* 'port-guid' in 'port-group' - any num of instances */ /* list of guid ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_guid_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); } } ; port_group_port_guid_start: TK_PORT_GUID { RESET_BUFFER; } ; port_group_pkey: port_group_pkey_start list_of_ranges { /* 'pkey' in 'port-group' - any num of instances */ /* list of pkey ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); __parser_add_pkey_range_to_port_map( &p_current_port_group->port_map, range_arr, range_len); } } ; port_group_pkey_start: TK_PKEY { RESET_BUFFER; } ; port_group_partition: port_group_partition_start string_list { /* 'partition' in 'port-group' - any num of instances */ __parser_add_partition_list_to_port_map( &p_current_port_group->port_map, &tmp_parser_struct.str_list); } ; port_group_partition_start: TK_PARTITION { RESET_BUFFER; } ; port_group_node_type: port_group_node_type_start port_group_node_type_list { /* 'node-type' in 'port-group' - any num of instances */ } ; port_group_node_type_start: TK_NODE_TYPE { RESET_BUFFER; } ; port_group_node_type_list: node_type_item | port_group_node_type_list TK_COMMA node_type_item ; node_type_item: node_type_ca | node_type_switch | node_type_router | node_type_all | node_type_self ; node_type_ca: TK_NODE_TYPE_CA { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_CA; } ; node_type_switch: TK_NODE_TYPE_SWITCH { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_SWITCH; } ; node_type_router: TK_NODE_TYPE_ROUTER { p_current_port_group->node_types |= OSM_QOS_POLICY_NODE_TYPE_ROUTER; } ; node_type_all: TK_NODE_TYPE_ALL { p_current_port_group->node_types |= (OSM_QOS_POLICY_NODE_TYPE_CA | OSM_QOS_POLICY_NODE_TYPE_SWITCH | OSM_QOS_POLICY_NODE_TYPE_ROUTER); } ; node_type_self: TK_NODE_TYPE_SELF { osm_port_t * p_osm_port = osm_get_port_by_guid(p_qos_policy->p_subn, p_qos_policy->p_subn->sm_port_guid); if (p_osm_port) __parser_add_port_to_port_map( &p_current_port_group->port_map, p_osm_port->p_physp); } ; /* * vlarb_scope_entry values: * vlarb_scope_group * vlarb_scope_across * vlarb_scope_vlarb_high * vlarb_scope_vlarb_low * vlarb_scope_vlarb_high_limit */ vlarb_scope_group: vlarb_scope_group_start string_list { /* 'group' in 'vlarb-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_vlarb_scope->group_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; vlarb_scope_group_start: TK_GROUP { RESET_BUFFER; } ; vlarb_scope_across: vlarb_scope_across_start string_list { /* 'across' in 'vlarb-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_vlarb_scope->across_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; vlarb_scope_across_start: TK_ACROSS { RESET_BUFFER; } ; vlarb_scope_vlarb_high_limit: vlarb_scope_vlarb_high_limit_start single_number { /* 'vl-high-limit' in 'vlarb-scope' - one instance of one number */ cl_list_iterator_t list_iterator; uint64_t * p_tmp_num; list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_tmp_num = (uint64_t*)cl_list_obj(list_iterator); if (p_tmp_num) { p_current_vlarb_scope->vl_high_limit = (uint32_t)(*p_tmp_num); p_current_vlarb_scope->vl_high_limit_set = TRUE; free(p_tmp_num); } cl_list_remove_all(&tmp_parser_struct.num_list); } ; vlarb_scope_vlarb_high_limit_start: TK_VLARB_HIGH_LIMIT { RESET_BUFFER; } ; vlarb_scope_vlarb_high: vlarb_scope_vlarb_high_start num_list_with_dotdot { /* 'vlarb-high' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */ cl_list_iterator_t list_iterator; uint64_t * num_pair; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) cl_list_insert_tail(&p_current_vlarb_scope->vlarb_high_list,num_pair); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } ; vlarb_scope_vlarb_high_start: TK_VLARB_HIGH { RESET_BUFFER; } ; vlarb_scope_vlarb_low: vlarb_scope_vlarb_low_start num_list_with_dotdot { /* 'vlarb-low' in 'vlarb-scope' - list of pairs of numbers with ':' and ',' */ cl_list_iterator_t list_iterator; uint64_t * num_pair; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) cl_list_insert_tail(&p_current_vlarb_scope->vlarb_low_list,num_pair); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } ; vlarb_scope_vlarb_low_start: TK_VLARB_LOW { RESET_BUFFER; } ; /* * sl2vl_scope_entry values: * sl2vl_scope_group * sl2vl_scope_across * sl2vl_scope_across_from * sl2vl_scope_across_to * sl2vl_scope_from * sl2vl_scope_to * sl2vl_scope_sl2vl_table */ sl2vl_scope_group: sl2vl_scope_group_start string_list { /* 'group' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_sl2vl_scope->group_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; sl2vl_scope_group_start: TK_GROUP { RESET_BUFFER; } ; sl2vl_scope_across: sl2vl_scope_across_start string_list { /* 'across' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str); cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,strdup(tmp_str)); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; sl2vl_scope_across_start: TK_ACROSS { RESET_BUFFER; } ; sl2vl_scope_across_from: sl2vl_scope_across_from_start string_list { /* 'across-from' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_sl2vl_scope->across_from_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; sl2vl_scope_across_from_start: TK_ACROSS_FROM { RESET_BUFFER; } ; sl2vl_scope_across_to: sl2vl_scope_across_to_start string_list { /* 'across-to' in 'sl2vl-scope' - any num of instances */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { cl_list_insert_tail(&p_current_sl2vl_scope->across_to_list,tmp_str); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; sl2vl_scope_across_to_start: TK_ACROSS_TO { RESET_BUFFER; } ; sl2vl_scope_from: sl2vl_scope_from_start sl2vl_scope_from_list_or_asterisk { /* 'from' in 'sl2vl-scope' - any num of instances */ } ; sl2vl_scope_from_start: TK_FROM { RESET_BUFFER; } ; sl2vl_scope_to: sl2vl_scope_to_start sl2vl_scope_to_list_or_asterisk { /* 'to' in 'sl2vl-scope' - any num of instances */ } ; sl2vl_scope_to_start: TK_TO { RESET_BUFFER; } ; sl2vl_scope_from_list_or_asterisk: sl2vl_scope_from_asterisk | sl2vl_scope_from_list_of_ranges ; sl2vl_scope_from_asterisk: TK_ASTERISK { int i; for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++) p_current_sl2vl_scope->from[i] = TRUE; } ; sl2vl_scope_to_list_or_asterisk: sl2vl_scope_to_asterisk | sl2vl_scope_to_list_of_ranges ; sl2vl_scope_to_asterisk: TK_ASTERISK { int i; for (i = 0; i < OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH; i++) p_current_sl2vl_scope->to[i] = TRUE; } ; sl2vl_scope_from_list_of_ranges: list_of_ranges { int i; cl_list_iterator_t list_iterator; uint64_t * num_pair; uint8_t num1, num2; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) { if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH ) { yyerror("port number out of range 'from' list"); free(num_pair); cl_list_remove_all(&tmp_parser_struct.num_pair_list); return 1; } num1 = (uint8_t)num_pair[0]; num2 = (uint8_t)num_pair[1]; free(num_pair); for (i = num1; i <= num2; i++) p_current_sl2vl_scope->from[i] = TRUE; } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } ; sl2vl_scope_to_list_of_ranges: list_of_ranges { int i; cl_list_iterator_t list_iterator; uint64_t * num_pair; uint8_t num1, num2; list_iterator = cl_list_head(&tmp_parser_struct.num_pair_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_pair_list) ) { num_pair = (uint64_t*)cl_list_obj(list_iterator); if (num_pair) { if ( num_pair[1] >= OSM_QOS_POLICY_MAX_PORTS_ON_SWITCH ) { yyerror("port number out of range 'to' list"); free(num_pair); cl_list_remove_all(&tmp_parser_struct.num_pair_list); return 1; } num1 = (uint8_t)num_pair[0]; num2 = (uint8_t)num_pair[1]; free(num_pair); for (i = num1; i <= num2; i++) p_current_sl2vl_scope->to[i] = TRUE; } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.num_pair_list); } ; sl2vl_scope_sl2vl_table: sl2vl_scope_sl2vl_table_start num_list { /* 'sl2vl-table' - one instance of exactly OSM_QOS_POLICY_SL2VL_TABLE_LEN numbers */ cl_list_iterator_t list_iterator; uint64_t num; uint64_t * p_num; int i = 0; if (p_current_sl2vl_scope->sl2vl_table_set) { yyerror("sl2vl-scope has more than one sl2vl-table"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } if (cl_list_count(&tmp_parser_struct.num_list) != OSM_QOS_POLICY_SL2VL_TABLE_LEN) { yyerror("wrong number of values in 'sl2vl-table' (should be 16)"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); while( list_iterator != cl_list_end(&tmp_parser_struct.num_list) ) { p_num = (uint64_t*)cl_list_obj(list_iterator); num = *p_num; free(p_num); if (num >= OSM_QOS_POLICY_MAX_VL_NUM) { yyerror("wrong VL value in 'sl2vl-table' (should be 0 to 15)"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_sl2vl_scope->sl2vl_table[i++] = (uint8_t)num; list_iterator = cl_list_next(list_iterator); } p_current_sl2vl_scope->sl2vl_table_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } ; sl2vl_scope_sl2vl_table_start: TK_SL2VL_TABLE { RESET_BUFFER; } ; /* * qos_level_entry values: * qos_level_name * qos_level_use * qos_level_sl * qos_level_mtu_limit * qos_level_rate_limit * qos_level_packet_life * qos_level_path_bits * qos_level_pkey */ qos_level_name: qos_level_name_start single_string { /* 'name' of 'qos-level' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_level->name) { yyerror("qos-level has multiple 'name' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_level->name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_level_name_start: TK_NAME { RESET_BUFFER; } ; qos_level_use: qos_level_use_start single_string { /* 'use' of 'qos-level' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_level->use) { yyerror("qos-level has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_level->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_level_use_start: TK_USE { RESET_BUFFER; } ; qos_level_sl: qos_level_sl_start single_number { /* 'sl' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->sl_set) { yyerror("'qos-level' has multiple 'sl' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); p_current_qos_level->sl = (uint8_t)(*p_num); free(p_num); p_current_qos_level->sl_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } ; qos_level_sl_start: TK_SL { RESET_BUFFER; } ; qos_level_mtu_limit: qos_level_mtu_limit_start single_number { /* 'mtu-limit' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->mtu_limit_set) { yyerror("'qos-level' has multiple 'mtu-limit' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_num > OSM_QOS_POLICY_MAX_MTU || *p_num < OSM_QOS_POLICY_MIN_MTU) { yyerror("mtu limit is out of range, value: %d", *p_num); free(p_num); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_qos_level->mtu_limit = (uint8_t)(*p_num); free(p_num); p_current_qos_level->mtu_limit_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } ; qos_level_mtu_limit_start: TK_MTU_LIMIT { /* 'mtu-limit' in 'qos-level' - one instance */ RESET_BUFFER; } ; qos_level_rate_limit: qos_level_rate_limit_start single_number { /* 'rate-limit' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->rate_limit_set) { yyerror("'qos-level' has multiple 'rate-limit' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); if (*p_num > OSM_QOS_POLICY_MAX_RATE || *p_num < OSM_QOS_POLICY_MIN_RATE) { yyerror("rate limit is out of range, value: %d", *p_num); free(p_num); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } p_current_qos_level->rate_limit = (uint8_t)(*p_num); free(p_num); p_current_qos_level->rate_limit_set = TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } ; qos_level_rate_limit_start: TK_RATE_LIMIT { /* 'rate-limit' in 'qos-level' - one instance */ RESET_BUFFER; } ; qos_level_packet_life: qos_level_packet_life_start single_number { /* 'packet-life' in 'qos-level' - one instance */ cl_list_iterator_t list_iterator; uint64_t * p_num; if (p_current_qos_level->pkt_life_set) { yyerror("'qos-level' has multiple 'packet-life' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.num_list); p_num = (uint64_t*)cl_list_obj(list_iterator); p_current_qos_level->pkt_life = (uint8_t)(*p_num); free(p_num); p_current_qos_level->pkt_life_set= TRUE; cl_list_remove_all(&tmp_parser_struct.num_list); } ; qos_level_packet_life_start: TK_PACKET_LIFE { /* 'packet-life' in 'qos-level' - one instance */ RESET_BUFFER; } ; qos_level_path_bits: qos_level_path_bits_start list_of_ranges { /* 'path-bits' in 'qos-level' - any num of instances */ /* list of path bit ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_level->path_bits_range_len ) { p_current_qos_level->path_bits_range_arr = range_arr; p_current_qos_level->path_bits_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_level->path_bits_range_arr, p_current_qos_level->path_bits_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_level->path_bits_range_arr = new_range_arr; p_current_qos_level->path_bits_range_len = new_range_len; } } } ; qos_level_path_bits_start: TK_PATH_BITS { RESET_BUFFER; } ; qos_level_pkey: qos_level_pkey_start list_of_ranges { /* 'pkey' in 'qos-level' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_level->pkey_range_len ) { p_current_qos_level->pkey_range_arr = range_arr; p_current_qos_level->pkey_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_level->pkey_range_arr, p_current_qos_level->pkey_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_level->pkey_range_arr = new_range_arr; p_current_qos_level->pkey_range_len = new_range_len; } } } ; qos_level_pkey_start: TK_PKEY { RESET_BUFFER; } ; /* * qos_match_rule_entry values: * qos_match_rule_use * qos_match_rule_qos_class * qos_match_rule_qos_level_name * qos_match_rule_source * qos_match_rule_destination * qos_match_rule_service_id * qos_match_rule_pkey */ qos_match_rule_use: qos_match_rule_use_start single_string { /* 'use' of 'qos-match-rule' - one instance */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_match_rule->use) { yyerror("'qos-match-rule' has multiple 'use' tags"); cl_list_remove_all(&tmp_parser_struct.str_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_match_rule->use = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_match_rule_use_start: TK_USE { RESET_BUFFER; } ; qos_match_rule_qos_class: qos_match_rule_qos_class_start list_of_ranges { /* 'qos-class' in 'qos-match-rule' - num of instances of list of ranges */ /* list of class ranges (QoS Class is 12-bit value) */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->qos_class_range_len ) { p_current_qos_match_rule->qos_class_range_arr = range_arr; p_current_qos_match_rule->qos_class_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->qos_class_range_arr, p_current_qos_match_rule->qos_class_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->qos_class_range_arr = new_range_arr; p_current_qos_match_rule->qos_class_range_len = new_range_len; } } } ; qos_match_rule_qos_class_start: TK_QOS_CLASS { RESET_BUFFER; } ; qos_match_rule_source: qos_match_rule_source_start string_list { /* 'source' in 'qos-match-rule' - text */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_qos_match_rule->source_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_match_rule_source_start: TK_SOURCE { RESET_BUFFER; } ; qos_match_rule_destination: qos_match_rule_destination_start string_list { /* 'destination' in 'qos-match-rule' - text */ cl_list_iterator_t list_iterator; char * tmp_str; list_iterator = cl_list_head(&tmp_parser_struct.str_list); while( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) cl_list_insert_tail(&p_current_qos_match_rule->destination_list,tmp_str); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_match_rule_destination_start: TK_DESTINATION { RESET_BUFFER; } ; qos_match_rule_qos_level_name: qos_match_rule_qos_level_name_start single_string { /* 'qos-level-name' in 'qos-match-rule' - single string */ cl_list_iterator_t list_iterator; char * tmp_str; if (p_current_qos_match_rule->qos_level_name) { yyerror("qos-match-rule has multiple 'qos-level-name' tags"); cl_list_remove_all(&tmp_parser_struct.num_list); return 1; } list_iterator = cl_list_head(&tmp_parser_struct.str_list); if ( list_iterator != cl_list_end(&tmp_parser_struct.str_list) ) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) p_current_qos_match_rule->qos_level_name = tmp_str; } cl_list_remove_all(&tmp_parser_struct.str_list); } ; qos_match_rule_qos_level_name_start: TK_QOS_LEVEL_NAME { RESET_BUFFER; } ; qos_match_rule_service_id: qos_match_rule_service_id_start list_of_ranges { /* 'service-id' in 'qos-match-rule' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->service_id_range_len ) { p_current_qos_match_rule->service_id_range_arr = range_arr; p_current_qos_match_rule->service_id_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->service_id_range_arr, p_current_qos_match_rule->service_id_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->service_id_range_arr = new_range_arr; p_current_qos_match_rule->service_id_range_len = new_range_len; } } } ; qos_match_rule_service_id_start: TK_SERVICE_ID { RESET_BUFFER; } ; qos_match_rule_pkey: qos_match_rule_pkey_start list_of_ranges { /* 'pkey' in 'qos-match-rule' - num of instances of list of ranges */ if (cl_list_count(&tmp_parser_struct.num_pair_list)) { uint64_t ** range_arr; unsigned range_len; __pkey_rangelist2rangearr( &tmp_parser_struct.num_pair_list, &range_arr, &range_len ); if ( !p_current_qos_match_rule->pkey_range_len ) { p_current_qos_match_rule->pkey_range_arr = range_arr; p_current_qos_match_rule->pkey_range_len = range_len; } else { uint64_t ** new_range_arr; unsigned new_range_len; __merge_rangearr( p_current_qos_match_rule->pkey_range_arr, p_current_qos_match_rule->pkey_range_len, range_arr, range_len, &new_range_arr, &new_range_len ); p_current_qos_match_rule->pkey_range_arr = new_range_arr; p_current_qos_match_rule->pkey_range_len = new_range_len; } } } ; qos_match_rule_pkey_start: TK_PKEY { RESET_BUFFER; } ; /* * Common part */ single_string: single_string_elems { cl_list_insert_tail(&tmp_parser_struct.str_list, strdup(__parser_strip_white(tmp_parser_struct.str))); tmp_parser_struct.str[0] = '\0'; } ; single_string_elems: single_string_element | single_string_elems single_string_element ; single_string_element: TK_TEXT { strcat(tmp_parser_struct.str,$1); free($1); } ; string_list: single_string | string_list TK_COMMA single_string ; single_number: number ; num_list: number | num_list TK_COMMA number ; number: TK_NUMBER { uint64_t * p_num = (uint64_t*)malloc(sizeof(uint64_t)); __parser_str2uint64(p_num,$1); free($1); cl_list_insert_tail(&tmp_parser_struct.num_list, p_num); } ; num_list_with_dotdot: number_from_pair_1 TK_DOTDOT number_from_pair_2 { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } | num_list_with_dotdot TK_COMMA number_from_pair_1 TK_DOTDOT number_from_pair_2 { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } ; number_from_pair_1: TK_NUMBER { __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1); free($1); } ; number_from_pair_2: TK_NUMBER { __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1); free($1); } ; list_of_ranges: num_list_with_dash ; num_list_with_dash: single_number_from_range { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } | number_from_range_1 TK_DASH number_from_range_2 { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) { num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; } else { num_pair[1] = tmp_parser_struct.num_pair[0]; num_pair[0] = tmp_parser_struct.num_pair[1]; } cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } | num_list_with_dash TK_COMMA number_from_range_1 TK_DASH number_from_range_2 { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); if (tmp_parser_struct.num_pair[0] <= tmp_parser_struct.num_pair[1]) { num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; } else { num_pair[1] = tmp_parser_struct.num_pair[0]; num_pair[0] = tmp_parser_struct.num_pair[1]; } cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } | num_list_with_dash TK_COMMA single_number_from_range { uint64_t * num_pair = (uint64_t*)malloc(sizeof(uint64_t)*2); num_pair[0] = tmp_parser_struct.num_pair[0]; num_pair[1] = tmp_parser_struct.num_pair[1]; cl_list_insert_tail(&tmp_parser_struct.num_pair_list, num_pair); } ; single_number_from_range: TK_NUMBER { __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1); __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1); free($1); } ; number_from_range_1: TK_NUMBER { __parser_str2uint64(&tmp_parser_struct.num_pair[0],$1); free($1); } ; number_from_range_2: TK_NUMBER { __parser_str2uint64(&tmp_parser_struct.num_pair[1],$1); free($1); } ; %% /*************************************************** ***************************************************/ int osm_qos_parse_policy_file(IN osm_subn_t * p_subn) { int res = 0; static boolean_t first_time = TRUE; p_qos_parser_osm_log = &p_subn->p_osm->log; OSM_LOG_ENTER(p_qos_parser_osm_log); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; yyin = fopen (p_subn->opt.qos_policy_file, "r"); if (!yyin) { if (strcmp(p_subn->opt.qos_policy_file,OSM_DEFAULT_QOS_POLICY_FILE)) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC01: " "Failed opening QoS policy file %s - %s\n", p_subn->opt.qos_policy_file, strerror(errno)); res = 1; } else OSM_LOG(p_qos_parser_osm_log, OSM_LOG_VERBOSE, "QoS policy file not found (%s)\n", p_subn->opt.qos_policy_file); goto Exit; } if (first_time) { first_time = FALSE; __setup_simple_qos_levels(); __setup_ulp_match_rules(); OSM_LOG(p_qos_parser_osm_log, OSM_LOG_INFO, "Loading QoS policy file (%s)\n", p_subn->opt.qos_policy_file); } else /* * ULP match rules list was emptied at the end of * previous parsing iteration. * What's left is to clear simple QoS levels. */ __clear_simple_qos_levels(); column_num = 1; line_num = 1; p_subn->p_qos_policy = osm_qos_policy_create(p_subn); __parser_tmp_struct_init(); p_qos_policy = p_subn->p_qos_policy; res = yyparse(); __parser_tmp_struct_destroy(); if (res != 0) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC03: " "Failed parsing QoS policy file (%s)\n", p_subn->opt.qos_policy_file); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; res = 1; goto Exit; } /* add generated ULP match rules to the usual match rules */ __process_ulp_match_rules(); if (osm_qos_policy_validate(p_subn->p_qos_policy,p_qos_parser_osm_log)) { OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC04: " "Error(s) in QoS policy file (%s)\n", p_subn->opt.qos_policy_file); fprintf(stderr, "Error(s) in QoS policy file (%s)\n", p_subn->opt.qos_policy_file); osm_qos_policy_destroy(p_subn->p_qos_policy); p_subn->p_qos_policy = NULL; res = 1; goto Exit; } Exit: if (yyin) { yyrestart(yyin); fclose(yyin); } OSM_LOG_EXIT(p_qos_parser_osm_log); return res; } /*************************************************** ***************************************************/ int yywrap() { return(1); } /*************************************************** ***************************************************/ static void yyerror(const char *format, ...) { char s[256]; va_list pvar; OSM_LOG_ENTER(p_qos_parser_osm_log); va_start(pvar, format); vsnprintf(s, sizeof(s), format, pvar); va_end(pvar); OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC05: " "Syntax error (line %d:%d): %s\n", line_num, column_num, s); fprintf(stderr, "Error in QoS Policy File (line %d:%d): %s.\n", line_num, column_num, s); OSM_LOG_EXIT(p_qos_parser_osm_log); } /*************************************************** ***************************************************/ static char * __parser_strip_white(char * str) { char *p; while (isspace(*str)) str++; if (!*str) return str; p = str + strlen(str) - 1; while (isspace(*p)) *p-- = '\0'; return str; } /*************************************************** ***************************************************/ static void __parser_str2uint64(uint64_t * p_val, char * str) { *p_val = strtoull(str, NULL, 0); } /*************************************************** ***************************************************/ static void __parser_port_group_start() { p_current_port_group = osm_qos_policy_port_group_create(); } /*************************************************** ***************************************************/ static int __parser_port_group_end() { if(!p_current_port_group->name) { yyerror("port-group validation failed - no port group name specified"); return -1; } cl_list_insert_tail(&p_qos_policy->port_groups, p_current_port_group); p_current_port_group = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_vlarb_scope_start() { p_current_vlarb_scope = osm_qos_policy_vlarb_scope_create(); } /*************************************************** ***************************************************/ static int __parser_vlarb_scope_end() { if ( !cl_list_count(&p_current_vlarb_scope->group_list) && !cl_list_count(&p_current_vlarb_scope->across_list) ) { yyerror("vlarb-scope validation failed - no port groups specified by 'group' or by 'across'"); return -1; } cl_list_insert_tail(&p_qos_policy->vlarb_tables, p_current_vlarb_scope); p_current_vlarb_scope = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_sl2vl_scope_start() { p_current_sl2vl_scope = osm_qos_policy_sl2vl_scope_create(); } /*************************************************** ***************************************************/ static int __parser_sl2vl_scope_end() { if (!p_current_sl2vl_scope->sl2vl_table_set) { yyerror("sl2vl-scope validation failed - no sl2vl table specified"); return -1; } if ( !cl_list_count(&p_current_sl2vl_scope->group_list) && !cl_list_count(&p_current_sl2vl_scope->across_to_list) && !cl_list_count(&p_current_sl2vl_scope->across_from_list) ) { yyerror("sl2vl-scope validation failed - no port groups specified by 'group', 'across-to' or 'across-from'"); return -1; } cl_list_insert_tail(&p_qos_policy->sl2vl_tables, p_current_sl2vl_scope); p_current_sl2vl_scope = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_qos_level_start() { p_current_qos_level = osm_qos_policy_qos_level_create(); } /*************************************************** ***************************************************/ static int __parser_qos_level_end() { if (!p_current_qos_level->sl_set) { yyerror("qos-level validation failed - no 'sl' specified"); return -1; } if (!p_current_qos_level->name) { yyerror("qos-level validation failed - no 'name' specified"); return -1; } cl_list_insert_tail(&p_qos_policy->qos_levels, p_current_qos_level); p_current_qos_level = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_match_rule_start() { p_current_qos_match_rule = osm_qos_policy_match_rule_create(); } /*************************************************** ***************************************************/ static int __parser_match_rule_end() { if (!p_current_qos_match_rule->qos_level_name) { yyerror("match-rule validation failed - no 'qos-level-name' specified"); return -1; } cl_list_insert_tail(&p_qos_policy->qos_match_rules, p_current_qos_match_rule); p_current_qos_match_rule = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_ulp_match_rule_start() { p_current_qos_match_rule = osm_qos_policy_match_rule_create(); } /*************************************************** ***************************************************/ static int __parser_ulp_match_rule_end() { CL_ASSERT(p_current_qos_match_rule->p_qos_level); cl_list_insert_tail(&__ulp_match_rules, p_current_qos_match_rule); p_current_qos_match_rule = NULL; return 0; } /*************************************************** ***************************************************/ static void __parser_tmp_struct_init() { tmp_parser_struct.str[0] = '\0'; cl_list_construct(&tmp_parser_struct.str_list); cl_list_init(&tmp_parser_struct.str_list, 10); cl_list_construct(&tmp_parser_struct.num_list); cl_list_init(&tmp_parser_struct.num_list, 10); cl_list_construct(&tmp_parser_struct.num_pair_list); cl_list_init(&tmp_parser_struct.num_pair_list, 10); } /*************************************************** ***************************************************/ /* * Do NOT free objects from the temp struct. * Either they are inserted into the parse tree data * structure, or they are already freed when copying * their values to the parse tree data structure. */ static void __parser_tmp_struct_reset() { tmp_parser_struct.str[0] = '\0'; cl_list_remove_all(&tmp_parser_struct.str_list); cl_list_remove_all(&tmp_parser_struct.num_list); cl_list_remove_all(&tmp_parser_struct.num_pair_list); } /*************************************************** ***************************************************/ static void __parser_tmp_struct_destroy() { __parser_tmp_struct_reset(); cl_list_destroy(&tmp_parser_struct.str_list); cl_list_destroy(&tmp_parser_struct.num_list); cl_list_destroy(&tmp_parser_struct.num_pair_list); } /*************************************************** ***************************************************/ #define __SIMPLE_QOS_LEVEL_NAME "SimpleQoSLevel_SL" #define __SIMPLE_QOS_LEVEL_DEFAULT_NAME "SimpleQoSLevel_DEFAULT" static void __setup_simple_qos_levels() { uint8_t i; char tmp_buf[30]; memset(osm_qos_policy_simple_qos_levels, 0, sizeof(osm_qos_policy_simple_qos_levels)); for (i = 0; i < 16; i++) { osm_qos_policy_simple_qos_levels[i].sl = i; osm_qos_policy_simple_qos_levels[i].sl_set = TRUE; sprintf(tmp_buf, "%s%u", __SIMPLE_QOS_LEVEL_NAME, i); osm_qos_policy_simple_qos_levels[i].name = strdup(tmp_buf); } memset(&__default_simple_qos_level, 0, sizeof(__default_simple_qos_level)); __default_simple_qos_level.name = strdup(__SIMPLE_QOS_LEVEL_DEFAULT_NAME); } /*************************************************** ***************************************************/ static void __clear_simple_qos_levels() { /* * Simple QoS levels are static. * What's left is to invalidate default simple QoS level. */ __default_simple_qos_level.sl_set = FALSE; } /*************************************************** ***************************************************/ static void __setup_ulp_match_rules() { cl_list_construct(&__ulp_match_rules); cl_list_init(&__ulp_match_rules, 10); } /*************************************************** ***************************************************/ static void __process_ulp_match_rules() { cl_list_iterator_t list_iterator; osm_qos_match_rule_t *p_qos_match_rule = NULL; list_iterator = cl_list_head(&__ulp_match_rules); while (list_iterator != cl_list_end(&__ulp_match_rules)) { p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator); if (p_qos_match_rule) cl_list_insert_tail(&p_qos_policy->qos_match_rules, p_qos_match_rule); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&__ulp_match_rules); } /*************************************************** ***************************************************/ static int __cmp_num_range(const void * p1, const void * p2) { uint64_t * pair1 = *((uint64_t **)p1); uint64_t * pair2 = *((uint64_t **)p2); if (pair1[0] < pair2[0]) return -1; if (pair1[0] > pair2[0]) return 1; if (pair1[1] < pair2[1]) return -1; if (pair1[1] > pair2[1]) return 1; return 0; } /*************************************************** ***************************************************/ static void __sort_reduce_rangearr( uint64_t ** arr, unsigned arr_len, uint64_t ** * p_res_arr, unsigned * p_res_arr_len ) { unsigned i = 0; unsigned j = 0; unsigned last_valid_ind = 0; unsigned valid_cnt = 0; uint64_t ** res_arr; boolean_t * is_valid_arr; *p_res_arr = NULL; *p_res_arr_len = 0; qsort(arr, arr_len, sizeof(uint64_t*), __cmp_num_range); is_valid_arr = (boolean_t *)malloc(arr_len * sizeof(boolean_t)); is_valid_arr[last_valid_ind] = TRUE; valid_cnt++; for (i = 1; i < arr_len; i++) { if (arr[i][0] <= arr[last_valid_ind][1]) { if (arr[i][1] > arr[last_valid_ind][1]) arr[last_valid_ind][1] = arr[i][1]; free(arr[i]); arr[i] = NULL; is_valid_arr[i] = FALSE; } else if ((arr[i][0] - 1) == arr[last_valid_ind][1]) { arr[last_valid_ind][1] = arr[i][1]; free(arr[i]); arr[i] = NULL; is_valid_arr[i] = FALSE; } else { is_valid_arr[i] = TRUE; last_valid_ind = i; valid_cnt++; } } res_arr = (uint64_t **)malloc(valid_cnt * sizeof(uint64_t *)); for (i = 0; i < arr_len; i++) { if (is_valid_arr[i]) res_arr[j++] = arr[i]; } free(is_valid_arr); free(arr); *p_res_arr = res_arr; *p_res_arr_len = valid_cnt; } /*************************************************** ***************************************************/ static void __pkey_rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len) { uint64_t tmp_pkey; uint64_t * p_pkeys; cl_list_iterator_t list_iterator; list_iterator= cl_list_head(p_list); while( list_iterator != cl_list_end(p_list) ) { p_pkeys = (uint64_t *)cl_list_obj(list_iterator); p_pkeys[0] &= 0x7fff; p_pkeys[1] &= 0x7fff; if (p_pkeys[0] > p_pkeys[1]) { tmp_pkey = p_pkeys[1]; p_pkeys[1] = p_pkeys[0]; p_pkeys[0] = tmp_pkey; } list_iterator = cl_list_next(list_iterator); } __rangelist2rangearr(p_list, p_arr, p_arr_len); } /*************************************************** ***************************************************/ static void __rangelist2rangearr( cl_list_t * p_list, uint64_t ** * p_arr, unsigned * p_arr_len) { cl_list_iterator_t list_iterator; unsigned len = cl_list_count(p_list); unsigned i = 0; uint64_t ** tmp_arr; uint64_t ** res_arr = NULL; unsigned res_arr_len = 0; tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *)); list_iterator = cl_list_head(p_list); while( list_iterator != cl_list_end(p_list) ) { tmp_arr[i++] = (uint64_t *)cl_list_obj(list_iterator); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(p_list); __sort_reduce_rangearr( tmp_arr, len, &res_arr, &res_arr_len ); *p_arr = res_arr; *p_arr_len = res_arr_len; } /*************************************************** ***************************************************/ static void __merge_rangearr( uint64_t ** range_arr_1, unsigned range_len_1, uint64_t ** range_arr_2, unsigned range_len_2, uint64_t ** * p_arr, unsigned * p_arr_len ) { unsigned i = 0; unsigned j = 0; unsigned len = range_len_1 + range_len_2; uint64_t ** tmp_arr; uint64_t ** res_arr = NULL; unsigned res_arr_len = 0; *p_arr = NULL; *p_arr_len = 0; tmp_arr = (uint64_t **)malloc(len * sizeof(uint64_t *)); for (i = 0; i < range_len_1; i++) tmp_arr[j++] = range_arr_1[i]; for (i = 0; i < range_len_2; i++) tmp_arr[j++] = range_arr_2[i]; free(range_arr_1); free(range_arr_2); __sort_reduce_rangearr( tmp_arr, len, &res_arr, &res_arr_len ); *p_arr = res_arr; *p_arr_len = res_arr_len; } /*************************************************** ***************************************************/ static void __parser_add_port_to_port_map( cl_qmap_t * p_map, osm_physp_t * p_physp) { if (cl_qmap_get(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp))) == cl_qmap_end(p_map)) { osm_qos_port_t * p_port = osm_qos_policy_port_create(p_physp); if (p_port) cl_qmap_insert(p_map, cl_ntoh64(osm_physp_get_port_guid(p_physp)), &p_port->map_item); } } /*************************************************** ***************************************************/ static void __parser_add_guid_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len) { unsigned i; uint64_t guid_ho; osm_port_t * p_osm_port; if (!range_arr || !range_len) return; for (i = 0; i < range_len; i++) { for (guid_ho = range_arr[i][0]; guid_ho <= range_arr[i][1]; guid_ho++) { p_osm_port = osm_get_port_by_guid(p_qos_policy->p_subn, cl_hton64(guid_ho)); if (p_osm_port) __parser_add_port_to_port_map(p_map, p_osm_port->p_physp); } free(range_arr[i]); } free(range_arr); } /*************************************************** ***************************************************/ static void __parser_add_pkey_range_to_port_map( cl_qmap_t * p_map, uint64_t ** range_arr, unsigned range_len) { unsigned i; uint64_t pkey_64; ib_net16_t pkey; osm_prtn_t * p_prtn; if (!range_arr || !range_len) return; for (i = 0; i < range_len; i++) { for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) { pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); p_prtn = (osm_prtn_t *) cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey); if (p_prtn != (osm_prtn_t *)cl_qmap_end( &p_qos_policy->p_subn->prtn_pkey_tbl)) { __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl); __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl); } } free(range_arr[i]); } free(range_arr); } /*************************************************** ***************************************************/ static void __parser_add_partition_list_to_port_map( cl_qmap_t * p_map, cl_list_t * p_list) { cl_list_iterator_t list_iterator; char * tmp_str; osm_prtn_t * p_prtn; /* extract all the ports from the partition to the port map of this port group */ list_iterator = cl_list_head(p_list); while(list_iterator != cl_list_end(p_list)) { tmp_str = (char*)cl_list_obj(list_iterator); if (tmp_str) { p_prtn = osm_prtn_find_by_name(p_qos_policy->p_subn, tmp_str); if (p_prtn) { __parser_add_map_to_port_map(p_map, &p_prtn->part_guid_tbl); __parser_add_map_to_port_map(p_map, &p_prtn->full_guid_tbl); } free(tmp_str); } list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(p_list); } /*************************************************** ***************************************************/ static void __parser_add_map_to_port_map( cl_qmap_t * p_dmap, cl_map_t * p_smap) { cl_map_iterator_t map_iterator; osm_physp_t * p_physp; if (!p_dmap || !p_smap) return; map_iterator = cl_map_head(p_smap); while (map_iterator != cl_map_end(p_smap)) { p_physp = (osm_physp_t*)cl_map_obj(map_iterator); __parser_add_port_to_port_map(p_dmap, p_physp); map_iterator = cl_map_next(map_iterator); } } /*************************************************** ***************************************************/ static int __validate_pkeys( uint64_t ** range_arr, unsigned range_len, boolean_t is_ipoib) { unsigned i; uint64_t pkey_64; ib_net16_t pkey; osm_prtn_t * p_prtn; if (!range_arr || !range_len) return 0; for (i = 0; i < range_len; i++) { for (pkey_64 = range_arr[i][0]; pkey_64 <= range_arr[i][1]; pkey_64++) { pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); p_prtn = (osm_prtn_t *) cl_qmap_get(&p_qos_policy->p_subn->prtn_pkey_tbl, pkey); if (p_prtn == (osm_prtn_t *)cl_qmap_end( &p_qos_policy->p_subn->prtn_pkey_tbl)) p_prtn = NULL; if (is_ipoib) { /* * Be very strict for IPoIB partition: * - the partition for the pkey have to exist * - it has to have at least 2 full members */ if (!p_prtn) { yyerror("IPoIB partition, pkey 0x%04X - " "partition doesn't exist", cl_ntoh16(pkey)); return 1; } else if (cl_map_count(&p_prtn->full_guid_tbl) < 2) { yyerror("IPoIB partition, pkey 0x%04X - " "partition has less than two full members", cl_ntoh16(pkey)); return 1; } } else if (!p_prtn) { /* * For non-IPoIB pkey we just want to check that * the relevant partition exists. * And even if it doesn't, don't exit - just print * error message and continue. */ OSM_LOG(p_qos_parser_osm_log, OSM_LOG_ERROR, "ERR AC02: " "pkey 0x%04X - partition doesn't exist", cl_ntoh16(pkey)); } } } return 0; } /*************************************************** ***************************************************/ opensm-3.3.20/opensm/osm_qos_parser_l.l0000644000205000001450000005111012104655725015042 00000000000000%{ /* * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2008 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: * Lexer of OSM QoS parser. * * Environment: * Linux User Mode * * Author: * Yevgeny Kliteynik, Mellanox */ #include #define FILE_ID OSM_FILE_QOS_PARSER_L_L #include #include "osm_qos_parser_y.h" #define HANDLE_IF_IN_DESCRIPTION if (in_description) { yylval = strdup(yytext); return TK_TEXT; } #define SAVE_POS save_pos() static void save_pos(); extern int column_num; extern int line_num; extern FILE * yyin; extern YYSTYPE yylval; boolean_t in_description = FALSE; boolean_t in_list_of_hex_num_ranges = FALSE; boolean_t in_node_type = FALSE; boolean_t in_list_of_numbers = FALSE; boolean_t in_list_of_strings = FALSE; boolean_t in_list_of_num_pairs = FALSE; boolean_t in_asterisk_or_list_of_numbers = FALSE; boolean_t in_list_of_num_ranges = FALSE; boolean_t in_single_string = FALSE; boolean_t in_single_number = FALSE; static void reset_new_line_flags(); #define RESET_NEW_LINE_FLAGS reset_new_line_flags() #define START_USE {in_description = TRUE;} /* list of strings including whitespace (description) */ #define START_PORT_GUID {in_list_of_hex_num_ranges = TRUE;} /* comma-separated list of hex num ranges */ #define START_PORT_NAME {in_list_of_strings = TRUE;} /* comma-separated list of following strings: ../../.. */ #define START_PARTITION {in_single_string = TRUE;} /* single string w/o whitespaces (partition name) */ #define START_NAME {in_single_string = TRUE;} /* single string w/o whitespaces (port group name) */ #define START_QOS_LEVEL_NAME {in_single_string = TRUE;} /* single string w/o whitespaces (qos level name in match rule) */ #define START_NODE_TYPE {in_node_type = TRUE;} /* comma-separated list of node types (ROUTER,CA,...) */ #define START_SL2VL_TABLE {in_list_of_numbers = TRUE;} /* comma-separated list of hex or dec numbers */ #define START_GROUP {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS_TO {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_ACROSS_FROM {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_SOURCE {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_DESTINATION {in_list_of_strings = TRUE;} /* list of strings w/o whitespaces (group names) */ #define START_VLARB_HIGH {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */ #define START_VLARB_LOW {in_list_of_num_pairs = TRUE;} /* comma-separated list of hex or dec num pairs: "num1:num2" */ #define START_TO {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */ #define START_FROM {in_asterisk_or_list_of_numbers = TRUE;} /* (asterisk) or (comma-separated list of hex or dec numbers) */ #define START_PATH_BITS {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_QOS_CLASS {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_SERVICE_ID {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_PKEY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_SL {in_single_number = TRUE;} /* single number */ #define START_VLARB_HIGH_LIMIT {in_single_number = TRUE;} /* single number */ #define START_MTU_LIMIT {in_single_number = TRUE;} /* single number */ #define START_RATE_LIMIT {in_single_number = TRUE;} /* single number */ #define START_PACKET_LIFE {in_single_number = TRUE;} /* single number */ #define START_ULP_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_ANY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_SDP_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_SDP_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_RDS_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_RDS_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_ISER_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_ISER_PORT {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_SRP_GUID {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ #define START_ULP_IPOIB_DEFAULT {in_single_number = TRUE;} /* single number */ #define START_ULP_IPOIB_PKEY {in_list_of_num_ranges = TRUE;} /* comma-separated list of hex or dec num ranges */ %} %option nounput noinput QOS_ULPS_START qos\-ulps QOS_ULPS_END end\-qos\-ulps PORT_GROUPS_START port\-groups PORT_GROUPS_END end\-port\-groups PORT_GROUP_START port\-group PORT_GROUP_END end\-port\-group PORT_NUM port\-num NAME name USE use PORT_GUID port\-guid TARGET_PORT_GUID target\-port\-guid SOURCE_PORT_GUID source\-port\-guid SOURCE_TARGET_PORT_GUID source\-target\-port\-guid PORT_NAME port\-name PARTITION partition NODE_TYPE node\-type QOS_SETUP_START qos\-setup QOS_SETUP_END end\-qos\-setup VLARB_TABLES_START vlarb\-tables VLARB_TABLES_END end\-vlarb\-tables VLARB_SCOPE_START vlarb\-scope VLARB_SCOPE_END end\-vlarb\-scope GROUP group ACROSS across VLARB_HIGH vlarb\-high VLARB_LOW vlarb\-low VLARB_HIGH_LIMIT vl\-high\-limit SL2VL_TABLES_START sl2vl\-tables SL2VL_TABLES_END end\-sl2vl\-tables SL2VL_SCOPE_START sl2vl\-scope SL2VL_SCOPE_END end\-sl2vl\-scope TO to FROM from ACROSS_TO across\-to ACROSS_FROM across\-from SL2VL_TABLE sl2vl\-table QOS_LEVELS_START qos\-levels QOS_LEVELS_END end\-qos\-levels QOS_LEVEL_START qos\-level QOS_LEVEL_END end\-qos\-level SL sl MTU_LIMIT mtu\-limit RATE_LIMIT rate\-limit PACKET_LIFE packet\-life PATH_BITS path\-bits QOS_MATCH_RULES_START qos\-match\-rules QOS_MATCH_RULES_END end\-qos\-match\-rules QOS_MATCH_RULE_START qos\-match\-rule QOS_MATCH_RULE_END end\-qos\-match\-rule QOS_CLASS qos\-class SOURCE source DESTINATION destination SERVICE_ID service\-id PKEY pkey QOS_LEVEL_NAME qos\-level\-name ROUTER [Rr][Oo][Uu][Tt][Ee][Rr] CA [Cc][Aa] SWITCH [Ss][Ww][Ii][Tt][Cc][Hh] SELF [Ss][Ee][Ll][Ff] ALL [Aa][Ll][Ll] ULP_SDP [Ss][Dd][Pp] ULP_SRP [Ss][Rr][Pp] ULP_RDS [Rr][Dd][Ss] ULP_IPOIB [Ii][Pp][Oo][Ii][Bb] ULP_ISER [Ii][Ss][Ee][Rr] ULP_ANY [Aa][Nn][Yy] ULP_DEFAULT [Dd][Ee][Ff][Aa][Uu][Ll][Tt] WHITE [ \t]+ NEW_LINE \n COMMENT \#.*\n WHITE_DOTDOT_WHITE [ \t]*:[ \t]* WHITE_COMMA_WHITE [ \t]*,[ \t]* QUOTED_TEXT \"[^\"]*\" %% {COMMENT} { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* swallow comment */ {WHITE}{NEW_LINE} { SAVE_POS; RESET_NEW_LINE_FLAGS; } /* trailing blanks with new line */ {WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; } {NEW_LINE} { SAVE_POS; RESET_NEW_LINE_FLAGS; } {QOS_ULPS_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_START; } {QOS_ULPS_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_ULPS_END; } {PORT_GROUPS_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_START; } {PORT_GROUPS_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUPS_END; } {PORT_GROUP_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_START; } {PORT_GROUP_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_PORT_GROUP_END; } {QOS_SETUP_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_START; } {QOS_SETUP_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_SETUP_END; } {VLARB_TABLES_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_START; } {VLARB_TABLES_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_TABLES_END; } {VLARB_SCOPE_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_START; } {VLARB_SCOPE_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_VLARB_SCOPE_END; } {SL2VL_TABLES_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_START; } {SL2VL_TABLES_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_TABLES_END; } {SL2VL_SCOPE_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_START; } {SL2VL_SCOPE_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_SL2VL_SCOPE_END; } {QOS_LEVELS_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_START; } {QOS_LEVELS_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVELS_END; } {QOS_LEVEL_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_START; } {QOS_LEVEL_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_LEVEL_END; } {QOS_MATCH_RULES_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_START; } {QOS_MATCH_RULES_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULES_END; } {QOS_MATCH_RULE_START} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_START; } {QOS_MATCH_RULE_END} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; return TK_QOS_MATCH_RULE_END; } {PORT_GUID}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_GUID; return TK_PORT_GUID; } {PORT_NAME}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PORT_NAME; return TK_PORT_NAME; } {PARTITION}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PARTITION; return TK_PARTITION; } {NODE_TYPE}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NODE_TYPE; return TK_NODE_TYPE; } {NAME}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_NAME; return TK_NAME; } {USE}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_USE; return TK_USE; } {GROUP}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_GROUP; return TK_GROUP; } {VLARB_HIGH}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH; return TK_VLARB_HIGH; } {VLARB_LOW}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_LOW; return TK_VLARB_LOW; } {VLARB_HIGH_LIMIT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_VLARB_HIGH_LIMIT; return TK_VLARB_HIGH_LIMIT;} {TO}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_TO; return TK_TO; } {FROM}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_FROM; return TK_FROM; } {ACROSS_TO}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_TO; return TK_ACROSS_TO; } {ACROSS_FROM}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS_FROM; return TK_ACROSS_FROM;} {ACROSS}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ACROSS; return TK_ACROSS; } {SL2VL_TABLE}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL2VL_TABLE; return TK_SL2VL_TABLE;} {SL}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SL; return TK_SL; } {MTU_LIMIT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_MTU_LIMIT; return TK_MTU_LIMIT; } {RATE_LIMIT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_RATE_LIMIT; return TK_RATE_LIMIT; } {PACKET_LIFE}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PACKET_LIFE; return TK_PACKET_LIFE;} {PATH_BITS}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PATH_BITS; return TK_PATH_BITS; } {QOS_CLASS}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_CLASS; return TK_QOS_CLASS; } {SOURCE}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SOURCE; return TK_SOURCE; } {DESTINATION}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_DESTINATION; return TK_DESTINATION;} {SERVICE_ID}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_SERVICE_ID; return TK_SERVICE_ID; } {PKEY}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_PKEY; return TK_PKEY; } {QOS_LEVEL_NAME}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_QOS_LEVEL_NAME; return TK_QOS_LEVEL_NAME;} {ROUTER} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ROUTER; yylval = strdup(yytext); return TK_TEXT; } {CA} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_CA; yylval = strdup(yytext); return TK_TEXT; } {SWITCH} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SWITCH; yylval = strdup(yytext); return TK_TEXT; } {SELF} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_SELF; yylval = strdup(yytext); return TK_TEXT; } {ALL} { SAVE_POS; if (in_node_type) return TK_NODE_TYPE_ALL; yylval = strdup(yytext); return TK_TEXT; } {ULP_DEFAULT}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_DEFAULT; return TK_ULP_DEFAULT; } {ULP_ANY}{WHITE_COMMA_WHITE}{SERVICE_ID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SERVICE_ID; } {ULP_ANY}{WHITE_COMMA_WHITE}{PKEY} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_PKEY; } {ULP_ANY}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_TARGET_PORT_GUID; } {ULP_ANY}{WHITE_COMMA_WHITE}{SOURCE_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SOURCE_PORT_GUID; } {ULP_ANY}{WHITE_COMMA_WHITE}{SOURCE_TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_ANY; return TK_ULP_ANY_SOURCE_TARGET_PORT_GUID; } {ULP_SDP}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_SDP_DEFAULT; } {ULP_SDP}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_SDP_PORT; } {ULP_RDS}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_DEFAULT; return TK_ULP_RDS_DEFAULT; } {ULP_RDS}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_RDS_PORT; return TK_ULP_RDS_PORT; } {ULP_ISER}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_DEFAULT; return TK_ULP_ISER_DEFAULT; } {ULP_ISER}{WHITE_COMMA_WHITE}{PORT_NUM} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SDP_PORT; return TK_ULP_ISER_PORT; } {ULP_SRP}{WHITE_COMMA_WHITE}{TARGET_PORT_GUID} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_SRP_GUID; return TK_ULP_SRP_GUID; } {ULP_IPOIB}{WHITE_DOTDOT_WHITE} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_DEFAULT; return TK_ULP_IPOIB_DEFAULT; } {ULP_IPOIB}{WHITE_COMMA_WHITE}{PKEY} { SAVE_POS; HANDLE_IF_IN_DESCRIPTION; START_ULP_IPOIB_PKEY; return TK_ULP_IPOIB_PKEY; } 0[xX][0-9a-fA-F]+ { SAVE_POS; yylval = strdup(yytext); if (in_description || in_list_of_strings || in_single_string) return TK_TEXT; return TK_NUMBER; } [0-9]+ { SAVE_POS; yylval = strdup(yytext); if (in_description || in_list_of_strings || in_single_string) return TK_TEXT; return TK_NUMBER; } - { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_DASH; } : { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_DOTDOT; } , { SAVE_POS; if (in_description) { yylval = strdup(yytext); return TK_TEXT; } return TK_COMMA; } \* { SAVE_POS; if (in_description || in_list_of_strings || in_single_string) { yylval = strdup(yytext); return TK_TEXT; } return TK_ASTERISK; } {QUOTED_TEXT} { SAVE_POS; yylval = strdup(&yytext[1]); yylval[strlen(yylval)-1] = '\0'; return TK_TEXT; } . { SAVE_POS; yylval = strdup(yytext); return TK_TEXT;} <> { YY_NEW_FILE; yyterminate(); } %% /********************************************* *********************************************/ static void save_pos() { int i; for (i = 0; i < yyleng; i++) { if (yytext[i] == '\n') { line_num ++; column_num = 1; } else column_num ++; } } /********************************************* *********************************************/ static void reset_new_line_flags() { in_description = FALSE; in_list_of_hex_num_ranges = FALSE; in_node_type = FALSE; in_list_of_numbers = FALSE; in_list_of_strings = FALSE; in_list_of_num_pairs = FALSE; in_asterisk_or_list_of_numbers = FALSE; in_list_of_num_ranges = FALSE; in_single_string = FALSE; in_single_number = FALSE; } opensm-3.3.20/opensm/osm_qos_policy.c0000644000205000001450000007637712272264653014551 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2012 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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: * OSM QoS Policy functions. * * Author: * Yevgeny Kliteynik, Mellanox */ #include #include #include #include #include #include #include #define FILE_ID OSM_FILE_QOS_POLICY_C #include #include #include #include #include #include extern osm_qos_level_t __default_simple_qos_level; /*************************************************** ***************************************************/ static void __build_nodebyname_hash(osm_qos_policy_t * p_qos_policy) { osm_node_t * p_node; cl_qmap_t * p_node_guid_tbl = &p_qos_policy->p_subn->node_guid_tbl; p_qos_policy->p_node_hash = st_init_strtable(); CL_ASSERT(p_qos_policy->p_node_hash); if (!p_node_guid_tbl || !cl_qmap_count(p_node_guid_tbl)) return; for (p_node = (osm_node_t *) cl_qmap_head(p_node_guid_tbl); p_node != (osm_node_t *) cl_qmap_end(p_node_guid_tbl); p_node = (osm_node_t *) cl_qmap_next(&p_node->map_item)) { if (!st_lookup(p_qos_policy->p_node_hash, (st_data_t)p_node->print_desc, NULL)) st_insert(p_qos_policy->p_node_hash, (st_data_t)p_node->print_desc, (st_data_t)p_node); } } /*************************************************** ***************************************************/ static boolean_t __is_num_in_range_arr(uint64_t ** range_arr, unsigned range_arr_len, uint64_t num) { unsigned ind_1 = 0; unsigned ind_2 = range_arr_len - 1; unsigned ind_mid; if (!range_arr || !range_arr_len) return FALSE; while (ind_1 <= ind_2) { if (num < range_arr[ind_1][0] || num > range_arr[ind_2][1]) return FALSE; else if (num <= range_arr[ind_1][1] || num >= range_arr[ind_2][0]) return TRUE; ind_mid = ind_1 + (ind_2 - ind_1 + 1)/2; if (num < range_arr[ind_mid][0]) ind_2 = ind_mid; else if (num > range_arr[ind_mid][1]) ind_1 = ind_mid; else return TRUE; ind_1++; ind_2--; } return FALSE; } /*************************************************** ***************************************************/ static void __free_single_element(void *p_element, void *context) { if (p_element) free(p_element); } /*************************************************** ***************************************************/ osm_qos_port_t *osm_qos_policy_port_create(osm_physp_t *p_physp) { osm_qos_port_t *p = (osm_qos_port_t *) calloc(1, sizeof(osm_qos_port_t)); if (p) p->p_physp = p_physp; return p; } /*************************************************** ***************************************************/ osm_qos_port_group_t *osm_qos_policy_port_group_create() { osm_qos_port_group_t *p = (osm_qos_port_group_t *) calloc(1, sizeof(osm_qos_port_group_t)); if (p) cl_qmap_init(&p->port_map); return p; } /*************************************************** ***************************************************/ void osm_qos_policy_port_group_destroy(osm_qos_port_group_t * p) { osm_qos_port_t * p_port; osm_qos_port_t * p_old_port; if (!p) return; if (p->name) free(p->name); if (p->use) free(p->use); p_port = (osm_qos_port_t *) cl_qmap_head(&p->port_map); while (p_port != (osm_qos_port_t *) cl_qmap_end(&p->port_map)) { p_old_port = p_port; p_port = (osm_qos_port_t *) cl_qmap_next(&p_port->map_item); free(p_old_port); } cl_qmap_remove_all(&p->port_map); free(p); } /*************************************************** ***************************************************/ osm_qos_vlarb_scope_t *osm_qos_policy_vlarb_scope_create() { osm_qos_vlarb_scope_t *p = (osm_qos_vlarb_scope_t *) calloc(1, sizeof(osm_qos_vlarb_scope_t)); if (p) { cl_list_init(&p->group_list, 10); cl_list_init(&p->across_list, 10); cl_list_init(&p->vlarb_high_list, 10); cl_list_init(&p->vlarb_low_list, 10); } return p; } /*************************************************** ***************************************************/ void osm_qos_policy_vlarb_scope_destroy(osm_qos_vlarb_scope_t * p) { if (!p) return; cl_list_apply_func(&p->group_list, __free_single_element, NULL); cl_list_apply_func(&p->across_list, __free_single_element, NULL); cl_list_apply_func(&p->vlarb_high_list, __free_single_element, NULL); cl_list_apply_func(&p->vlarb_low_list, __free_single_element, NULL); cl_list_remove_all(&p->group_list); cl_list_remove_all(&p->across_list); cl_list_remove_all(&p->vlarb_high_list); cl_list_remove_all(&p->vlarb_low_list); cl_list_destroy(&p->group_list); cl_list_destroy(&p->across_list); cl_list_destroy(&p->vlarb_high_list); cl_list_destroy(&p->vlarb_low_list); free(p); } /*************************************************** ***************************************************/ osm_qos_sl2vl_scope_t *osm_qos_policy_sl2vl_scope_create() { osm_qos_sl2vl_scope_t *p = (osm_qos_sl2vl_scope_t *) calloc(1, sizeof(osm_qos_sl2vl_scope_t)); if (p) { cl_list_init(&p->group_list, 10); cl_list_init(&p->across_from_list, 10); cl_list_init(&p->across_to_list, 10); } return p; } /*************************************************** ***************************************************/ void osm_qos_policy_sl2vl_scope_destroy(osm_qos_sl2vl_scope_t * p) { if (!p) return; cl_list_apply_func(&p->group_list, __free_single_element, NULL); cl_list_apply_func(&p->across_from_list, __free_single_element, NULL); cl_list_apply_func(&p->across_to_list, __free_single_element, NULL); cl_list_remove_all(&p->group_list); cl_list_remove_all(&p->across_from_list); cl_list_remove_all(&p->across_to_list); cl_list_destroy(&p->group_list); cl_list_destroy(&p->across_from_list); cl_list_destroy(&p->across_to_list); free(p); } /*************************************************** ***************************************************/ osm_qos_level_t *osm_qos_policy_qos_level_create() { osm_qos_level_t *p = (osm_qos_level_t *) calloc(1, sizeof(osm_qos_level_t)); return p; } /*************************************************** ***************************************************/ void osm_qos_policy_qos_level_destroy(osm_qos_level_t * p) { unsigned i; if (!p) return; free(p->name); free(p->use); for (i = 0; i < p->path_bits_range_len; i++) free(p->path_bits_range_arr[i]); free(p->path_bits_range_arr); for(i = 0; i < p->pkey_range_len; i++) free((p->pkey_range_arr[i])); free(p->pkey_range_arr); free(p); } /*************************************************** ***************************************************/ boolean_t osm_qos_level_has_pkey(IN const osm_qos_level_t * p_qos_level, IN ib_net16_t pkey) { if (!p_qos_level || !p_qos_level->pkey_range_len) return FALSE; return __is_num_in_range_arr(p_qos_level->pkey_range_arr, p_qos_level->pkey_range_len, cl_ntoh16(ib_pkey_get_base(pkey))); } /*************************************************** ***************************************************/ ib_net16_t osm_qos_level_get_shared_pkey(IN const osm_qos_level_t * p_qos_level, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN const boolean_t allow_both_pkeys) { unsigned i; uint16_t pkey_ho = 0; if (!p_qos_level || !p_qos_level->pkey_range_len) return 0; /* * ToDo: This approach is not optimal. * Think how to find shared pkey that also exists * in QoS level in less runtime. */ for (i = 0; i < p_qos_level->pkey_range_len; i++) { for (pkey_ho = p_qos_level->pkey_range_arr[i][0]; pkey_ho <= p_qos_level->pkey_range_arr[i][1]; pkey_ho++) { if (osm_physp_share_this_pkey (p_src_physp, p_dest_physp, cl_hton16(pkey_ho), allow_both_pkeys)) return cl_hton16(pkey_ho); } } return 0; } /*************************************************** ***************************************************/ osm_qos_match_rule_t *osm_qos_policy_match_rule_create() { osm_qos_match_rule_t *p = (osm_qos_match_rule_t *) calloc(1, sizeof(osm_qos_match_rule_t)); if (p) { cl_list_init(&p->source_list, 10); cl_list_init(&p->source_group_list, 10); cl_list_init(&p->destination_list, 10); cl_list_init(&p->destination_group_list, 10); } return p; } /*************************************************** ***************************************************/ void osm_qos_policy_match_rule_destroy(osm_qos_match_rule_t * p) { unsigned i; if (!p) return; if (p->qos_level_name) free(p->qos_level_name); if (p->use) free(p->use); if (p->service_id_range_arr) { for (i = 0; i < p->service_id_range_len; i++) free(p->service_id_range_arr[i]); free(p->service_id_range_arr); } if (p->qos_class_range_arr) { for (i = 0; i < p->qos_class_range_len; i++) free(p->qos_class_range_arr[i]); free(p->qos_class_range_arr); } if (p->pkey_range_arr) { for (i = 0; i < p->pkey_range_len; i++) free(p->pkey_range_arr[i]); free(p->pkey_range_arr); } cl_list_apply_func(&p->source_list, __free_single_element, NULL); cl_list_remove_all(&p->source_list); cl_list_destroy(&p->source_list); cl_list_remove_all(&p->source_group_list); cl_list_destroy(&p->source_group_list); cl_list_apply_func(&p->destination_list, __free_single_element, NULL); cl_list_remove_all(&p->destination_list); cl_list_destroy(&p->destination_list); cl_list_remove_all(&p->destination_group_list); cl_list_destroy(&p->destination_group_list); free(p); } /*************************************************** ***************************************************/ osm_qos_policy_t * osm_qos_policy_create(osm_subn_t * p_subn) { osm_qos_policy_t * p_qos_policy = (osm_qos_policy_t *)calloc(1, sizeof(osm_qos_policy_t)); if (!p_qos_policy) return NULL; cl_list_construct(&p_qos_policy->port_groups); cl_list_init(&p_qos_policy->port_groups, 10); cl_list_construct(&p_qos_policy->vlarb_tables); cl_list_init(&p_qos_policy->vlarb_tables, 10); cl_list_construct(&p_qos_policy->sl2vl_tables); cl_list_init(&p_qos_policy->sl2vl_tables, 10); cl_list_construct(&p_qos_policy->qos_levels); cl_list_init(&p_qos_policy->qos_levels, 10); cl_list_construct(&p_qos_policy->qos_match_rules); cl_list_init(&p_qos_policy->qos_match_rules, 10); p_qos_policy->p_subn = p_subn; __build_nodebyname_hash(p_qos_policy); return p_qos_policy; } /*************************************************** ***************************************************/ void osm_qos_policy_destroy(osm_qos_policy_t * p_qos_policy) { cl_list_iterator_t list_iterator; osm_qos_port_group_t *p_port_group = NULL; osm_qos_vlarb_scope_t *p_vlarb_scope = NULL; osm_qos_sl2vl_scope_t *p_sl2vl_scope = NULL; osm_qos_level_t *p_qos_level = NULL; osm_qos_match_rule_t *p_qos_match_rule = NULL; if (!p_qos_policy) return; list_iterator = cl_list_head(&p_qos_policy->port_groups); while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { p_port_group = (osm_qos_port_group_t *) cl_list_obj(list_iterator); if (p_port_group) osm_qos_policy_port_group_destroy(p_port_group); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&p_qos_policy->port_groups); cl_list_destroy(&p_qos_policy->port_groups); list_iterator = cl_list_head(&p_qos_policy->vlarb_tables); while (list_iterator != cl_list_end(&p_qos_policy->vlarb_tables)) { p_vlarb_scope = (osm_qos_vlarb_scope_t *) cl_list_obj(list_iterator); if (p_vlarb_scope) osm_qos_policy_vlarb_scope_destroy(p_vlarb_scope); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&p_qos_policy->vlarb_tables); cl_list_destroy(&p_qos_policy->vlarb_tables); list_iterator = cl_list_head(&p_qos_policy->sl2vl_tables); while (list_iterator != cl_list_end(&p_qos_policy->sl2vl_tables)) { p_sl2vl_scope = (osm_qos_sl2vl_scope_t *) cl_list_obj(list_iterator); if (p_sl2vl_scope) osm_qos_policy_sl2vl_scope_destroy(p_sl2vl_scope); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&p_qos_policy->sl2vl_tables); cl_list_destroy(&p_qos_policy->sl2vl_tables); list_iterator = cl_list_head(&p_qos_policy->qos_levels); while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); if (p_qos_level) osm_qos_policy_qos_level_destroy(p_qos_level); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&p_qos_policy->qos_levels); cl_list_destroy(&p_qos_policy->qos_levels); list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator); if (p_qos_match_rule) osm_qos_policy_match_rule_destroy(p_qos_match_rule); list_iterator = cl_list_next(list_iterator); } cl_list_remove_all(&p_qos_policy->qos_match_rules); cl_list_destroy(&p_qos_policy->qos_match_rules); if (p_qos_policy->p_node_hash) st_free_table(p_qos_policy->p_node_hash); free(p_qos_policy); p_qos_policy = NULL; } /*************************************************** ***************************************************/ static boolean_t __qos_policy_is_port_in_group(osm_subn_t * p_subn, const osm_physp_t * p_physp, osm_qos_port_group_t * p_port_group) { osm_node_t *p_node = osm_physp_get_node_ptr(p_physp); ib_net64_t port_guid = osm_physp_get_port_guid(p_physp); uint64_t port_guid_ho = cl_ntoh64(port_guid); /* check whether this port's type matches any of group's types */ if ( p_port_group->node_types & (((uint8_t)1)<port_map, port_guid_ho) != cl_qmap_end(&p_port_group->port_map)) return TRUE; return FALSE; } /* __qos_policy_is_port_in_group() */ /*************************************************** ***************************************************/ static boolean_t __qos_policy_is_port_in_group_list(const osm_qos_policy_t * p_qos_policy, const osm_physp_t * p_physp, cl_list_t * p_port_group_list) { osm_qos_port_group_t *p_port_group; cl_list_iterator_t list_iterator; list_iterator = cl_list_head(p_port_group_list); while (list_iterator != cl_list_end(p_port_group_list)) { p_port_group = (osm_qos_port_group_t *) cl_list_obj(list_iterator); if (p_port_group) { if (__qos_policy_is_port_in_group (p_qos_policy->p_subn, p_physp, p_port_group)) return TRUE; } list_iterator = cl_list_next(list_iterator); } return FALSE; } /*************************************************** ***************************************************/ static osm_qos_match_rule_t *__qos_policy_get_match_rule_by_params( const osm_qos_policy_t * p_qos_policy, uint64_t service_id, uint16_t qos_class, uint16_t pkey, const osm_physp_t * p_src_physp, const osm_physp_t * p_dest_physp, ib_net64_t comp_mask) { osm_qos_match_rule_t *p_qos_match_rule = NULL; cl_list_iterator_t list_iterator; osm_log_t * p_log = &p_qos_policy->p_subn->p_osm->log; boolean_t matched_by_sguid = FALSE, matched_by_dguid = FALSE, matched_by_sordguid = FALSE, matched_by_class = FALSE, matched_by_sid = FALSE, matched_by_pkey = FALSE; if (!cl_list_count(&p_qos_policy->qos_match_rules)) return NULL; OSM_LOG_ENTER(p_log); /* Go over all QoS match rules and find the one that matches the request */ list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); while (list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(list_iterator); if (!p_qos_match_rule) { list_iterator = cl_list_next(list_iterator); continue; } /* If a match rule has Source groups and no Destination groups, * PR request source has to be in this list */ if (cl_list_count(&p_qos_match_rule->source_group_list) && !cl_list_count(&p_qos_match_rule->destination_group_list)) { if (!__qos_policy_is_port_in_group_list(p_qos_policy, p_src_physp, &p_qos_match_rule-> source_group_list)) { list_iterator = cl_list_next(list_iterator); continue; } matched_by_sguid = TRUE; } /* If a match rule has Destination groups and no Source groups, * PR request dest. has to be in this list */ if (cl_list_count(&p_qos_match_rule->destination_group_list) && !cl_list_count(&p_qos_match_rule->source_group_list)) { if (!__qos_policy_is_port_in_group_list(p_qos_policy, p_dest_physp, &p_qos_match_rule-> destination_group_list)) { list_iterator = cl_list_next(list_iterator); continue; } matched_by_dguid = TRUE; } /* If a match rule has both Source and Destination groups, * PR request source or dest. must be in respective list */ if (cl_list_count(&p_qos_match_rule->source_group_list) && cl_list_count(&p_qos_match_rule->destination_group_list)) { if (__qos_policy_is_port_in_group_list(p_qos_policy, p_src_physp, &p_qos_match_rule-> source_group_list) && __qos_policy_is_port_in_group_list(p_qos_policy, p_dest_physp, &p_qos_match_rule-> destination_group_list)) matched_by_sordguid = TRUE; else { list_iterator = cl_list_next(list_iterator); continue; } } /* If a match rule has QoS classes, PR request HAS to have a matching QoS class to match the rule */ if (p_qos_match_rule->qos_class_range_len) { if (!(comp_mask & IB_PR_COMPMASK_QOS_CLASS)) { list_iterator = cl_list_next(list_iterator); continue; } if (!__is_num_in_range_arr (p_qos_match_rule->qos_class_range_arr, p_qos_match_rule->qos_class_range_len, qos_class)) { list_iterator = cl_list_next(list_iterator); continue; } matched_by_class = TRUE; } /* If a match rule has Service IDs, PR request HAS to have a matching Service ID to match the rule */ if (p_qos_match_rule->service_id_range_len) { if (!(comp_mask & IB_PR_COMPMASK_SERVICEID_MSB) || !(comp_mask & IB_PR_COMPMASK_SERVICEID_LSB)) { list_iterator = cl_list_next(list_iterator); continue; } if (!__is_num_in_range_arr (p_qos_match_rule->service_id_range_arr, p_qos_match_rule->service_id_range_len, service_id)) { list_iterator = cl_list_next(list_iterator); continue; } matched_by_sid = TRUE; } /* If a match rule has PKeys, PR request HAS to have a matching PKey to match the rule */ if (p_qos_match_rule->pkey_range_len) { if (!(comp_mask & IB_PR_COMPMASK_PKEY)) { list_iterator = cl_list_next(list_iterator); continue; } if (!__is_num_in_range_arr (p_qos_match_rule->pkey_range_arr, p_qos_match_rule->pkey_range_len, pkey & 0x7FFF)) { list_iterator = cl_list_next(list_iterator); continue; } matched_by_pkey = TRUE; } /* if we got here, then this match-rule matched this PR request */ break; } if (list_iterator == cl_list_end(&p_qos_policy->qos_match_rules)) p_qos_match_rule = NULL; if (p_qos_match_rule) OSM_LOG(p_log, OSM_LOG_DEBUG, "request matched rule (%s) by:%s%s%s%s%s%s\n", (p_qos_match_rule->use) ? p_qos_match_rule->use : "no description", (matched_by_sguid) ? " SGUID" : "", (matched_by_dguid) ? " DGUID" : "", (matched_by_sordguid) ? "SorDGUID" : "", (matched_by_class) ? " QoS_Class" : "", (matched_by_sid) ? " ServiceID" : "", (matched_by_pkey) ? " PKey" : ""); else OSM_LOG(p_log, OSM_LOG_DEBUG, "request not matched any rule\n"); OSM_LOG_EXIT(p_log); return p_qos_match_rule; } /* __qos_policy_get_match_rule_by_params() */ /*************************************************** ***************************************************/ static osm_qos_level_t *__qos_policy_get_qos_level_by_name( const osm_qos_policy_t * p_qos_policy, const char *name) { osm_qos_level_t *p_qos_level = NULL; cl_list_iterator_t list_iterator; list_iterator = cl_list_head(&p_qos_policy->qos_levels); while (list_iterator != cl_list_end(&p_qos_policy->qos_levels)) { p_qos_level = (osm_qos_level_t *) cl_list_obj(list_iterator); if (!p_qos_level) continue; /* names are case INsensitive */ if (strcasecmp(name, p_qos_level->name) == 0) return p_qos_level; list_iterator = cl_list_next(list_iterator); } return NULL; } /*************************************************** ***************************************************/ static osm_qos_port_group_t *__qos_policy_get_port_group_by_name( const osm_qos_policy_t * p_qos_policy, const char *const name) { osm_qos_port_group_t *p_port_group = NULL; cl_list_iterator_t list_iterator; list_iterator = cl_list_head(&p_qos_policy->port_groups); while (list_iterator != cl_list_end(&p_qos_policy->port_groups)) { p_port_group = (osm_qos_port_group_t *) cl_list_obj(list_iterator); if (!p_port_group) continue; /* names are case INsensitive */ if (strcasecmp(name, p_port_group->name) == 0) return p_port_group; list_iterator = cl_list_next(list_iterator); } return NULL; } /*************************************************** ***************************************************/ static void __qos_policy_validate_pkey( osm_qos_policy_t * p_qos_policy, osm_qos_match_rule_t * p_qos_match_rule, osm_prtn_t * p_prtn) { int i = 0; if (!p_qos_policy || !p_qos_match_rule || !p_prtn) return; if (!p_qos_match_rule->p_qos_level->sl_set || p_prtn->sl == p_qos_match_rule->p_qos_level->sl) return; /* overriding partition's SL */ OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_ERROR, "ERR AC15: pkey 0x%04X in match rule - " "overriding partition SL (%u) with QoS Level SL (%u)\n", cl_ntoh16(p_prtn->pkey), p_prtn->sl, p_qos_match_rule->p_qos_level->sl); p_prtn->sl = p_qos_match_rule->p_qos_level->sl; /* If this partition has default MCast groups. * Fix those group's SL too */ for (i = 0; i < p_prtn->nmgrps; i++) { uint8_t sl; uint32_t flow; uint8_t hop; CL_ASSERT((cl_ntoh16(p_prtn->mgrps[i]->mcmember_rec.pkey) & 0x7fff) == (cl_ntoh16(p_prtn->pkey) & 0x7fff)); ib_member_get_sl_flow_hop(p_prtn->mgrps[i]->mcmember_rec.sl_flow_hop, &sl, &flow, &hop); if (sl != p_prtn->sl) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(&p_qos_policy->p_subn->p_osm->log, OSM_LOG_DEBUG, "Updating MCGroup (MGID %s) SL to " "match partition SL (%u)\n", inet_ntop(AF_INET6, p_prtn->mgrps[i]->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), p_prtn->sl); p_prtn->mgrps[i]->mcmember_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p_prtn->sl, flow, hop); } } } /*************************************************** ***************************************************/ int osm_qos_policy_validate(osm_qos_policy_t * p_qos_policy, osm_log_t *p_log) { cl_list_iterator_t match_rules_list_iterator; cl_list_iterator_t list_iterator; osm_qos_port_group_t *p_port_group = NULL; osm_qos_match_rule_t *p_qos_match_rule = NULL; char *str; unsigned i, j; int res = 0; uint64_t pkey_64; ib_net16_t pkey; osm_prtn_t * p_prtn; OSM_LOG_ENTER(p_log); /* set default qos level */ p_qos_policy->p_default_qos_level = __qos_policy_get_qos_level_by_name(p_qos_policy, OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); if (!p_qos_policy->p_default_qos_level) { /* There's no default QoS level in the usual qos-level section. Check whether the 'simple' default QoS level that can be defined in the qos-ulp section exists */ if (__default_simple_qos_level.sl_set) { p_qos_policy->p_default_qos_level = &__default_simple_qos_level; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC10: " "Default qos-level (%s) not defined.\n", OSM_QOS_POLICY_DEFAULT_LEVEL_NAME); res = 1; goto Exit; } } /* scan all the match rules, and fill the lists of pointers to relevant qos levels and port groups to speed up PR matching */ i = 1; match_rules_list_iterator = cl_list_head(&p_qos_policy->qos_match_rules); while (match_rules_list_iterator != cl_list_end(&p_qos_policy->qos_match_rules)) { p_qos_match_rule = (osm_qos_match_rule_t *) cl_list_obj(match_rules_list_iterator); CL_ASSERT(p_qos_match_rule); /* find the matching qos-level for each match-rule */ if (!p_qos_match_rule->p_qos_level) p_qos_match_rule->p_qos_level = __qos_policy_get_qos_level_by_name(p_qos_policy, p_qos_match_rule->qos_level_name); if (!p_qos_match_rule->p_qos_level) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC11: " "qos-match-rule num %u: qos-level '%s' not found\n", i, p_qos_match_rule->qos_level_name); res = 1; goto Exit; } /* find the matching port-group for element of source_list */ if (cl_list_count(&p_qos_match_rule->source_list)) { list_iterator = cl_list_head(&p_qos_match_rule->source_list); while (list_iterator != cl_list_end(&p_qos_match_rule->source_list)) { str = (char *)cl_list_obj(list_iterator); CL_ASSERT(str); p_port_group = __qos_policy_get_port_group_by_name(p_qos_policy, str); if (!p_port_group) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC12: " "qos-match-rule num %u: source port-group '%s' not found\n", i, str); res = 1; goto Exit; } cl_list_insert_tail(&p_qos_match_rule-> source_group_list, p_port_group); list_iterator = cl_list_next(list_iterator); } } /* find the matching port-group for element of destination_list */ if (cl_list_count(&p_qos_match_rule->destination_list)) { list_iterator = cl_list_head(&p_qos_match_rule->destination_list); while (list_iterator != cl_list_end(&p_qos_match_rule-> destination_list)) { str = (char *)cl_list_obj(list_iterator); CL_ASSERT(str); p_port_group = __qos_policy_get_port_group_by_name(p_qos_policy,str); if (!p_port_group) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC13: " "qos-match-rule num %u: destination port-group '%s' not found\n", i, str); res = 1; goto Exit; } cl_list_insert_tail(&p_qos_match_rule-> destination_group_list, p_port_group); list_iterator = cl_list_next(list_iterator); } } /* * Scan all the pkeys in matching rule, and if the * partition for these pkeys exists, set the SL * according to the QoS Level. * Warn if there's mismatch between QoS level SL * and Partition SL. */ for (j = 0; j < p_qos_match_rule->pkey_range_len; j++) { for ( pkey_64 = p_qos_match_rule->pkey_range_arr[j][0]; pkey_64 <= p_qos_match_rule->pkey_range_arr[j][1]; pkey_64++) { pkey = cl_hton16((uint16_t)(pkey_64 & 0x7fff)); p_prtn = (osm_prtn_t *)cl_qmap_get( &p_qos_policy->p_subn->prtn_pkey_tbl, pkey); if (p_prtn == (osm_prtn_t *)cl_qmap_end( &p_qos_policy->p_subn->prtn_pkey_tbl)) /* partition for this pkey not found */ OSM_LOG(p_log, OSM_LOG_ERROR, "ERR AC14: " "pkey 0x%04X in match rule - " "partition doesn't exist\n", cl_ntoh16(pkey)); else __qos_policy_validate_pkey(p_qos_policy, p_qos_match_rule, p_prtn); } } /* done with the current match-rule */ match_rules_list_iterator = cl_list_next(match_rules_list_iterator); i++; } Exit: OSM_LOG_EXIT(p_log); return res; } /* osm_qos_policy_validate() */ /*************************************************** ***************************************************/ static osm_qos_level_t * __qos_policy_get_qos_level_by_params( IN const osm_qos_policy_t * p_qos_policy, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN uint64_t service_id, IN uint16_t qos_class, IN uint16_t pkey, IN ib_net64_t comp_mask) { osm_qos_match_rule_t *p_qos_match_rule = NULL; if (!p_qos_policy) return NULL; p_qos_match_rule = __qos_policy_get_match_rule_by_params( p_qos_policy, service_id, qos_class, pkey, p_src_physp, p_dest_physp, comp_mask); return p_qos_match_rule ? p_qos_match_rule->p_qos_level : p_qos_policy->p_default_qos_level; } /* __qos_policy_get_qos_level_by_params() */ /*************************************************** ***************************************************/ osm_qos_level_t * osm_qos_policy_get_qos_level_by_pr( IN const osm_qos_policy_t * p_qos_policy, IN const ib_path_rec_t * p_pr, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN ib_net64_t comp_mask) { return __qos_policy_get_qos_level_by_params( p_qos_policy, p_src_physp, p_dest_physp, cl_ntoh64(p_pr->service_id), ib_path_rec_qos_class(p_pr), cl_ntoh16(p_pr->pkey), comp_mask); } /*************************************************** ***************************************************/ osm_qos_level_t * osm_qos_policy_get_qos_level_by_mpr( IN const osm_qos_policy_t * p_qos_policy, IN const ib_multipath_rec_t * p_mpr, IN const osm_physp_t * p_src_physp, IN const osm_physp_t * p_dest_physp, IN ib_net64_t comp_mask) { ib_net64_t pr_comp_mask = 0; if (!p_qos_policy) return NULL; /* * Converting MultiPathRecord compmask to the PathRecord * compmask. Note that only relevant bits are set. */ pr_comp_mask = ((comp_mask & IB_MPR_COMPMASK_QOS_CLASS) ? IB_PR_COMPMASK_QOS_CLASS : 0) | ((comp_mask & IB_MPR_COMPMASK_PKEY) ? IB_PR_COMPMASK_PKEY : 0) | ((comp_mask & IB_MPR_COMPMASK_SERVICEID_MSB) ? IB_PR_COMPMASK_SERVICEID_MSB : 0) | ((comp_mask & IB_MPR_COMPMASK_SERVICEID_LSB) ? IB_PR_COMPMASK_SERVICEID_LSB : 0); return __qos_policy_get_qos_level_by_params( p_qos_policy, p_src_physp, p_dest_physp, cl_ntoh64(ib_multipath_rec_service_id(p_mpr)), ib_multipath_rec_qos_class(p_mpr), cl_ntoh16(p_mpr->pkey), pr_comp_mask); } /*************************************************** ***************************************************/ opensm-3.3.20/opensm/osm_congestion_control.c0000644000205000001450000005433512452572167016270 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2009 HNR Consulting. All rights reserved. * Copyright (c) 2012 Lawrence Livermore National Lab. All rights reserved. * Copyright (c) 2014 Mellanox Technologies LTD. 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: * OSM Congestion Control configuration implementation * * Author: * Albert Chu, LLNL */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #define FILE_ID OSM_FILE_CONGESTION_CONTROL_C #include #include #include #include #include #define CONGESTION_CONTROL_INITIAL_TID_VALUE 0x7A93 static void cc_mad_post(osm_congestion_control_t *p_cc, osm_madw_t *p_madw, osm_node_t *p_node, osm_physp_t *p_physp, ib_net16_t attr_id, ib_net32_t attr_mod) { osm_subn_opt_t *p_opt = &p_cc->subn->opt; ib_cc_mad_t *p_cc_mad; uint8_t port; OSM_LOG_ENTER(p_cc->log); port = osm_physp_get_port_num(p_physp); p_cc_mad = osm_madw_get_cc_mad_ptr(p_madw); p_cc_mad->header.base_ver = 1; p_cc_mad->header.mgmt_class = IB_MCLASS_CC; p_cc_mad->header.class_ver = 2; p_cc_mad->header.method = IB_MAD_METHOD_SET; p_cc_mad->header.status = 0; p_cc_mad->header.class_spec = 0; p_cc_mad->header.trans_id = cl_hton64((uint64_t) cl_atomic_inc(&p_cc->trans_id) & (uint64_t) (0xFFFFFFFF)); if (p_cc_mad->header.trans_id == 0) p_cc_mad->header.trans_id = cl_hton64((uint64_t) cl_atomic_inc(&p_cc->trans_id) & (uint64_t) (0xFFFFFFFF)); p_cc_mad->header.attr_id = attr_id; p_cc_mad->header.resv = 0; p_cc_mad->header.attr_mod = attr_mod; p_cc_mad->cc_key = p_opt->cc_key; memset(p_cc_mad->log_data, '\0', IB_CC_LOG_DATA_SIZE); p_madw->mad_addr.dest_lid = osm_node_get_base_lid(p_node, port); p_madw->mad_addr.addr_type.gsi.remote_qp = IB_QP1; p_madw->mad_addr.addr_type.gsi.remote_qkey = cl_hton32(IB_QP1_WELL_KNOWN_Q_KEY); p_madw->resp_expected = TRUE; p_madw->fail_msg = CL_DISP_MSGID_NONE; p_madw->context.cc_context.node_guid = osm_node_get_node_guid(p_node); p_madw->context.cc_context.port_guid = osm_physp_get_port_guid(p_physp); p_madw->context.cc_context.port = port; p_madw->context.cc_context.mad_method = IB_MAD_METHOD_SET; p_madw->context.cc_context.attr_mod = attr_mod; cl_spinlock_acquire(&p_cc->mad_queue_lock); cl_atomic_inc(&p_cc->outstanding_mads); cl_qlist_insert_tail(&p_cc->mad_queue, &p_madw->list_item); cl_spinlock_release(&p_cc->mad_queue_lock); cl_event_signal(&p_cc->cc_poller_wakeup); OSM_LOG_EXIT(p_cc->log); } static void cc_setup_mad_data(osm_sm_t * p_sm) { osm_congestion_control_t *p_cc = &p_sm->p_subn->p_osm->cc; osm_subn_opt_t *p_opt = &p_sm->p_subn->opt; uint16_t ccti_limit; int i; /* Switch Congestion Setting */ p_cc->sw_cong_setting.control_map = p_opt->cc_sw_cong_setting_control_map; memcpy(p_cc->sw_cong_setting.victim_mask, p_opt->cc_sw_cong_setting_victim_mask, IB_CC_PORT_MASK_DATA_SIZE); memcpy(p_cc->sw_cong_setting.credit_mask, p_opt->cc_sw_cong_setting_credit_mask, IB_CC_PORT_MASK_DATA_SIZE); /* threshold is 4 bits, takes up upper nibble of byte */ p_cc->sw_cong_setting.threshold_resv = (p_opt->cc_sw_cong_setting_threshold << 4); p_cc->sw_cong_setting.packet_size = p_opt->cc_sw_cong_setting_packet_size; /* cs threshold is 4 bits, takes up upper nibble of short */ p_cc->sw_cong_setting.cs_threshold_resv = cl_hton16(p_opt->cc_sw_cong_setting_credit_starvation_threshold << 12); p_cc->sw_cong_setting.cs_return_delay = cl_hton16(p_opt->cc_sw_cong_setting_credit_starvation_return_delay.shift << 14 | p_opt->cc_sw_cong_setting_credit_starvation_return_delay.multiplier); p_cc->sw_cong_setting.marking_rate = p_opt->cc_sw_cong_setting_marking_rate; /* CA Congestion Setting */ p_cc->ca_cong_setting.port_control = p_opt->cc_ca_cong_setting_port_control; p_cc->ca_cong_setting.control_map = p_opt->cc_ca_cong_setting_control_map; for (i = 0; i < IB_CA_CONG_ENTRY_DATA_SIZE; i++) { ib_ca_cong_entry_t *p_entry; p_entry = &p_cc->ca_cong_setting.entry_list[i]; p_entry->ccti_timer = p_opt->cc_ca_cong_entries[i].ccti_timer; p_entry->ccti_increase = p_opt->cc_ca_cong_entries[i].ccti_increase; p_entry->trigger_threshold = p_opt->cc_ca_cong_entries[i].trigger_threshold; p_entry->ccti_min = p_opt->cc_ca_cong_entries[i].ccti_min; p_entry->resv0 = 0; p_entry->resv1 = 0; } /* Congestion Control Table */ /* if no entries, we will always send at least 1 mad to set ccti_limit = 0 */ if (!p_opt->cc_cct.entries_len) p_cc->cc_tbl_mads = 1; else { p_cc->cc_tbl_mads = p_opt->cc_cct.entries_len - 1; p_cc->cc_tbl_mads /= IB_CC_TBL_ENTRY_LIST_MAX; p_cc->cc_tbl_mads += 1; } CL_ASSERT(p_cc->cc_tbl_mads <= OSM_CCT_ENTRY_MAD_BLOCKS); if (!p_opt->cc_cct.entries_len) ccti_limit = 0; else ccti_limit = p_opt->cc_cct.entries_len - 1; for (i = 0; i < p_cc->cc_tbl_mads; i++) { int j; p_cc->cc_tbl[i].ccti_limit = cl_hton16(ccti_limit); p_cc->cc_tbl[i].resv = 0; memset(p_cc->cc_tbl[i].entry_list, '\0', sizeof(p_cc->cc_tbl[i].entry_list)); if (!ccti_limit) break; for (j = 0; j < IB_CC_TBL_ENTRY_LIST_MAX; j++) { int k; k = (i * IB_CC_TBL_ENTRY_LIST_MAX) + j; p_cc->cc_tbl[i].entry_list[j].shift_multiplier = cl_hton16(p_opt->cc_cct.entries[k].shift << 14 | p_opt->cc_cct.entries[k].multiplier); } } } static ib_api_status_t cc_send_sw_cong_setting(osm_sm_t * p_sm, osm_node_t *p_node) { osm_congestion_control_t *p_cc = &p_sm->p_subn->p_osm->cc; unsigned force_update; osm_physp_t *p_physp; osm_madw_t *p_madw = NULL; ib_cc_mad_t *p_cc_mad = NULL; ib_sw_cong_setting_t *p_sw_cong_setting = NULL; OSM_LOG_ENTER(p_sm->p_log); p_physp = osm_node_get_physp_ptr(p_node, 0); force_update = p_physp->need_update || p_sm->p_subn->need_update; if (!force_update && !memcmp(&p_cc->sw_cong_setting, &p_physp->cc.sw.sw_cong_setting, sizeof(p_cc->sw_cong_setting))) return IB_SUCCESS; p_madw = osm_mad_pool_get(p_cc->mad_pool, p_cc->bind_handle, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR C101: " "failed to allocate mad\n"); return IB_INSUFFICIENT_MEMORY; } p_cc_mad = osm_madw_get_cc_mad_ptr(p_madw); p_sw_cong_setting = ib_cc_mad_get_mgt_data_ptr(p_cc_mad); memcpy(p_sw_cong_setting, &p_cc->sw_cong_setting, sizeof(p_cc->sw_cong_setting)); cc_mad_post(p_cc, p_madw, p_node, p_physp, IB_MAD_ATTR_SW_CONG_SETTING, 0); OSM_LOG_EXIT(p_sm->p_log); return IB_SUCCESS; } static ib_api_status_t cc_send_ca_cong_setting(osm_sm_t * p_sm, osm_node_t *p_node, osm_physp_t *p_physp) { osm_congestion_control_t *p_cc = &p_sm->p_subn->p_osm->cc; unsigned force_update; osm_madw_t *p_madw = NULL; ib_cc_mad_t *p_cc_mad = NULL; ib_ca_cong_setting_t *p_ca_cong_setting = NULL; OSM_LOG_ENTER(p_sm->p_log); force_update = p_physp->need_update || p_sm->p_subn->need_update; if (!force_update && !memcmp(&p_cc->ca_cong_setting, &p_physp->cc.ca.ca_cong_setting, sizeof(p_cc->ca_cong_setting))) return IB_SUCCESS; p_madw = osm_mad_pool_get(p_cc->mad_pool, p_cc->bind_handle, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR C102: " "failed to allocate mad\n"); return IB_INSUFFICIENT_MEMORY; } p_cc_mad = osm_madw_get_cc_mad_ptr(p_madw); p_ca_cong_setting = ib_cc_mad_get_mgt_data_ptr(p_cc_mad); memcpy(p_ca_cong_setting, &p_cc->ca_cong_setting, sizeof(p_cc->ca_cong_setting)); cc_mad_post(p_cc, p_madw, p_node, p_physp, IB_MAD_ATTR_CA_CONG_SETTING, 0); OSM_LOG_EXIT(p_sm->p_log); return IB_SUCCESS; } static ib_api_status_t cc_send_cct(osm_sm_t * p_sm, osm_node_t *p_node, osm_physp_t *p_physp) { osm_congestion_control_t *p_cc = &p_sm->p_subn->p_osm->cc; unsigned force_update; osm_madw_t *p_madw = NULL; ib_cc_mad_t *p_cc_mad = NULL; ib_cc_tbl_t *p_cc_tbl = NULL; unsigned int index = 0; OSM_LOG_ENTER(p_sm->p_log); force_update = p_physp->need_update || p_sm->p_subn->need_update; for (index = 0; index < p_cc->cc_tbl_mads; index++) { if (!force_update && !memcmp(&p_cc->cc_tbl[index], &p_physp->cc.ca.cc_tbl[index], sizeof(p_cc->cc_tbl[index]))) continue; p_madw = osm_mad_pool_get(p_cc->mad_pool, p_cc->bind_handle, MAD_BLOCK_SIZE, NULL); if (p_madw == NULL) { OSM_LOG(p_sm->p_log, OSM_LOG_ERROR, "ERR C103: " "failed to allocate mad\n"); return IB_INSUFFICIENT_MEMORY; } p_cc_mad = osm_madw_get_cc_mad_ptr(p_madw); p_cc_tbl = (ib_cc_tbl_t *)ib_cc_mad_get_mgt_data_ptr(p_cc_mad); memcpy(p_cc_tbl, &p_cc->cc_tbl[index], sizeof(p_cc->cc_tbl[index])); cc_mad_post(p_cc, p_madw, p_node, p_physp, IB_MAD_ATTR_CC_TBL, cl_hton32(index)); } OSM_LOG_EXIT(p_sm->p_log); return IB_SUCCESS; } int osm_congestion_control_setup(struct osm_opensm *p_osm) { cl_qmap_t *p_tbl; cl_map_item_t *p_next; int ret = 0; if (!p_osm->subn.opt.congestion_control) return 0; OSM_LOG_ENTER(&p_osm->log); /* * Do nothing unless the most recent routing attempt was successful. */ if (!p_osm->routing_engine_used) return 0; cc_setup_mad_data(&p_osm->sm); cl_plock_acquire(&p_osm->lock); p_tbl = &p_osm->subn.port_guid_tbl; p_next = cl_qmap_head(p_tbl); while (p_next != cl_qmap_end(p_tbl)) { osm_port_t *p_port = (osm_port_t *) p_next; osm_node_t *p_node = p_port->p_node; ib_api_status_t status; p_next = cl_qmap_next(p_next); if (p_port->cc_unavailable_flag) continue; if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) { status = cc_send_sw_cong_setting(&p_osm->sm, p_node); if (status != IB_SUCCESS) ret = -1; } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_CA) { status = cc_send_ca_cong_setting(&p_osm->sm, p_node, p_port->p_physp); if (status != IB_SUCCESS) ret = -1; status = cc_send_cct(&p_osm->sm, p_node, p_port->p_physp); if (status != IB_SUCCESS) ret = -1; } } cl_plock_release(&p_osm->lock); OSM_LOG_EXIT(&p_osm->log); return ret; } int osm_congestion_control_wait_pending_transactions(struct osm_opensm *p_osm) { osm_congestion_control_t *cc = &p_osm->cc; if (!p_osm->subn.opt.congestion_control) return 0; while (1) { unsigned count = cc->outstanding_mads; if (!count || osm_exit_flag) break; cl_event_wait_on(&cc->outstanding_mads_done_event, EVENT_NO_TIMEOUT, TRUE); } return osm_exit_flag; } static inline void decrement_outstanding_mads(osm_congestion_control_t *p_cc) { uint32_t outstanding; outstanding = cl_atomic_dec(&p_cc->outstanding_mads); if (!outstanding) cl_event_signal(&p_cc->outstanding_mads_done_event); cl_atomic_dec(&p_cc->outstanding_mads_on_wire); cl_event_signal(&p_cc->sig_mads_on_wire_continue); } static void cc_rcv_mad(void *context, void *data) { osm_congestion_control_t *p_cc = context; osm_opensm_t *p_osm = p_cc->osm; osm_madw_t *p_madw = data; ib_cc_mad_t *p_cc_mad; osm_madw_context_t *p_mad_context = &p_madw->context; ib_mad_t *p_mad = osm_madw_get_mad_ptr(p_madw); ib_net64_t node_guid = p_mad_context->cc_context.node_guid; ib_net64_t port_guid = p_mad_context->cc_context.port_guid; uint8_t port = p_mad_context->cc_context.port; osm_port_t *p_port; OSM_LOG_ENTER(p_cc->log); OSM_LOG(p_cc->log, OSM_LOG_VERBOSE, "Processing received MAD status 0x%x for " "attr ID %u mod 0x%x node 0x%" PRIx64 " port %u\n", cl_ntoh16(p_mad->status), cl_ntoh16(p_mad->attr_id), cl_ntoh32(p_mad_context->cc_context.attr_mod), cl_ntoh64(node_guid), port); p_cc_mad = osm_madw_get_cc_mad_ptr(p_madw); cl_plock_acquire(&p_osm->lock); p_port = osm_get_port_by_guid(p_cc->subn, port_guid); if (!p_port) { OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C109: " "Port GUID 0x%" PRIx64 " not in table\n", cl_ntoh64(port_guid)); cl_plock_release(&p_osm->lock); goto Exit; } p_port->cc_timeout_count = 0; if (p_cc_mad->header.status) { if (p_cc_mad->header.status & IB_MAD_STATUS_UNSUP_CLASS_VER || p_cc_mad->header.status & IB_MAD_STATUS_UNSUP_METHOD || p_cc_mad->header.status & IB_MAD_STATUS_UNSUP_METHOD_ATTR) p_port->cc_unavailable_flag = TRUE; cl_plock_release(&p_osm->lock); goto Exit; } else p_port->cc_unavailable_flag = FALSE; if (p_cc_mad->header.attr_id == IB_MAD_ATTR_SW_CONG_SETTING) { ib_sw_cong_setting_t *p_sw_cong_setting; p_sw_cong_setting = ib_cc_mad_get_mgt_data_ptr(p_cc_mad); p_port->p_physp->cc.sw.sw_cong_setting = *p_sw_cong_setting; } else if (p_cc_mad->header.attr_id == IB_MAD_ATTR_CA_CONG_SETTING) { ib_ca_cong_setting_t *p_ca_cong_setting; p_ca_cong_setting = ib_cc_mad_get_mgt_data_ptr(p_cc_mad); p_port->p_physp->cc.ca.ca_cong_setting = *p_ca_cong_setting; } else if (p_cc_mad->header.attr_id == IB_MAD_ATTR_CC_TBL) { ib_net32_t attr_mod = p_mad_context->cc_context.attr_mod; uint32_t index = cl_ntoh32(attr_mod); ib_cc_tbl_t *p_cc_tbl; p_cc_tbl = ib_cc_mad_get_mgt_data_ptr(p_cc_mad); p_port->p_physp->cc.ca.cc_tbl[index] = *p_cc_tbl; } else OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C10A: " "Unexpected MAD attribute ID %u received\n", cl_ntoh16(p_cc_mad->header.attr_id)); cl_plock_release(&p_osm->lock); Exit: decrement_outstanding_mads(p_cc); osm_mad_pool_put(p_cc->mad_pool, p_madw); OSM_LOG_EXIT(p_cc->log); } static void cc_poller_send(osm_congestion_control_t *p_cc, osm_madw_t *p_madw) { osm_subn_opt_t *p_opt = &p_cc->subn->opt; ib_api_status_t status; cl_status_t sts; osm_madw_context_t mad_context = p_madw->context; status = osm_vendor_send(p_cc->bind_handle, p_madw, TRUE); if (status == IB_SUCCESS) { cl_atomic_inc(&p_cc->outstanding_mads_on_wire); while (p_cc->outstanding_mads_on_wire > (int32_t)p_opt->cc_max_outstanding_mads) { wait: sts = cl_event_wait_on(&p_cc->sig_mads_on_wire_continue, EVENT_NO_TIMEOUT, TRUE); if (sts != CL_SUCCESS) goto wait; } } else OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C104: " "send failed to node 0x%" PRIx64 "port %u\n", cl_ntoh64(mad_context.cc_context.node_guid), mad_context.cc_context.port); } static void cc_poller(void *p_ptr) { osm_congestion_control_t *p_cc = p_ptr; osm_madw_t *p_madw; OSM_LOG_ENTER(p_cc->log); if (p_cc->thread_state == OSM_THREAD_STATE_NONE) p_cc->thread_state = OSM_THREAD_STATE_RUN; while (p_cc->thread_state == OSM_THREAD_STATE_RUN) { cl_spinlock_acquire(&p_cc->mad_queue_lock); p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_cc->mad_queue); cl_spinlock_release(&p_cc->mad_queue_lock); if (p_madw != (osm_madw_t *) cl_qlist_end(&p_cc->mad_queue)) cc_poller_send(p_cc, p_madw); else cl_event_wait_on(&p_cc->cc_poller_wakeup, EVENT_NO_TIMEOUT, TRUE); } OSM_LOG_EXIT(p_cc->log); } ib_api_status_t osm_congestion_control_init(osm_congestion_control_t * p_cc, struct osm_opensm *p_osm, const osm_subn_opt_t * p_opt) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osm->log); memset(p_cc, 0, sizeof(*p_cc)); p_cc->osm = p_osm; p_cc->subn = &p_osm->subn; p_cc->sm = &p_osm->sm; p_cc->log = &p_osm->log; p_cc->mad_pool = &p_osm->mad_pool; p_cc->trans_id = CONGESTION_CONTROL_INITIAL_TID_VALUE; p_cc->vendor = p_osm->p_vendor; p_cc->cc_disp_h = cl_disp_register(&p_osm->disp, OSM_MSG_MAD_CC, cc_rcv_mad, p_cc); if (p_cc->cc_disp_h == CL_DISP_INVALID_HANDLE) goto Exit; cl_qlist_init(&p_cc->mad_queue); status = cl_spinlock_init(&p_cc->mad_queue_lock); if (status != IB_SUCCESS) goto Exit; cl_event_construct(&p_cc->cc_poller_wakeup); status = cl_event_init(&p_cc->cc_poller_wakeup, FALSE); if (status != IB_SUCCESS) goto Exit; cl_event_construct(&p_cc->outstanding_mads_done_event); status = cl_event_init(&p_cc->outstanding_mads_done_event, FALSE); if (status != IB_SUCCESS) goto Exit; cl_event_construct(&p_cc->sig_mads_on_wire_continue); status = cl_event_init(&p_cc->sig_mads_on_wire_continue, FALSE); if (status != IB_SUCCESS) goto Exit; p_cc->thread_state = OSM_THREAD_STATE_NONE; status = cl_thread_init(&p_cc->cc_poller, cc_poller, p_cc, "cc poller"); if (status != IB_SUCCESS) goto Exit; status = IB_SUCCESS; Exit: OSM_LOG_EXIT(p_cc->log); return status; } static void cc_mad_recv_callback(osm_madw_t * p_madw, void *bind_context, osm_madw_t * p_req_madw) { osm_congestion_control_t *p_cc = bind_context; OSM_LOG_ENTER(p_cc->log); CL_ASSERT(p_madw); /* HACK - should be extended when supporting CC traps */ CL_ASSERT(p_req_madw != NULL); osm_madw_copy_context(p_madw, p_req_madw); osm_mad_pool_put(p_cc->mad_pool, p_req_madw); /* Do not decrement outstanding mads here, do it in the dispatcher */ if (cl_disp_post(p_cc->cc_disp_h, OSM_MSG_MAD_CC, p_madw, NULL, NULL) != CL_SUCCESS) { OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C105: " "Congestion Control Dispatcher post failed\n"); osm_mad_pool_put(p_cc->mad_pool, p_madw); } OSM_LOG_EXIT(p_cc->log); } static void cc_mad_send_err_callback(void *bind_context, osm_madw_t * p_madw) { osm_congestion_control_t *p_cc = bind_context; osm_madw_context_t *p_madw_context = &p_madw->context; osm_opensm_t *p_osm = p_cc->osm; uint64_t node_guid = p_madw_context->cc_context.node_guid; uint64_t port_guid = p_madw_context->cc_context.port_guid; uint8_t port = p_madw_context->cc_context.port; osm_port_t *p_port; int log_flag = 1; OSM_LOG_ENTER(p_cc->log); cl_plock_acquire(&p_osm->lock); p_port = osm_get_port_by_guid(p_cc->subn, port_guid); if (!p_port) { OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C10B: " "Port GUID 0x%" PRIx64 " not in table\n", cl_ntoh64(port_guid)); cl_plock_release(&p_osm->lock); goto Exit; } /* If timed out before, don't bothering logging again * we assume no CC support */ if (p_madw->status == IB_TIMEOUT && p_port->cc_timeout_count) log_flag = 0; if (log_flag) OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C106: MAD Error (%s): " "attr id = %u LID %u GUID 0x%016" PRIx64 " port %u " "TID 0x%" PRIx64 "\n", ib_get_err_str(p_madw->status), p_madw->p_mad->attr_id, cl_ntoh16(p_madw->mad_addr.dest_lid), cl_ntoh64(node_guid), port, cl_ntoh64(p_madw->p_mad->trans_id)); if (p_madw->status == IB_TIMEOUT) { p_port->cc_timeout_count++; if (p_port->cc_timeout_count > OSM_CC_TIMEOUT_COUNT_THRESHOLD && !p_port->cc_unavailable_flag) { p_port->cc_unavailable_flag = TRUE; p_port->cc_timeout_count = 0; } } else p_cc->subn->subnet_initialization_error = TRUE; cl_plock_release(&p_osm->lock); Exit: osm_mad_pool_put(p_cc->mad_pool, p_madw); decrement_outstanding_mads(p_cc); OSM_LOG_EXIT(p_cc->log); } ib_api_status_t osm_congestion_control_bind(osm_congestion_control_t * p_cc, ib_net64_t port_guid) { osm_bind_info_t bind_info; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_cc->log); bind_info.port_guid = p_cc->port_guid = port_guid; bind_info.mad_class = IB_MCLASS_CC; bind_info.class_version = 2; bind_info.is_responder = FALSE; bind_info.is_report_processor = FALSE; bind_info.is_trap_processor = FALSE; bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE; bind_info.send_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE; bind_info.timeout = p_cc->subn->opt.transaction_timeout; bind_info.retries = p_cc->subn->opt.transaction_retries; OSM_LOG(p_cc->log, OSM_LOG_VERBOSE, "Binding to port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); p_cc->bind_handle = osm_vendor_bind(p_cc->vendor, &bind_info, p_cc->mad_pool, cc_mad_recv_callback, cc_mad_send_err_callback, p_cc); if (p_cc->bind_handle == OSM_BIND_INVALID_HANDLE) { status = IB_ERROR; OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C107: Vendor specific bind failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(p_cc->log); return status; } void osm_congestion_control_shutdown(osm_congestion_control_t * p_cc) { OSM_LOG_ENTER(p_cc->log); if (p_cc->bind_handle == OSM_BIND_INVALID_HANDLE) { OSM_LOG(p_cc->log, OSM_LOG_ERROR, "ERR C108: No previous bind\n"); goto Exit; } cl_disp_unregister(p_cc->cc_disp_h); Exit: OSM_LOG_EXIT(p_cc->log); } void osm_congestion_control_destroy(osm_congestion_control_t * p_cc) { osm_madw_t *p_madw; OSM_LOG_ENTER(p_cc->log); p_cc->thread_state = OSM_THREAD_STATE_EXIT; cl_event_signal(&p_cc->sig_mads_on_wire_continue); cl_event_signal(&p_cc->cc_poller_wakeup); cl_thread_destroy(&p_cc->cc_poller); cl_spinlock_acquire(&p_cc->mad_queue_lock); while (!cl_is_qlist_empty(&p_cc->mad_queue)) { p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_cc->mad_queue); osm_mad_pool_put(p_cc->mad_pool, p_madw); } cl_spinlock_release(&p_cc->mad_queue_lock); cl_spinlock_destroy(&p_cc->mad_queue_lock); cl_event_destroy(&p_cc->cc_poller_wakeup); cl_event_destroy(&p_cc->outstanding_mads_done_event); cl_event_destroy(&p_cc->sig_mads_on_wire_continue); OSM_LOG_EXIT(p_cc->log); } opensm-3.3.20/opensm/libopensm.map0000644000205000001450000000450512272264653014015 00000000000000OPENSM_1.5 { global: osm_log; osm_log_msg_box; osm_is_debug; osm_log_init; osm_log_init_v2; osm_log_reopen_file; osm_mad_pool_construct; osm_mad_pool_destroy; osm_mad_pool_init; osm_mad_pool_get; osm_mad_pool_put; osm_mad_pool_get_wrapper; osm_mad_pool_get_wrapper_raw; ib_get_sa_method_str; ib_get_sm_method_str; ib_get_sm_attr_str; ib_get_sa_attr_str; ib_get_trap_str; ib_zero_gid; osm_dump_port_info; osm_dump_port_info_v2; osm_dump_portinfo_record; osm_dump_portinfo_record_v2; osm_dump_guid_info; osm_dump_guid_info_v2; osm_dump_guidinfo_record; osm_dump_guidinfo_record_v2; osm_dump_node_info; osm_dump_node_info_v2; osm_dump_node_record; osm_dump_node_record_v2; osm_dump_path_record; osm_dump_path_record_v2; osm_dump_multipath_record; osm_dump_multipath_record_v2; osm_dump_mc_record; osm_dump_mc_record_v2; osm_dump_service_record; osm_dump_service_record_v2; osm_dump_inform_info; osm_dump_inform_info_v2; osm_dump_inform_info_record; osm_dump_inform_info_record_v2; osm_dump_link_record; osm_dump_link_record_v2; osm_dump_switch_info; osm_dump_switch_info_v2; osm_dump_switch_info_record; osm_dump_switch_info_record_v2; osm_dump_slvl_map_table; osm_dump_slvl_map_table_v2; osm_dump_vl_arb_table; osm_dump_vl_arb_table_v2; osm_dump_sm_info; osm_dump_sm_info_v2; osm_dump_sm_info_record; osm_dump_sm_info_record_v2; osm_dump_notice; osm_dump_notice_v2; osm_dump_dr_smp; osm_dump_dr_smp_v2; osm_dump_sa_mad; osm_dump_sa_mad_v2; osm_dump_dr_path; osm_dump_dr_path_v2; osm_dump_dr_path_as_buf; osm_dump_smp_dr_path; osm_dump_smp_dr_path_v2; osm_dump_pkey_block; osm_dump_pkey_block_v2; osm_log_raw; osm_get_sm_state_str; osm_get_sm_signal_str; osm_get_disp_msg_str; osm_get_port_state_str_fixed_width; osm_get_node_type_str_fixed_width; osm_get_manufacturer_str; osm_get_mtu_str; osm_get_lwa_str; osm_get_lsa_str; osm_get_sm_mgr_signal_str; osm_get_sm_mgr_state_str; ib_mtu_is_valid; ib_rate_is_valid; ib_path_compare_rates; ib_path_rate_get_prev; ib_path_rate_get_next; osm_dump_mlnx_ext_port_info; osm_dump_mlnx_ext_port_info_v2; osm_log_v2; osm_log_msg_box_v2; osm_log_is_active_v2; osm_get_log_per_module; osm_set_log_per_module; osm_reset_log_per_module; local: *; }; opensm-3.3.20/opensm/libopensm.ver0000644000205000001450000000053312726304160014021 00000000000000# In this file we track the current API version # of the opensm common interface (and libraries) # The version is built of the following # tree numbers: # API_REV:RUNNING_REV:AGE # API_REV - advance on any added API # RUNNING_REV - advance any change to the vendor files # AGE - number of backward versions the API still supports LIBVERSION=7:3:2 opensm-3.3.20/osmtest/0000755000205000001450000000000012726324776011606 500000000000000opensm-3.3.20/osmtest/include/0000755000205000001450000000000012726324776013231 500000000000000opensm-3.3.20/osmtest/include/osmt_inform.h0000644000205000001450000000513112104655725015645 00000000000000/* * 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. * */ #ifndef __OSMT_INFORM__ #define __OSMT_INFORM__ #ifdef OSM_VENDOR_INTF_MTL #include #include #include "osmt_mtl_regular_qp.h" #endif typedef struct _osmt_qp_ctx { #ifdef OSM_VENDOR_INTF_MTL osmt_mtl_mad_res_t qp_bind_hndl; #endif uint8_t *p_send_buf; uint8_t *p_recv_buf; #ifdef OSM_VENDOR_INTF_MTL IB_MGT_mad_hndl_t ib_mgt_qp0_handle; #endif } osmt_qp_ctx_t; ib_api_status_t osmt_bind_inform_qp(IN osmtest_t * const p_osmt, OUT osmt_qp_ctx_t * p_qp_ctx); void osmt_unbind_inform_qp(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx); ib_api_status_t osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt, IN osmt_qp_ctx_t * p_qp_ctx, IN ib_inform_info_t * p_inform_info, IN uint8_t reg_flag); ib_api_status_t osmt_trap_wait(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx); ib_api_status_t osmt_init_inform_info(IN osmtest_t * const p_osmt, OUT ib_inform_info_t * p_ii); ib_api_status_t osmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt, IN ib_net16_t trap_num, OUT ib_inform_info_t * p_ii); #endif /* __OSMT_INFORM__ */ opensm-3.3.20/osmtest/include/osmtest_subnet.h0000644000205000001450000001615212104655725016374 00000000000000/* * Copyright (c) 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: * Declaration of osmtest_t. * This object represents the OSMTest Test object. * */ #ifndef _OSMTEST_SUBNET_H_ #define _OSMTEST_SUBNET_H_ #include #include #include #include #include #include /****s* Subnet Database/generic_t * NAME * generic_t * * DESCRIPTION * Subnet database object for fields common to all record types. * All other database types must be castable to this type. * * SYNOPSIS */ typedef struct _generic { cl_map_item_t map_item; /* must be first element! */ uint32_t count; /* must be second element! */ } generic_t; /* * FIELDS * * SEE ALSO *********/ /****s* Subnet Database/node_t * NAME * node_t * * DESCRIPTION * Subnet database object for nodes. * Must be castable to generic_t. * * SYNOPSIS */ typedef struct _node { cl_map_item_t map_item; /* must be first element! */ uint32_t count; /* must be second element! */ ib_node_record_t rec; ib_node_record_t comp; } node_t; /* * FIELDS * map_item * Provides linkage for the qmap container. * * rec * NodeRecord for this node as read from the database file. * * comp * NodeRecord indicating which fields should be compared against rec. * Bits set in the comp NodeRecord indicate that bit in the rec structure * should be compared against real-time data from the SA. * * count * Utility counter used by the validation logic. Typically used to * to indicate the number of times a matching node was received from * the SA. * * SEE ALSO *********/ static inline node_t *node_new(void) { node_t *p_obj; p_obj = malloc(sizeof(*p_obj)); if (p_obj) memset(p_obj, 0, sizeof(*p_obj)); return (p_obj); } static inline void node_delete(IN node_t * p_obj) { free(p_obj); } /****s* Subnet Database/port_t * NAME * port_t * * DESCRIPTION * Subnet database object for ports. * Must be castable to generic_t. * * SYNOPSIS */ typedef struct _port { cl_map_item_t map_item; /* must be first element! */ uint32_t count; /* must be second element! */ /* Since there is no unique identifier for all ports we must be able to have such a key by the lid and port num */ uint64_t port_id; ib_portinfo_record_t rec; ib_portinfo_record_t comp; } port_t; /* * FIELDS * * map_item * Provides linkage for the qmap container. * * rec * PortInfoRecord for this port as read from the database file. * * comp * PortInfoRecord indicating which fields should be compared against rec. * Bits set in the comp NodeRecord indicate that bit in the rec structure * should be compared against real-time data from the SA. * * count * Utility counter used by the validation logic. Typically used to * to indicate the number of times a matching node was received from * the SA. * * SEE ALSO *********/ static inline port_t *port_new(void) { port_t *p_obj; p_obj = malloc(sizeof(*p_obj)); if (p_obj) memset(p_obj, 0, sizeof(*p_obj)); return (p_obj); } static inline void port_delete(IN port_t * p_obj) { free(p_obj); } static inline uint64_t port_gen_id(IN ib_net16_t const lid, IN uint8_t const port_num) { return (lid << 8 | port_num); } static inline void port_ext_id(IN uint64_t id, IN ib_net16_t * p_lid, IN uint8_t * p_port_num) { CL_ASSERT((id & 0xFF) < 0x100); *p_port_num = (uint8_t) (id & 0xFF); CL_ASSERT(((id >> 8) & 0xFFFF) < 0x10000); *p_lid = (uint16_t) ((id >> 8) & 0xFFFF); } static inline void port_set_id(IN port_t * p_obj, IN ib_net16_t const lid, IN uint8_t const port_num) { p_obj->port_id = port_gen_id(lid, port_num); } static inline void port_get_id(IN port_t * p_obj, IN ib_net16_t * p_lid, IN uint8_t * p_port_num) { port_ext_id(p_obj->port_id, p_lid, p_port_num); } /****s* Subnet Database/path_t * NAME * node_t * * DESCRIPTION * Subnet database object for paths. * Must be castable to generic_t. * * SYNOPSIS */ typedef struct _path { cl_map_item_t map_item; /* must be first element! */ uint32_t count; /* must be second element! */ ib_path_rec_t rec; ib_path_rec_t comp; } path_t; /* * FIELDS * map_item * Provides linkage for the qmap container. * * rec * PathRecord for this path as read from the database file. * * comp * PathRecord indicating which fields should be compared against rec. * Bits set in the comp PathRecord indicate that bit in the rec structure * should be compared against real-time data from the SA. * * count * Utility counter used by the validation logic. Typically used to * to indicate the number of times a matching node was received from * the SA. * * SEE ALSO *********/ static inline path_t *path_new(void) { path_t *p_obj; p_obj = malloc(sizeof(*p_obj)); if (p_obj) memset(p_obj, 0, sizeof(*p_obj)); return (p_obj); } static inline void path_delete(IN path_t * p_obj) { free(p_obj); } /****s* Subnet Database/subnet_t * NAME * subnet_t * * DESCRIPTION * Subnet database object. * * SYNOPSIS */ typedef struct _subnet { cl_qmap_t node_lid_tbl; cl_qmap_t node_guid_tbl; cl_qmap_t mgrp_mlid_tbl; /* cl_qmap_t port_lid_tbl; */ /* cl_qmap_t port_guid_tbl; */ cl_qmap_t port_key_tbl; cl_qmap_t link_tbl; cl_qmap_t path_tbl; } subnet_t; /* * FIELDS * * SEE ALSO *********/ /****f* Subnet Database/subnet_construct * NAME * subnet_construct * * DESCRIPTION * This function constructs an subnet database object. * This function cannot fail. * * SYNOPSIS */ void subnet_construct(IN subnet_t * const p_subn); /* * FIELDS * * SEE ALSO *********/ /****f* Subnet Database/subnet_init * NAME * subnet_init * * DESCRIPTION * This function initializes an subnet database object. * * SYNOPSIS */ cl_status_t subnet_init(IN subnet_t * const p_subn); /* * FIELDS * * SEE ALSO *********/ #endif opensm-3.3.20/osmtest/include/osmtest.h0000644000205000001450000002475012350021334015001 00000000000000/* * Copyright (c) 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: * Declaration of osmtest_t. * This object represents the OSMTest Test object. * */ #ifndef _OSMTEST_H_ #define _OSMTEST_H_ #include #include #include #include #include #include #include "osmtest_base.h" #include "osmtest_subnet.h" enum OSMT_FLOWS { OSMT_FLOW_ALL = 0, OSMT_FLOW_CREATE_INVENTORY, OSMT_FLOW_VALIDATE_INVENTORY, OSMT_FLOW_SERVICE_REGISTRATION, OSMT_FLOW_EVENT_FORWARDING, OSMT_FLOW_STRESS_SA, OSMT_FLOW_MULTICAST, OSMT_FLOW_QOS, OSMT_FLOW_TRAP, }; /****s* OpenSM: Subnet/osmtest_opt_t * NAME * osmtest_opt_t * * DESCRIPTION * Subnet options structure. This structure contains the various * site specific configuration parameters for osmtest. * * SYNOPSIS */ typedef struct _osmtest_opt { uint32_t transaction_timeout; boolean_t force_log_flush; boolean_t create; boolean_t with_grh; uint32_t retry_count; uint32_t stress; uint32_t mmode; char file_name[OSMTEST_FILE_PATH_MAX]; uint8_t flow; uint8_t wait_time; char *log_file; boolean_t ignore_path_records; boolean_t full_world_path_recs; } osmtest_opt_t; /* * FIELDS * * SEE ALSO *********/ /****h* OSMTest/OSMTest * NAME * OSMTest * * DESCRIPTION * The OSMTest object tests an SM/SA for conformance to a known * set of data about an Infiniband subnet. * * AUTHOR * Steve King, Intel * *********/ /****s* OSMTest/osmtest_t * NAME * osmtest_t * * DESCRIPTION * OSMTest structure. * * This object should be treated as opaque and should * be manipulated only through the provided functions. * * SYNOPSIS */ typedef struct _osmtest { osm_log_t log; struct _osm_vendor *p_vendor; osm_bind_handle_t h_bind; osm_mad_pool_t mad_pool; osmtest_opt_t opt; ib_port_attr_t local_port; ib_gid_t local_port_gid; ib_gid_t sm_port_gid; subnet_t exp_subn; cl_qpool_t node_pool; cl_qpool_t port_pool; cl_qpool_t link_pool; uint16_t max_lid; } osmtest_t; /* * FIELDS * log * Log facility used by all OSMTest components. * * p_vendor * Pointer to the vendor transport layer. * * h_bind * The bind handle obtained by osm_vendor_sa_api/osmv_bind_sa * * mad_pool * The mad pool provided for teh vendor layer to allocate mad wrappers in * * opt * osmtest options structure * * local_port * Port attributes for the port over which osmtest is running. * * exp_subn * Subnet object representing the expected subnet * * node_pool * Pool of objects for use in populating the subnet databases. * * port_pool * Pool of objects for use in populating the subnet databases. * * link_pool * Pool of objects for use in populating the subnet databases. * * SEE ALSO *********/ /****s* OpenSM: Subnet/osmtest_req_context_t * NAME * osmtest_req_context_t * * DESCRIPTION * Query context for ib_query callback function. * * SYNOPSIS */ typedef struct _osmtest_req_context { osmtest_t *p_osmt; osmv_query_res_t result; } osmtest_req_context_t; typedef struct _osmtest_mgrp_t { cl_map_item_t map_item; ib_member_rec_t mcmember_rec; } osmtest_mgrp_t; /* * FIELDS * * SEE ALSO *********/ /****f* OSMTest/osmtest_construct * NAME * osmtest_construct * * DESCRIPTION * This function constructs an OSMTest object. * * SYNOPSIS */ void osmtest_construct(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to a OSMTest object to construct. * * RETURN VALUE * This function does not return a value. * * NOTES * Allows calling osmtest_init, osmtest_destroy. * * Calling osmtest_construct is a prerequisite to calling any other * method except osmtest_init. * * SEE ALSO * SM object, osmtest_init, osmtest_destroy *********/ /****f* OSMTest/osmtest_destroy * NAME * osmtest_destroy * * DESCRIPTION * The osmtest_destroy function destroys an osmtest object, releasing * all resources. * * SYNOPSIS */ void osmtest_destroy(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to a OSMTest object to destroy. * * RETURN VALUE * This function does not return a value. * * NOTES * Performs any necessary cleanup of the specified OSMTest object. * Further operations should not be attempted on the destroyed object. * This function should only be called after a call to osmtest_construct or * osmtest_init. * * SEE ALSO * SM object, osmtest_construct, osmtest_init *********/ /****f* OSMTest/osmtest_init * NAME * osmtest_init * * DESCRIPTION * The osmtest_init function initializes a OSMTest object for use. * * SYNOPSIS */ ib_api_status_t osmtest_init(IN osmtest_t * const p_osmt, IN const osmtest_opt_t * const p_opt, IN const osm_log_level_t log_flags); /* * PARAMETERS * p_osmt * [in] Pointer to an osmtest_t object to initialize. * * p_opt * [in] Pointer to the options structure. * * log_flags * [in] Log level flags to set. * * RETURN VALUES * IB_SUCCESS if the OSMTest object was initialized successfully. * * NOTES * Allows calling other OSMTest methods. * * SEE ALSO * SM object, osmtest_construct, osmtest_destroy *********/ /****f* OSMTest/osmtest_run * NAME * osmtest_run * * DESCRIPTION * Runs the osmtest suite. * * SYNOPSIS */ ib_api_status_t osmtest_run(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to an osmtest_t object. * * guid * [in] Port GUID over which to run the test suite. * * RETURN VALUES * IB_SUCCESS * * NOTES * * SEE ALSO *********/ /****f* OSMTest/osmtest_bind * NAME * osmtest_bind * * DESCRIPTION * Binds osmtest to a local port. * * SYNOPSIS */ ib_api_status_t osmtest_bind(IN osmtest_t * p_osmt, IN uint16_t max_lid, IN ib_net64_t guid OPTIONAL); /* * PARAMETERS * p_osmt * [in] Pointer to an osmtest_t object. * * max_lid * [in] The maximal lid to query about (if RMPP is not supported) * * guid * [in] Port GUID over which to run the test suite. * If zero, the bind function will display a menu of local * port guids and wait for user input. * * RETURN VALUES * IB_SUCCESS * * NOTES * * SEE ALSO *********/ /****f* OSMTest/osmtest_query_res_cb * NAME * osmtest_query_res_cb * * DESCRIPTION * A Callback for the query to invoke on completion * * SYNOPSIS */ void osmtest_query_res_cb(IN osmv_query_res_t * p_rec); /* * PARAMETERS * p_rec * [in] Pointer to an ib_query_rec_t object used for the query. * * RETURN VALUES * NONE * * NOTES * * SEE ALSO *********/ /****f* OSMTest/ib_get_mad_status_str * NAME * ib_get_mad_status_str * * DESCRIPTION * return the string representing the given mad status * * SYNOPSIS */ const char *ib_get_mad_status_str(IN const ib_mad_t * const p_mad); /* * PARAMETERS * p_mad * [in] Pointer to the mad payload * * RETURN VALUES * NONE * * NOTES * * SEE ALSO *********/ /****f* OSMTest/osmt_run_service_records_flow * NAME * osmt_run_service_records_flow * * DESCRIPTION * Run the service record testing flow. * * SYNOPSIS */ ib_api_status_t osmt_run_service_records_flow(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to the osmtest obj * * RETURN VALUES * IB_SUCCESS if PASS * * NOTES * * SEE ALSO *********/ ib_api_status_t osmt_run_inform_info_flow(IN osmtest_t * const p_osmt); /****f* OSMTest/osmt_run_slvl_and_vlarb_records_flow * NAME * osmt_run_slvl_and_vlarb_records_flow * * DESCRIPTION * Run the sl2vl and vlarb tables testing flow. * * SYNOPSIS */ ib_api_status_t osmt_run_slvl_and_vlarb_records_flow(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to the osmtest obj * * RETURN VALUES * IB_SUCCESS if PASS * * NOTES * * SEE ALSO *********/ /****f* OSMTest/osmt_run_mcast_flow * NAME * osmt_run_mcast_flow * * DESCRIPTION * Run the multicast test flow * * SYNOPSIS */ ib_api_status_t osmt_run_mcast_flow(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to the osmtest obj * * RETURN VALUES * IB_SUCCESS if PASS * * NOTES * * SEE ALSO *********/ /****f* OSMTest/osmt_run_trap64_65_flow * NAME * osmt_run_trap64_65_flow * * DESCRIPTION * Run the trap 64/65 test flow. This test is ran with * an outside tool. * * SYNOPSIS */ ib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt); /* * PARAMETERS * p_osmt * [in] Pointer to the osmtest obj * * RETURN VALUES * IB_SUCCESS if PASS * * NOTES * * SEE ALSO *********/ ib_api_status_t osmtest_get_all_recs(IN osmtest_t * const p_osmt, IN ib_net16_t const attr_id, IN size_t const attr_size, IN OUT osmtest_req_context_t * const p_context); ib_api_status_t osmtest_get_local_port_lmc(IN osmtest_t * const p_osmt, IN ib_net16_t lid, OUT uint8_t * const p_lmc); /* * A few auxiliary macros for logging */ #define EXPECTING_ERRORS_START "[[ ===== Expecting Errors - START ===== " #define EXPECTING_ERRORS_END " ===== Expecting Errors - END ===== ]]" #endif /* _OSMTEST_H_ */ opensm-3.3.20/osmtest/include/osmt_mtl_regular_qp.h0000644000205000001450000001354512104655725017400 00000000000000/* * Copyright (c) 2001-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. * */ /* * mad.h - * Header file for common special QP resources creation code. * * Creation date: * * Version: osmt_mtl_regular_qp.h,v 1.2 2003/03/20 16:05:10 eitan * * Authors: * Elazar Raab * * Changes: */ #ifndef H_MAD_H #define H_MAD_H #include #include #include #include #if defined(MAD_IN) || defined(MAD_OUT) #error MACROS MAD_IN and MAD_OUT are in use, do not override #endif #define MAD_IN #define MAD_OUT /* HCA Constants */ #define HCA_ID "mt21108_pci0" #define GRH_LEN 40 #define KNOWN_QP1_QKEY 0x80010000 #define MAX_OUTS_SQ 2 /* Max. buffers posted for requests in SQ */ #define MAX_OUTS_RQ 5 /* Max. buffers posted for responses in RQ */ #define MAX_POLL_CNT 300 #define POLL_SLEEP 1 /* for usleep */ #define MAD_SIZE 256 /* MADs are always 256B */ #define MAD_ATTR_OFFSET 16 #define MAD_TID_OFFSET 8 /* Verbs SQP resources handles */ typedef struct { VAPI_hca_id_t hca_id; /*id of HCA */ u_int8_t port_num; /* the port num to use */ VAPI_hca_hndl_t hca_hndl; /*handle of HCA */ VAPI_qp_hndl_t qp_hndl; /*handle of QP I use */ VAPI_mr_hndl_t mr_hndl; /*handle of memory region */ VAPI_cq_hndl_t rq_cq_hndl, sq_cq_hndl; /*handle of send & receive completion Queues */ VAPI_pd_hndl_t pd_hndl; /*handle of Partition Domain */ /* VAPI_ud_av_hndl_t av_hndl; */ IB_lid_t slid; /*LID*/ void *buf_ptr; /*mem buffer for outstanding pkts */ MT_size_t buf_size; /*size of mem buffer for outstanding pkts */ u_int32_t max_outs_sq; /*max # of outstanding pkts in send queue */ u_int32_t max_outs_rq; /*max # of outstanding pkts in receive queue */ IB_rkey_t l_key; /*my l_key for memory regions */ VAPI_qkey_t qkey; /*my qkey */ EVAPI_compl_handler_hndl_t rq_cq_eventh, sq_cq_eventh; /* event handlers for polling */ bool is_sqp; /* relate to union below - my QP */ union { VAPI_special_qp_t sqp_type; VAPI_qp_num_t qp_num; } qp_id; void *wait_q; } osmt_mtl_mad_res_t; /* init an osmt_mtl_mad_res_t with all resources initialized (use functions below) */ VAPI_ret_t osmt_mtl_init(osmt_mtl_mad_res_t * res /*pointer to res (resources) struct */ ); VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t * res /*pointer to res (resources) struct */ ); /* Cleanup all resources of (which are valid) in res */ VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t * res /*pointer to res (resources) struct */ ); /* create CQs and QP as given in res->is_sqp (if TRUE, get special QP) */ VAPI_ret_t osmt_mtl_get_qp_resources(osmt_mtl_mad_res_t * res /*pointer to res (resources) struct */ ); /* move QP to RTS state */ VAPI_ret_t osmt_mtl_mad_qp_init(osmt_mtl_mad_res_t * res /*max number of outstanding packets allowed in send queue */ ); /* create and register res->buf_ptr */ VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t * res /*pointer to res (resources) struct */ ); VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t * res, /* pointer to res (resources) struct */ int16_t dlid, /*destination lid */ VAPI_ud_av_hndl_t * avh_p /* address vectr handle to update */ ); /* Send MAD to given dest QP*/ VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t * res, /*pointer to res (resources) struct */ VAPI_wr_id_t id, /*wqe ID */ void *mad, /*mad buffer to send */ VAPI_qp_num_t dest_qp, /*destination QP */ IB_sl_t sl, /*Service Level */ u_int32_t dest_qkey, /*Destination QP KEY */ VAPI_ud_av_hndl_t avh /* address vectr handle to use */ ); /* post buffers to RQ. returns num of buffers actually posted */ int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t * res, /*pointer to res (resources) struct */ void *buf_array, /*array of receive buffers */ u_int32_t num_o_bufs, /*number of receive buffers */ u_int32_t size, /* size of expected receive packet - MAD */ VAPI_wr_id_t start_id /* start id for receive buffers */ ); /* Poll given CQ for completion max_poll times (POLL_SLEEP [usec] delays). result in wc_desc_p. */ VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca, /*handle for HCA */ VAPI_cq_hndl_t cq, /*handle for Completion Queue - Rcv/Send */ VAPI_wc_desc_t * wc_desc_p, /*handle of cqe */ u_int32_t max_poll, /*number of polling iterations */ u_int32_t poll_sleep, /*timeout for each polling */ VAPI_ud_av_hndl_t * avh_p /* address vectopr handle to cleanup */ ); #endif opensm-3.3.20/osmtest/include/osmtest_base.h0000644000205000001450000000417712104655725016012 00000000000000/* * 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: * Declaration of osmtest_t. * This object represents the OSMTest Test object. * */ #ifndef _OSMTEST_BASE_H_ #define _OSMTEST_BASE_H_ #ifndef __WIN__ #include #else #include #endif #define OSMTEST_MAX_LINE_LEN 120 #define OSMTEST_FILE_PATH_MAX PATH_MAX #define STRESS_SMALL_RMPP_THR 100000 /* Take long times when querying big clusters (over 40 nodes), an average of : 0.25 sec for query each query receives 1000 records */ #define STRESS_LARGE_RMPP_THR 4000 #define STRESS_LARGE_PR_RMPP_THR 20000 #define STRESS_GET_PR 100000 extern const char *const p_file; #endif /* _OSMTEST_BASE_H_ */ opensm-3.3.20/osmtest/Makefile.am0000644000205000001450000000121712272264654013555 00000000000000 if DEBUG DBGFLAGS = -ggdb -D_DEBUG_ else DBGFLAGS = -g endif INCLUDES = -I$(srcdir)/include $(OSMV_INCLUDES) sbin_PROGRAMS = osmtest osmtest_SOURCES = main.c osmtest.c osmt_service.c osmt_slvl_vl_arb.c \ osmt_multicast.c osmt_inform.c if OSMV_VAPI osmtest_SOURCES += osmt_mtl_regular_qp.c endif osmtest_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) osmtest_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L../opensm -lopensm $(OSMV_LDADD) EXTRA_DIST = $(srcdir)/include/osmt_inform.h \ $(srcdir)/include/osmtest_subnet.h \ $(srcdir)/include/osmtest.h \ $(srcdir)/include/osmt_mtl_regular_qp.h \ $(srcdir)/include/osmtest_base.h opensm-3.3.20/osmtest/Makefile.in0000644000205000001450000007464212726323426013577 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ sbin_PROGRAMS = osmtest$(EXEEXT) @OSMV_VAPI_TRUE@am__append_1 = osmt_mtl_regular_qp.c subdir = osmtest DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" PROGRAMS = $(sbin_PROGRAMS) am__osmtest_SOURCES_DIST = main.c osmtest.c osmt_service.c \ osmt_slvl_vl_arb.c osmt_multicast.c osmt_inform.c \ osmt_mtl_regular_qp.c @OSMV_VAPI_TRUE@am__objects_1 = osmtest-osmt_mtl_regular_qp.$(OBJEXT) am_osmtest_OBJECTS = osmtest-main.$(OBJEXT) osmtest-osmtest.$(OBJEXT) \ osmtest-osmt_service.$(OBJEXT) \ osmtest-osmt_slvl_vl_arb.$(OBJEXT) \ osmtest-osmt_multicast.$(OBJEXT) osmtest-osmt_inform.$(OBJEXT) \ $(am__objects_1) osmtest_OBJECTS = $(am_osmtest_OBJECTS) am__DEPENDENCIES_1 = osmtest_DEPENDENCIES = $(am__DEPENDENCIES_1) osmtest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(osmtest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(osmtest_SOURCES) DIST_SOURCES = $(am__osmtest_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @DEBUG_FALSE@DBGFLAGS = -g @DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_ INCLUDES = -I$(srcdir)/include $(OSMV_INCLUDES) osmtest_SOURCES = main.c osmtest.c osmt_service.c osmt_slvl_vl_arb.c \ osmt_multicast.c osmt_inform.c $(am__append_1) osmtest_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) osmtest_LDADD = -L../complib -losmcomp -L../libvendor -losmvendor -L../opensm -lopensm $(OSMV_LDADD) EXTRA_DIST = $(srcdir)/include/osmt_inform.h \ $(srcdir)/include/osmtest_subnet.h \ $(srcdir)/include/osmtest.h \ $(srcdir)/include/osmt_mtl_regular_qp.h \ $(srcdir)/include/osmtest_base.h all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign osmtest/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign osmtest/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list osmtest$(EXEEXT): $(osmtest_OBJECTS) $(osmtest_DEPENDENCIES) @rm -f osmtest$(EXEEXT) $(osmtest_LINK) $(osmtest_OBJECTS) $(osmtest_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmt_inform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmt_multicast.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmt_service.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/osmtest-osmtest.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< osmtest-main.o: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-main.o -MD -MP -MF $(DEPDIR)/osmtest-main.Tpo -c -o osmtest-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-main.Tpo $(DEPDIR)/osmtest-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='osmtest-main.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c osmtest-main.obj: main.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-main.obj -MD -MP -MF $(DEPDIR)/osmtest-main.Tpo -c -o osmtest-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-main.Tpo $(DEPDIR)/osmtest-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='main.c' object='osmtest-main.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi` osmtest-osmtest.o: osmtest.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmtest.o -MD -MP -MF $(DEPDIR)/osmtest-osmtest.Tpo -c -o osmtest-osmtest.o `test -f 'osmtest.c' || echo '$(srcdir)/'`osmtest.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmtest.Tpo $(DEPDIR)/osmtest-osmtest.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmtest.c' object='osmtest-osmtest.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmtest.o `test -f 'osmtest.c' || echo '$(srcdir)/'`osmtest.c osmtest-osmtest.obj: osmtest.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmtest.obj -MD -MP -MF $(DEPDIR)/osmtest-osmtest.Tpo -c -o osmtest-osmtest.obj `if test -f 'osmtest.c'; then $(CYGPATH_W) 'osmtest.c'; else $(CYGPATH_W) '$(srcdir)/osmtest.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmtest.Tpo $(DEPDIR)/osmtest-osmtest.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmtest.c' object='osmtest-osmtest.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmtest.obj `if test -f 'osmtest.c'; then $(CYGPATH_W) 'osmtest.c'; else $(CYGPATH_W) '$(srcdir)/osmtest.c'; fi` osmtest-osmt_service.o: osmt_service.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_service.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_service.Tpo -c -o osmtest-osmt_service.o `test -f 'osmt_service.c' || echo '$(srcdir)/'`osmt_service.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_service.Tpo $(DEPDIR)/osmtest-osmt_service.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_service.c' object='osmtest-osmt_service.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_service.o `test -f 'osmt_service.c' || echo '$(srcdir)/'`osmt_service.c osmtest-osmt_service.obj: osmt_service.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_service.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_service.Tpo -c -o osmtest-osmt_service.obj `if test -f 'osmt_service.c'; then $(CYGPATH_W) 'osmt_service.c'; else $(CYGPATH_W) '$(srcdir)/osmt_service.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_service.Tpo $(DEPDIR)/osmtest-osmt_service.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_service.c' object='osmtest-osmt_service.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_service.obj `if test -f 'osmt_service.c'; then $(CYGPATH_W) 'osmt_service.c'; else $(CYGPATH_W) '$(srcdir)/osmt_service.c'; fi` osmtest-osmt_slvl_vl_arb.o: osmt_slvl_vl_arb.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_slvl_vl_arb.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo -c -o osmtest-osmt_slvl_vl_arb.o `test -f 'osmt_slvl_vl_arb.c' || echo '$(srcdir)/'`osmt_slvl_vl_arb.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_slvl_vl_arb.c' object='osmtest-osmt_slvl_vl_arb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_slvl_vl_arb.o `test -f 'osmt_slvl_vl_arb.c' || echo '$(srcdir)/'`osmt_slvl_vl_arb.c osmtest-osmt_slvl_vl_arb.obj: osmt_slvl_vl_arb.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_slvl_vl_arb.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo -c -o osmtest-osmt_slvl_vl_arb.obj `if test -f 'osmt_slvl_vl_arb.c'; then $(CYGPATH_W) 'osmt_slvl_vl_arb.c'; else $(CYGPATH_W) '$(srcdir)/osmt_slvl_vl_arb.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Tpo $(DEPDIR)/osmtest-osmt_slvl_vl_arb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_slvl_vl_arb.c' object='osmtest-osmt_slvl_vl_arb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_slvl_vl_arb.obj `if test -f 'osmt_slvl_vl_arb.c'; then $(CYGPATH_W) 'osmt_slvl_vl_arb.c'; else $(CYGPATH_W) '$(srcdir)/osmt_slvl_vl_arb.c'; fi` osmtest-osmt_multicast.o: osmt_multicast.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_multicast.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_multicast.Tpo -c -o osmtest-osmt_multicast.o `test -f 'osmt_multicast.c' || echo '$(srcdir)/'`osmt_multicast.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_multicast.Tpo $(DEPDIR)/osmtest-osmt_multicast.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_multicast.c' object='osmtest-osmt_multicast.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_multicast.o `test -f 'osmt_multicast.c' || echo '$(srcdir)/'`osmt_multicast.c osmtest-osmt_multicast.obj: osmt_multicast.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_multicast.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_multicast.Tpo -c -o osmtest-osmt_multicast.obj `if test -f 'osmt_multicast.c'; then $(CYGPATH_W) 'osmt_multicast.c'; else $(CYGPATH_W) '$(srcdir)/osmt_multicast.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_multicast.Tpo $(DEPDIR)/osmtest-osmt_multicast.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_multicast.c' object='osmtest-osmt_multicast.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_multicast.obj `if test -f 'osmt_multicast.c'; then $(CYGPATH_W) 'osmt_multicast.c'; else $(CYGPATH_W) '$(srcdir)/osmt_multicast.c'; fi` osmtest-osmt_inform.o: osmt_inform.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_inform.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_inform.Tpo -c -o osmtest-osmt_inform.o `test -f 'osmt_inform.c' || echo '$(srcdir)/'`osmt_inform.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_inform.Tpo $(DEPDIR)/osmtest-osmt_inform.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_inform.c' object='osmtest-osmt_inform.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_inform.o `test -f 'osmt_inform.c' || echo '$(srcdir)/'`osmt_inform.c osmtest-osmt_inform.obj: osmt_inform.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_inform.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_inform.Tpo -c -o osmtest-osmt_inform.obj `if test -f 'osmt_inform.c'; then $(CYGPATH_W) 'osmt_inform.c'; else $(CYGPATH_W) '$(srcdir)/osmt_inform.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_inform.Tpo $(DEPDIR)/osmtest-osmt_inform.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_inform.c' object='osmtest-osmt_inform.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_inform.obj `if test -f 'osmt_inform.c'; then $(CYGPATH_W) 'osmt_inform.c'; else $(CYGPATH_W) '$(srcdir)/osmt_inform.c'; fi` osmtest-osmt_mtl_regular_qp.o: osmt_mtl_regular_qp.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_mtl_regular_qp.o -MD -MP -MF $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo -c -o osmtest-osmt_mtl_regular_qp.o `test -f 'osmt_mtl_regular_qp.c' || echo '$(srcdir)/'`osmt_mtl_regular_qp.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_mtl_regular_qp.c' object='osmtest-osmt_mtl_regular_qp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_mtl_regular_qp.o `test -f 'osmt_mtl_regular_qp.c' || echo '$(srcdir)/'`osmt_mtl_regular_qp.c osmtest-osmt_mtl_regular_qp.obj: osmt_mtl_regular_qp.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -MT osmtest-osmt_mtl_regular_qp.obj -MD -MP -MF $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo -c -o osmtest-osmt_mtl_regular_qp.obj `if test -f 'osmt_mtl_regular_qp.c'; then $(CYGPATH_W) 'osmt_mtl_regular_qp.c'; else $(CYGPATH_W) '$(srcdir)/osmt_mtl_regular_qp.c'; fi` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Tpo $(DEPDIR)/osmtest-osmt_mtl_regular_qp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='osmt_mtl_regular_qp.c' object='osmtest-osmt_mtl_regular_qp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(osmtest_CFLAGS) $(CFLAGS) -c -o osmtest-osmt_mtl_regular_qp.obj `if test -f 'osmt_mtl_regular_qp.c'; then $(CYGPATH_W) 'osmt_mtl_regular_qp.c'; else $(CYGPATH_W) '$(srcdir)/osmt_mtl_regular_qp.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-sbinPROGRAMS ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-sbinPROGRAMS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/osmtest/main.c0000644000205000001450000004632112370461757012620 00000000000000/* * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2009 HNR Consulting. 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: * Command line interface for osmtest. * */ #include #include #include #include #include "osmtest.h" /******************************************************************** D E F I N E G L O B A L V A R I A B L E S *********************************************************************/ /* This is the global osmtest object. One osmtest object is required per subnet. Future versions could support multiple subents by instantiating more than one osmtest object. */ #define MAX_LOCAL_IBPORTS 64 #define OSMT_DEFAULT_RETRY_COUNT 3 #define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000 #define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10 #define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL) boolean_t osmt_is_debug(void) { #if defined( _DEBUG_ ) return TRUE; #else return FALSE; #endif /* defined( _DEBUG_ ) */ } void show_usage() { printf ("\n------- osmtest - Usage and options ----------------------\n"); printf("Usage: osmtest [options]\n"); printf("Options:\n"); printf("-f \n" "--flow \n" " This option directs osmtest to run a specific flow:\n" " FLOW DESCRIPTION\n" " c = create an inventory file with all nodes, ports and paths\n" " a = run all validation tests (expecting an input inventory)\n" " v = only validate the given inventory file\n" " s = run service registration, deregistration, and lease test\n" " e = run event forwarding test\n" " f = flood the SA with queries according to the stress mode\n" " m = multicast flow\n" " q = QoS info: dump VLArb and SLtoVL tables\n" " t = run trap 64/65 flow (this flow requires running of external tool)\n" " (default is all flows except QoS)\n\n"); printf("-w \n" "--wait \n" " This option specifies the wait time for trap 64/65 in seconds\n" " It is used only when running -f t - the trap 64/65 flow\n" " (default to 10 sec)\n\n"); printf("-d \n" "--debug \n" " This option specifies a debug option\n" " These options are not normally needed\n" " The number following -d selects the debug\n" " option to enable as follows:\n" " OPT Description\n" " --- -----------------\n" " -d0 - Unused.\n" " -d1 - Do not scan/compare path records.\n" " -d2 - Force log flushing after each log message.\n" " -d4 - Use full world path record queries.\n" " Without -d, no debug options are enabled\n\n"); printf("-m \n" "--max_lid \n" " This option specifies the maximal LID number to be searched\n" " for during inventory file build (default to 100)\n\n"); printf("-g \n" "--guid \n" " This option specifies the local port GUID value\n" " with which osmtest should bind. osmtest may be\n" " bound to 1 port at a time\n\n"); printf("-p \n" "--port\n" " This option displays a menu of possible local port GUID values\n" " with which osmtest could bind\n\n"); printf("-h\n" "--help\n" " Display this usage info then exit\n\n"); printf("-i \n" "--inventory \n" " This option specifies the name of the inventory file\n" " Normally, osmtest expects to find an inventory file,\n" " which osmtest uses to validate real-time information\n" " received from the SA during testing\n" " If -i is not specified, osmtest defaults to the file\n" " 'osmtest.dat'\n" " See -c option for related information\n\n"); printf("-s\n" "--stress\n" " This option runs the specified stress test instead\n" " of the normal test suite\n" " Stress test options are as follows:\n" " OPT Description\n" " --- -----------------\n" " -s1 - Single-MAD (RMPP) response SA queries\n" " -s2 - Multi-MAD (RMPP) response SA queries\n" " -s3 - Multi-MAD (RMPP) Path Record SA queries\n" " -s4 - Single-MAD (non RMPP) get Path Record SA queries\n" " Without -s, stress testing is not performed\n\n"); printf("-G\n" "--grh\n" " sends all SA queries with GRH with exception of\n" " GetMulti MultiPathRecord\n\n"); printf("-M\n" "--Multicast_Mode\n" " This option specify length of Multicast test:\n" " OPT Description\n" " --- -----------------\n" " -M1 - Short Multicast Flow (default) - single mode\n" " -M2 - Short Multicast Flow - multiple mode\n" " -M3 - Long Multicast Flow - single mode\n" " -M4 - Long Multicast Flow - multiple mode\n" " Single mode - Osmtest is tested alone, with no other\n" " apps that interact with OpenSM MC\n" " Multiple mode - Could be run with other apps using MC with\n" " OpenSM." " Without -M, default flow testing is performed\n\n"); printf("-t \n" " This option specifies the time in milliseconds\n" " used for transaction timeouts\n" " Specifying -t 0 disables timeouts\n" " Without -t, osmtest defaults to a timeout value of\n" " 1 second\n\n"); printf("-l\n" "--log_file\n" " This option defines the log to be the given file\n" " By default the log goes to stdout\n\n"); printf("-v\n" " This option increases the log verbosity level\n" " The -v option may be specified multiple times\n" " to further increase the verbosity level\n" " See the -vf option for more information about.\n" " log verbosity\n\n"); printf("-V\n" " This option sets the maximum verbosity level and\n" " forces log flushing\n" " The -V is equivalent to '-vf 0xFF -d 2'\n" " See the -vf option for more information about.\n" " log verbosity\n\n"); printf("-vf \n" " This option sets the log verbosity level\n" " A flags field must follow the -vf option\n" " A bit set/clear in the flags enables/disables a\n" " specific log level as follows:\n" " BIT LOG LEVEL ENABLED\n" " ---- -----------------\n" " 0x01 - ERROR (error messages)\n" " 0x02 - INFO (basic messages, low volume)\n" " 0x04 - VERBOSE (interesting stuff, moderate volume)\n" " 0x08 - DEBUG (diagnostic, high volume)\n" " 0x10 - FUNCS (function entry/exit, very high volume)\n" " 0x20 - FRAMES (dumps all SMP and GMP frames)\n" " 0x40 - currently unused\n" " 0x80 - currently unused\n" " Without -vf, osmtest defaults to ERROR + INFO (0x3)\n" " Specifying -vf 0 disables all messages\n" " Specifying -vf 0xFF enables all messages (see -V)\n" " High verbosity levels may require increasing\n" " the transaction timeout with the -t option\n\n"); } static void print_all_guids(IN osmtest_t * p_osmt) { ib_api_status_t status; uint32_t num_ports = MAX_LOCAL_IBPORTS; ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS] = { {0} }; uint32_t i; /* Call the transport layer for a list of local port GUID values. */ status = osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array, &num_ports); if (status != IB_SUCCESS) { printf("\nError from osm_vendor_get_all_port_attr (%x)\n", status); return; } printf("\nListing GUIDs:\n"); for (i = 0; i < num_ports; i++) printf("Port %i: 0x%" PRIx64 "\n", i, cl_hton64(attr_array[i].port_guid)); } ib_net64_t get_port_guid(IN osmtest_t * p_osmt, uint64_t port_guid) { ib_api_status_t status; uint32_t num_ports = MAX_LOCAL_IBPORTS; ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS] = { {0} }; uint32_t i; /* Call the transport layer for a list of local port GUID values. */ /* "local ports" is(?) phys, shouldn't this exclude port 0 then ? */ status = osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array, &num_ports); if (status != IB_SUCCESS) { printf("\nError from osm_vendor_get_all_port_attr (%x)\n", status); return (0); } if (num_ports == 1) { printf("using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid)); return (attr_array[0].port_guid); } for (i = 0; i < num_ports; i++) { if (attr_array[i].port_guid == port_guid || (!port_guid && attr_array[i].link_state > IB_LINK_DOWN)) return attr_array[i].port_guid; } return 0; } int main(int argc, char *argv[]) { static osmtest_t osm_test; osmtest_opt_t opt = { 0 }; ib_net64_t guid = 0; uint16_t max_lid = 100; ib_api_status_t status; uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO; int32_t vendor_debug = 0; char flow_name[64]; uint32_t next_option; const char *const short_option = "f:l:m:M:d:g:s:t:i:pcvGVh"; /* * In the array below, the 2nd parameter specified the number * of arguments as follows: * 0: no arguments * 1: argument * 2: optional */ const struct option long_option[] = { {"create", 0, NULL, 'c'}, {"debug", 1, NULL, 'd'}, {"flow", 1, NULL, 'f'}, {"wait", 1, NULL, 'w'}, {"inventory", 1, NULL, 'i'}, {"max_lid", 1, NULL, 'm'}, {"guid", 1, NULL, 'g'}, {"port", 0, NULL, 'p'}, {"help", 0, NULL, 'h'}, {"stress", 1, NULL, 's'}, {"grh", 0, NULL, 'G'}, {"Multicast_Mode", 1, NULL, 'M'}, {"timeout", 1, NULL, 't'}, {"verbose", 0, NULL, 'v'}, {"log_file", 1, NULL, 'l'}, {"vf", 1, NULL, 'x'}, {"V", 0, NULL, 'V'}, {NULL, 0, NULL, 0} /* Required at end of array */ }; /* Make sure that the opensm, complib and osmtest were compiled using same modes (debug/free) */ if (osm_is_debug() != cl_is_debug() || osm_is_debug() != osmt_is_debug() || osmt_is_debug() != cl_is_debug()) { fprintf(stderr, "-E- OpenSM, Complib and OsmTest were compiled using different modes\n"); fprintf(stderr, "-E- OpenSM debug:%d Complib debug:%d OsmTest debug:%d \n", osm_is_debug(), cl_is_debug(), osmt_is_debug()); exit(1); } opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC; opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC; opt.retry_count = OSMT_DEFAULT_RETRY_COUNT; opt.force_log_flush = FALSE; opt.stress = 0; opt.log_file = NULL; opt.create = FALSE; opt.mmode = 1; opt.ignore_path_records = FALSE; /* Do path Records too */ opt.full_world_path_recs = FALSE; opt.flow = OSMT_FLOW_ALL; /* run all validation tests */ opt.with_grh = FALSE; strcpy(flow_name, "All Validations"); strcpy(opt.file_name, "osmtest.dat"); printf("\nCommand Line Arguments\n"); do { next_option = getopt_long_only(argc, argv, short_option, long_option, NULL); switch (next_option) { case 'c': /* * Create the inventory file. */ opt.create = TRUE; printf("\tCreating inventory file\n"); break; case 'i': /* * Specifies inventory file name. */ if (strlen(optarg) > OSMTEST_FILE_PATH_MAX) printf ("\nError: path name too long (ignored)\n"); else strcpy(opt.file_name, optarg); printf("\tFile = %s\n", opt.file_name); break; case 'f': /* * Specifies Flow. */ if (strlen(optarg) > OSMTEST_FILE_PATH_MAX) printf ("\nError: path name too long (ignored)\n"); else strcpy(flow_name, optarg); if (!strcmp("c", optarg)) { strcpy(flow_name, "Create Inventory"); opt.flow = OSMT_FLOW_CREATE_INVENTORY; } else if (!strcmp("v", optarg)) { strcpy(flow_name, "Validate Inventory"); opt.flow = OSMT_FLOW_VALIDATE_INVENTORY; } else if (!strcmp("s", optarg)) { strcpy(flow_name, "Services Registration"); opt.flow = OSMT_FLOW_SERVICE_REGISTRATION; } else if (!strcmp("e", optarg)) { strcpy(flow_name, "Event Forwarding"); opt.flow = OSMT_FLOW_EVENT_FORWARDING; } else if (!strcmp("f", optarg)) { strcpy(flow_name, "Stress SA"); opt.flow = OSMT_FLOW_STRESS_SA; } else if (!strcmp("m", optarg)) { strcpy(flow_name, "Multicast"); opt.flow = OSMT_FLOW_MULTICAST; } else if (!strcmp("q", optarg)) { strcpy(flow_name, "QoS: VLArb and SLtoVL"); opt.flow = OSMT_FLOW_QOS; } else if (!strcmp("t", optarg)) { strcpy(flow_name, "Trap 64/65"); opt.flow = OSMT_FLOW_TRAP; } else if (!strcmp("a", optarg)) { strcpy(flow_name, "All Validations"); opt.flow = OSMT_FLOW_ALL; } else { printf("\nError: unknown flow %s\n", flow_name); exit(2); } break; case 'w': /* * Specifies trap 64/65 wait time */ CL_ASSERT(strtol(optarg, NULL, 0) < 0x100); opt.wait_time = (uint8_t) strtol(optarg, NULL, 0); printf("\tTrap 64/65 wait time = %d\n", opt.wait_time); break; case 'm': /* * Specifies the max LID to search for during exploration. */ max_lid = (uint16_t) atoi(optarg); printf("\tMAX-LID %u\n", max_lid); break; case 'g': /* * Specifies port guid with which to bind. */ guid = cl_hton64(strtoull(optarg, NULL, 16)); printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(guid)); break; case 'p': /* * Display current port guids */ guid = INVALID_GUID; break; case 't': /* * Specifies transaction timeout. */ opt.transaction_timeout = strtol(optarg, NULL, 0); printf("\tTransaction timeout = %d\n", opt.transaction_timeout); break; case 'l': opt.log_file = optarg; printf("\tLog File: %s\n", opt.log_file); break; case 'v': /* * Increases log verbosity. */ log_flags = (log_flags << 1) | 1; printf("\tVerbose option -v (log flags = 0x%X)\n", log_flags); break; case 'V': /* * Specifies maximum log verbosity. */ log_flags = 0xFFFFFFFF; opt.force_log_flush = TRUE; printf("\tEnabling maximum log verbosity\n"); break; case 's': /* * Perform stress test. */ opt.stress = strtol(optarg, NULL, 0); printf("\tStress test enabled: "); switch (opt.stress) { case 1: printf("Small SA queries\n"); break; case 2: printf("Large SA queries\n"); break; case 3: printf("Large Path Record SA queries\n"); break; case 4: printf("SA Get Path Record queries\n"); break; default: printf("Unknown value %u (ignored)\n", opt.stress); opt.stress = 0; break; } break; case 'M': /* * Perform multicast test. */ opt.mmode = strtol(optarg, NULL, 0); printf("\tMulticast test enabled: "); switch (opt.mmode) { case 1: printf ("Short MC Flow - single mode (default)\n"); break; case 2: printf("Short MC Flow - multiple mode\n"); break; case 3: printf("Long MC Flow - single mode\n"); break; case 4: printf("Long MC Flow - multiple mode\n"); break; default: printf("Unknown value %u (ignored)\n", opt.stress); opt.mmode = 0; break; } break; case 'd': /* * Debug Options */ printf("\tDebug Option: "); switch (strtol(optarg, NULL, 0)) { case 1: printf("Ignore Path Records\n"); opt.ignore_path_records = TRUE; break; case 2: printf("Force Log Flush\n"); opt.force_log_flush = TRUE; break; case 4: printf("Use Full World Path Record Queries\n"); opt.full_world_path_recs = TRUE; break; case 3: /* Used to be memory tracking */ default: printf("Unknown value %ld (ignored)\n", strtol(optarg, NULL, 0)); break; } break; case 'h': show_usage(); return 0; case 'x': log_flags = strtol(optarg, NULL, 0); printf("\tVerbose option -vf (log flags = 0x%X)\n", log_flags); break; case 'G': opt.with_grh = TRUE; break; case -1: printf("Done with args\n"); break; default: /* something wrong */ abort(); } } while (next_option != -1); printf("\tFlow = %s\n", flow_name); if (vendor_debug) osm_vendor_set_debug(osm_test.p_vendor, vendor_debug); complib_init(); status = osmtest_init(&osm_test, &opt, (osm_log_level_t) log_flags); if (status != IB_SUCCESS) { printf("\nError from osmtest_init: %s\n", ib_get_err_str(status)); goto Exit; } if (cl_hton64(guid) == cl_hton64(INVALID_GUID)) { print_all_guids(&osm_test); complib_exit(); return (status); } /* If the user didn't specify a GUID on the command line, then get a port GUID value with which to bind. */ if (guid == 0 && !(guid = get_port_guid(&osm_test, guid))) { printf("\nError: port guid 0x%" PRIx64 " not found\n", guid); goto Exit; } /* * Guid may be zero going into this function if the user * hasn't specified a binding port on the command line. */ status = osmtest_bind(&osm_test, max_lid, guid); if (status != IB_SUCCESS) exit(status); status = osmtest_run(&osm_test); if (status != IB_SUCCESS) { printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name); } else { printf("OSMTEST: TEST \"%s\" PASS\n", flow_name); } osmtest_destroy(&osm_test); complib_exit(); Exit: return (status); } opensm-3.3.20/osmtest/osmtest.c0000644000205000001450000064521412726323014013364 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2007 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2009,2010 HNR Consulting. 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. * */ /* TODO : Check why we dont free the cl_qmap_items we store when reading DB */ /* * Abstract: * Implementation of osmtest_t. * This object represents the OSMTest Test object. * */ #include #include #include #include #include #include "osmtest.h" #define POOL_MIN_ITEMS 64 #define MAX_LOCAL_IBPORTS 64 typedef struct _osmtest_sm_info_rec { ib_net64_t sm_guid; ib_net16_t lid; uint8_t priority; uint8_t sm_state; } osmtest_sm_info_rec_t; typedef struct _osmtest_inform_info { boolean_t subscribe; ib_net32_t qpn; ib_net16_t trap; } osmtest_inform_info_t; typedef struct _osmtest_inform_info_rec { ib_gid_t subscriber_gid; ib_net16_t subscriber_enum; } osmtest_inform_info_rec_t; typedef enum _osmtest_token_val { OSMTEST_TOKEN_COMMENT = 0, OSMTEST_TOKEN_END, OSMTEST_TOKEN_DEFINE_NODE, OSMTEST_TOKEN_DEFINE_PORT, OSMTEST_TOKEN_DEFINE_PATH, OSMTEST_TOKEN_DEFINE_LINK, OSMTEST_TOKEN_LID, OSMTEST_TOKEN_BASE_VERSION, OSMTEST_TOKEN_CLASS_VERSION, OSMTEST_TOKEN_NODE_TYPE, OSMTEST_TOKEN_NUM_PORTS, OSMTEST_TOKEN_SYS_GUID, OSMTEST_TOKEN_NODE_GUID, OSMTEST_TOKEN_PORT_GUID, OSMTEST_TOKEN_PARTITION_CAP, OSMTEST_TOKEN_DEVICE_ID, OSMTEST_TOKEN_REVISION, OSMTEST_TOKEN_PORT_NUM, OSMTEST_TOKEN_VENDOR_ID, OSMTEST_TOKEN_DGID, OSMTEST_TOKEN_SGID, OSMTEST_TOKEN_DLID, OSMTEST_TOKEN_SLID, OSMTEST_TOKEN_HOP_FLOW_RAW, OSMTEST_TOKEN_TCLASS, OSMTEST_TOKEN_NUM_PATH, OSMTEST_TOKEN_PKEY, OSMTEST_TOKEN_SL, OSMTEST_TOKEN_RATE, OSMTEST_TOKEN_PKT_LIFE, OSMTEST_TOKEN_PREFERENCE, OSMTEST_TOKEN_MKEY, OSMTEST_TOKEN_SUBN_PREF, OSMTEST_TOKEN_BASE_LID, OSMTEST_TOKEN_SM_BASE_LID, OSMTEST_TOKEN_CAP_MASK, OSMTEST_TOKEN_DIAG_CODE, OSMTEST_TOKEN_MKEY_LEASE_PER, OSMTEST_TOKEN_LOC_PORT_NUM, OSMTEST_TOKEN_LINK_WID_EN, OSMTEST_TOKEN_LINK_WID_SUP, OSMTEST_TOKEN_LINK_WID_ACT, OSMTEST_TOKEN_LINK_SPEED_SUP, OSMTEST_TOKEN_PORT_STATE, OSMTEST_TOKEN_STATE_INFO2, OSMTEST_TOKEN_MKEY_PROT_BITS, OSMTEST_TOKEN_LMC, OSMTEST_TOKEN_LINK_SPEED, OSMTEST_TOKEN_MTU_SMSL, OSMTEST_TOKEN_VL_CAP, OSMTEST_TOKEN_VL_HIGH_LIMIT, OSMTEST_TOKEN_VL_ARB_HIGH_CAP, OSMTEST_TOKEN_VL_ARB_LOW_CAP, OSMTEST_TOKEN_MTU_CAP, OSMTEST_TOKEN_VL_STALL_LIFE, OSMTEST_TOKEN_VL_ENFORCE, OSMTEST_TOKEN_MKEY_VIOL, OSMTEST_TOKEN_PKEY_VIOL, OSMTEST_TOKEN_QKEY_VIOL, OSMTEST_TOKEN_GUID_CAP, OSMTEST_TOKEN_SUBN_TIMEOUT, OSMTEST_TOKEN_RESP_TIME_VAL, OSMTEST_TOKEN_ERR_THRESHOLD, OSMTEST_TOKEN_MTU, OSMTEST_TOKEN_FROMLID, OSMTEST_TOKEN_FROMPORTNUM, OSMTEST_TOKEN_TOPORTNUM, OSMTEST_TOKEN_TOLID, OSMTEST_TOKEN_UNKNOWN } osmtest_token_val_t; typedef struct _osmtest_token { osmtest_token_val_t val; size_t str_size; const char *str; } osmtest_token_t; const osmtest_token_t token_array[] = { {OSMTEST_TOKEN_COMMENT, 1, "#"}, {OSMTEST_TOKEN_END, 3, "END"}, {OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"}, {OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"}, {OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"}, {OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"}, {OSMTEST_TOKEN_LID, 3, "LID"}, {OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"}, {OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"}, {OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"}, {OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"}, {OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"}, {OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"}, {OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"}, {OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"}, {OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"}, {OSMTEST_TOKEN_REVISION, 8, "REVISION"}, {OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"}, {OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"}, {OSMTEST_TOKEN_DGID, 4, "DGID"}, {OSMTEST_TOKEN_SGID, 4, "SGID"}, {OSMTEST_TOKEN_DLID, 4, "DLID"}, {OSMTEST_TOKEN_SLID, 4, "SLID"}, {OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"}, {OSMTEST_TOKEN_TCLASS, 6, "TCLASS"}, {OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"}, {OSMTEST_TOKEN_PKEY, 4, "PKEY"}, {OSMTEST_TOKEN_SL, 2, "SL"}, {OSMTEST_TOKEN_RATE, 4, "RATE"}, {OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"}, {OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"}, {OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"}, {OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"}, {OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"}, {OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"}, {OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"}, {OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"}, {OSMTEST_TOKEN_LOC_PORT_NUM, 14, "local_port_num"}, {OSMTEST_TOKEN_LINK_WID_EN, 18, "link_width_enabled"}, {OSMTEST_TOKEN_LINK_WID_SUP, 20, "link_width_supported"}, {OSMTEST_TOKEN_LINK_WID_ACT, 17, "link_width_active"}, {OSMTEST_TOKEN_LINK_SPEED_SUP, 20, "link_speed_supported"}, {OSMTEST_TOKEN_PORT_STATE, 10, "port_state"}, {OSMTEST_TOKEN_STATE_INFO2, 10, "state_info2"}, {OSMTEST_TOKEN_MKEY_PROT_BITS, 3, "mpb"}, {OSMTEST_TOKEN_LMC, 3, "lmc"}, {OSMTEST_TOKEN_LINK_SPEED, 10, "link_speed"}, {OSMTEST_TOKEN_MTU_SMSL, 8, "mtu_smsl"}, {OSMTEST_TOKEN_VL_CAP, 6, "vl_cap"}, {OSMTEST_TOKEN_VL_HIGH_LIMIT, 13, "vl_high_limit"}, {OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"}, {OSMTEST_TOKEN_VL_ARB_LOW_CAP, 14, "vl_arb_low_cap"}, {OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"}, {OSMTEST_TOKEN_VL_STALL_LIFE, 13, "vl_stall_life"}, {OSMTEST_TOKEN_VL_ENFORCE, 10, "vl_enforce"}, {OSMTEST_TOKEN_MKEY_VIOL, 16, "m_key_violations"}, {OSMTEST_TOKEN_PKEY_VIOL, 16, "p_key_violations"}, {OSMTEST_TOKEN_QKEY_VIOL, 16, "q_key_violations"}, {OSMTEST_TOKEN_GUID_CAP, 8, "guid_cap"}, {OSMTEST_TOKEN_SUBN_TIMEOUT, 14, "subnet_timeout"}, {OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"}, {OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"}, {OSMTEST_TOKEN_MKEY, 4, "M_KEY"}, /* must be after the other mkey... tokens. */ {OSMTEST_TOKEN_MTU, 3, "MTU"}, /* must be after the other mtu... tokens. */ {OSMTEST_TOKEN_FROMLID, 8, "from_lid"}, {OSMTEST_TOKEN_FROMPORTNUM, 13, "from_port_num"}, {OSMTEST_TOKEN_TOPORTNUM, 11, "to_port_num"}, {OSMTEST_TOKEN_TOLID, 6, "to_lid"}, {OSMTEST_TOKEN_UNKNOWN, 0, ""} /* must be last entry */ }; static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY"; static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT"; static const char ib_mad_status_str_unsup_class_ver[] = "IB_MAD_STATUS_UNSUP_CLASS_VER"; static const char ib_mad_status_str_unsup_method[] = "IB_MAD_STATUS_UNSUP_METHOD"; static const char ib_mad_status_str_unsup_method_attr[] = "IB_MAD_STATUS_UNSUP_METHOD_ATTR"; static const char ib_mad_status_str_invalid_field[] = "IB_MAD_STATUS_INVALID_FIELD"; static const char ib_mad_status_str_no_resources[] = "IB_SA_MAD_STATUS_NO_RESOURCES"; static const char ib_mad_status_str_req_invalid[] = "IB_SA_MAD_STATUS_REQ_INVALID"; static const char ib_mad_status_str_no_records[] = "IB_SA_MAD_STATUS_NO_RECORDS"; static const char ib_mad_status_str_too_many_records[] = "IB_SA_MAD_STATUS_TOO_MANY_RECORDS"; static const char ib_mad_status_str_invalid_gid[] = "IB_SA_MAD_STATUS_INVALID_GID"; static const char ib_mad_status_str_insuf_comps[] = "IB_SA_MAD_STATUS_INSUF_COMPS"; static const char generic_or_str[] = " | "; static ib_api_status_t osmtest_create_db(IN osmtest_t * const p_osmt); const char *ib_get_mad_status_str(IN const ib_mad_t * const p_mad) { static char line[512]; uint32_t offset = 0; ib_net16_t status; boolean_t first = TRUE; line[offset] = '\0'; status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); if (status == 0) { strcat(&line[offset], "IB_SUCCESS"); return (line); } if (status & IB_MAD_STATUS_BUSY) { strcat(&line[offset], ib_mad_status_str_busy); offset += sizeof(ib_mad_status_str_busy); } if (status & IB_MAD_STATUS_REDIRECT) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_redirect); offset += sizeof(ib_mad_status_str_redirect) - 1; } if ((status & IB_MAD_STATUS_INVALID_FIELD) == IB_MAD_STATUS_UNSUP_CLASS_VER) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_unsup_class_ver); offset += sizeof(ib_mad_status_str_unsup_class_ver) - 1; } if ((status & IB_MAD_STATUS_INVALID_FIELD) == IB_MAD_STATUS_UNSUP_METHOD) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_unsup_method); offset += sizeof(ib_mad_status_str_unsup_method) - 1; } if ((status & IB_MAD_STATUS_INVALID_FIELD) == IB_MAD_STATUS_UNSUP_METHOD_ATTR) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_unsup_method_attr); offset += sizeof(ib_mad_status_str_unsup_method_attr) - 1; } if ((status & IB_MAD_STATUS_INVALID_FIELD) == IB_MAD_STATUS_INVALID_FIELD) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_invalid_field); offset += sizeof(ib_mad_status_str_invalid_field) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_NO_RESOURCES) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_no_resources); offset += sizeof(ib_mad_status_str_no_resources) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_REQ_INVALID) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_req_invalid); offset += sizeof(ib_mad_status_str_req_invalid) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_NO_RECORDS) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_no_records); offset += sizeof(ib_mad_status_str_no_records) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_TOO_MANY_RECORDS) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_too_many_records); offset += sizeof(ib_mad_status_str_too_many_records) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_INVALID_GID) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_invalid_gid); offset += sizeof(ib_mad_status_str_invalid_gid) - 1; } if ((status & IB_MAD_STATUS_CLASS_MASK) == IB_SA_MAD_STATUS_INSUF_COMPS) { if (!first) { strcat(&line[offset], generic_or_str); offset += sizeof(generic_or_str) - 1; } first = FALSE; strcat(&line[offset], ib_mad_status_str_insuf_comps); offset += sizeof(ib_mad_status_str_insuf_comps) - 1; } return (line); } void subnet_construct(IN subnet_t * const p_subn) { cl_qmap_init(&p_subn->link_tbl); cl_qmap_init(&p_subn->node_lid_tbl); cl_qmap_init(&p_subn->node_guid_tbl); cl_qmap_init(&p_subn->mgrp_mlid_tbl); /* NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */ /* cl_qmap_init( &p_subn->port_lid_tbl ); */ /* cl_qmap_init( &p_subn->port_guid_tbl ); */ /* port key is a lid and num pair */ cl_qmap_init(&p_subn->port_key_tbl); cl_qmap_init(&p_subn->path_tbl); } cl_status_t subnet_init(IN subnet_t * const p_subn) { cl_status_t status = IB_SUCCESS; subnet_construct(p_subn); return (status); } void osmtest_construct(IN osmtest_t * const p_osmt) { memset(p_osmt, 0, sizeof(*p_osmt)); osm_log_construct(&p_osmt->log); subnet_construct(&p_osmt->exp_subn); } void osmtest_destroy(IN osmtest_t * const p_osmt) { cl_map_item_t *p_item, *p_next_item; /* Currently there is a problem with IBAL exit flow - memory overrun, so bypass vendor deletion - it will be cleaned by the Windows OS */ #ifndef __WIN__ if (p_osmt->p_vendor) osm_vendor_delete(&p_osmt->p_vendor); #endif cl_qpool_destroy(&p_osmt->port_pool); cl_qpool_destroy(&p_osmt->node_pool); /* destroy the qmap tables */ p_next_item = cl_qmap_head(&p_osmt->exp_subn.link_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.link_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } p_next_item = cl_qmap_head(&p_osmt->exp_subn.mgrp_mlid_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.mgrp_mlid_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } p_next_item = cl_qmap_head(&p_osmt->exp_subn.node_guid_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.node_guid_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } p_next_item = cl_qmap_head(&p_osmt->exp_subn.node_lid_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.node_lid_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } p_next_item = cl_qmap_head(&p_osmt->exp_subn.path_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.path_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } p_next_item = cl_qmap_head(&p_osmt->exp_subn.port_key_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.port_key_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); free(p_item); } osm_log_destroy(&p_osmt->log); } ib_api_status_t osmtest_init(IN osmtest_t * const p_osmt, IN const osmtest_opt_t * const p_opt, IN const osm_log_level_t log_flags) { ib_api_status_t status; /* Can't use log macros here, since we're initializing the log. */ osmtest_construct(p_osmt); status = osm_log_init_v2(&p_osmt->log, p_opt->force_log_flush, 0x0001, p_opt->log_file, 0, TRUE); if (status != IB_SUCCESS) return (status); /* but we do not want any extra stuff here */ osm_log_set_level(&p_osmt->log, log_flags); OSM_LOG(&p_osmt->log, OSM_LOG_FUNCS, "[\n"); p_osmt->opt = *p_opt; status = cl_qpool_init(&p_osmt->node_pool, POOL_MIN_ITEMS, 0, POOL_MIN_ITEMS, sizeof(node_t), NULL, NULL, NULL); CL_ASSERT(status == CL_SUCCESS); status = cl_qpool_init(&p_osmt->port_pool, POOL_MIN_ITEMS, 0, POOL_MIN_ITEMS, sizeof(port_t), NULL, NULL, NULL); CL_ASSERT(status == CL_SUCCESS); p_osmt->p_vendor = osm_vendor_new(&p_osmt->log, p_opt->transaction_timeout); if (p_osmt->p_vendor == NULL) { status = IB_INSUFFICIENT_RESOURCES; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0001: " "Unable to allocate vendor object"); status = IB_ERROR; goto Exit; } osm_mad_pool_construct(&p_osmt->mad_pool); status = osm_mad_pool_init(&p_osmt->mad_pool); if (status != IB_SUCCESS) goto Exit; Exit: OSM_LOG(&p_osmt->log, OSM_LOG_FUNCS, "]\n"); return (status); } void osmtest_query_res_cb(IN osmv_query_res_t * p_rec) { osmtest_req_context_t *const p_ctxt = (osmtest_req_context_t *) p_rec->query_context; osmtest_t *const p_osmt = p_ctxt->p_osmt; OSM_LOG_ENTER(&p_osmt->log); p_ctxt->result = *p_rec; if (p_rec->status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0003: " "Error on query (%s)\n", ib_get_err_str(p_rec->status)); } OSM_LOG_EXIT(&p_osmt->log); } ib_api_status_t osmtest_get_all_recs(IN osmtest_t * const p_osmt, IN ib_net16_t const attr_id, IN size_t const attr_size, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting all %s records\n", ib_get_sa_attr_str(attr_id)); /* * Do a blocking query for all records in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); p_context->p_osmt = p_osmt; user.attr_id = attr_id; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0004: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0064: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (p_context->result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_validate_sa_class_port_info(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; osmv_query_req_t req; ib_class_port_info_t *p_cpi; osmtest_req_context_t context; osmtest_req_context_t *p_context = &context; ib_sa_mad_t *p_resp_sa_madp; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting ClassPortInfo\n"); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); p_context->p_osmt = p_osmt; req.query_type = OSMV_QUERY_CLASS_PORT_INFO; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = 0; req.sm_key = 0; if (p_osmt->opt.flow != OSMT_FLOW_CREATE_INVENTORY && p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0065: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0070: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (p_context->result. p_result_madw))); } goto Exit; } /* ok we got it so please print it out */ p_resp_sa_madp = (ib_sa_mad_t *) osm_madw_get_mad_ptr(context.result.p_result_madw); p_cpi = (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_madp); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "\n-----------------------------\n" "SA Class Port Info:\n" " base_ver:%u\n" " class_ver:%u\n" " cap_mask:0x%X\n" " cap_mask2:0x%X\n" " resp_time_val:0x%X\n" "-----------------------------\n", p_cpi->base_ver, p_cpi->class_ver, cl_ntoh16(p_cpi->cap_mask), ib_class_cap_mask2(p_cpi), ib_class_resp_time_val(p_cpi)); Exit: #if 0 if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } #endif OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_get_node_rec(IN osmtest_t * const p_osmt, IN ib_net64_t const node_guid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_node_record_t record; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting node record for 0x%016" PRIx64 "\n", cl_ntoh64(node_guid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.node_info.node_guid = node_guid; p_context->p_osmt = p_osmt; user.comp_mask = IB_NR_COMPMASK_NODEGUID; user.attr_id = IB_MAD_ATTR_NODE_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0071: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0072: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (p_context->result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get a node record by node LID **********************************************************************/ ib_api_status_t osmtest_get_node_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_node_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting node record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; user.comp_mask = IB_NR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_NODE_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0073: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0074: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_get_path_rec_by_half_world_query(IN osmtest_t * const p_osmt, IN ib_net64_t sguid, IN osmtest_req_context_t * p_context) { cl_status_t status = IB_SUCCESS; osmv_query_req_t req; osmv_user_query_t user; ib_path_rec_t record; OSM_LOG_ENTER(&p_osmt->log); memset(&req, 0, sizeof(req)); memset(p_context, 0, sizeof(*p_context)); memset(&record, 0, sizeof(record)); memset(&user, 0, sizeof(user)); ib_gid_set_default(&(record.sgid), sguid); record.num_path = 0x01; p_context->p_osmt = p_osmt; user.comp_mask = (IB_PR_COMPMASK_SGID | IB_PR_COMPMASK_NUMBPATH); user.attr_id = IB_MAD_ATTR_PATH_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0063: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = (*p_context).result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0066: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr ((*p_context).result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_get_path_rec_by_guid_pair(IN osmtest_t * const p_osmt, IN ib_net64_t sguid, IN ib_net64_t dguid, IN osmtest_req_context_t * p_context) { cl_status_t status = IB_SUCCESS; osmv_query_req_t req; osmv_guid_pair_t guid_pair; OSM_LOG_ENTER(&p_osmt->log); memset(&req, 0, sizeof(req)); memset(p_context, 0, sizeof(*p_context)); p_context->p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS; guid_pair.dest_guid = dguid; guid_pair.src_guid = sguid; req.p_query_input = &guid_pair; req.sm_key = 0; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Query for path from 0x%" PRIx64 " to 0x%" PRIx64 "\n", cl_ntoh64(sguid), cl_ntoh64(dguid)); if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0063: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = (*p_context).result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0066: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr ((*p_context).result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_get_path_rec_by_gid_pair(IN osmtest_t * const p_osmt, IN ib_gid_t sgid, IN ib_gid_t dgid, IN osmtest_req_context_t * p_context) { cl_status_t status = IB_SUCCESS; osmv_query_req_t req; osmv_gid_pair_t gid_pair; OSM_LOG_ENTER(&p_osmt->log); memset(&req, 0, sizeof(req)); memset(p_context, 0, sizeof(*p_context)); p_context->p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS; gid_pair.dest_gid = dgid; gid_pair.src_gid = sgid; req.p_query_input = &gid_pair; req.sm_key = 0; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Query for path from 0x%016" PRIx64 " 0x%016" PRIx64 " to 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh64(sgid.unicast.prefix), cl_ntoh64(sgid.unicast.interface_id), cl_ntoh64(dgid.unicast.prefix), cl_ntoh64(dgid.unicast.interface_id)); if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006A: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = (*p_context).result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006B: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr ((*p_context).result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) static ib_api_status_t osmtest_get_multipath_rec(IN osmtest_t * const p_osmt, IN osmv_multipath_req_t * p_request, IN osmtest_req_context_t * p_context) { cl_status_t status = IB_SUCCESS; osmv_query_req_t req; OSM_LOG_ENTER(&p_osmt->log); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); p_context->p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.query_type = OSMV_QUERY_MULTIPATH_REC; req.p_query_input = p_request; req.sm_key = 0; status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0068: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0069: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (p_context->result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } #endif ib_api_status_t osmtest_get_port_rec(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_portinfo_record_t record; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting PortInfoRecord for port with LID 0x%X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; user.comp_mask = IB_PIR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0075: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0076: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (p_context->result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_get_port_rec_by_num(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN uint8_t const port_num, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_portinfo_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting PortInfoRecord for port with LID 0x%X Num:0x%X\n", cl_ntoh16(lid), port_num); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; record.port_num = port_num; user.p_attr = &record; p_context->p_osmt = p_osmt; req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0077: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0078: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_port_recs_large(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_portinfo_record_t *p_rec; uint32_t i; cl_status_t status; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all PortInfoRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PORTINFO_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0006: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; *p_num_recs += num_recs; ++*p_num_queries; if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_portinfo_rec(context.result. p_result_madw, i); osm_dump_portinfo_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_node_recs_large(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_node_record_t *p_rec; uint32_t i; cl_status_t status; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0007: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; *p_num_recs += num_recs; ++*p_num_queries; if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_node_rec(context.result. p_result_madw, i); osm_dump_node_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_path_recs_large(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_path_rec_t *p_rec; uint32_t i; cl_status_t status; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all PathRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0008: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; *p_num_recs += num_recs; ++*p_num_queries; if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result. p_result_madw, i); osm_dump_path_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_path_recs_by_guid(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_path_rec_t *p_rec; uint32_t i; cl_status_t status = IB_SUCCESS; uint32_t num_recs = 0; node_t *p_src_node, *p_dst_node; cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; p_tbl = &p_osmt->exp_subn.node_guid_tbl; p_src_node = (node_t *) cl_qmap_head(p_tbl); /* * Go over all nodes that exist in the subnet * for each pair that are not switch nodes get the path record */ while (p_src_node != (node_t *) cl_qmap_end(p_tbl)) { p_dst_node = (node_t *) cl_qmap_head(p_tbl); while (p_dst_node != (node_t *) cl_qmap_end(p_tbl)) { /* * Do a blocking query for CA to CA Path Record */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Source : guid = 0x%" PRIx64 " type = %d" "Target : guid = 0x%" PRIx64 " type = %d\n", cl_ntoh64(p_src_node->rec.node_info.port_guid), p_src_node->rec.node_info.node_type, cl_ntoh64(p_dst_node->rec.node_info.port_guid), p_dst_node->rec.node_info.node_type); if (p_src_node->rec.node_info.node_type == IB_NODE_TYPE_CA && p_dst_node->rec.node_info.node_type == IB_NODE_TYPE_CA) { status = osmtest_get_path_rec_by_guid_pair(p_osmt, p_src_node-> rec. node_info. port_guid, p_dst_node-> rec. node_info. port_guid, &context); /* In a case of TIMEOUT you still can try sending but cant count, maybe its a temporary issue */ if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0009: " "osmtest_get_path_rec_by_guid_pair failed (%s)\n", ib_get_err_str(status)); if (status != IB_TIMEOUT) goto Exit; } else { /* we might have received several records */ num_recs = context.result.result_cnt; /* * Populate the database with the received records. */ *p_num_recs += num_recs; ++*p_num_queries; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); /* Dont waste time if not VERBOSE and above */ if (p_osmt->log.level & OSM_LOG_VERBOSE) { for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec (context.result. p_result_madw, i); osm_dump_path_record (&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } } if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result. p_result_madw); context.result.p_result_madw = NULL; } } /* next one please */ p_dst_node = (node_t *) cl_qmap_next(&p_dst_node->map_item); } p_src_node = (node_t *) cl_qmap_next(&p_src_node->map_item); } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_port_recs_small(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_portinfo_record_t *p_rec; uint32_t i; cl_status_t status; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for our own PortInfoRecord in the subnet. */ status = osmtest_get_port_rec(p_osmt, cl_ntoh16(p_osmt->local_port.lid), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0010: " "osmtest_get_port_rec failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; *p_num_recs += num_recs; ++*p_num_queries; if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_portinfo_rec(context.result. p_result_madw, i); osm_dump_portinfo_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_get_local_port_lmc(IN osmtest_t * const p_osmt, IN ib_net16_t lid, OUT uint8_t * const p_lmc) { osmtest_req_context_t context; ib_portinfo_record_t *p_rec; uint32_t i; cl_status_t status; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for our own PortInfoRecord in the subnet. */ status = osmtest_get_port_rec(p_osmt, cl_ntoh16(lid), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 001A: " "osmtest_get_port_rec failed (%s)\n", ib_get_err_str(status)); goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_portinfo_rec(context.result.p_result_madw, i); osm_dump_portinfo_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); if (p_lmc) { *p_lmc = ib_port_info_get_lmc(&p_rec->port_info); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "LMC %d\n", *p_lmc); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Use a wrong SM_Key in a simple port query and report success if * failed. **********************************************************************/ ib_api_status_t osmtest_wrong_sm_key_ignored(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_portinfo_record_t record; osmtest_req_context_t context; osmtest_req_context_t *p_context = &context; uint8_t port_num = 1; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Trying PortInfoRecord for port with LID 0x%X Num:0x%X\n", p_osmt->local_port.sm_lid, port_num); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = p_osmt->local_port.sm_lid; record.port_num = port_num; user.p_attr = &record; p_context->p_osmt = p_osmt; req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 9999; context.result.p_result_madw = NULL; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmv_query_sa(p_osmt->h_bind, &req); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); /* since we use a wrong sm_key we should get a timeout */ if (status != IB_TIMEOUT) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0011: " "Did not get a timeout but got (%s)\n", ib_get_err_str(status)); if (status == IB_SUCCESS) { /* assign some error value to status, since IB_SUCCESS is a bad rc */ status = IB_ERROR; } goto Exit; } else { status = IB_SUCCESS; } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_write_port_info(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_portinfo_record_t * const p_rec) { int result; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); result = fprintf(fh, "DEFINE_PORT\n" "lid 0x%X\n" "port_num 0x%X\n" "m_key 0x%016" PRIx64 "\n" "subnet_prefix 0x%016" PRIx64 "\n" "base_lid 0x%X\n" "master_sm_base_lid 0x%X\n" "capability_mask 0x%X\n" "diag_code 0x%X\n" "m_key_lease_period 0x%X\n" "local_port_num 0x%X\n" "link_width_enabled 0x%X\n" "link_width_supported 0x%X\n" "link_width_active 0x%X\n" "link_speed_supported 0x%X\n" "port_state %s\n" "state_info2 0x%X\n" "mpb 0x%X\n" "lmc 0x%X\n" "link_speed 0x%X\n" "mtu_smsl 0x%X\n" "vl_cap 0x%X\n" "vl_high_limit 0x%X\n" "vl_arb_high_cap 0x%X\n" "vl_arb_low_cap 0x%X\n" "mtu_cap 0x%X\n" "vl_stall_life 0x%X\n" "vl_enforce 0x%X\n" "m_key_violations 0x%X\n" "p_key_violations 0x%X\n" "q_key_violations 0x%X\n" "guid_cap 0x%X\n" "subnet_timeout 0x%X\n" "resp_time_value 0x%X\n" "error_threshold 0x%X\n" "END\n\n", cl_ntoh16(p_rec->lid), p_rec->port_num, cl_ntoh64(p_rec->port_info.m_key), cl_ntoh64(p_rec->port_info.subnet_prefix), cl_ntoh16(p_rec->port_info.base_lid), cl_ntoh16(p_rec->port_info.master_sm_base_lid), cl_ntoh32(p_rec->port_info.capability_mask), cl_ntoh16(p_rec->port_info.diag_code), cl_ntoh16(p_rec->port_info.m_key_lease_period), p_rec->port_info.local_port_num, p_rec->port_info.link_width_enabled, p_rec->port_info.link_width_supported, p_rec->port_info.link_width_active, ib_port_info_get_link_speed_sup(&p_rec->port_info), ib_get_port_state_str(ib_port_info_get_port_state (&p_rec->port_info)), p_rec->port_info.state_info2, ib_port_info_get_mpb(&p_rec->port_info), ib_port_info_get_lmc(&p_rec->port_info), p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl, p_rec->port_info.vl_cap, p_rec->port_info.vl_high_limit, p_rec->port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_low_cap, p_rec->port_info.mtu_cap, p_rec->port_info.vl_stall_life, p_rec->port_info.vl_enforce, cl_ntoh16(p_rec->port_info.m_key_violations), cl_ntoh16(p_rec->port_info.p_key_violations), cl_ntoh16(p_rec->port_info.q_key_violations), p_rec->port_info.guid_cap, ib_port_info_get_timeout(&p_rec->port_info), p_rec->port_info.resp_time_value, p_rec->port_info.error_threshold); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0161: " "Write failed\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_write_path_info(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_path_rec_t * const p_rec) { int result; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); result = fprintf(fh, "DEFINE_PATH\n" "dgid 0x%016" PRIx64 " 0x%016" PRIx64 "\nsgid 0x%016" PRIx64 " 0x%016" PRIx64 "\ndlid 0x%X\n" "slid 0x%X\n" "# hop_flow_raw 0x%X\n" "# tclass 0x%X\n" "# num_path 0x%X\n" "pkey 0x%X\n" "# sl 0x%X\n" "# qos_class 0x%X\n" "# mtu 0x%X\n" "# rate 0x%X\n" "# pkt_life 0x%X\n" "# preference 0x%X\n" "END\n\n", cl_ntoh64(p_rec->dgid.unicast.prefix), cl_ntoh64(p_rec->dgid.unicast.interface_id), cl_ntoh64(p_rec->sgid.unicast.prefix), cl_ntoh64(p_rec->sgid.unicast.interface_id), cl_ntoh16(p_rec->dlid), cl_ntoh16(p_rec->slid), cl_ntoh32(p_rec->hop_flow_raw), p_rec->tclass, p_rec->num_path, cl_ntoh16(p_rec->pkey), ib_path_rec_sl(p_rec), ib_path_rec_qos_class(p_rec), p_rec->mtu, p_rec->rate, p_rec->pkt_life, p_rec->preference); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0162: " "Write failed\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_write_node_info(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_node_record_t * const p_rec) { int result; cl_status_t status = IB_SUCCESS; char desc[IB_NODE_DESCRIPTION_SIZE + 1]; OSM_LOG_ENTER(&p_osmt->log); memcpy(desc, p_rec->node_desc.description, IB_NODE_DESCRIPTION_SIZE); desc[IB_NODE_DESCRIPTION_SIZE] = '\0'; result = fprintf(fh, "DEFINE_NODE\n" "lid 0x%X\n" "base_version 0x%X\n" "class_version 0x%X\n" "node_type 0x%X # (%s)\n" "num_ports 0x%X\n" "sys_guid 0x%016" PRIx64 "\n" "node_guid 0x%016" PRIx64 "\n" "port_guid 0x%016" PRIx64 "\n" "partition_cap 0x%X\n" "device_id 0x%X\n" "revision 0x%X\n" "# port_num 0x%X\n" "# vendor_id 0x%X\n" "# node_desc %s\n" "END\n\n", cl_ntoh16(p_rec->lid), p_rec->node_info.base_version, p_rec->node_info.class_version, p_rec->node_info.node_type, ib_get_node_type_str(p_rec->node_info.node_type), p_rec->node_info.num_ports, cl_ntoh64(p_rec->node_info.sys_guid), cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh64(p_rec->node_info.port_guid), cl_ntoh16(p_rec->node_info.partition_cap), cl_ntoh16(p_rec->node_info.device_id), cl_ntoh32(p_rec->node_info.revision), ib_node_info_get_local_port_num(&p_rec->node_info), cl_ntoh32(ib_node_info_get_vendor_id (&p_rec->node_info)), desc); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0163: " "Write failed\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_write_link(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_link_record_t * const p_rec) { int result; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); result = fprintf(fh, "DEFINE_LINK\n" "from_lid 0x%X\n" "from_port_num 0x%X\n" "to_port_num 0x%X\n" "to_lid 0x%X\n" "END\n\n", cl_ntoh16(p_rec->from_lid), p_rec->from_port_num, p_rec->to_port_num, cl_ntoh16(p_rec->to_lid)); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0164: " "Write failed\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_write_all_link_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_link_record_t *p_rec; uint32_t i; cl_status_t status; size_t num_recs; int result; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_LINK_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0165: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Write the received records out to the file. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); result = fprintf(fh, "#\n" "# Link Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0166: " "Write failed\n"); status = IB_ERROR; goto Exit; } for (i = 0; i < num_recs; i++) { p_rec = (ib_link_record_t *) osmv_get_query_result(context.result. p_result_madw, i); osmtest_write_link(p_osmt, fh, p_rec); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_get_path_rec_by_lid_pair(IN osmtest_t * const p_osmt, IN ib_net16_t slid, IN ib_net16_t dlid, IN osmtest_req_context_t * p_context) { cl_status_t status = IB_SUCCESS; osmv_query_req_t req; osmv_lid_pair_t lid_pair; OSM_LOG_ENTER(&p_osmt->log); memset(&req, 0, sizeof(req)); memset(p_context, 0, sizeof(*p_context)); p_context->p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS; lid_pair.dest_lid = dlid; lid_pair.src_lid = slid; req.p_query_input = &lid_pair; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Query for path from 0x%X to 0x%X\n", cl_ntoh16(slid), cl_ntoh16(dlid)); status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0053: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = (*p_context).result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0067: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr ((*p_context).result. p_result_madw))); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } #ifdef VENDOR_RMPP_SUPPORT /********************************************************************** * ASSUMES RMPP **********************************************************************/ static ib_api_status_t osmtest_write_all_node_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_node_record_t *p_rec; uint32_t i; cl_status_t status; size_t num_recs; int result; node_t *p_guid_node; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0022: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Write the received records out to the file. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); result = fprintf(fh, "#\n" "# Node Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0023: " "Write failed\n"); status = IB_ERROR; goto Exit; } for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_node_rec(context.result.p_result_madw, i); osmtest_write_node_info(p_osmt, fh, p_rec); /* create a subnet object */ p_guid_node = node_new(); CL_ASSERT(p_guid_node != NULL); /* copy the info to the subnet node object */ p_guid_node->rec = *p_rec; cl_qmap_insert(&p_osmt->exp_subn.node_guid_tbl, p_guid_node->rec.node_info.port_guid, &p_guid_node->map_item); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * ASSUMES RMPP **********************************************************************/ static ib_api_status_t osmtest_write_all_port_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_portinfo_record_t *p_rec; uint32_t i; cl_status_t status; size_t num_recs; int result; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PORTINFO_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0167: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Write the received records out to the file. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); result = fprintf(fh, "#\n" "# PortInfo Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0024: " "Write failed\n"); status = IB_ERROR; goto Exit; } for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_portinfo_rec(context.result.p_result_madw, i); osmtest_write_port_info(p_osmt, fh, p_rec); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * ASSUMES RMPP **********************************************************************/ static ib_api_status_t osmtest_write_all_path_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_path_rec_t *p_rec; uint32_t i; cl_status_t status = CL_SUCCESS; size_t num_recs; int result; node_t *p_dst_node; cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); if (p_osmt->opt.full_world_path_recs) goto full_world; result = fprintf(fh, "#\n" "# Path Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0026: " "Write failed\n"); status = IB_ERROR; goto Exit; } p_tbl = &p_osmt->exp_subn.node_guid_tbl; p_dst_node = (node_t *) cl_qmap_head(p_tbl); while (p_dst_node != (node_t *) cl_qmap_end(p_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG,"Source : lid = 0x%d type = %d\n", cl_ntoh16(p_dst_node->rec.lid), p_dst_node->rec.node_info.node_type); status = osmtest_get_path_rec_by_half_world_query(p_osmt, p_dst_node->rec.node_info.port_guid, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0025: " "osmtest_get_all_path_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Write the received records out to the file. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, i); osmtest_write_path_info(p_osmt, fh, p_rec); } p_dst_node = (node_t *) cl_qmap_next(&p_dst_node->map_item); } goto Exit; full_world: memset(&context, 0, sizeof(context)); /* * Do a blocking query for all PathRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0002: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Write the received records out to the file. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); result = fprintf(fh, "#\n" "# Path Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0005: " "Write failed\n"); status = IB_ERROR; goto Exit; } for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, i); osmtest_write_path_info(p_osmt, fh, p_rec); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } #else /* * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER */ static ib_api_status_t osmtest_write_all_node_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; node_t *p_node; node_t *p_guid_node; const ib_node_record_t *p_rec; cl_status_t status = CL_SUCCESS; int result; uint16_t lid; OSM_LOG_ENTER(&p_osmt->log); result = fprintf(fh, "#\n" "# Node Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0027: " "Write failed\n"); status = IB_ERROR; goto Exit; } /* * Go over all LIDs in the range 1 to max_lid and do a * NodeRecord query by that lid. */ for (lid = 1; lid <= p_osmt->max_lid; lid++) { /* prepare the query context */ memset(&context, 0, sizeof(context)); status = osmtest_get_node_rec_by_lid(p_osmt, cl_ntoh16(lid), &context); if (status != IB_SUCCESS) { if (status != IB_SA_MAD_STATUS_NO_RECORDS) { OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "ERR 0028: " "failed to get node info for LID:0x%02X (%s)\n", cl_ntoh16(lid), ib_get_err_str(status)); goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "WRN 0121: " "failed to get node info for LID:0x%02X (%s)\n", cl_ntoh16(lid), ib_get_err_str(status)); status = IB_SUCCESS; } } else { /* OK we got something */ p_rec = osmv_get_query_node_rec(context.result. p_result_madw, 0); osmtest_write_node_info(p_osmt, fh, p_rec); /* create a subnet object */ p_node = node_new(); CL_ASSERT(p_node != NULL); /* copy the info to the subnet node object */ p_node->rec = *p_rec; cl_qmap_insert(&p_osmt->exp_subn.node_lid_tbl, p_node->rec.lid, &p_node->map_item); p_guid_node = node_new(); CL_ASSERT(p_guid_node != NULL); *p_guid_node = *p_node; cl_qmap_insert(&p_osmt->exp_subn.node_guid_tbl, p_guid_node->rec.node_info.node_guid, &p_guid_node->map_item); } if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /* * GET ALL PORT RECORDS IN THE FABRIC - * one by one by using the node info received */ static ib_api_status_t osmtest_write_all_port_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_node_record_t *p_node_rec; const ib_portinfo_record_t *p_rec; uint8_t port_num; cl_status_t status = CL_SUCCESS; cl_qmap_t *p_tbl; node_t *p_node; port_t *p_port; int result; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* print header */ result = fprintf(fh, "#\n" "# PortInfo Records\n" "#\n"); if (result < 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0029: " "Write failed\n"); status = IB_ERROR; goto Exit; } /* use the pre-explored set of nodes */ p_tbl = &p_osmt->exp_subn.node_lid_tbl; p_node = (node_t *) cl_qmap_head(p_tbl); /* * Go over all LIDs in the range 1 to max_lid and do a * NodeRecord query by that lid. */ while (p_node != (node_t *) cl_qmap_end(p_tbl)) { p_node_rec = &(p_node->rec); /* go through all ports of the node: */ for (port_num = 0; port_num <= p_node_rec->node_info.num_ports; port_num++) { /* prepare the query context */ memset(&context, 0, sizeof(context)); status = osmtest_get_port_rec_by_num(p_osmt, p_node_rec->lid, port_num, &context); if (status != IB_SUCCESS) { if (status != IB_SA_MAD_STATUS_NO_RECORDS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "WRN 0122: " "Error encountered getting port info for LID:0x%04X Num:0x%02X (%s)\n", p_node_rec->lid, port_num, ib_get_err_str(status)); goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "WRN 0123: " "failed to get port info for LID:0x%04X Num:0x%02X (%s)\n", p_node_rec->lid, port_num, ib_get_err_str(status)); status = IB_SUCCESS; } } else { /* OK we got something */ p_rec = osmv_get_query_portinfo_rec(context.result. p_result_madw, 0); osmtest_write_port_info(p_osmt, fh, p_rec); /* create a subnet object */ p_port = port_new(); CL_ASSERT(p_port != NULL); /* copy the info to the subnet node object */ p_port->rec = *p_rec; cl_qmap_insert(&p_osmt->exp_subn.port_key_tbl, port_gen_id(p_node_rec->lid, port_num), &p_port->map_item); } if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } } p_node = (node_t *) cl_qmap_next(&p_node->map_item); } /* we must set the exist status to avoid abort of the over all algorith */ Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * ASSUMES NO RMPP **********************************************************************/ static ib_api_status_t osmtest_write_all_path_recs(IN osmtest_t * const p_osmt, IN FILE * fh) { osmtest_req_context_t context; const ib_path_rec_t *p_rec; cl_status_t status = CL_SUCCESS; int num_recs, i; cl_qmap_t *p_tbl; node_t *p_src_node, *p_dst_node; ib_api_status_t got_status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Go over all nodes that exist in the subnet * for each pair that are not switch nodes get the path record */ context.p_osmt = p_osmt; p_tbl = &p_osmt->exp_subn.node_lid_tbl; p_src_node = (node_t *) cl_qmap_head(p_tbl); while (p_src_node != (node_t *) cl_qmap_end(p_tbl)) { /* HACK we use capability_mask to know diff a CA node from switch node */ /* if(p_src_node->rec.node_info.capability_mask ) { */ p_dst_node = (node_t *) cl_qmap_head(p_tbl); while (p_dst_node != (node_t *) cl_qmap_end(p_tbl)) { /* HACK we use capability_mask to know diff a CA node from switch node */ /* if (p_dst_node->rec.node_info.capability_mask) { */ /* query for it: */ status = osmtest_get_path_rec_by_lid_pair(p_osmt, p_src_node-> rec.lid, p_dst_node-> rec.lid, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012D: " "failed to get path info from LID:0x%X To LID:0x%X (%s)\n", p_src_node->rec.lid, p_dst_node->rec.lid, ib_get_err_str(status)); /* remember the first error status */ got_status = (got_status == IB_SUCCESS) ? status : got_status; } else { /* we might have received several records */ num_recs = context.result.result_cnt; for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context. result. p_result_madw, i); osmtest_write_path_info(p_osmt, fh, p_rec); } } /* } */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } /* next one please */ p_dst_node = (node_t *) cl_qmap_next(&p_dst_node->map_item); } /* } */ p_src_node = (node_t *) cl_qmap_next(&p_src_node->map_item); } if (got_status != IB_SUCCESS) status = got_status; /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } #endif static ib_api_status_t osmtest_create_inventory_file(IN osmtest_t * const p_osmt) { FILE *fh; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); fh = fopen(p_osmt->opt.file_name, "w"); if (fh == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0079: " "Unable to open inventory file (%s)\n", p_osmt->opt.file_name); status = IB_ERROR; goto Exit; } /* HACK: the order is important: nodes ports paths */ status = osmtest_write_all_node_recs(p_osmt, fh); if (status != IB_SUCCESS) goto Exit; status = osmtest_write_all_port_recs(p_osmt, fh); if (status != IB_SUCCESS) goto Exit; if (!p_osmt->opt.ignore_path_records) { status = osmtest_write_all_path_recs(p_osmt, fh); if (status != IB_SUCCESS) goto Exit; } status = osmtest_write_all_link_recs(p_osmt, fh); if (status != IB_SUCCESS) goto Exit; fclose(fh); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_stress_large_rmpp_pr(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; uint64_t num_recs = 0; uint64_t num_queries = 0; uint32_t delta_recs; uint32_t delta_queries; uint32_t print_freq = 0; struct timeval start_tv, end_tv; long sec_diff, usec_diff; float ratio; OSM_LOG_ENTER(&p_osmt->log); gettimeofday(&start_tv, NULL); printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec); while (num_queries < STRESS_LARGE_PR_RMPP_THR) { delta_recs = 0; delta_queries = 0; status = osmtest_stress_path_recs_by_guid(p_osmt, &delta_recs, &delta_queries); if (status != IB_SUCCESS) goto Exit; num_recs += delta_recs; num_queries += delta_queries; print_freq += delta_recs; if (print_freq > 10000) { gettimeofday(&end_tv, NULL); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); printf("-I- Querying %" PRId64 " Path Record queries CA to CA (rmpp)\n\ttook %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); if (num_recs == 0) ratio = 0; else ratio = ((float)num_queries / (float)num_recs); printf("-I- Queries to Record Ratio is %" PRIu64 " records, %" PRIu64 " queries : %.2f \n", num_recs, num_queries, ratio); print_freq = 0; } } Exit: gettimeofday(&end_tv, NULL); printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- Querying %" PRId64 " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_stress_large_rmpp(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; uint64_t num_recs = 0; uint64_t num_queries = 0; uint32_t delta_recs; uint32_t delta_queries; uint32_t print_freq = 0; struct timeval start_tv, end_tv; long sec_diff, usec_diff; OSM_LOG_ENTER(&p_osmt->log); gettimeofday(&start_tv, NULL); printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec); while (num_queries < STRESS_LARGE_RMPP_THR) { delta_recs = 0; delta_queries = 0; status = osmtest_stress_node_recs_large(p_osmt, &delta_recs, &delta_queries); if (status != IB_SUCCESS) goto Exit; status = osmtest_stress_path_recs_large(p_osmt, &delta_recs, &delta_queries); if (status != IB_SUCCESS) goto Exit; status = osmtest_stress_port_recs_large(p_osmt, &delta_recs, &delta_queries); if (status != IB_SUCCESS) goto Exit; num_recs += delta_recs; num_queries += delta_queries; print_freq += delta_recs; if (print_freq > 100000) { gettimeofday(&end_tv, NULL); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); printf("%" PRIu64 " records, %" PRIu64 " queries\n", num_recs, num_queries); print_freq = 0; } } Exit: gettimeofday(&end_tv, NULL); printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_stress_small_rmpp(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; uint64_t num_recs = 0; uint64_t num_queries = 0; uint32_t delta_recs; uint32_t delta_queries; uint32_t print_freq = 0; int num_timeouts = 0; struct timeval start_tv, end_tv; long sec_diff, usec_diff; OSM_LOG_ENTER(&p_osmt->log); gettimeofday(&start_tv, NULL); printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec); while ((num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100)) { delta_recs = 0; delta_queries = 0; status = osmtest_stress_port_recs_small(p_osmt, &delta_recs, &delta_queries); if (status == IB_TIMEOUT) { num_timeouts++; continue; } else if (status != IB_SUCCESS) goto Exit; num_recs += delta_recs; num_queries += delta_queries; print_freq += delta_recs; if (print_freq > 5000) { gettimeofday(&end_tv, NULL); printf("%" PRIu64 " records, %" PRIu64 " queries\n", num_recs, num_queries); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); print_freq = 0; } } Exit: gettimeofday(&end_tv, NULL); printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); if (num_timeouts > 50) { status = IB_TIMEOUT; } /* Exit: */ OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_stress_path_recs_by_lid(IN osmtest_t * const p_osmt, OUT uint32_t * const p_num_recs, OUT uint32_t * const p_num_queries) { osmtest_req_context_t context; ib_path_rec_t *p_rec; cl_status_t status; ib_net16_t dlid, slid; int num_recs, i; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); slid = cl_ntoh16(p_osmt->local_port.lid); dlid = cl_ntoh16(p_osmt->local_port.sm_lid); /* * Do a blocking query for the PathRecord. */ status = osmtest_get_path_rec_by_lid_pair(p_osmt, slid, dlid, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 000A: " "osmtest_get_path_rec_by_lid_pair failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; *p_num_recs += num_recs; ++*p_num_queries; if (osm_log_is_active(&p_osmt->log, OSM_LOG_VERBOSE)) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, 0); osm_dump_path_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_stress_get_pr(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; uint64_t num_recs = 0; uint64_t num_queries = 0; uint32_t delta_recs; uint32_t delta_queries; uint32_t print_freq = 0; int num_timeouts = 0; struct timeval start_tv, end_tv; long sec_diff, usec_diff; OSM_LOG_ENTER(&p_osmt->log); gettimeofday(&start_tv, NULL); printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec); while ((num_queries < STRESS_GET_PR) && (num_timeouts < 100)) { delta_recs = 0; delta_queries = 0; status = osmtest_stress_path_recs_by_lid(p_osmt, &delta_recs, &delta_queries); if (status == IB_TIMEOUT) { num_timeouts++; continue; } else if (status != IB_SUCCESS) goto Exit; num_recs += delta_recs; num_queries += delta_queries; print_freq += delta_recs; if (print_freq > 5000) { gettimeofday(&end_tv, NULL); printf("%" PRIu64 " records, %" PRIu64 " queries\n", num_recs, num_queries); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); printf("-I- Querying %" PRId64 " path_rec queries took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); print_freq = 0; } } Exit: gettimeofday(&end_tv, NULL); printf("-I- End time is : %09ld:%06ld [sec:usec]\n", end_tv.tv_sec, (long)end_tv.tv_usec); if (end_tv.tv_usec > start_tv.tv_usec) { sec_diff = end_tv.tv_sec - start_tv.tv_sec; usec_diff = end_tv.tv_usec - start_tv.tv_usec; } else { sec_diff = end_tv.tv_sec - start_tv.tv_sec - 1; usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec); } printf("-I- Querying %" PRId64 " path_rec queries took %04ld:%06ld [sec:usec]\n", num_queries, sec_diff, usec_diff); if (num_timeouts > 50) { status = IB_TIMEOUT; } /* Exit: */ OSM_LOG_EXIT(&p_osmt->log); return (status); } static void osmtest_prepare_db_generic(IN osmtest_t * const p_osmt, IN cl_qmap_t * const p_tbl) { generic_t *p_generic; OSM_LOG_ENTER(&p_osmt->log); p_generic = (generic_t *) cl_qmap_head(p_tbl); while (p_generic != (generic_t *) cl_qmap_end(p_tbl)) { p_generic->count = 0; p_generic = (generic_t *) cl_qmap_next(&p_generic->map_item); } OSM_LOG_EXIT(&p_osmt->log); } static void osmtest_prepare_db(IN osmtest_t * const p_osmt) { OSM_LOG_ENTER(&p_osmt->log); osmtest_prepare_db_generic(p_osmt, &p_osmt->exp_subn.node_lid_tbl); osmtest_prepare_db_generic(p_osmt, &p_osmt->exp_subn.path_tbl); OSM_LOG_EXIT(&p_osmt->log); } static ib_api_status_t osmtest_check_missing_nodes(IN osmtest_t * const p_osmt) { const node_t *p_node; cl_status_t status = IB_SUCCESS; cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); p_tbl = &p_osmt->exp_subn.node_lid_tbl; p_node = (node_t *) cl_qmap_head(p_tbl); while (p_node != (node_t *) cl_qmap_end(p_tbl)) { if (p_node->count == 0) { /* * This node was not reported by the SA */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0080: " "Missing node 0x%016" PRIx64 "\n", cl_ntoh64(p_node->rec.node_info.node_guid)); status = IB_ERROR; } p_node = (node_t *) cl_qmap_next(&p_node->map_item); } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_check_missing_ports(IN osmtest_t * const p_osmt) { const port_t *p_port; cl_status_t status = IB_SUCCESS; cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); p_tbl = &p_osmt->exp_subn.port_key_tbl; p_port = (port_t *) cl_qmap_head(p_tbl); while (p_port != (port_t *) cl_qmap_end(p_tbl)) { if (p_port->count == 0) { /* * This port was not reported by the SA */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0081: " "Missing port LID:0x%X Num:0x%X\n", cl_ntoh16(p_port->rec.lid), p_port->rec.port_num); status = IB_ERROR; } p_port = (port_t *) cl_qmap_next(&p_port->map_item); } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_check_missing_paths(IN osmtest_t * const p_osmt) { const path_t *p_path; cl_status_t status = IB_SUCCESS; cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); p_tbl = &p_osmt->exp_subn.path_tbl; p_path = (path_t *) cl_qmap_head(p_tbl); while (p_path != (path_t *) cl_qmap_end(p_tbl)) { if (p_path->count == 0) { /* * This path was not reported by the SA */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0051: " "SA did not return path SLID 0x%X to DLID 0x%X\n", cl_ntoh16(p_path->rec.slid), cl_ntoh16(p_path->rec.dlid)); status = IB_ERROR; goto Exit; } p_path = (path_t *) cl_qmap_next(&p_path->map_item); } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static inline uint32_t osmtest_path_rec_key_get(IN const ib_path_rec_t * const p_rec) { return (p_rec->dlid << 16 | p_rec->slid); } static boolean_t osmtest_path_rec_kay_is_valid(IN osmtest_t * const p_osmt, IN const path_t * const p_path) { if ((p_path->comp.dlid == 0) || (p_path->comp.slid == 0)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0168: " "SLID and DLID must be specified for defined paths\n"); return (FALSE); } return (TRUE); } static ib_api_status_t osmtest_validate_path_data(IN osmtest_t * const p_osmt, IN path_t * const p_path, IN const ib_path_rec_t * const p_rec) { cl_status_t status = IB_SUCCESS; uint8_t lmc = 0; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Checking path SLID 0x%X to DLID 0x%X\n", cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid)); status = osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc); if (status != IB_SUCCESS) goto Exit; /* HACK: Assume uniform LMC across endports in the subnet */ /* This is the only LMC mode which OpenSM currently supports */ /* In absence of this assumption, validation of this is much more complicated */ if (lmc == 0) { /* * Has this record already been returned? */ if (p_path->count != 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0056: " "Already received path SLID 0x%X to DLID 0x%X\n", cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid)); status = IB_ERROR; goto Exit; } } else { /* Also, this doesn't detect fewer than the correct number of paths being returned */ if (p_path->count >= (uint32_t) (1 << (2 * lmc))) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0052: " "Already received path SLID 0x%X to DLID 0x%X count %d LMC %d\n", cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid), p_path->count, lmc); status = IB_ERROR; goto Exit; } } ++p_path->count; /* * Check the fields the user wants checked. */ if ((p_path->comp.dgid.unicast.interface_id & p_path->rec.dgid.unicast.interface_id) != (p_path->comp.dgid.unicast.interface_id & p_rec->dgid.unicast.interface_id)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0169: " "DGID mismatch on path SLID 0x%X to DLID 0x%X\n" "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 "\n" "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh16(p_path->rec.slid), cl_ntoh16(p_path->rec.dlid), cl_ntoh64(p_path->rec.dgid.unicast.prefix), cl_ntoh64(p_path->rec.dgid.unicast.interface_id), cl_ntoh64(p_rec->dgid.unicast.prefix), cl_ntoh64(p_rec->dgid.unicast.interface_id)); status = IB_ERROR; goto Exit; } /* * Check the fields the user wants checked. */ if ((p_path->comp.sgid.unicast.interface_id & p_path->rec.sgid.unicast.interface_id) != (p_path->comp.sgid.unicast.interface_id & p_rec->sgid.unicast.interface_id)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0057: " "SGID mismatch on path SLID 0x%X to DLID 0x%X\n" "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n" "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n", cl_ntoh16(p_path->rec.slid), cl_ntoh16(p_path->rec.dlid), cl_ntoh64(p_path->rec.sgid.unicast.prefix), cl_ntoh64(p_path->rec.sgid.unicast.interface_id), cl_ntoh64(p_rec->sgid.unicast.prefix), cl_ntoh64(p_rec->sgid.unicast.interface_id)); status = IB_ERROR; goto Exit; } /* * Compare the fields the user wishes to validate. */ if ((p_path->comp.pkey & p_path->rec.pkey) != (p_path->comp.pkey & p_rec->pkey)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0012: " "PKEY mismatch on path SLID 0x%X to DLID 0x%X\n" "\t\t\t\tExpected 0x%X, received 0x%X\n", cl_ntoh16(p_path->rec.slid), cl_ntoh16(p_path->rec.dlid), cl_ntoh16(p_path->rec.pkey), cl_ntoh16(p_rec->pkey)); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_node_data(IN osmtest_t * const p_osmt, IN node_t * const p_node, IN const ib_node_record_t * const p_rec) { cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Checking node 0x%016" PRIx64 ", LID 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid)); /* * Has this record already been returned? */ if (p_node->count != 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0013: " "Already received node 0x%016" PRIx64 "\n", cl_ntoh64(p_node->rec.node_info.node_guid)); status = IB_ERROR; goto Exit; } ++p_node->count; /* * Compare the fields the user wishes to validate. */ if ((p_node->comp.lid & p_node->rec.lid) != (p_node->comp.lid & p_rec->lid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0014: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected LID 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), p_node->rec.lid, p_rec->lid); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.base_version & p_node->rec.node_info.base_version) != (p_node->comp.node_info.base_version & p_rec->node_info.base_version)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0015: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected base_version 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), p_node->rec.node_info.base_version, p_rec->node_info.base_version); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.class_version & p_node->rec.node_info.class_version) != (p_node->comp.node_info.class_version & p_rec->node_info.class_version)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0016: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected class_version 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), p_node->rec.node_info.class_version, p_rec->node_info.class_version); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.node_type & p_node->rec.node_info.node_type) != (p_node->comp.node_info.node_type & p_rec->node_info.node_type)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0017: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected node_type 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), p_node->rec.node_info.node_type, p_rec->node_info.node_type); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.sys_guid & p_node->rec.node_info.sys_guid) != (p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0018: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected sys_guid 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh64(p_node->rec.node_info.sys_guid), cl_ntoh64(p_rec->node_info.sys_guid)); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.node_guid & p_node->rec.node_info.node_guid) != (p_node->comp.node_info.node_guid & p_rec->node_info.node_guid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0019: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected node_guid 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh64(p_node->rec.node_info.node_guid), cl_ntoh64(p_rec->node_info.node_guid)); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.port_guid & p_node->rec.node_info.port_guid) != (p_node->comp.node_info.port_guid & p_rec->node_info.port_guid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0031: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected port_guid 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh64(p_node->rec.node_info.port_guid), cl_ntoh64(p_rec->node_info.port_guid)); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.partition_cap & p_node->rec.node_info.partition_cap) != (p_node->comp.node_info.partition_cap & p_rec->node_info.partition_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0032: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected partition_cap 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh16(p_node->rec.node_info.partition_cap), cl_ntoh16(p_rec->node_info.partition_cap)); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.device_id & p_node->rec.node_info.device_id) != (p_node->comp.node_info.device_id & p_rec->node_info.device_id)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0033: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected device_id 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh16(p_node->rec.node_info.device_id), cl_ntoh16(p_rec->node_info.device_id)); status = IB_ERROR; goto Exit; } if ((p_node->comp.node_info.revision & p_node->rec.node_info.revision) != (p_node->comp.node_info.revision & p_rec->node_info.revision)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0034: " "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n" "\t\t\t\tExpected revision 0x%X, received 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid), cl_ntoh32(p_node->rec.node_info.revision), cl_ntoh32(p_rec->node_info.revision)); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_node_rec(IN osmtest_t * const p_osmt, IN const ib_node_record_t * const p_rec) { cl_status_t status = IB_SUCCESS; node_t *p_node; const cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); /* * Find proper node record in the database. */ p_tbl = &p_osmt->exp_subn.node_lid_tbl; p_node = (node_t *) cl_qmap_get(p_tbl, p_rec->lid); if (p_node == (node_t *) cl_qmap_end(p_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0035: " "Unexpected node 0x%016" PRIx64 ", LID 0x%X\n", cl_ntoh64(p_rec->node_info.node_guid), cl_ntoh16(p_rec->lid)); status = IB_ERROR; goto Exit; } status = osmtest_validate_node_data(p_osmt, p_node, p_rec); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_port_data(IN osmtest_t * const p_osmt, IN port_t * const p_port, IN const ib_portinfo_record_t * const p_rec) { cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Checking port LID 0x%X, Num 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num); /* * Has this record already been returned? */ if (p_port->count != 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0036: " "Already received port LID 0x%X, Num 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num); status = IB_ERROR; goto Exit; } ++p_port->count; /* * Compare the fields the user wishes to validate. */ if ((p_port->comp.lid & p_port->rec.lid) != (p_port->comp.lid & p_rec->lid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0037: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected LID 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.lid, p_rec->lid); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_num & p_port->rec.port_num) != (p_port->comp.port_num & p_rec->port_num)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0038: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected port_num 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_num, p_rec->port_num); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.m_key & p_port->rec.port_info.m_key) != (p_port->comp.port_info.m_key & p_rec->port_info.m_key)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0039: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected m_key 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.m_key, p_rec->port_info.m_key); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.subnet_prefix & p_port->rec.port_info. subnet_prefix) != (p_port->comp.port_info.subnet_prefix & p_rec->port_info. subnet_prefix)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0040: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected subnet_prefix 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.subnet_prefix, p_rec->port_info.subnet_prefix); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.base_lid & p_port->rec.port_info. base_lid) != (p_port->comp.port_info.base_lid & p_rec->port_info.base_lid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0041: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected base_lid 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.base_lid, p_rec->port_info.base_lid); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info. master_sm_base_lid) != (p_port->comp.port_info.master_sm_base_lid & p_rec->port_info. master_sm_base_lid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0042: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.master_sm_base_lid, p_rec->port_info.master_sm_base_lid); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.capability_mask & p_port->rec.port_info. capability_mask) != (p_port->comp.port_info.capability_mask & p_rec->port_info. capability_mask)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0043: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected capability_mask 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, cl_ntoh32(p_port->rec.port_info.capability_mask), cl_ntoh32(p_rec->port_info.capability_mask)); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.diag_code & p_port->rec.port_info. diag_code) != (p_port->comp.port_info.diag_code & p_rec->port_info.diag_code)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0044: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected diag_code 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.diag_code, p_rec->port_info.diag_code); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info. m_key_lease_period) != (p_port->comp.port_info.m_key_lease_period & p_rec->port_info. m_key_lease_period)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0045: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.m_key_lease_period, p_rec->port_info.m_key_lease_period); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.local_port_num & p_port->rec.port_info. local_port_num) != (p_port->comp.port_info.local_port_num & p_rec->port_info. local_port_num)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0046: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected local_port_num 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.local_port_num, p_rec->port_info.local_port_num); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.link_width_enabled & p_port->rec.port_info. link_width_enabled) != (p_port->comp.port_info.link_width_enabled & p_rec->port_info. link_width_enabled)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0047: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.link_width_enabled, p_rec->port_info.link_width_enabled); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.link_width_supported & p_port->rec. port_info.link_width_supported) != (p_port->comp.port_info.link_width_supported & p_rec->port_info. link_width_supported)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0048: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected link_width_supported 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.link_width_supported, p_rec->port_info.link_width_supported); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.link_width_active & p_port->rec.port_info. link_width_active) != (p_port->comp.port_info.link_width_active & p_rec->port_info. link_width_active)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0049: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected link_width_active 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.link_width_active, p_rec->port_info.link_width_active); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.link_speed & p_port->rec.port_info. link_speed) != (p_port->comp.port_info.link_speed & p_rec->port_info.link_speed)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0054: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.link_speed, p_rec->port_info.link_speed); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.state_info1 & p_port->rec.port_info. state_info1) != (p_port->comp.port_info.state_info1 & p_rec->port_info. state_info1)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0055: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected state_info1 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.state_info1, p_rec->port_info.state_info1); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.state_info2 & p_port->rec.port_info. state_info2) != (p_port->comp.port_info.state_info2 & p_rec->port_info. state_info2)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0058: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected state_info2 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.state_info2, p_rec->port_info.state_info2); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.mkey_lmc & p_port->rec.port_info. mkey_lmc) != (p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0059: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.mkey_lmc, p_rec->port_info.mkey_lmc); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.link_speed & p_port->rec.port_info. link_speed) != (p_port->comp.port_info.link_speed & p_rec->port_info.link_speed)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0060: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.link_speed, p_rec->port_info.link_speed); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.mtu_smsl & p_port->rec.port_info. mtu_smsl) != (p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0061: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.mtu_smsl, p_rec->port_info.mtu_smsl); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap) != (p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0062: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_cap 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.vl_high_limit & p_port->rec.port_info. vl_high_limit) != (p_port->comp.port_info.vl_high_limit & p_rec->port_info. vl_high_limit)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0082: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_high_limit, p_rec->port_info.vl_high_limit); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info. vl_arb_high_cap) != (p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info. vl_arb_high_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0083: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_high_cap); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info. vl_arb_low_cap) != (p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info. vl_arb_low_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0084: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_arb_low_cap, p_rec->port_info.vl_arb_low_cap); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap) != (p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0085: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected mtu_cap 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.mtu_cap, p_rec->port_info.mtu_cap); status = IB_ERROR; goto Exit; } #if 0 /* this is a dynamic attribute */ if ((p_port->comp.port_info.vl_stall_life & p_port->rec.port_info. vl_stall_life) != (p_port->comp.port_info.vl_stall_life & p_rec->port_info. vl_stall_life)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012F: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_stall_life, p_rec->port_info.vl_stall_life); status = IB_ERROR; goto Exit; } #endif if ((p_port->comp.port_info.vl_enforce & p_port->rec.port_info. vl_enforce) != (p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0086: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected vl_enforce 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.vl_enforce, p_rec->port_info.vl_enforce); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.m_key_violations & p_port->rec.port_info. m_key_violations) != (p_port->comp.port_info.m_key_violations & p_rec->port_info. m_key_violations)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0087: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected m_key_violations 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, cl_ntoh16(p_port->rec.port_info.m_key_violations), cl_ntoh16(p_rec->port_info.m_key_violations)); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.p_key_violations & p_port->rec.port_info. p_key_violations) != (p_port->comp.port_info.p_key_violations & p_rec->port_info. p_key_violations)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0088: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected p_key_violations 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, cl_ntoh16(p_port->rec.port_info.p_key_violations), cl_ntoh16(p_rec->port_info.p_key_violations)); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.q_key_violations & p_port->rec.port_info. q_key_violations) != (p_port->comp.port_info.q_key_violations & p_rec->port_info. q_key_violations)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0089: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected q_key_violations 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, cl_ntoh16(p_port->rec.port_info.q_key_violations), cl_ntoh16(p_rec->port_info.q_key_violations)); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.guid_cap & p_port->rec.port_info. guid_cap) != (p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0090: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected guid_cap 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.guid_cap, p_rec->port_info.guid_cap); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.subnet_timeout & p_port->rec.port_info. subnet_timeout) != (p_port->comp.port_info.subnet_timeout & p_rec->port_info. subnet_timeout)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0091: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, ib_port_info_get_timeout(&p_port->rec.port_info), ib_port_info_get_timeout(&p_rec->port_info)); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.resp_time_value & p_port->rec.port_info. resp_time_value) != (p_port->comp.port_info.resp_time_value & p_rec->port_info. resp_time_value)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0092: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected resp_time_value 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.resp_time_value, p_rec->port_info.resp_time_value); status = IB_ERROR; goto Exit; } if ((p_port->comp.port_info.error_threshold & p_port->rec.port_info. error_threshold) != (p_port->comp.port_info.error_threshold & p_rec->port_info. error_threshold)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0093: " "Field mismatch port LID 0x%X Num:0x%X\n" "\t\t\t\tExpected error_threshold 0x%X, received 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_port->rec.port_info.error_threshold, p_rec->port_info.error_threshold); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_port_rec(IN osmtest_t * const p_osmt, IN const ib_portinfo_record_t * const p_rec) { cl_status_t status = IB_SUCCESS; port_t *p_port; const cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); /* * Find proper port record in the database. * (we use by guid - since lid is not unique) */ p_tbl = &p_osmt->exp_subn.port_key_tbl; p_port = (port_t *) cl_qmap_get(p_tbl, port_gen_id(p_rec->lid, p_rec->port_num)); if (p_port == (port_t *) cl_qmap_end(p_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0094: " "Unexpected port LID 0x%X, Num:0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num); status = IB_ERROR; goto Exit; } status = osmtest_validate_port_data(p_osmt, p_port, p_rec); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_path_rec(IN osmtest_t * const p_osmt, IN const ib_path_rec_t * const p_rec) { cl_status_t status = IB_SUCCESS; path_t *p_path; const cl_qmap_t *p_tbl; OSM_LOG_ENTER(&p_osmt->log); /* * Find proper path record in the database. */ p_tbl = &p_osmt->exp_subn.path_tbl; p_path = (path_t *) cl_qmap_get(p_tbl, osmtest_path_rec_key_get(p_rec)); if (p_path == (path_t *) cl_qmap_end(p_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0095: " "Unexpected path SLID 0x%X to DLID 0x%X\n", cl_ntoh16(p_rec->slid), cl_ntoh16(p_rec->dlid)); status = IB_ERROR; goto Exit; } status = osmtest_validate_path_data(p_osmt, p_path, p_rec); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } #ifdef VENDOR_RMPP_SUPPORT ib_net64_t portguid = 0; static ib_api_status_t osmtest_validate_all_node_recs(IN osmtest_t * const p_osmt) { osmtest_req_context_t context; const ib_node_record_t *p_rec; uint32_t i; cl_status_t status; size_t num_recs; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0096: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); /* * Compare the received records to the database. */ osmtest_prepare_db(p_osmt); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_node_rec(context.result.p_result_madw, i); status = osmtest_validate_node_rec(p_osmt, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0097: " "osmtest_valid_node_rec failed (%s)\n", ib_get_err_str(status)); goto Exit; } if (!portguid) portguid = p_rec->node_info.port_guid; } status = osmtest_check_missing_nodes(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0098: " "osmtest_check_missing_nodes failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_all_guidinfo_recs(IN osmtest_t * const p_osmt) { osmtest_req_context_t context; const ib_guidinfo_record_t *p_rec; cl_status_t status; size_t num_recs; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all GuidInfoRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_GUIDINFO_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0099: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); /* No validation as yet */ Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_all_path_recs(IN osmtest_t * const p_osmt) { osmtest_req_context_t context; const ib_path_rec_t *p_rec; uint32_t i; cl_status_t status; size_t num_recs; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all PathRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_PATH_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009A: " "osmtest_get_all_recs failed (%s)\n", ib_get_err_str(status)); goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %zu records\n", num_recs); /* * Compare the received records to the database. */ osmtest_prepare_db(p_osmt); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, i); status = osmtest_validate_path_rec(p_osmt, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0100: " "osmtest_validate_path_rec failed (%s)\n", ib_get_err_str(status)); goto Exit; } } status = osmtest_check_missing_paths(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0101: " "osmtest_check_missing_paths failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get link record by LID **********************************************************************/ ib_api_status_t osmtest_get_link_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const from_lid, IN ib_net16_t const to_lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_link_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting link record from LID 0x%02X to LID 0x%02X\n", cl_ntoh16(from_lid), cl_ntoh16(to_lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.from_lid = from_lid; record.to_lid = to_lid; p_context->p_osmt = p_osmt; if (from_lid) user.comp_mask |= IB_LR_COMPMASK_FROM_LID; if (to_lid) user.comp_mask |= IB_LR_COMPMASK_TO_LID; user.attr_id = IB_MAD_ATTR_LINK_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007A: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007B: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "osmtest_get_link_rec_by_lid: " "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get GUIDInfo record by LID **********************************************************************/ ib_api_status_t osmtest_get_guidinfo_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_guidinfo_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting GUIDInfo record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; user.comp_mask = IB_GIR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_GUIDINFO_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007C: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007D: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get PKeyTable record by LID **********************************************************************/ ib_api_status_t osmtest_get_pkeytbl_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN ib_net64_t const sm_key, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_pkey_table_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting PKeyTable record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; user.comp_mask = IB_PKEY_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_PKEY_TBL_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = sm_key; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007E: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 007F: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get SwitchInfo record by LID **********************************************************************/ ib_api_status_t osmtest_get_sw_info_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_switch_info_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting SwitchInfo record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; if (lid) user.comp_mask = IB_SWIR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_SWITCH_INFO_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006C: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 006D: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get LFT record by LID **********************************************************************/ ib_api_status_t osmtest_get_lft_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_lft_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting LFT record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; if (lid) user.comp_mask = IB_LFTR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_LFT_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008A: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008B: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * Get MFT record by LID **********************************************************************/ ib_api_status_t osmtest_get_mft_rec_by_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_mft_record_t record; ib_mad_t *p_mad; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting MFT record for LID 0x%02X\n", cl_ntoh16(lid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; p_context->p_osmt = p_osmt; if (lid) user.comp_mask = IB_MFTR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_MFT_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009B: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 009C: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_sminfo_record_request(IN osmtest_t * const p_osmt, IN uint8_t method, IN void *p_options, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_sminfo_record_t record; ib_mad_t *p_mad; osmtest_sm_info_rec_t *p_sm_info_opt; OSM_LOG_ENTER(&p_osmt->log); /* * Do a blocking query for these records in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); p_context->p_osmt = p_osmt; user.attr_id = IB_MAD_ATTR_SMINFO_RECORD; p_sm_info_opt = p_options; if (p_sm_info_opt->sm_guid != 0) { record.sm_info.guid = p_sm_info_opt->sm_guid; user.comp_mask |= IB_SMIR_COMPMASK_GUID; } if (p_sm_info_opt->lid != 0) { record.lid = p_sm_info_opt->lid; user.comp_mask |= IB_SMIR_COMPMASK_LID; } if (p_sm_info_opt->priority != 0) { record.sm_info.pri_state = (p_sm_info_opt->priority & 0x0F) << 4; user.comp_mask |= IB_SMIR_COMPMASK_PRIORITY; } if (p_sm_info_opt->sm_state != 0) { record.sm_info.pri_state |= p_sm_info_opt->sm_state & 0x0F; user.comp_mask |= IB_SMIR_COMPMASK_SMSTATE; } user.method = method; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008C: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { if (status != IB_INVALID_PARAMETER) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008D: " "ib_query failed (%s)\n", ib_get_err_str(status)); } if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_informinfo_request(IN osmtest_t * const p_osmt, IN ib_net16_t attr_id, IN uint8_t method, IN void *p_options, IN OUT osmtest_req_context_t * const p_context) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_inform_info_t rec; ib_inform_info_record_t record; ib_mad_t *p_mad; osmtest_inform_info_t *p_inform_info_opt; osmtest_inform_info_rec_t *p_inform_info_rec_opt; OSM_LOG_ENTER(&p_osmt->log); /* * Do a blocking query for these records in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&rec, 0, sizeof(rec)); memset(&record, 0, sizeof(record)); p_context->p_osmt = p_osmt; user.attr_id = attr_id; if (attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD) { p_inform_info_rec_opt = p_options; if (p_inform_info_rec_opt->subscriber_gid.unicast.prefix != 0 && p_inform_info_rec_opt->subscriber_gid.unicast. interface_id != 0) { record.subscriber_gid = p_inform_info_rec_opt->subscriber_gid; user.comp_mask = IB_IIR_COMPMASK_SUBSCRIBERGID; } record.subscriber_enum = cl_hton16(p_inform_info_rec_opt->subscriber_enum); user.comp_mask |= IB_IIR_COMPMASK_ENUM; user.p_attr = &record; } else { /* comp mask bits below are for InformInfoRecord rather than InformInfo */ /* as currently no comp mask bits defined for InformInfo!!! */ user.comp_mask = IB_IIR_COMPMASK_SUBSCRIBE; p_inform_info_opt = p_options; rec.subscribe = (uint8_t) p_inform_info_opt->subscribe; if (p_inform_info_opt->qpn) { rec.g_or_v.generic.qpn_resp_time_val = cl_hton32(p_inform_info_opt->qpn << 8); user.comp_mask |= IB_IIR_COMPMASK_QPN; } if (p_inform_info_opt->trap) { rec.g_or_v.generic.trap_num = cl_hton16(p_inform_info_opt->trap); user.comp_mask |= IB_IIR_COMPMASK_TRAPNUMB; } user.p_attr = &rec; } user.method = method; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = p_context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008E: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = p_context->result.status; if (status != IB_SUCCESS) { if (status != IB_INVALID_PARAMETER) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 008F: " "ib_query failed (%s)\n", ib_get_err_str(status)); } if (status == IB_REMOTE_ERROR) { p_mad = osm_madw_get_mad_ptr(p_context->result. p_result_madw); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(p_mad)); status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK); } goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } #endif static ib_api_status_t osmtest_validate_single_path_rec_lid_pair(IN osmtest_t * const p_osmt, IN path_t * const p_path) { osmtest_req_context_t context; const ib_path_rec_t *p_rec; cl_status_t status = IB_SUCCESS; size_t num_recs; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); status = osmtest_get_path_rec_by_lid_pair(p_osmt, p_path->rec.slid, p_path->rec.dlid, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0102: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } num_recs = context.result.result_cnt; if (num_recs != 1) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0103: " "Too many records. Expected 1, received %zu\n", num_recs); status = IB_ERROR; } else { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, 0); status = osmtest_validate_path_data(p_osmt, p_path, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0104: " "osmtest_validate_path_data failed (%s)\n", ib_get_err_str(status)); } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_node_rec_lid(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN node_t * const p_node) { cl_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_node_record_t record; osmtest_req_context_t context; const ib_node_record_t *p_rec; int num_recs, i; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting NodeRecord for node with LID 0x%X\n", cl_ntoh16(lid)); memset(&context, 0, sizeof(context)); memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&record, 0, sizeof(record)); record.lid = lid; context.p_osmt = p_osmt; user.comp_mask = IB_NR_COMPMASK_LID; user.attr_id = IB_MAD_ATTR_NODE_RECORD; user.p_attr = &record; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0105: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0106: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %d nodes\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_node_rec(context.result.p_result_madw, i); status = osmtest_validate_node_rec(p_osmt, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0107: " "osmtest_validate_node_data failed (%s)\n", ib_get_err_str(status)); goto Exit; } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_port_rec_lid(IN osmtest_t * const p_osmt, IN port_t * const p_port) { osmtest_req_context_t context; const ib_portinfo_record_t *p_rec; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; status = osmtest_get_port_rec_by_num(p_osmt, p_port->rec.lid, p_port->rec.port_num, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0108: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* we should have got exactly one port */ p_rec = osmv_get_query_portinfo_rec(context.result.p_result_madw, 0); status = osmtest_validate_port_rec(p_osmt, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0109: " "osmtest_validate_port_data failed (%s)\n", ib_get_err_str(status)); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_path_rec_guid_pair(IN osmtest_t * const p_osmt, IN const osmv_guid_pair_t * const p_pair) { osmtest_req_context_t context; const ib_path_rec_t *p_rec; cl_status_t status = IB_SUCCESS; size_t num_recs; osmv_query_req_t req; uint32_t i; boolean_t got_error = FALSE; OSM_LOG_ENTER(&p_osmt->log); memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "\n\t\t\t\tChecking src 0x%016" PRIx64 " to dest 0x%016" PRIx64 "\n", cl_ntoh64(p_pair->src_guid), cl_ntoh64(p_pair->dest_guid)); context.p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS; req.p_query_input = p_pair; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0110: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0111: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "%zu records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_path_rec(context.result.p_result_madw, i); /* * Make sure the GUID values are correct */ if (p_rec->dgid.unicast.interface_id != p_pair->dest_guid) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0112: " "Destination GUID mismatch\n" "\t\t\t\texpected 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n", cl_ntoh64(p_pair->dest_guid), cl_ntoh64(p_rec->dgid.unicast.interface_id)); got_error = TRUE; } if (p_rec->sgid.unicast.interface_id != p_pair->src_guid) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0113: " "Source GUID mismatch\n" "\t\t\t\texpected 0x%016" PRIx64 ", received 0x%016" PRIx64 ".\n", cl_ntoh64(p_pair->src_guid), cl_ntoh64(p_rec->sgid.unicast.interface_id)); got_error = TRUE; } status = osmtest_validate_path_rec(p_osmt, p_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0114: " "osmtest_validate_path_rec failed (%s)\n", ib_get_err_str(status)); got_error = TRUE; } if (got_error || (status != IB_SUCCESS)) { osm_dump_path_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); if (status == IB_SUCCESS) status = IB_ERROR; goto Exit; } } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_get_sm_gid(IN osmtest_t * const p_osmt) { cl_status_t status = IB_SUCCESS; node_t *p_node; const cl_qmap_t *p_tbl; ib_port_attr_t *local_port; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Calculate SM GID for use in subsequent SA queries\n"); local_port = &p_osmt->local_port; p_osmt->sm_port_gid.unicast.prefix = cl_hton64(p_osmt->local_port_gid.unicast.prefix); if (local_port->lid != local_port->sm_lid) { status = osmtest_create_db(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0155: Database creation failed (%s)\n", ib_get_err_str(status)); goto Exit; } p_tbl = &p_osmt->exp_subn.node_lid_tbl; p_node = (node_t *) cl_qmap_get(p_tbl, cl_hton16(local_port->sm_lid)); if (p_node == (node_t *) cl_qmap_end(p_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0154: SM LID 0x%X doesn't exist\n", local_port->sm_lid); status = IB_ERROR; goto Exit; } p_osmt->sm_port_gid.unicast.interface_id = p_node->rec.node_info.port_guid; } else { p_osmt->sm_port_gid.unicast.interface_id = cl_hton64(p_osmt->local_port_gid.unicast.interface_id); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "SM GID 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh64(p_osmt->sm_port_gid.unicast.prefix), cl_ntoh64(p_osmt->sm_port_gid.unicast.interface_id)); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_path_recs(IN osmtest_t * const p_osmt) { path_t *p_path; cl_status_t status = IB_SUCCESS; const cl_qmap_t *p_path_tbl; /* We skip node to node path record validation since it might contains NONEXISTENT PATHS, i.e. when using UPDN */ osmv_guid_pair_t guid_pair; uint16_t cnt; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Validating individual path record queries\n"); p_path_tbl = &p_osmt->exp_subn.path_tbl; osmtest_prepare_db(p_osmt); /* * Walk the list of all path records, and ask for each one * specifically. Make sure we get it. */ cnt = 0; p_path = (path_t *) cl_qmap_head(p_path_tbl); while (p_path != (path_t *) cl_qmap_end(p_path_tbl)) { status = osmtest_validate_single_path_rec_lid_pair(p_osmt, p_path); if (status != IB_SUCCESS) goto Exit; cnt++; p_path = (path_t *) cl_qmap_next(&p_path->map_item); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Total of %u path records validated using LID based query\n", cnt); status = osmtest_check_missing_paths(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0115: " "osmtest_check_missing_paths failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* * Do the whole thing again with port GUID pairs. * Note that multiple path records may be returned * for each guid pair if LMC > 0. */ osmtest_prepare_db(p_osmt); cnt = 0; p_path = (path_t *) cl_qmap_head(p_path_tbl); while (p_path != (path_t *) cl_qmap_end(p_path_tbl)) { guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id; guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id; status = osmtest_validate_single_path_rec_guid_pair(p_osmt, &guid_pair); if (status != IB_SUCCESS) goto Exit; cnt++; p_path = (path_t *) cl_qmap_next(&p_path->map_item); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Total of %u path records validated using GUID based query\n", cnt); status = osmtest_check_missing_paths(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0116: " "osmtest_check_missing_paths failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_node_recs(IN osmtest_t * const p_osmt) { node_t *p_node; cl_status_t status = IB_SUCCESS; const cl_qmap_t *p_node_lid_tbl; uint16_t cnt = 0; OSM_LOG_ENTER(&p_osmt->log); p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl; osmtest_prepare_db(p_osmt); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Validating individual node record queries\n"); /* * Walk the list of all node records, and ask for each one * specifically. Make sure we get it. */ p_node = (node_t *) cl_qmap_head(p_node_lid_tbl); while (p_node != (node_t *) cl_qmap_end(p_node_lid_tbl)) { status = osmtest_validate_single_node_rec_lid(p_osmt, (ib_net16_t) cl_qmap_key((cl_map_item_t *) p_node), p_node); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 011A: " "osmtest_validate_single_node_rec_lid (%s)\n", ib_get_err_str(status)); goto Exit; } cnt++; p_node = (node_t *) cl_qmap_next(&p_node->map_item); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Total of %u node records validated\n", cnt); status = osmtest_check_missing_nodes(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0117: " "osmtest_check_missing_nodes (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_single_port_recs(IN osmtest_t * const p_osmt) { port_t *p_port; cl_status_t status = IB_SUCCESS; const cl_qmap_t *p_port_key_tbl; uint16_t cnt = 0; OSM_LOG_ENTER(&p_osmt->log); p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl; osmtest_prepare_db(p_osmt); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Validating individual port record queries\n"); /* * Walk the list of all port records, and ask for each one * specifically. Make sure we get it. */ p_port = (port_t *) cl_qmap_head(p_port_key_tbl); while (p_port != (port_t *) cl_qmap_end(p_port_key_tbl)) { status = osmtest_validate_single_port_rec_lid(p_osmt, p_port); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 011B: " "osmtest_validate_single_port_rec_lid (%s)\n", ib_get_err_str(status)); goto Exit; } cnt++; p_port = (port_t *) cl_qmap_next(&p_port->map_item); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Total of %u port records validated\n", cnt); status = osmtest_check_missing_ports(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0118: " "osmtest_check_missing_paths failed (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_validate_against_db(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; ib_gid_t portgid, mgid; osmtest_sm_info_rec_t sm_info_rec_opt; osmtest_inform_info_t inform_info_opt; osmtest_inform_info_rec_t inform_info_rec_opt; #ifdef VENDOR_RMPP_SUPPORT ib_net64_t sm_key; ib_net16_t test_lid; uint8_t lmc; osmtest_req_context_t context; #ifdef DUAL_SIDED_RMPP osmv_multipath_req_t request; #endif uint8_t i; #endif OSM_LOG_ENTER(&p_osmt->log); #ifdef VENDOR_RMPP_SUPPORT status = osmtest_validate_all_node_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; #endif status = osmtest_validate_single_node_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; /* Exercise SA PathRecord multicast destination code */ memset(&context, 0, sizeof(context)); ib_gid_set_default(&portgid, portguid); /* Set IPoIB broadcast MGID */ mgid.unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); /* Can't check status as don't know whether port is running IPoIB */ osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context); /* Other link local unicast PathRecord */ memset(&context, 0, sizeof(context)); ib_gid_set_default(&portgid, portguid); ib_gid_set_default(&mgid, portguid); mgid.raw[7] = 0xff; /* not default GID prefix */ /* Can't check status as don't know whether ??? */ osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context); /* Off subnet (site local) unicast PathRecord */ memset(&context, 0, sizeof(context)); ib_gid_set_default(&portgid, portguid); ib_gid_set_default(&mgid, portguid); mgid.raw[1] = 0xc0; /* site local */ /* Can't check status as don't know whether ??? */ osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context); /* More than link local scope multicast PathRecord */ memset(&context, 0, sizeof(context)); ib_gid_set_default(&portgid, portguid); /* Set IPoIB broadcast MGID */ mgid.unicast.prefix = CL_HTON64(0xff15401bffff0000ULL); /* site local */ mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); /* Can't check status as don't know whether port is running IPoIB */ osmtest_get_path_rec_by_gid_pair(p_osmt, portgid, mgid, &context); #if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) memset(&context, 0, sizeof(context)); memset(&request, 0, sizeof(request)); request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; request.sgid_count = 1; request.dgid_count = 1; ib_gid_set_default(&request.gids[0], portguid); ib_gid_set_default(&request.gids[1], portguid); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); memset(&request, 0, sizeof(request)); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } memset(&context, 0, sizeof(context)); memset(&request, 0, sizeof(request)); request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT; request.sgid_count = 1; ib_gid_set_default(&request.gids[0], portguid); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } memset(&context, 0, sizeof(context)); memset(&request, 0, sizeof(request)); request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; request.sgid_count = 1; request.dgid_count = 1; ib_gid_set_default(&request.gids[0], portguid); /* Set IPoIB broadcast MGID as DGID */ request.gids[1].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); request.gids[1].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } memset(&context, 0, sizeof(context)); request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT; request.sgid_count = 1; request.dgid_count = 1; /* Set IPoIB broadcast MGID as SGID */ request.gids[0].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL); request.gids[0].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL); ib_gid_set_default(&request.gids[1], portguid); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } memset(&context, 0, sizeof(context)); memset(&request, 0, sizeof(request)); request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT | IB_MPR_COMPMASK_NUMBPATH; request.sgid_count = 2; request.dgid_count = 2; request.num_path = 2; ib_gid_set_default(&request.gids[0], portguid); ib_gid_set_default(&request.gids[1], portguid); ib_gid_set_default(&request.gids[2], portguid); ib_gid_set_default(&request.gids[3], portguid); status = osmtest_get_multipath_rec(p_osmt, &request, &context); if (status != IB_SUCCESS) goto Exit; #endif #ifdef VENDOR_RMPP_SUPPORT /* GUIDInfoRecords */ status = osmtest_validate_all_guidinfo_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; /* If LMC > 0, test non base LID SA PortInfoRecord request */ status = osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc); if (status != IB_SUCCESS) goto Exit; if (lmc != 0) { status = osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid + 1, NULL); if (status != IB_SUCCESS) goto Exit; } status = osmtest_get_local_port_lmc(p_osmt, 0xffff, NULL); if (status != IB_SUCCESS) goto Exit; test_lid = cl_ntoh16(p_osmt->local_port.lid); /* More GUIDInfo Record tests */ memset(&context, 0, sizeof(context)); status = osmtest_get_guidinfo_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); status = osmtest_get_guidinfo_rec_by_lid(p_osmt, 0xffff, &context); if (status != IB_SUCCESS) goto Exit; /* Some PKeyTable Record tests */ sm_key = OSM_DEFAULT_SM_KEY; memset(&context, 0, sizeof(context)); status = osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, sm_key, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, 0, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } memset(&context, 0, sizeof(context)); status = osmtest_get_pkeytbl_rec_by_lid(p_osmt, 0xffff, sm_key, &context); if (status != IB_SUCCESS) goto Exit; /* SwitchInfo Record tests */ memset(&context, 0, sizeof(context)); status = osmtest_get_sw_info_rec_by_lid(p_osmt, 0, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); status = osmtest_get_sw_info_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* LFT Record tests */ memset(&context, 0, sizeof(context)); status = osmtest_get_lft_rec_by_lid(p_osmt, 0, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); status = osmtest_get_lft_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* MFT Record tests */ memset(&context, 0, sizeof(context)); status = osmtest_get_mft_rec_by_lid(p_osmt, 0, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); status = osmtest_get_mft_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* Some LinkRecord tests */ /* FromLID */ memset(&context, 0, sizeof(context)); status = osmtest_get_link_rec_by_lid(p_osmt, test_lid, 0, &context); if (status != IB_SUCCESS) goto Exit; /* ToLID */ memset(&context, 0, sizeof(context)); status = osmtest_get_link_rec_by_lid(p_osmt, 0, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* FromLID & ToLID */ memset(&context, 0, sizeof(context)); status = osmtest_get_link_rec_by_lid(p_osmt, test_lid, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* NodeRecord test */ memset(&context, 0, sizeof(context)); status = osmtest_get_node_rec_by_lid(p_osmt, 0xffff, &context); if (status != IB_SUCCESS) goto Exit; /* SMInfoRecord tests */ memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_SET, &sm_info_rec_opt, &context); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); } memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE, &sm_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); sm_info_rec_opt.lid = test_lid; /* local LID */ memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE, &sm_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; if (portguid != 0) { memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); sm_info_rec_opt.sm_guid = portguid; /* local GUID */ memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE, &sm_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; } for (i = 1; i < 16; i++) { memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); sm_info_rec_opt.priority = i; memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE, &sm_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; } for (i = 1; i < 4; i++) { memset(&sm_info_rec_opt, 0, sizeof(sm_info_rec_opt)); sm_info_rec_opt.sm_state = i; memset(&context, 0, sizeof(context)); status = osmtest_sminfo_record_request(p_osmt, IB_MAD_METHOD_GETTABLE, &sm_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; } /* InformInfoRecord tests */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a BAD - Set Unsubscribe request\n"); memset(&inform_info_opt, 0, sizeof(inform_info_opt)); memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_SET, &inform_info_rec_opt, &context); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfoRecord " "IS EXPECTED ERROR ^^^^\n"); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - Empty GetTable request\n"); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; /* InformInfo tests */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a BAD - Empty Get request " "(should fail with NO_RECORDS)\n"); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_GET, &inform_info_opt, &context); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfo " "IS EXPECTED ERROR ^^^^\n"); } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a BAD - Set Unsubscribe request\n"); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "InformInfo UnSubscribe " "IS EXPECTED ERROR ^^^^\n"); } /* Now subscribe */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a Good - Set Subscribe request\n"); inform_info_opt.subscribe = TRUE; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Now unsubscribe (QPN needs to be 1 to work) */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a Good - Set Unsubscribe request\n"); inform_info_opt.subscribe = FALSE; inform_info_opt.qpn = 1; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Now subscribe again */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a Good - Set Subscribe request\n"); inform_info_opt.subscribe = TRUE; inform_info_opt.qpn = 1; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Subscribe over existing subscription */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a Good - Set Subscribe (again) request\n"); inform_info_opt.qpn = 0; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* More InformInfoRecord tests */ /* RID lookup (with currently invalid enum) */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable by GID\n"); ib_gid_set_default(&inform_info_rec_opt.subscriber_gid, p_osmt->local_port.port_guid); inform_info_rec_opt.subscriber_enum = 1; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Enum lookup */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable (subscriber_enum == 0) request\n"); inform_info_rec_opt.subscriber_enum = 0; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Get all InformInfoRecords */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable (ALL records) request\n"); memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Another subscription */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending another Good - Set Subscribe (again) request\n"); inform_info_opt.qpn = 0; inform_info_opt.trap = 0x1234; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Get all InformInfoRecords again */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable (ALL records) request\n"); memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Cleanup subscriptions before further testing */ /* Does order of deletion matter ? Test this !!! */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo " "Sending a Good - Set (cleanup) request\n"); inform_info_opt.subscribe = FALSE; inform_info_opt.qpn = 1; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Get all InformInfoRecords again */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable (ALL records) request\n"); memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfo" "Sending a Good - Set (cleanup) request\n"); inform_info_opt.subscribe = FALSE; inform_info_opt.qpn = 1; inform_info_opt.trap = 0; memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO, IB_MAD_METHOD_SET, &inform_info_opt, &context); if (status != IB_SUCCESS) goto Exit; /* Get all InformInfoRecords a final time */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "InformInfoRecord " "Sending a Good - GetTable (ALL records) request\n"); memset(&inform_info_rec_opt, 0, sizeof(inform_info_rec_opt)); memset(&context, 0, sizeof(context)); status = osmtest_informinfo_request(p_osmt, IB_MAD_ATTR_INFORM_INFO_RECORD, IB_MAD_METHOD_GETTABLE, &inform_info_rec_opt, &context); if (status != IB_SUCCESS) goto Exit; if (lmc != 0) { test_lid = cl_ntoh16(p_osmt->local_port.lid + 1); /* Another GUIDInfo Record test */ memset(&context, 0, sizeof(context)); status = osmtest_get_guidinfo_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* Another PKeyTable Record test */ memset(&context, 0, sizeof(context)); status = osmtest_get_pkeytbl_rec_by_lid(p_osmt, test_lid, sm_key, &context); if (status != IB_SUCCESS) goto Exit; /* Another SwitchInfo Record test */ memset(&context, 0, sizeof(context)); status = osmtest_get_sw_info_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* Another LFT Record test */ memset(&context, 0, sizeof(context)); status = osmtest_get_lft_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* Another MFT Record test */ memset(&context, 0, sizeof(context)); status = osmtest_get_mft_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* More LinkRecord tests */ /* FromLID */ memset(&context, 0, sizeof(context)); status = osmtest_get_link_rec_by_lid(p_osmt, test_lid, 0, &context); if (status != IB_SUCCESS) goto Exit; /* ToLID */ memset(&context, 0, sizeof(context)); status = osmtest_get_link_rec_by_lid(p_osmt, 0, test_lid, &context); if (status != IB_SUCCESS) goto Exit; /* Another NodeRecord test */ memset(&context, 0, sizeof(context)); status = osmtest_get_node_rec_by_lid(p_osmt, test_lid, &context); if (status != IB_SUCCESS) goto Exit; } /* PathRecords */ if (!p_osmt->opt.ignore_path_records) { status = osmtest_validate_all_path_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; if (lmc != 0) { memset(&context, 0, sizeof(context)); status = osmtest_get_path_rec_by_lid_pair(p_osmt, test_lid, test_lid, &context); if (status != IB_SUCCESS) goto Exit; memset(&context, 0, sizeof(context)); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_path_rec_by_lid_pair(p_osmt, 0xffff, 0xffff, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmtest_get_path_rec_by_lid_pair(p_osmt, test_lid, 0xffff, &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Got error %s\n", ib_get_err_str(status)); } OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { status = IB_ERROR; goto Exit; } } } #endif status = osmtest_validate_single_port_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; if (!p_osmt->opt.ignore_path_records) { status = osmtest_validate_single_path_recs(p_osmt); if (status != IB_SUCCESS) goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static const osmtest_token_t *str_get_token(IN char *const p_str) { const osmtest_token_t *p_tok; uint32_t index = 0; p_tok = &token_array[index]; while (p_tok->val != OSMTEST_TOKEN_UNKNOWN) { if (strncasecmp(p_str, p_tok->str, p_tok->str_size) == 0) return (p_tok); p_tok = &token_array[++index]; } return (NULL); } /********************************************************************** Returns true if not whitespace character encountered before EOL. **********************************************************************/ static boolean_t str_skip_white(IN char line[], IN OUT uint32_t * const p_offset) { while (((line[*p_offset] == '\t') || (line[*p_offset] == ' ')) && (line[*p_offset] != '\n') && (line[*p_offset] != '\0')) { ++*p_offset; } if ((line[*p_offset] == '\n') || (line[*p_offset] == '\0')) return (FALSE); else return (TRUE); } /********************************************************************** Returns true if not whitespace character encountered before EOL. **********************************************************************/ static void str_skip_token(IN char line[], IN OUT uint32_t * const p_offset) { while ((line[*p_offset] != '\t') && (line[*p_offset] != ' ') && (line[*p_offset] != '\0')) { ++*p_offset; } } static ib_api_status_t osmtest_parse_node(IN osmtest_t * const p_osmt, IN FILE * const fh, IN OUT uint32_t * const p_line_num) { ib_api_status_t status = IB_SUCCESS; uint32_t offset; char line[OSMTEST_MAX_LINE_LEN]; boolean_t done = FALSE; node_t *p_node; node_t *p_guid_node; const osmtest_token_t *p_tok; OSM_LOG_ENTER(&p_osmt->log); p_node = node_new(); CL_ASSERT(p_node != NULL); /* * Parse the inventory file and create the database. */ while (!done) { if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) { /* * End of file in the middle of a definition. */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0119: " "Unexpected end of file\n"); status = IB_ERROR; goto Exit; } ++*p_line_num; /* * Skip whitespace */ offset = 0; if (!str_skip_white(line, &offset)) continue; /* whole line was whitespace */ p_tok = str_get_token(&line[offset]); if (p_tok == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0120: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); continue; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Found '%s' (line %u)\n", p_tok->str, *p_line_num); str_skip_token(line, &offset); switch (p_tok->val) { case OSMTEST_TOKEN_COMMENT: break; case OSMTEST_TOKEN_LID: p_node->comp.lid = 0xFFFF; p_node->rec.lid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lid = 0x%X\n", cl_ntoh16(p_node->rec.lid)); break; case OSMTEST_TOKEN_BASE_VERSION: p_node->comp.node_info.base_version = 0xFF; p_node->rec.node_info.base_version = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "base_version = 0x%X\n", p_node->rec.node_info.base_version); break; case OSMTEST_TOKEN_CLASS_VERSION: p_node->comp.node_info.class_version = 0xFF; p_node->rec.node_info.class_version = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "class_version = 0x%X\n", p_node->rec.node_info.class_version); break; case OSMTEST_TOKEN_NODE_TYPE: p_node->comp.node_info.node_type = 0xFF; p_node->rec.node_info.node_type = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "node_type = 0x%X\n", p_node->rec.node_info.node_type); break; case OSMTEST_TOKEN_NUM_PORTS: p_node->comp.node_info.num_ports = 0xFF; p_node->rec.node_info.num_ports = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "num_ports = 0x%X\n", p_node->rec.node_info.num_ports); break; case OSMTEST_TOKEN_SYS_GUID: p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL; p_node->rec.node_info.sys_guid = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "sys_guid = 0x%016" PRIx64 "\n", cl_ntoh64(p_node->rec.node_info.sys_guid)); break; case OSMTEST_TOKEN_NODE_GUID: p_node->comp.node_info.node_guid = 0xFFFFFFFFFFFFFFFFULL; p_node->rec.node_info.node_guid = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "node_guid = 0x%016" PRIx64 "\n", cl_ntoh64(p_node->rec.node_info.node_guid)); break; case OSMTEST_TOKEN_PORT_GUID: p_node->comp.node_info.port_guid = 0xFFFFFFFFFFFFFFFFULL; p_node->rec.node_info.port_guid = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "port_guid = 0x%016" PRIx64 "\n", cl_ntoh64(p_node->rec.node_info.port_guid)); break; case OSMTEST_TOKEN_PARTITION_CAP: p_node->comp.node_info.partition_cap = 0xFFFF; p_node->rec.node_info.partition_cap = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "partition_cap = 0x%X\n", cl_ntoh16(p_node->rec.node_info.partition_cap)); break; case OSMTEST_TOKEN_DEVICE_ID: p_node->comp.node_info.device_id = 0xFFFF; p_node->rec.node_info.device_id = cl_hton16((uint16_t) strtoul (&line [offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "device_id = 0x%X\n", cl_ntoh16(p_node->rec.node_info.device_id)); break; case OSMTEST_TOKEN_REVISION: p_node->comp.node_info.revision = 0xFFFFFFFF; p_node->rec.node_info.revision = cl_hton32(strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "revision = 0x%X\n", cl_ntoh32(p_node->rec.node_info.revision)); break; case OSMTEST_TOKEN_PORT_NUM: p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_PORT_NUM_MASK; p_node->rec.node_info.port_num_vendor_id |= (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "local_port_num = 0x%X\n", ib_node_info_get_local_port_num (&p_node->rec.node_info)); break; case OSMTEST_TOKEN_VENDOR_ID: p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_VEND_ID_MASK; p_node->rec.node_info.port_num_vendor_id |= cl_hton32(strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vendor_id = 0x%X\n", cl_ntoh32(ib_node_info_get_vendor_id (&p_node->rec.node_info))); break; case OSMTEST_TOKEN_END: done = TRUE; break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0121: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); break; } } /* * Make sure the user specified enough information, then * add this object to the database. */ if (p_node->comp.lid == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0122: " "LID must be specified for defined nodes\n"); node_delete(p_node); goto Exit; } cl_qmap_insert(&p_osmt->exp_subn.node_lid_tbl, p_node->rec.lid, &p_node->map_item); p_guid_node = node_new(); CL_ASSERT(p_node != NULL); *p_guid_node = *p_node; cl_qmap_insert(&p_osmt->exp_subn.node_guid_tbl, p_guid_node->rec.node_info.node_guid, &p_guid_node->map_item); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_parse_port(IN osmtest_t * const p_osmt, IN FILE * const fh, IN OUT uint32_t * const p_line_num) { ib_api_status_t status = IB_SUCCESS; uint32_t offset; char line[OSMTEST_MAX_LINE_LEN]; boolean_t done = FALSE; port_t *p_port; const osmtest_token_t *p_tok; OSM_LOG_ENTER(&p_osmt->log); p_port = port_new(); CL_ASSERT(p_port != NULL); /* * Parse the inventory file and create the database. */ while (!done) { if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) { /* * End of file in the middle of a definition. */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0123: " "Unexpected end of file\n"); status = IB_ERROR; goto Exit; } ++*p_line_num; /* * Skip whitespace */ offset = 0; if (!str_skip_white(line, &offset)) continue; /* whole line was whitespace */ p_tok = str_get_token(&line[offset]); if (p_tok == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0124: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); continue; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Found '%s' (line %u)\n", p_tok->str, *p_line_num); str_skip_token(line, &offset); switch (p_tok->val) { case OSMTEST_TOKEN_COMMENT: break; case OSMTEST_TOKEN_LID: p_port->comp.lid = 0xFFFF; p_port->rec.lid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lid = 0x%X\n", cl_ntoh16(p_port->rec.lid)); break; case OSMTEST_TOKEN_PORT_NUM: p_port->comp.port_num = 0xFF; p_port->rec.port_num = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "port_num = 0x%u\n", p_port->rec.port_num); break; case OSMTEST_TOKEN_MKEY: p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL; p_port->rec.port_info.m_key = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "m_key = 0x%016" PRIx64 "\n", cl_ntoh64(p_port->rec.port_info.m_key)); break; case OSMTEST_TOKEN_SUBN_PREF: p_port->comp.port_info.subnet_prefix = 0xFFFFFFFFFFFFFFFFULL; p_port->rec.port_info.subnet_prefix = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "subnet_prefix = 0x%016" PRIx64 "\n", cl_ntoh64(p_port->rec.port_info.subnet_prefix)); break; case OSMTEST_TOKEN_BASE_LID: p_port->comp.port_info.base_lid = 0xFFFF; p_port->rec.port_info.base_lid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "base_lid = 0x%X\n", cl_ntoh16(p_port->rec.port_info.base_lid)); break; case OSMTEST_TOKEN_SM_BASE_LID: p_port->comp.port_info.master_sm_base_lid = 0xFFFF; p_port->rec.port_info.master_sm_base_lid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "master_sm_base_lid = 0x%X\n", cl_ntoh16(p_port->rec.port_info.master_sm_base_lid)); break; case OSMTEST_TOKEN_CAP_MASK: p_port->comp.port_info.capability_mask = 0xFFFFFFFF; p_port->rec.port_info.capability_mask = cl_hton32((uint32_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "capability_mask = 0x%X\n", cl_ntoh32(p_port->rec.port_info.capability_mask)); break; case OSMTEST_TOKEN_DIAG_CODE: p_port->comp.port_info.diag_code = 0xFFFF; p_port->rec.port_info.diag_code = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "diag_code = 0x%X\n", cl_ntoh16(p_port->rec.port_info.diag_code)); break; case OSMTEST_TOKEN_MKEY_LEASE_PER: p_port->comp.port_info.m_key_lease_period = 0xFFFF; p_port->rec.port_info.m_key_lease_period = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "m_key_lease_period = 0x%X\n", cl_ntoh16(p_port->rec.port_info.m_key_lease_period)); break; case OSMTEST_TOKEN_LOC_PORT_NUM: p_port->comp.port_info.local_port_num = 0xFF; p_port->rec.port_info.local_port_num = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "local_port_num = 0x%u\n", p_port->rec.port_info.local_port_num); break; case OSMTEST_TOKEN_LINK_WID_EN: p_port->comp.port_info.link_width_enabled = 0xFF; p_port->rec.port_info.link_width_enabled = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "link_width_enabled = 0x%u\n", p_port->rec.port_info.link_width_enabled); break; case OSMTEST_TOKEN_LINK_WID_SUP: p_port->comp.port_info.link_width_supported = 0xFF; p_port->rec.port_info.link_width_supported = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "link_width_supported = 0x%u\n", p_port->rec.port_info.link_width_supported); break; case OSMTEST_TOKEN_LINK_WID_ACT: p_port->comp.port_info.link_width_active = 0xFF; p_port->rec.port_info.link_width_active = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "link_width_active = 0x%u\n", p_port->rec.port_info.link_width_active); break; case OSMTEST_TOKEN_LINK_SPEED_SUP: p_port->comp.port_info.state_info1 = 0xFF; ib_port_info_set_link_speed_sup((uint8_t) strtoul(&line[offset], NULL, 0), &p_port->rec.port_info); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "link_speed_supported = 0x%u\n", ib_port_info_get_link_speed_sup(&p_port->rec.port_info)); break; case OSMTEST_TOKEN_PORT_STATE: str_skip_white(line, &offset); p_port->comp.port_info.state_info1 = 0xFF; ib_port_info_set_port_state(&p_port->rec.port_info, ib_get_port_state_from_str (&line[offset])); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "port_state = 0x%u\n", ib_port_info_get_port_state(&p_port->rec.port_info)); break; case OSMTEST_TOKEN_STATE_INFO2: p_port->comp.port_info.state_info2 = 0xFF; p_port->rec.port_info.state_info2 = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "state_info2 = 0x%u\n", p_port->rec.port_info.state_info2); break; case OSMTEST_TOKEN_MKEY_PROT_BITS: p_port->comp.port_info.mkey_lmc = 0xFF; ib_port_info_set_mpb(&p_port->rec.port_info, (uint8_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "mpb = 0x%u\n", ib_port_info_get_mpb(&p_port->rec.port_info)); break; case OSMTEST_TOKEN_LMC: p_port->comp.port_info.mkey_lmc = 0xFF; ib_port_info_set_lmc(&p_port->rec.port_info, (uint8_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "lmc = 0x%u\n", ib_port_info_get_lmc(&p_port->rec.port_info)); break; case OSMTEST_TOKEN_LINK_SPEED: p_port->comp.port_info.link_speed = 0xFF; p_port->rec.port_info.link_speed = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "link_speed = 0x%u\n", p_port->rec.port_info.link_speed); break; case OSMTEST_TOKEN_MTU_SMSL: p_port->comp.port_info.mtu_smsl = 0xFF; p_port->rec.port_info.mtu_smsl = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "mtu_smsl = 0x%u\n", p_port->rec.port_info.mtu_smsl); break; case OSMTEST_TOKEN_VL_CAP: p_port->comp.port_info.vl_cap = 0xFF; p_port->rec.port_info.vl_cap = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_cap = 0x%u\n", p_port->rec.port_info.vl_cap); break; case OSMTEST_TOKEN_VL_HIGH_LIMIT: p_port->comp.port_info.vl_high_limit = 0xFF; p_port->rec.port_info.vl_high_limit = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_high_limit = 0x%u\n", p_port->rec.port_info.vl_high_limit); break; case OSMTEST_TOKEN_VL_ARB_HIGH_CAP: p_port->comp.port_info.vl_arb_high_cap = 0xFF; p_port->rec.port_info.vl_arb_high_cap = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_arb_high_cap = 0x%u\n", p_port->rec.port_info.vl_arb_high_cap); break; case OSMTEST_TOKEN_VL_ARB_LOW_CAP: p_port->comp.port_info.vl_arb_low_cap = 0xFF; p_port->rec.port_info.vl_arb_low_cap = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_arb_low_cap = 0x%u\n", p_port->rec.port_info.vl_arb_low_cap); break; case OSMTEST_TOKEN_MTU_CAP: p_port->comp.port_info.mtu_cap = 0xFF; p_port->rec.port_info.mtu_cap = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "mtu_cap = 0x%u\n", p_port->rec.port_info.mtu_cap); break; case OSMTEST_TOKEN_VL_STALL_LIFE: p_port->comp.port_info.vl_stall_life = 0xFF; p_port->rec.port_info.vl_stall_life = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_stall_life = 0x%u\n", p_port->rec.port_info.vl_stall_life); break; case OSMTEST_TOKEN_VL_ENFORCE: p_port->comp.port_info.vl_enforce = 0xFF; p_port->rec.port_info.vl_enforce = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "vl_enforce = 0x%u\n", p_port->rec.port_info.vl_enforce); break; case OSMTEST_TOKEN_MKEY_VIOL: p_port->comp.port_info.m_key_violations = 0xFFFF; p_port->rec.port_info.m_key_violations = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "m_key_violations = 0x%X\n", cl_ntoh16(p_port->rec.port_info.m_key_violations)); break; case OSMTEST_TOKEN_PKEY_VIOL: p_port->comp.port_info.p_key_violations = 0xFFFF; p_port->rec.port_info.p_key_violations = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "p_key_violations = 0x%X\n", cl_ntoh16(p_port->rec.port_info.p_key_violations)); break; case OSMTEST_TOKEN_QKEY_VIOL: p_port->comp.port_info.q_key_violations = 0xFFFF; p_port->rec.port_info.q_key_violations = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "q_key_violations = 0x%X\n", cl_ntoh16(p_port->rec.port_info.q_key_violations)); break; case OSMTEST_TOKEN_GUID_CAP: p_port->comp.port_info.guid_cap = 0xFF; p_port->rec.port_info.guid_cap = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "guid_cap = 0x%u\n", p_port->rec.port_info.guid_cap); break; case OSMTEST_TOKEN_SUBN_TIMEOUT: p_port->comp.port_info.subnet_timeout = 0x1F; p_port->rec.port_info.subnet_timeout = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "subnet_timeout = 0x%u\n", ib_port_info_get_timeout(&p_port->rec.port_info)); break; case OSMTEST_TOKEN_RESP_TIME_VAL: p_port->comp.port_info.resp_time_value = 0xFF; p_port->rec.port_info.resp_time_value = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "resp_time_value = 0x%u\n", p_port->rec.port_info.resp_time_value); break; case OSMTEST_TOKEN_ERR_THRESHOLD: p_port->comp.port_info.error_threshold = 0xFF; p_port->rec.port_info.error_threshold = (uint8_t) strtoul(&line[offset], NULL, 0); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "error_threshold = 0x%u\n", p_port->rec.port_info.error_threshold); break; case OSMTEST_TOKEN_END: done = TRUE; break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0125: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); break; } } /* * Make sure the user specified enough information, then * add this object to the database. */ if (p_port->comp.lid == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0126: " "LID must be specified for defined ports\n"); port_delete(p_port); status = IB_ERROR; goto Exit; } cl_qmap_insert(&p_osmt->exp_subn.port_key_tbl, port_gen_id(p_port->rec.lid, p_port->rec.port_num), &p_port->map_item); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_parse_path(IN osmtest_t * const p_osmt, IN FILE * const fh, IN OUT uint32_t * const p_line_num) { ib_api_status_t status = IB_SUCCESS; uint32_t offset; char line[OSMTEST_MAX_LINE_LEN]; boolean_t done = FALSE; path_t *p_path; const osmtest_token_t *p_tok; boolean_t got_error = FALSE; OSM_LOG_ENTER(&p_osmt->log); p_path = path_new(); CL_ASSERT(p_path != NULL); /* * Parse the inventory file and create the database. */ while (!done) { if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) { /* * End of file in the middle of a definition. */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: " "Unexpected end of file\n"); status = IB_ERROR; goto Exit; } ++*p_line_num; /* * Skip whitespace */ offset = 0; if (!str_skip_white(line, &offset)) continue; /* whole line was whitespace */ p_tok = str_get_token(&line[offset]); if (p_tok == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0128: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); got_error = TRUE; continue; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Found '%s' (line %u)\n", p_tok->str, *p_line_num); str_skip_token(line, &offset); switch (p_tok->val) { case OSMTEST_TOKEN_COMMENT: break; case OSMTEST_TOKEN_DGID: p_path->comp.dgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL; p_path->comp.dgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL; str_skip_white(line, &offset); p_path->rec.dgid.unicast.prefix = cl_hton64(strtoull(&line[offset], NULL, 0)); str_skip_token(line, &offset); p_path->rec.dgid.unicast.interface_id = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "dgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh64(p_path->rec.dgid.unicast.prefix), cl_ntoh64(p_path->rec.dgid.unicast.interface_id)); break; case OSMTEST_TOKEN_SGID: p_path->comp.sgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL; p_path->comp.sgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL; str_skip_white(line, &offset); p_path->rec.sgid.unicast.prefix = cl_hton64(strtoull(&line[offset], NULL, 0)); str_skip_token(line, &offset); p_path->rec.sgid.unicast.interface_id = cl_hton64(strtoull(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "sgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n", cl_ntoh64(p_path->rec.sgid.unicast.prefix), cl_ntoh64(p_path->rec.sgid.unicast.interface_id)); break; case OSMTEST_TOKEN_DLID: p_path->comp.dlid = 0xFFFF; p_path->rec.dlid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "dlid = 0x%X\n", cl_ntoh16(p_path->rec.dlid)); break; case OSMTEST_TOKEN_SLID: p_path->comp.slid = 0xFFFF; p_path->rec.slid = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "slid = 0x%X\n", cl_ntoh16(p_path->rec.slid)); break; case OSMTEST_TOKEN_PKEY: p_path->comp.pkey = 0xFFFF; p_path->rec.pkey = cl_hton16((uint16_t) strtoul(&line[offset], NULL, 0)); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "pkey = 0x%X\n", cl_ntoh16(p_path->rec.pkey)); break; case OSMTEST_TOKEN_END: done = TRUE; break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0129: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); got_error = TRUE; break; } } if (got_error) { status = IB_ERROR; goto Exit; } /* * Make sure the user specified enough information, then * add this object to the database. */ if (osmtest_path_rec_kay_is_valid(p_osmt, p_path) == FALSE) { path_delete(p_path); status = IB_ERROR; goto Exit; } cl_qmap_insert(&p_osmt->exp_subn.path_tbl, osmtest_path_rec_key_get(&p_path->rec), &p_path->map_item); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_parse_link(IN osmtest_t * const p_osmt, IN FILE * const fh, IN OUT uint32_t * const p_line_num) { ib_api_status_t status = IB_SUCCESS; uint32_t offset; char line[OSMTEST_MAX_LINE_LEN]; boolean_t done = FALSE; const osmtest_token_t *p_tok; boolean_t got_error = FALSE; OSM_LOG_ENTER(&p_osmt->log); /* * Parse the inventory file and create the database. */ while (!done) { if (fgets(line, OSMTEST_MAX_LINE_LEN, fh) == NULL) { /* * End of file in the middle of a definition. */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012A: " "Unexpected end of file\n"); status = IB_ERROR; goto Exit; } ++*p_line_num; /* * Skip whitespace */ offset = 0; if (!str_skip_white(line, &offset)) continue; /* whole line was whitespace */ p_tok = str_get_token(&line[offset]); if (p_tok == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012B: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); got_error = TRUE; continue; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Found '%s' (line %u)\n", p_tok->str, *p_line_num); str_skip_token(line, &offset); switch (p_tok->val) { case OSMTEST_TOKEN_FROMLID: case OSMTEST_TOKEN_FROMPORTNUM: case OSMTEST_TOKEN_TOPORTNUM: case OSMTEST_TOKEN_TOLID: /* For now */ break; case OSMTEST_TOKEN_END: done = TRUE; break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 012C: " "Ignoring line %u with unknown token: %s\n", *p_line_num, &line[offset]); got_error = TRUE; break; } } if (got_error) status = IB_ERROR; Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmtest_create_db(IN osmtest_t * const p_osmt) { FILE *fh; ib_api_status_t status = IB_SUCCESS; uint32_t offset; char line[OSMTEST_MAX_LINE_LEN]; uint32_t line_num = 0; const osmtest_token_t *p_tok; boolean_t got_error = FALSE; OSM_LOG_ENTER(&p_osmt->log); fh = fopen(p_osmt->opt.file_name, "r"); if (fh == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0130: " "Unable to open inventory file (%s)\n", p_osmt->opt.file_name); status = IB_ERROR; goto Exit; } /* * Parse the inventory file and create the database. */ while (fgets(line, OSMTEST_MAX_LINE_LEN, fh) != NULL) { line_num++; /* * Skip whitespace */ offset = 0; if (!str_skip_white(line, &offset)) continue; /* whole line was whitespace */ p_tok = str_get_token(&line[offset]); if (p_tok == NULL) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0131: " "Ignoring line %u: %s\n", line_num, &line[offset]); got_error = TRUE; continue; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Found '%s' (line %u)\n", p_tok->str, line_num); switch (p_tok->val) { case OSMTEST_TOKEN_COMMENT: break; case OSMTEST_TOKEN_DEFINE_NODE: status = osmtest_parse_node(p_osmt, fh, &line_num); break; case OSMTEST_TOKEN_DEFINE_PORT: status = osmtest_parse_port(p_osmt, fh, &line_num); break; case OSMTEST_TOKEN_DEFINE_PATH: status = osmtest_parse_path(p_osmt, fh, &line_num); break; case OSMTEST_TOKEN_DEFINE_LINK: status = osmtest_parse_link(p_osmt, fh, &line_num); break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0132: " "Ignoring line %u: %s\n", line_num, &line[offset]); got_error = TRUE; break; } if (got_error) status = IB_ERROR; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0133: " "Bad status received during parsing (%s)\n", ib_get_err_str(status)); fclose(fh); goto Exit; } } fclose(fh); Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** Returns the index in the local port attribute array for the user's selection. **********************************************************************/ static uint32_t osmtest_get_user_port(IN osmtest_t * const p_osmt, IN const ib_port_attr_t p_attr_array[], IN uint32_t const num_ports) { uint32_t i, choice = 0; OSM_LOG_ENTER(&p_osmt->log); /* * User needs prompting for the local port GUID with which * to bind. */ while (1) { printf("\nChoose a local port number with which to bind:\n\n"); for (i = 0; i < num_ports; i++) { /* * Print the index + 1 since by convention, port numbers * start with 1 on host channel adapters. */ printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n", i + 1, cl_ntoh64(p_attr_array[i].port_guid), p_attr_array[i].lid, ib_get_port_state_str(p_attr_array[i]. link_state)); } printf("\nEnter choice (1-%u): ", i); fflush(stdout); if (scanf("%u", &choice) <= 0) { char junk[256]; if (scanf("%s", junk) <= 0) printf("\nError: Cannot scan!\n"); } else if (choice && choice <= num_ports) break; printf("\nError: Lame choice!\n"); } printf("\n"); OSM_LOG_EXIT(&p_osmt->log); return (choice - 1); } ib_api_status_t osmtest_bind(IN osmtest_t * p_osmt, IN uint16_t max_lid, IN ib_net64_t guid OPTIONAL) { uint32_t port_index; ib_api_status_t status; uint32_t num_ports = MAX_LOCAL_IBPORTS; ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS] = { {0} }; ib_gid_t gid[MAX_LOCAL_IBPORTS]; int i; OSM_LOG_ENTER(&p_osmt->log); for (i = 0; i < MAX_LOCAL_IBPORTS; i++) { attr_array[i].num_gids = 1; attr_array[i].p_gid_table = &gid[i]; } /* * Call the transport layer for a list of local port * GUID values. */ status = osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array, &num_ports); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0134: " "Failure getting local port attributes (%s)\n", ib_get_err_str(status)); goto Exit; } if (guid == 0) { /* * User needs prompting for the local port GUID with which * to bind. */ port_index = osmtest_get_user_port(p_osmt, attr_array, num_ports); if (num_ports == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0135: " "No local ports. Unable to proceed\n"); goto Exit; } guid = attr_array[port_index].port_guid; } else { for (port_index = 0; port_index < num_ports; port_index++) { if (attr_array[port_index].port_guid == guid) break; } if (port_index == num_ports) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0136: " "No local port with guid 0x%016" PRIx64 "\n", cl_ntoh64(guid)); status = IB_NOT_FOUND; goto Exit; } } /* * Copy the port info for the selected port. */ memcpy(&p_osmt->local_port, &attr_array[port_index], sizeof(p_osmt->local_port) - sizeof(p_osmt->local_port.p_gid_table)); if (p_osmt->local_port.num_gids) { p_osmt->local_port_gid.unicast.prefix = p_osmt->local_port.p_gid_table[0].unicast.prefix; p_osmt->local_port_gid.unicast.interface_id = p_osmt->local_port.p_gid_table[0].unicast.interface_id; } else { p_osmt->local_port_gid.unicast.prefix = IB_DEFAULT_SUBNET_PREFIX_HO; p_osmt->local_port_gid.unicast.interface_id = attr_array[port_index].port_guid; p_osmt->local_port.p_gid_table = NULL; } p_osmt->local_port.num_gids = 1; p_osmt->local_port.p_gid_table = &p_osmt->local_port_gid; /* bind to the SA */ OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Using port with SM LID:0x%04X\n", p_osmt->local_port.sm_lid); p_osmt->max_lid = max_lid; p_osmt->h_bind = osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid); if (p_osmt->h_bind == OSM_BIND_INVALID_HANDLE) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0137: " "Unable to bind to SA\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } ib_api_status_t osmtest_run(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); if (p_osmt->opt.flow != OSMT_FLOW_CREATE_INVENTORY && p_osmt->opt.with_grh) { /* Get SM GID for GRH DGID */ status = osmtest_get_sm_gid(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0153: calculating SM GID failed: (%s)\n", ib_get_err_str(status)); goto Exit; } } status = osmtest_validate_sa_class_port_info(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0138: " "Could not obtain SA ClassPortInfo (%s)\n", ib_get_err_str(status)); goto Exit; } if (p_osmt->opt.flow == OSMT_FLOW_CREATE_INVENTORY) { /* * Creating an inventory file with all nodes, ports and paths */ status = osmtest_create_inventory_file(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0139: " "Inventory file create failed (%s)\n", ib_get_err_str(status)); goto Exit; } } else { if (p_osmt->opt.flow == OSMT_FLOW_STRESS_SA) { /* * Stress SA - flood the SA with queries */ switch (p_osmt->opt.stress) { case 0: case 1: /* small response SA query stress */ status = osmtest_stress_small_rmpp(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0140: " "Small RMPP stress test failed (%s)\n", ib_get_err_str(status)); goto Exit; } break; case 2: /* large response SA query stress */ status = osmtest_stress_large_rmpp(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0141: " "Large RMPP stress test failed (%s)\n", ib_get_err_str(status)); goto Exit; } break; case 3: /* large response Path Record SA query stress */ status = osmtest_create_db(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0142: " "Database creation failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = osmtest_stress_large_rmpp_pr(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0143: " "Large RMPP stress test failed (%s)\n", ib_get_err_str(status)); goto Exit; } break; case 4: /* SA Get PR to SA LID */ status = osmtest_stress_get_pr(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 014B: " "SA Get PR stress test failed (%s)\n", ib_get_err_str(status)); goto Exit; } break; default: OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0144: " "Unknown stress test value %u\n", p_osmt->opt.stress); break; } } else { /* * Run normal validation tests. */ if (p_osmt->opt.flow == OSMT_FLOW_ALL || p_osmt->opt.flow == OSMT_FLOW_VALIDATE_INVENTORY) { /* * Only validate the given inventory file */ status = osmtest_create_db(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0145: " "Database creation failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = osmtest_validate_against_db(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0146: " "SA validation database failure (%s)\n", ib_get_err_str(status)); goto Exit; } } if (p_osmt->opt.flow == OSMT_FLOW_ALL) { status = osmtest_wrong_sm_key_ignored(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0147: " "Try wrong SM_Key failed (%s)\n", ib_get_err_str(status)); goto Exit; } } if (p_osmt->opt.flow == OSMT_FLOW_ALL || p_osmt->opt.flow == OSMT_FLOW_SERVICE_REGISTRATION) { /* * run service registration, deregistration, and lease test */ status = osmt_run_service_records_flow(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0148: " "Service Flow failed (%s)\n", ib_get_err_str(status)); goto Exit; } } if (p_osmt->opt.flow == OSMT_FLOW_ALL || p_osmt->opt.flow == OSMT_FLOW_EVENT_FORWARDING) { /* * Run event forwarding test */ #ifdef OSM_VENDOR_INTF_MTL status = osmt_run_inform_info_flow(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0149: " "Inform Info Flow failed: (%s)\n", ib_get_err_str(status)); goto Exit; } #else OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "The event forwarding flow " "is not implemented yet!\n"); status = IB_SUCCESS; goto Exit; #endif } if (p_osmt->opt.flow == OSMT_FLOW_QOS) { /* * QoS info: dump VLArb and SLtoVL tables. * Since it generates a huge file, we run it only * if explicitly required to */ status = osmtest_create_db(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 014A: " "Database creation failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = osmt_run_slvl_and_vlarb_records_flow (p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0150: " "Failed to get SLtoVL and VL Arbitration Tables (%s)\n", ib_get_err_str(status)); goto Exit; } } if (p_osmt->opt.flow == OSMT_FLOW_TRAP) { /* * Run trap 64/65 flow (this flow requires running of external tool) */ #ifdef OSM_VENDOR_INTF_MTL status = osmt_run_trap64_65_flow(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0151: " "Trap 64/65 Flow failed: (%s)\n", ib_get_err_str(status)); goto Exit; } #else OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Trap 64/65 flow " "is not implemented yet!\n"); status = IB_SUCCESS; goto Exit; #endif } if (p_osmt->opt.flow == OSMT_FLOW_ALL || p_osmt->opt.flow == OSMT_FLOW_MULTICAST) { /* * Multicast flow */ status = osmt_run_mcast_flow(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0152: " "Multicast Flow failed: (%s)\n", ib_get_err_str(status)); goto Exit; } } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "\n\n***************** ALL TESTS PASS *****************\n\n"); } } Exit: OSM_LOG_EXIT(&p_osmt->log); return (status); } opensm-3.3.20/osmtest/osmt_service.c0000644000205000001450000014050712725277041014372 00000000000000/* * Copyright (c) 2006-2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2010 HNR Consulting. 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 service records testing flow.. * Top level is osmt_run_service_records_flow: * osmt_register_service * osmt_get_service_by_name * osmt_get_all_services * osmt_delete_service_by_name * */ #ifndef __WIN__ #include #else #include #endif #include #include #include #include #include "osmtest.h" ib_api_status_t osmt_register_service(IN osmtest_t * const p_osmt, IN ib_net64_t service_id, IN ib_net16_t service_pkey, IN ib_net32_t service_lease, IN uint8_t service_key_lsb, IN char *service_name) { osmv_query_req_t req; osmv_user_query_t user; osmtest_req_context_t context; ib_service_record_t svc_rec; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status; OSM_LOG_ENTER(p_log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Registering service: name: %s id: 0x%" PRIx64 "\n", service_name, cl_ntoh64(service_id)); memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); memset(&user, 0, sizeof(user)); memset(&svc_rec, 0, sizeof(svc_rec)); /* set the new service record fields */ svc_rec.service_id = service_id; svc_rec.service_pkey = service_pkey; svc_rec.service_gid.unicast.prefix = p_osmt->local_port_gid.unicast.prefix; svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; svc_rec.service_lease = service_lease; memset(&svc_rec.service_key, 0, 16 * sizeof(uint8_t)); svc_rec.service_key[0] = service_key_lsb; memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memcpy(svc_rec.service_name, service_name, (strlen(service_name) + 1) * sizeof(char)); /* prepare the data used for this query */ /* sa_mad_data.method = IB_MAD_METHOD_SET; */ /* sa_mad_data.sm_key = 0; */ context.p_osmt = p_osmt; req.query_context = &context; req.query_type = OSMV_QUERY_USER_DEFINED; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.flags = OSM_SA_FLAGS_SYNC; req.sm_key = 0; req.timeout_ms = p_osmt->opt.transaction_timeout; user.method = IB_MAD_METHOD_SET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; if (ib_pkey_is_invalid(service_pkey)) { /* if given an invalid service_pkey - don't turn the PKEY compmask on */ user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME; } else { user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SPKEY | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME; } user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A01: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A02: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_register_service_with_full_key(IN osmtest_t * const p_osmt, IN ib_net64_t service_id, IN ib_net16_t service_pkey, IN ib_net32_t service_lease, IN uint8_t * service_key, IN char *service_name) { osmv_query_req_t req; osmv_user_query_t user; osmtest_req_context_t context; ib_service_record_t svc_rec, *p_rec; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status; uint8_t i, skey[16]; OSM_LOG_ENTER(p_log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Registering service: name: %s id: 0x%" PRIx64 "\n", service_name, cl_ntoh64(service_id)); memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); memset(&user, 0, sizeof(user)); memset(&svc_rec, 0, sizeof(svc_rec)); /* set the new service record fields */ svc_rec.service_id = service_id; svc_rec.service_pkey = service_pkey; svc_rec.service_gid.unicast.prefix = p_osmt->local_port_gid.unicast.prefix; svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; svc_rec.service_lease = service_lease; memset(&svc_rec.service_key, 0, 16 * sizeof(uint8_t)); memcpy(svc_rec.service_key, service_key, 16 * sizeof(uint8_t)); memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memset(skey, 0, 16 * sizeof(uint8_t)); memcpy(svc_rec.service_name, service_name, (strlen(service_name) + 1) * sizeof(char)); /* prepare the data used for this query */ /* sa_mad_data.method = IB_MAD_METHOD_SET; */ /* sa_mad_data.sm_key = 0; */ context.p_osmt = p_osmt; req.query_context = &context; req.query_type = OSMV_QUERY_USER_DEFINED; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.flags = OSM_SA_FLAGS_SYNC; req.sm_key = 0; req.timeout_ms = p_osmt->opt.transaction_timeout; user.method = IB_MAD_METHOD_SET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; if (ib_pkey_is_invalid(service_pkey)) { /* if given an invalid service_pkey - don't turn the PKEY compmask on */ user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME; } else { user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SPKEY | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME; } user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A03: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A04: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } /* Check service key on context to see if match */ p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Comparing service key...\n" "return key is:\n"); for (i = 0; i <= 15; i++) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "service_key sent[%u] = %u, service_key returned[%u] = %u\n", i, service_key[i], i, p_rec->service_key[i]); } /* since c15-0.1.14 not supported all key association queries should bring in return zero in service key */ if (memcmp(skey, p_rec->service_key, 16 * sizeof(uint8_t)) != 0) { status = IB_REMOTE_ERROR; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A33: " "Data mismatch in service_key\n"); goto Exit; } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_register_service_with_data(IN osmtest_t * const p_osmt, IN ib_net64_t service_id, IN ib_net16_t service_pkey, IN ib_net32_t service_lease, IN uint8_t service_key_lsb, IN uint8_t * service_data8, IN ib_net16_t * service_data16, IN ib_net32_t * service_data32, IN ib_net64_t * service_data64, IN char *service_name) { osmv_query_req_t req; osmv_user_query_t user; osmtest_req_context_t context; ib_service_record_t svc_rec, *p_rec; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status; /* ib_service_record_t* p_rec; */ OSM_LOG_ENTER(p_log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Registering service: name: %s id: 0x%" PRIx64 "\n", service_name, cl_ntoh64(service_id)); memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); memset(&user, 0, sizeof(user)); memset(&svc_rec, 0, sizeof(svc_rec)); /* set the new service record fields */ svc_rec.service_id = service_id; svc_rec.service_pkey = service_pkey; svc_rec.service_gid.unicast.prefix = p_osmt->local_port_gid.unicast.prefix; svc_rec.service_gid.unicast.interface_id = p_osmt->local_port.port_guid; svc_rec.service_lease = service_lease; memset(&svc_rec.service_key, 0, 16 * sizeof(uint8_t)); svc_rec.service_key[0] = service_key_lsb; /* Copy data to service_data arrays */ memcpy(svc_rec.service_data8, service_data8, 16 * sizeof(uint8_t)); memcpy(svc_rec.service_data16, service_data16, 8 * sizeof(ib_net16_t)); memcpy(svc_rec.service_data32, service_data32, 4 * sizeof(ib_net32_t)); memcpy(svc_rec.service_data64, service_data64, 2 * sizeof(ib_net64_t)); memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memcpy(svc_rec.service_name, service_name, (strlen(service_name) + 1) * sizeof(char)); /* prepare the data used for this query */ /* sa_mad_data.method = IB_MAD_METHOD_SET; */ /* sa_mad_data.sm_key = 0; */ context.p_osmt = p_osmt; req.query_context = &context; req.query_type = OSMV_QUERY_USER_DEFINED; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.flags = OSM_SA_FLAGS_SYNC; req.sm_key = 0; req.timeout_ms = p_osmt->opt.transaction_timeout; user.method = IB_MAD_METHOD_SET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; if (ib_pkey_is_invalid(service_pkey)) { /* if given an invalid service_pkey - don't turn the PKEY compmask on */ user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SDATA8_0 | IB_SR_COMPMASK_SDATA8_1 | IB_SR_COMPMASK_SDATA16_0 | IB_SR_COMPMASK_SDATA16_1 | IB_SR_COMPMASK_SDATA32_0 | IB_SR_COMPMASK_SDATA32_1 | IB_SR_COMPMASK_SDATA64_0 | IB_SR_COMPMASK_SDATA64_1; } else { user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID | IB_SR_COMPMASK_SPKEY | IB_SR_COMPMASK_SLEASE | IB_SR_COMPMASK_SKEY | IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SDATA8_0 | IB_SR_COMPMASK_SDATA8_1 | IB_SR_COMPMASK_SDATA16_0 | IB_SR_COMPMASK_SDATA16_1 | IB_SR_COMPMASK_SDATA32_0 | IB_SR_COMPMASK_SDATA32_1 | IB_SR_COMPMASK_SDATA64_0 | IB_SR_COMPMASK_SDATA64_1; } user.p_attr = &svc_rec; /* Dump to Service Data b4 send */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Dumping service data b4 send\n"); osm_dump_service_record(&p_osmt->log, &svc_rec, OSM_LOG_VERBOSE); if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A05: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A06: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } /* Check data on context to see if match */ p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Comparing service data...\n"); if (memcmp(service_data8, p_rec->service_data8, 16 * sizeof(uint8_t)) != 0 || memcmp(service_data16, p_rec->service_data16, 8 * sizeof(uint16_t)) != 0 || memcmp(service_data32, p_rec->service_data32, 4 * sizeof(uint32_t)) != 0 || memcmp(service_data64, p_rec->service_data64, 2 * sizeof(uint64_t)) != 0) { status = IB_REMOTE_ERROR; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Data mismatch in service_data8\n"); goto Exit; } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_get_service_by_id_and_name(IN osmtest_t * const p_osmt, IN uint32_t rec_num, IN ib_net64_t sid, IN char *sr_name, OUT ib_service_record_t * p_out_rec) { ib_api_status_t status = IB_SUCCESS; osmtest_req_context_t context; osmv_query_req_t req; ib_service_record_t svc_rec, *p_rec; uint32_t num_recs = 0; osmv_user_query_t user; const uint16_t ERR_SIZE = 512; char mad_stat_err[ERR_SIZE]; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting service record: id: 0x%016" PRIx64 " and name: %s\n", cl_ntoh64(sid), sr_name); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; /* prepare the data used for this query */ req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.sm_key = 0; memset(&svc_rec, 0, sizeof(svc_rec)); memset(&user, 0, sizeof(user)); /* set the new service record fields */ memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memcpy(svc_rec.service_name, sr_name, (strlen(sr_name) + 1) * sizeof(char)); svc_rec.service_id = sid; req.p_query_input = &user; user.method = IB_MAD_METHOD_GET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; user.comp_mask = IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SNAME; user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A07: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; num_recs = context.result.result_cnt; if (status != IB_SUCCESS) { /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, then this is fine */ if (status == IB_REMOTE_ERROR) strncpy(mad_stat_err, ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw)), ERR_SIZE -1); else strncpy(mad_stat_err, ib_get_err_str(status), ERR_SIZE -1); mad_stat_err[ERR_SIZE -1] = '\0'; if (status == IB_REMOTE_ERROR && !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && rec_num == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); status = IB_SUCCESS; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A08: " "Query failed: %s (%s)\n", ib_get_err_str(status), mad_stat_err); goto Exit; } } if (rec_num && num_recs != rec_num) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Unmatched number of records: expected: %d, received: %d\n", rec_num, num_recs); status = IB_REMOTE_ERROR; goto Exit; } p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); *p_out_rec = *p_rec; if (num_recs) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Found service record: name: %s id: 0x%016" PRIx64 "\n", p_rec->service_name, cl_ntoh64(p_rec->service_id)); osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); } Exit: OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Expected and found %d records\n", rec_num); if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_get_service_by_id(IN osmtest_t * const p_osmt, IN uint32_t rec_num, IN ib_net64_t sid, OUT ib_service_record_t * p_out_rec) { ib_api_status_t status = IB_SUCCESS; osmtest_req_context_t context; osmv_query_req_t req; ib_service_record_t svc_rec, *p_rec; uint32_t num_recs = 0; osmv_user_query_t user; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting service record: id: 0x%016" PRIx64 "\n", cl_ntoh64(sid)); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; /* prepare the data used for this query */ req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.sm_key = 0; memset(&svc_rec, 0, sizeof(svc_rec)); memset(&user, 0, sizeof(user)); /* set the new service record fields */ svc_rec.service_id = sid; req.p_query_input = &user; user.method = IB_MAD_METHOD_GET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; user.comp_mask = IB_SR_COMPMASK_SID; user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A09: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; num_recs = context.result.result_cnt; if (status != IB_SUCCESS) { char mad_stat_err[256]; /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, then this is fine */ if (status == IB_REMOTE_ERROR) strcpy(mad_stat_err, ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); else strcpy(mad_stat_err, ib_get_err_str(status)); if (status == IB_REMOTE_ERROR && !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && rec_num == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); status = IB_SUCCESS; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0A: " "Query failed: %s (%s)\n", ib_get_err_str(status), mad_stat_err); goto Exit; } } if (rec_num && num_recs != rec_num) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0B: " "Unmatched number of records: expected: %d received: %d\n", rec_num, num_recs); status = IB_REMOTE_ERROR; goto Exit; } p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); *p_out_rec = *p_rec; if (num_recs) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Found service record: name: %s id: 0x%016" PRIx64 "\n", p_rec->service_name, cl_ntoh64(p_rec->service_id)); osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); } Exit: OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Expected and found %d records\n", rec_num); if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_get_service_by_name_and_key(IN osmtest_t * const p_osmt, IN char *sr_name, IN uint32_t rec_num, IN uint8_t * skey, OUT ib_service_record_t * p_out_rec) { ib_api_status_t status = IB_SUCCESS; osmtest_req_context_t context; osmv_query_req_t req; ib_service_record_t svc_rec, *p_rec; uint32_t num_recs = 0, i; osmv_user_query_t user; const uint16_t ERR_SIZE = 512; char mad_stat_err[ERR_SIZE]; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting service record: name: %s and key: " "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", sr_name, skey[0], skey[1], skey[2], skey[3], skey[4], skey[5], skey[6], skey[7], skey[8], skey[9], skey[10], skey[11], skey[12], skey[13], skey[14], skey[15]); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; /* prepare the data used for this query */ req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.sm_key = 0; memset(&svc_rec, 0, sizeof(svc_rec)); memset(&user, 0, sizeof(user)); /* set the new service record fields */ memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memcpy(svc_rec.service_name, sr_name, (strlen(sr_name) + 1) * sizeof(char)); for (i = 0; i <= 15; i++) svc_rec.service_key[i] = skey[i]; req.p_query_input = &user; user.method = IB_MAD_METHOD_GET; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; user.comp_mask = IB_SR_COMPMASK_SNAME | IB_SR_COMPMASK_SKEY; user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0C: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; num_recs = context.result.result_cnt; if (status != IB_SUCCESS) { /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, then this is fine */ if (status == IB_REMOTE_ERROR) strncpy(mad_stat_err, ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw)), ERR_SIZE -1); else strncpy(mad_stat_err, ib_get_err_str(status), ERR_SIZE -1); mad_stat_err[ERR_SIZE -1] = '\0'; if (status == IB_REMOTE_ERROR && !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && rec_num == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); status = IB_SUCCESS; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0D: " "Query failed:%s (%s)\n", ib_get_err_str(status), mad_stat_err); goto Exit; } } if (rec_num && num_recs != rec_num) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Unmatched number of records: expected: %d, received: %d\n", rec_num, num_recs); status = IB_REMOTE_ERROR; goto Exit; } p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); *p_out_rec = *p_rec; if (num_recs) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Found service record: name: %s id: 0x%016" PRIx64 "\n", sr_name, cl_ntoh64(p_rec->service_id)); osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); } Exit: OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Expected and found %d records\n", rec_num); if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } ib_api_status_t osmt_get_service_by_name(IN osmtest_t * const p_osmt, IN char *sr_name, IN uint32_t rec_num, OUT ib_service_record_t * p_out_rec) { ib_api_status_t status = IB_SUCCESS; osmtest_req_context_t context; osmv_query_req_t req; ib_service_record_t *p_rec; ib_svc_name_t service_name; uint32_t num_recs = 0; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting service record: name: %s\n", sr_name); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; /* prepare the data used for this query */ req.query_type = OSMV_QUERY_SVC_REC_BY_NAME; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.sm_key = 0; memset(service_name, 0, sizeof(service_name)); memcpy(service_name, sr_name, (strlen(sr_name) + 1) * sizeof(char)); req.p_query_input = service_name; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0E: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; num_recs = context.result.result_cnt; if (status != IB_SUCCESS) { char mad_stat_err[256]; /* If the failure is due to IB_SA_MAD_STATUS_NO_RECORDS and rec_num is 0, then this is fine */ if (status == IB_REMOTE_ERROR) strcpy(mad_stat_err, ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); else strcpy(mad_stat_err, ib_get_err_str(status)); if (status == IB_REMOTE_ERROR && !strcmp(mad_stat_err, "IB_SA_MAD_STATUS_NO_RECORDS") && rec_num == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); status = IB_SUCCESS; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A0F: " "Query failed: %s (%s)\n", ib_get_err_str(status), mad_stat_err); goto Exit; } } if (rec_num && num_recs != rec_num) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A10: " "Unmatched number of records: expected: %d, received: %d\n", rec_num, num_recs); status = IB_REMOTE_ERROR; goto Exit; } p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, 0); *p_out_rec = *p_rec; if (num_recs) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Found service record: name: %s id: 0x%016" PRIx64 "\n", sr_name, cl_ntoh64(p_rec->service_id)); osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_DEBUG); } Exit: OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Expected and found %d records\n", rec_num); if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } #ifdef VENDOR_RMPP_SUPPORT ib_api_status_t osmt_get_all_services_and_check_names(IN osmtest_t * const p_osmt, IN ib_svc_name_t * const p_valid_service_names_arr, IN uint8_t num_of_valid_names, OUT uint32_t * num_services) { ib_api_status_t status = IB_SUCCESS; osmtest_req_context_t context; osmv_query_req_t req; ib_service_record_t *p_rec; uint32_t num_recs = 0, i, j; uint8_t *p_checked_names; OSM_LOG_ENTER(&p_osmt->log); /* Prepare tracker for the checked names */ p_checked_names = (uint8_t *) malloc(sizeof(uint8_t) * num_of_valid_names); for (j = 0; j < num_of_valid_names; j++) { p_checked_names[j] = 0; } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Getting all service records\n"); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; req.query_type = OSMV_QUERY_ALL_SVC_RECS; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A12: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { if (status != IB_INVALID_PARAMETER) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A13: " "ib_query failed (%s)\n", ib_get_err_str(status)); } if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_svc_rec(context.result.p_result_madw, i); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Found service record: name: %s id: 0x%016" PRIx64 "\n", p_rec->service_name, cl_ntoh64(p_rec->service_id)); osm_dump_service_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); for (j = 0; j < num_of_valid_names; j++) { /* If the service names exist in the record, mark it as checked (1) */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "-I- Comparing source name : >%s<, with record name : >%s<, idx : %d\n", p_valid_service_names_arr[j], p_rec->service_name, p_checked_names[j]); if (strcmp ((char *)p_valid_service_names_arr[j], (char *)p_rec->service_name) == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "-I- The service %s is valid\n", p_valid_service_names_arr[j]); p_checked_names[j] = 1; break; } } } /* Check that all service names have been identified */ for (j = 0; j < num_of_valid_names; j++) if (p_checked_names[j] == 0) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A14: " "Missing valid service: name: %s\n", p_valid_service_names_arr[j]); status = IB_ERROR; goto Exit; } *num_services = num_recs; Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return status; } #endif ib_api_status_t osmt_delete_service_by_name(IN osmtest_t * const p_osmt, IN uint8_t IsServiceExist, IN char *sr_name, IN uint32_t rec_num) { osmv_query_req_t req; osmv_user_query_t user; osmtest_req_context_t context; ib_service_record_t svc_rec; ib_api_status_t status; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Trying to Delete service name: %s\n", sr_name); memset(&svc_rec, 0, sizeof(svc_rec)); status = osmt_get_service_by_name(p_osmt, sr_name, rec_num, &svc_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A15: " "Failed to get service: name: %s\n", sr_name); goto ExitNoDel; } memset(&req, 0, sizeof(req)); memset(&context, 0, sizeof(context)); memset(&user, 0, sizeof(user)); /* set the new service record fields */ memset(svc_rec.service_name, 0, sizeof(svc_rec.service_name)); memcpy(svc_rec.service_name, sr_name, (strlen(sr_name) + 1) * sizeof(char)); /* prepare the data used for this query */ context.p_osmt = p_osmt; req.timeout_ms = p_osmt->opt.transaction_timeout; req.query_context = &context; req.query_type = OSMV_QUERY_USER_DEFINED; /* basically a don't care here */ req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.flags = OSM_SA_FLAGS_SYNC; req.sm_key = 0; user.method = IB_MAD_METHOD_DELETE; user.attr_id = IB_MAD_ATTR_SERVICE_RECORD; user.comp_mask = IB_SR_COMPMASK_SNAME; user.p_attr = &svc_rec; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A16: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (IsServiceExist) { /* If IsServiceExist = 1 then we should succeed here */ if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A17: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A18: Remote error = %s\n", ib_get_mad_status_str (osm_madw_get_mad_ptr (context.result.p_result_madw))); } } } else { /* If IsServiceExist = 0 then we should fail here */ if (status == IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A19: " "Succeeded to delete service: %s which " "shouldn't exist", sr_name); status = IB_ERROR; } else { /* The deletion should have failed, since the service_name shouldn't exist. */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "IS EXPECTED ERROR ^^^^\n"); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Failed to delete service_name: %s\n", sr_name); status = IB_SUCCESS; } } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } ExitNoDel: OSM_LOG_EXIT(&p_osmt->log); return status; } /* * Run a complete service records flow: * - register a service * - register a service (with a lease period) * - get a service by name * - get all services / must be 2 * - delete a service * - get all services / must be 1 * - wait for the lease to expire * - get all services / must be 0 * - get / set service by data */ ib_api_status_t osmt_run_service_records_flow(IN osmtest_t * const p_osmt) { ib_service_record_t srv_rec; ib_api_status_t status; uint8_t instance, i; uint8_t service_data8[16], service_key[16]; ib_net16_t service_data16[8]; ib_net32_t service_data32[4]; ib_net64_t service_data64[2]; uint64_t pid = getpid(); uint64_t id[7]; /* We use up to seven service names - we use the extra for bad flow */ ib_svc_name_t service_name[7]; #ifdef VENDOR_RMPP_SUPPORT /* This array contain only the valid names after registering vs SM */ ib_svc_name_t service_valid_names[3]; uint32_t num_recs = 0; #endif OSM_LOG_ENTER(&p_osmt->log); /* Init Service names */ for (i = 0; i < 7; i++) { #ifdef __WIN__ uint64_t rand_val = rand() - (uint64_t) i; #else uint64_t rand_val = random() - (uint64_t) i; #endif id[i] = abs((int)(pid - rand_val)); /* Just to be unique any place on any host */ sprintf((char *)(service_name[i]), "osmt.srvc.%" PRIu64 ".%" PRIu64, rand_val, pid); /*printf("-I- Service Name is : %s, ID is : 0x%" PRIx64 "\n",service_name[i],id[i]); */ } status = osmt_register_service(p_osmt, cl_ntoh64(id[0]), /* IN ib_net64_t service_id, */ IB_DEFAULT_PKEY, /* IN ib_net16_t service_pkey, */ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ 11, /* IN uint8_t service_key_lsb, */ (char *)service_name[0] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } status = osmt_register_service(p_osmt, cl_ntoh64(id[1]), /* IN ib_net64_t service_id, */ IB_DEFAULT_PKEY, /* IN ib_net16_t service_pkey, */ cl_hton32(0x00000004), /* IN ib_net32_t service_lease, */ 11, /* IN uint8_t service_key_lsb, */ (char *)service_name[1] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } status = osmt_register_service(p_osmt, cl_ntoh64(id[2]), /* IN ib_net64_t service_id, */ 0, /* IN ib_net16_t service_pkey, */ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ 11, /* Remove Service Record IN uint8_t service_key_lsb, */ (char *)service_name[2] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } /* Generate 2 instances of service record with consecutive data */ for (instance = 0; instance < 2; instance++) { /* First, clear all arrays */ memset(service_data8, 0, 16 * sizeof(uint8_t)); memset(service_data16, 0, 8 * sizeof(uint16_t)); memset(service_data32, 0, 4 * sizeof(uint32_t)); memset(service_data64, 0, 2 * sizeof(uint64_t)); service_data8[instance] = instance + 1; service_data16[instance] = cl_hton16(instance + 2); service_data32[instance] = cl_hton32(instance + 3); service_data64[instance] = cl_hton64(instance + 4); status = osmt_register_service_with_data(p_osmt, cl_ntoh64(id[3]), /* IN ib_net64_t service_id, */ IB_DEFAULT_PKEY, /* IN ib_net16_t service_pkey, */ cl_ntoh32(10), /* IN ib_net32_t service_lease, */ 12, /* IN uint8_t service_key_lsb, */ service_data8, service_data16, service_data32, service_data64, /* service data structures */ (char *)service_name[3] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } } /* Trying to create service with zero key */ memset(service_key, 0, 16 * sizeof(uint8_t)); status = osmt_register_service_with_full_key(p_osmt, cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */ 0, /* IN ib_net16_t service_pkey, */ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ service_key, /* full service_key, */ (char *)service_name[5] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } /* Now update it with Unique key and different service name */ for (i = 0; i <= 15; i++) { service_key[i] = i + 1; } status = osmt_register_service_with_full_key(p_osmt, cl_ntoh64(id[5]), /* IN ib_net64_t service_id, */ 0, /* IN ib_net16_t service_pkey, */ 0xFFFFFFFF, /* IN ib_net32_t service_lease, */ service_key, /* full service_key, */ (char *)service_name[6] /* IN char *service_name */ ); if (status != IB_SUCCESS) { goto Exit; } /* Let OpenSM handle it */ usleep(100); /* Make sure service_name[0] exists */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[0], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1A: " "Fail to find service: name: %s\n", (char *)service_name[0]); status = IB_ERROR; goto Exit; } /* Make sure service_name[1] exists */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[1], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1B: " "Fail to find service: name: %s\n", (char *)service_name[1]); status = IB_ERROR; goto Exit; } /* Make sure service_name[2] exists */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[2], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1C: " "Fail to find service: name: %s\n", (char *)service_name[2]); status = IB_ERROR; goto Exit; } /* Make sure service_name[3] exists. */ /* After 10 seconds the service should not exist: service_lease = 10 */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[3], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1D: " "Fail to find service: name: %s\n", (char *)service_name[3]); status = IB_ERROR; goto Exit; } sleep(10); status = osmt_get_service_by_name(p_osmt, (char *)service_name[3], 0, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1E: " "Found service: name: %s that should have been " "deleted due to service lease expiring\n", (char *)service_name[3]); status = IB_ERROR; goto Exit; } /* Check that for service: id[5] only one record exists */ status = osmt_get_service_by_id(p_osmt, 1, cl_ntoh64(id[5]), &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A1F: " "Found number of records != 1 for " "service: id: 0x%016" PRIx64 "\n", id[5]); status = IB_ERROR; goto Exit; } /* Bad Flow of Get with invalid Service ID: id[6] */ status = osmt_get_service_by_id(p_osmt, 0, cl_ntoh64(id[6]), &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A20: " "Found service: id: 0x%016" PRIx64 " " "that is invalid\n", id[6]); status = IB_ERROR; goto Exit; } /* Check by both id and service name: id[0], service_name[0] */ status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[0]), (char *)service_name[0], &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A21: " "Fail to find service: id: 0x%016" PRIx64 " " "name: %s\n", id[0], (char *)service_name[0]); status = IB_ERROR; goto Exit; } /* Check by both id and service name: id[5], service_name[6] */ status = osmt_get_service_by_id_and_name(p_osmt, 1, cl_ntoh64(id[5]), (char *)service_name[6], &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A22: " "Fail to find service: id: 0x%016" PRIx64 " " "name: %s\n", id[5], (char *)service_name[6]); status = IB_ERROR; goto Exit; } /* Bad Flow of Get with invalid name(service_name[3]) and valid ID(id[0]) */ status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[0]), (char *)service_name[3], &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A23: " "Found service: id: 0x%016" PRIx64 "name: %s which is an invalid service\n", id[0], (char *)service_name[3]); status = IB_ERROR; goto Exit; } /* Bad Flow of Get with unmatched name(service_name[5]) and id(id[3]) (both valid) */ status = osmt_get_service_by_id_and_name(p_osmt, 0, cl_ntoh64(id[3]), (char *)service_name[5], &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A24: " "Found service: id: 0x%016" PRIx64 "name: %s which is an invalid service\n", id[3], (char *)service_name[5]); status = IB_ERROR; goto Exit; } /* Bad Flow of Get with service name that doesn't exist (service_name[4]) */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[4], 0, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A25: " "Found service: name: %s that shouldn't exist\n", (char *)service_name[4]); status = IB_ERROR; goto Exit; } /* Bad Flow : Check that getting service_name[5] brings no records since another service has been updated with the same ID (service_name[6] */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[5], 0, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A26: " "Found service: name: %s which is an " "invalid service\n", (char *)service_name[5]); status = IB_ERROR; goto Exit; } /* Check that getting service_name[6] by name ONLY is valid, since we do not support key&name association, also trusted queries */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[6], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A27: " "Fail to find service: name: %s\n", (char *)service_name[6]); status = IB_ERROR; goto Exit; } /* Test Service Key */ memset(service_key, 0, 16 * sizeof(uint8_t)); /* Check for service_name[5] with service_key=0 - the service shouldn't exist with this name. */ status = osmt_get_service_by_name_and_key(p_osmt, (char *)service_name[5], 0, service_key, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A28: " "Found service: name: %s key:0 which is an " "invalid service (wrong name)\n", (char *)service_name[5]); status = IB_ERROR; goto Exit; } /* Check for service_name[6] with service_key=0 - the service should exist with different key. */ status = osmt_get_service_by_name_and_key(p_osmt, (char *)service_name[6], 0, service_key, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A29: " "Found service: name: %s key: 0 which is an " "invalid service (wrong service_key)\n", (char *)service_name[6]); status = IB_ERROR; goto Exit; } /* check for service_name[6] with the correct service_key */ for (i = 0; i <= 15; i++) service_key[i] = i + 1; status = osmt_get_service_by_name_and_key(p_osmt, (char *)service_name[6], 1, service_key, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2A: " "Fail to find service: name: %s with " "correct service key\n", (char *)service_name[6]); status = IB_ERROR; goto Exit; } #ifdef VENDOR_RMPP_SUPPORT /* These ar the only service_names which are valid */ memcpy(&service_valid_names[0], &service_name[0], sizeof(uint8_t) * 64); memcpy(&service_valid_names[1], &service_name[2], sizeof(uint8_t) * 64); memcpy(&service_valid_names[2], &service_name[6], sizeof(uint8_t) * 64); status = osmt_get_all_services_and_check_names(p_osmt, service_valid_names, 3, &num_recs); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2B: " "Fail to find all services that should exist\n"); status = IB_ERROR; goto Exit; } #endif /* Delete service_name[0] */ status = osmt_delete_service_by_name(p_osmt, 1, (char *)service_name[0], 1); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2C: " "Fail to delete service: name: %s\n", (char *)service_name[0]); status = IB_ERROR; goto Exit; } /* Make sure deletion of service_name[0] succeeded */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[0], 0, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2D: " "Found service: name: %s that was deleted\n", (char *)service_name[0]); status = IB_ERROR; goto Exit; } /* Make sure service_name[1] doesn't exist (expired service lease) */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[1], 0, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2E: " "Found service: name: %s that should have expired\n", (char *)service_name[1]); status = IB_ERROR; goto Exit; } /* Make sure service_name[2] exists */ status = osmt_get_service_by_name(p_osmt, (char *)service_name[2], 1, &srv_rec); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A2F: " "Fail to find service: name: %s\n", (char *)service_name[2]); status = IB_ERROR; goto Exit; } /* Bad Flow - try to delete non-existent service_name[5] */ status = osmt_delete_service_by_name(p_osmt, 0, (char *)service_name[5], 0); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A30: " "Succeed to delete non-existent service: name: %s\n", (char *)service_name[5]); status = IB_ERROR; goto Exit; } /* Delete service_name[2] */ status = osmt_delete_service_by_name(p_osmt, 1, (char *)service_name[2], 1); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A31: " "Fail to delete service: name: %s\n", (char *)service_name[2]); status = IB_ERROR; goto Exit; } /* Delete service_name[6] */ status = osmt_delete_service_by_name(p_osmt, 1, (char *)service_name[6], 1); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 4A32: " "Failed to delete service name: %s\n", (char *)service_name[6]); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(&p_osmt->log); return status; } opensm-3.3.20/osmtest/osmt_slvl_vl_arb.c0000644000205000001450000003440212352076501015225 00000000000000/* * Copyright (c) 2006-2008 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 SLtoVL and VL Arbitration testing flow.. * Top level is osmt_run_slvl_and_vlarb_records_flow: * osmt_query_all_ports_vl_arb * osmt_query_all_ports_slvl_map * */ #ifndef __WIN__ #include #endif #include #include #include #include #include "osmtest.h" static ib_api_status_t osmtest_write_vl_arb_table(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_vl_arb_table_record_t * const p_rec) { int i; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); fprintf(fh, "VL_ARBITRATION_TABLE\n" "lid 0x%X\n" "port_num 0x%X\n" "block 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->port_num, p_rec->block_num); fprintf(fh, " "); for (i = 0; i < 32; i++) fprintf(fh, "| %-2u ", i); fprintf(fh, "|\nVL: "); for (i = 0; i < 32; i++) fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].vl); fprintf(fh, "|\nWEIGHT:"); for (i = 0; i < 32; i++) fprintf(fh, "|0x%02X", p_rec->vl_arb_tbl.vl_entry[i].weight); fprintf(fh, "|\nEND\n\n"); /* Exit: */ OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER **********************************************************************/ ib_api_status_t osmt_query_vl_arb(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN uint8_t const port_num, IN uint8_t const block_num, IN FILE * fh) { osmtest_req_context_t context; ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_vl_arb_table_record_t record, *p_rec; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting VL_Arbitration Table for port with LID 0x%X Num:0x%X\n", cl_ntoh16(lid), port_num); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; record.lid = lid; record.port_num = port_num; record.block_num = block_num; user.p_attr = &record; req.query_type = OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0405: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0466: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } /* ok it worked */ p_rec = osmv_get_query_result(context.result.p_result_madw, 0); if (fh) { osmtest_write_vl_arb_table(p_osmt, fh, p_rec); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmt_query_all_ports_vl_arb(IN osmtest_t * const p_osmt, IN FILE * fh) { cl_status_t status = CL_SUCCESS; cl_qmap_t *p_tbl; port_t *p_src_port; uint8_t block, anyErr = 0; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Obtaining ALL Ports VL Arbitration Tables\n"); /* * Go over all ports that exist in the subnet * get the relevant VLarbs */ p_tbl = &p_osmt->exp_subn.port_key_tbl; p_src_port = (port_t *) cl_qmap_head(p_tbl); while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) { /* HACK we use capability_mask to know diff a CA port from switch port */ if (p_src_port->rec.port_info.capability_mask) { /* this is an hca port */ for (block = 1; block <= 4; block++) { /* NOTE to comply we must set port number to 0 and the SA should figure it out */ /* since it is a CA port */ status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, 0, block, fh); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0467: " "Failed to get Lid:0x%X Port:0x%X (%s)\n", cl_ntoh16(p_src_port->rec.lid), 0, ib_get_err_str(status)); anyErr = 1; } } } else { /* this is a switch port */ for (block = 1; block <= 4; block++) { status = osmt_query_vl_arb(p_osmt, p_src_port->rec.lid, p_src_port->rec.port_num, block, fh); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0468: " "Failed to get Lid:0x%X Port:0x%X (%s)\n", cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, ib_get_err_str(status)); anyErr = 1; } } } p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item); } OSM_LOG_EXIT(&p_osmt->log); if (anyErr) { status = IB_ERROR; } return (status); } /******************************************************************************* SLtoVL *******************************************************************************/ static ib_api_status_t osmtest_write_slvl_map_table(IN osmtest_t * const p_osmt, IN FILE * fh, IN const ib_slvl_table_record_t * const p_rec) { int i; cl_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); fprintf(fh, "SLtoVL_MAP_TABLE\n" "lid 0x%X\n" "in_port_num 0x%X\n" "out_port_num 0x%X\n", cl_ntoh16(p_rec->lid), p_rec->in_port_num, p_rec->out_port_num); fprintf(fh, "SL:"); for (i = 0; i < 16; i++) fprintf(fh, "| %-2u ", i); fprintf(fh, "|\nVL:"); for (i = 0; i < 16; i++) fprintf(fh, "| 0x%01X ", ib_slvl_table_get(&p_rec->slvl_tbl, (uint8_t) i)); fprintf(fh, "|\nEND\n\n"); /* Exit: */ OSM_LOG_EXIT(&p_osmt->log); return (status); } /********************************************************************** * GET A SINGLE PORT INFO BY NODE LID AND PORT NUMBER **********************************************************************/ ib_api_status_t osmt_query_slvl_map(IN osmtest_t * const p_osmt, IN ib_net16_t const lid, IN uint8_t const out_port_num, IN uint8_t const in_port_num, IN FILE * fh) { osmtest_req_context_t context; ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; ib_slvl_table_record_t record, *p_rec; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Getting SLtoVL Map Table for out-port with LID 0x%X Num:0x%X from In-Port:0x%X\n", cl_ntoh16(lid), out_port_num, in_port_num); /* * Do a blocking query for this record in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&context, 0, sizeof(context)); context.p_osmt = p_osmt; record.lid = lid; record.in_port_num = in_port_num; record.out_port_num = out_port_num; user.p_attr = &record; req.query_type = OSMV_QUERY_SLVL_BY_LID_AND_PORTS; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; req.sm_key = 0; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0469: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0470: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } goto Exit; } /* ok it worked */ p_rec = osmv_get_query_result(context.result.p_result_madw, 0); if (fh) { osmtest_write_slvl_map_table(p_osmt, fh, p_rec); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } static ib_api_status_t osmt_query_all_ports_slvl_map(IN osmtest_t * const p_osmt, IN FILE * fh) { cl_status_t status = CL_SUCCESS; cl_qmap_t *p_tbl; port_t *p_src_port; uint8_t in_port, anyErr = 0, num_ports; node_t *p_node; const cl_qmap_t *p_node_tbl; OSM_LOG_ENTER(&p_osmt->log); /* * Go over all ports that exist in the subnet * get the relevant SLtoVLs */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Obtaining ALL Ports (to other ports) SLtoVL Maps\n"); p_tbl = &p_osmt->exp_subn.port_key_tbl; p_node_tbl = &p_osmt->exp_subn.node_lid_tbl; p_src_port = (port_t *) cl_qmap_head(p_tbl); while (p_src_port != (port_t *) cl_qmap_end(p_tbl)) { /* HACK we use capability_mask to know diff a CA port from switch port */ if (p_src_port->rec.port_info.capability_mask) { /* this is an hca port */ /* NOTE to comply we must set port number to 0 and the SA should figure it out */ /* since it is a CA port */ status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, 0, 0, fh); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0471: " "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X(%s)\n", cl_ntoh16(p_src_port->rec.lid), 0, 0, ib_get_err_str(status)); anyErr = 1; } } else { /* this is a switch port */ /* get the node */ p_node = (node_t *) cl_qmap_get(p_node_tbl, p_src_port->rec.lid); if (p_node == (node_t *) cl_qmap_end(p_node_tbl)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0472: " "Failed to get Node by Lid:0x%X\n", p_src_port->rec.lid); goto Exit; } num_ports = p_node->rec.node_info.num_ports; for (in_port = 1; in_port <= num_ports; in_port++) { status = osmt_query_slvl_map(p_osmt, p_src_port->rec.lid, p_src_port->rec. port_num, in_port, fh); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0473: " "Failed to get Lid:0x%X In-Port:0x%X Out-Port:0x%X (%s)\n", cl_ntoh16(p_src_port->rec.lid), p_src_port->rec.port_num, in_port, ib_get_err_str(status)); anyErr = 1; } } } p_src_port = (port_t *) cl_qmap_next(&p_src_port->map_item); } Exit: OSM_LOG_EXIT(&p_osmt->log); if (anyErr) { status = IB_ERROR; } return (status); } /* * Run a vl arbitration queries and sl2vl maps queries flow: * Good flow: * - for each physical port on the network - obtain the VL Arb * - for each CA physical port obtain its SLtoVL Map * - for each SW physical port (out) obtain the SLtoVL Map to each other port * BAD flow: * - Try get with multiple results * - Try gettable * - Try providing non existing port */ ib_api_status_t osmt_run_slvl_and_vlarb_records_flow(IN osmtest_t * const p_osmt) { ib_api_status_t status; FILE *fh; ib_net16_t test_lid; uint8_t lmc; OSM_LOG_ENTER(&p_osmt->log); fh = fopen("qos.txt", "w"); if (!fh) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0474: " "Failed to open file qos.txt for writing\n"); status = IB_ERROR; goto Exit; } /* go over all ports in the subnet */ status = osmt_query_all_ports_vl_arb(p_osmt, fh); if (status != IB_SUCCESS) { goto Exit; } status = osmt_query_all_ports_slvl_map(p_osmt, fh); if (status != IB_SUCCESS) { goto Exit; } /* If LMC > 0, test non base LID SA QoS Record requests */ status = osmtest_get_local_port_lmc(p_osmt, p_osmt->local_port.lid, &lmc); if (status != IB_SUCCESS) goto Exit; if (lmc != 0) { test_lid = cl_ntoh16(p_osmt->local_port.lid + 1); status = osmt_query_vl_arb(p_osmt, test_lid, 0, 1, NULL); if (status != IB_SUCCESS) goto Exit; status = osmt_query_slvl_map(p_osmt, test_lid, 0, 0, NULL); if (status != IB_SUCCESS) goto Exit; } Exit: if (fh) fclose(fh); OSM_LOG_EXIT(&p_osmt->log); return status; } opensm-3.3.20/osmtest/osmt_multicast.c0000644000205000001450000027634512726323024014743 00000000000000/* * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved. * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. * Copyright (c) 2010 HNR Consulting. 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 Multicast Member testing flow.. * */ #ifndef __WIN__ #include #endif #include #include #include #include #include #include #include #include "osmtest.h" static void __osmt_print_all_multicast_records(IN osmtest_t * const p_osmt) { uint32_t i; ib_api_status_t status; osmv_query_req_t req; osmv_user_query_t user; osmtest_req_context_t context; ib_member_rec_t *mcast_record; memset(&context, 0, sizeof(context)); memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = 1; req.flags = OSM_SA_FLAGS_SYNC; context.p_osmt = p_osmt; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } /* UnTrusted (SMKey of 0) - get the multicast groups */ status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B5: " "Failed getting the multicast groups records - %s/%s\n", ib_get_err_str(status), ib_get_err_str(context.result.status)); return; } osm_log(&p_osmt->log, OSM_LOG_INFO, "\n |------------------------------------------|" "\n | Remaining Multicast Groups |" "\n |------------------------------------------|\n"); for (i = 0; i < context.result.result_cnt; i++) { mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i); osm_dump_mc_record(&p_osmt->log, mcast_record, OSM_LOG_INFO); } /* Trusted - now get the multicast group members */ req.sm_key = OSM_DEFAULT_SM_KEY; status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS || context.result.status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B6: " "Failed getting the multicast group members records - %s/%s\n", ib_get_err_str(status), ib_get_err_str(context.result.status)); return; } osm_log(&p_osmt->log, OSM_LOG_INFO, "\n |--------------------------------------------------|" "\n | Remaining Multicast Group Members |" "\n |--------------------------------------------------|\n"); for (i = 0; i < context.result.result_cnt; i++) { mcast_record = osmv_get_query_mc_rec(context.result.p_result_madw, i); osm_dump_mc_record(&p_osmt->log, mcast_record, OSM_LOG_INFO); } } static cl_status_t __match_mgids(IN const void *const p_object, IN void *context) { ib_gid_t *p_mgid_context = (ib_gid_t *) context; ib_gid_t *p_mgid_list_item = (ib_gid_t *) p_object; int32_t count; count = memcmp(p_mgid_context, p_mgid_list_item, sizeof(ib_gid_t)); if (count == 0) return CL_SUCCESS; else return CL_NOT_FOUND; } ib_api_status_t osmt_query_mcast(IN osmtest_t * const p_osmt) { ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; osmtest_req_context_t context; ib_member_rec_t *p_rec; uint32_t i, num_recs = 0; cl_list_t mgids_list; cl_list_t *p_mgids_list; cl_list_iterator_t p_mgids_res; cl_status_t cl_status; cl_map_item_t *p_item, *p_next_item; osmtest_mgrp_t *p_mgrp; OSM_LOG_ENTER(&p_osmt->log); /* * Do a blocking query for all Multicast Records in the subnet. * The result is returned in the result field of the caller's * context structure. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); context.p_osmt = p_osmt; user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; req.query_type = OSMV_QUERY_USER_DEFINED; req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0203: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0264: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s.\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); goto Exit; } /* ok we have got something */ /* First Delete the old MGID Table */ p_next_item = cl_qmap_head(&p_osmt->exp_subn.mgrp_mlid_tbl); while (p_next_item != cl_qmap_end(&p_osmt->exp_subn.mgrp_mlid_tbl)) { p_item = p_next_item; p_next_item = cl_qmap_next(p_item); cl_qmap_remove_item(&p_osmt->exp_subn.mgrp_mlid_tbl, p_item); free(p_item); } cl_list_construct(&mgids_list); cl_list_init(&mgids_list, num_recs); p_mgids_list = &mgids_list; num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_result(context.result.p_result_madw, i); p_mgids_res = cl_list_find_from_head(p_mgids_list, __match_mgids, &(p_rec->mgid)); /* If returns iterator other than end of list, same mgid exists already */ if (p_mgids_res != cl_list_end(p_mgids_list)) { char gid_str[INET6_ADDRSTRLEN]; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0265: " "MCG MGIDs are the same - invalid MGID : %s\n", inet_ntop(AF_INET6, p_rec->mgid.raw, gid_str, sizeof gid_str)); status = IB_ERROR; goto Exit; } osm_dump_mc_record(&p_osmt->log, p_rec, OSM_LOG_VERBOSE); cl_status = cl_list_insert_head(p_mgids_list, &(p_rec->mgid)); if (cl_status) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0205: " "Could not add MGID to cl_list\n"); status = IB_ERROR; goto Exit; } p_mgrp = (osmtest_mgrp_t *) malloc(sizeof(*p_mgrp)); if (!p_mgrp) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0204: " "Could not allocate new MCG\n"); status = IB_ERROR; goto Exit; } memcpy(&p_mgrp->mcmember_rec, p_rec, sizeof(p_mgrp->mcmember_rec)); cl_qmap_insert(&p_osmt->exp_subn.mgrp_mlid_tbl, cl_ntoh16(p_rec->mlid), &p_mgrp->map_item); } Exit: if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } /* given a multicast request send and wait for response. */ ib_api_status_t osmt_send_mcast_request(IN osmtest_t * const p_osmt, IN uint8_t is_set, IN ib_member_rec_t * p_mc_req, IN uint64_t comp_mask, OUT ib_sa_mad_t * p_res) { osmtest_req_context_t context; ib_api_status_t status = IB_SUCCESS; osmv_user_query_t user; osmv_query_req_t req; OSM_LOG_ENTER(&p_osmt->log); /* * Do a blocking query for this record in the subnet. * * The query structures are locals. */ memset(&req, 0, sizeof(req)); memset(&user, 0, sizeof(user)); memset(&context, 0, sizeof(context)); memset(p_res, 0, sizeof(ib_sa_mad_t)); context.p_osmt = p_osmt; user.p_attr = p_mc_req; user.comp_mask = comp_mask; if (is_set == 1) req.query_type = OSMV_QUERY_UD_MULTICAST_SET; else if (is_set == 0) req.query_type = OSMV_QUERY_UD_MULTICAST_DELETE; else if (is_set == 0xee) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Set USER DEFINED QUERY\n"); req.query_type = OSMV_QUERY_USER_DEFINED; user.method = IB_MAD_METHOD_GET; user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; } else if (is_set == 0xff) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Set USER DEFINED QUERY\n"); req.query_type = OSMV_QUERY_USER_DEFINED; user.method = IB_MAD_METHOD_SET; user.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD; } /* TODO : Check the validity of all user fields in order to use OSMV_QUERY_USER_DEFINED p_user_query = ( osmv_user_query_t * ) p_query_req->p_query_input; if (p_user_query->method) sa_mad_data.method = p_user_query->method; sa_mad_data.attr_offset = p_user_query->attr_offset; sa_mad_data.attr_id = p_user_query->attr_id; sa_mad_data.comp_mask = p_user_query->comp_mask; sa_mad_data.p_attr = p_user_query->p_attr; */ req.timeout_ms = p_osmt->opt.transaction_timeout; req.retry_cnt = p_osmt->opt.retry_count; req.flags = OSM_SA_FLAGS_SYNC; req.query_context = &context; req.pfn_query_cb = osmtest_query_res_cb; req.p_query_input = &user; if (p_osmt->opt.with_grh) { req.with_grh = 1; memcpy(&req.gid, &p_osmt->sm_port_gid, 16); } status = osmv_query_sa(p_osmt->h_bind, &req); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0206: " "ib_query failed (%s)\n", ib_get_err_str(status)); goto Exit; } /* ok it worked */ memcpy(p_res, osm_madw_get_mad_ptr(context.result.p_result_madw), sizeof(ib_sa_mad_t)); status = context.result.status; if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0224: " "ib_query failed (%s)\n", ib_get_err_str(status)); if (status == IB_REMOTE_ERROR) OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str(osm_madw_get_mad_ptr (context.result. p_result_madw))); } Exit: /* * Return the IB query MAD to the pool as necessary. */ if (context.result.p_result_madw != NULL) { osm_mad_pool_put(&p_osmt->mad_pool, context.result.p_result_madw); context.result.p_result_madw = NULL; } OSM_LOG_EXIT(&p_osmt->log); return (status); } void osmt_init_mc_query_rec(IN osmtest_t * const p_osmt, IN OUT ib_member_rec_t * p_mc_req) { /* use default values so we can change only what we want later */ memset(p_mc_req, 0, sizeof(ib_member_rec_t)); /* we leave the MGID to the user */ memcpy(&p_mc_req->port_gid.unicast.interface_id, &p_osmt->local_port.port_guid, sizeof(p_osmt->local_port.port_guid)); /* use our own subnet prefix: */ p_mc_req->port_gid.unicast.prefix = cl_hton64(p_osmt->local_port_gid.unicast.prefix); /* ib_net32_t qkey; */ /* ib_net16_t mlid; - we keep it zero for upper level to decide. */ /* uint8_t mtu; - keep it zero means - anything you have please. */ /* uint8_t tclass; can leave as zero for now (between subnets) */ /* ib_net16_t pkey; leave as zero */ p_mc_req->rate = IB_PATH_RECORD_RATE_2_5_GBS; /* uint8_t pkt_life; zero means greater than zero ... */ /* ib_net32_t sl_flow_hop; keep it all zeros */ /* we want to use a link local scope: 0x02 */ p_mc_req->scope_state = ib_member_set_scope_state(0x02, 0); } /*********************************************************************** * UD Multicast testing flow: * o15.0.1.3: * - Request new MCG with not enough components in comp_mask : * ERR_INSUFFICIENT_COMPONENTS * o15.0.1.8: * - Request a join with irrelevant RATE and get a ERR_INVALID_REQ * o15.0.1.4: * - Create an MGID by asking for a join with MGID = 0 * providing P_Key, Q_Key, SL, FlowLabel, Tclass. * o15.0.1.5: * - Check the returned MGID is valid. (p 804) * o15.0.1.6: * - Create a new MCG with valid requested MGID. * - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID * - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) * - Try to create again the already created group: ERR_REQ_INVALID * o15.0.1.7 - implicitly checked during the prev steps. * o15.0.1.9 * - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID * o15.0.1.10 - can't check on a single client . * o15.0.1.11: * - Try to join into a MGID that exists with JoinState=SendOnlyMember - * see that it updates JoinState. What is the routing change? * - We can not check simple join since we have only one tester (for now) * o15.0.1.12: * - The last join should have a special treatment in the SA (sender only) * but what is it ? * o15.0.1.13: * - Try joining with wrong rate - ERR_REQ_INVALID * o15.0.1.14: * - Try partial delete - actually updating the join state. check it. * - Register by InformInfo flow to receive trap 67 on MCG delete. * - Try full delete (JoinState and should be 0) * - Wait for trap 67. * - Try joining (not full mem) again to see the group was deleted. * (should fail - o15.0.1.13) * o15.0.1.15: * - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID * o15.0.1.16: * - Try GetTable with PortGUID wildcarded and get back some groups. ***********************************************************************/ #define PREFIX_MASK CL_HTON64(0xff10ffff00000000ULL) #define PREFIX_SIGNATURE CL_HTON64(0xff10601b00000000ULL) #define IPV4_PREFIX_MASK CL_HTON64(0xff10ffff00000000ULL) #define PREFIX_SIGNATURE_IPV4 CL_HTON64(0xff10401b00000000ULL) static unsigned is_ipv4_mgid(ib_gid_t * mgid) { return ((mgid->unicast.prefix & IPV4_PREFIX_MASK) == PREFIX_SIGNATURE_IPV4); } static unsigned is_ipv6_mgid(ib_gid_t * mgid) { return ((mgid->unicast.prefix & PREFIX_MASK) == PREFIX_SIGNATURE); } /* The following macro can be used only within the osmt_run_mcast_flow() function */ #define IS_IPOIB_MGID(p_mgid) (is_ipv4_mgid(p_mgid) || is_ipv6_mgid(p_mgid)) ib_api_status_t osmt_run_mcast_flow(IN osmtest_t * const p_osmt) { char gid_str[INET6_ADDRSTRLEN]; char gid_str2[INET6_ADDRSTRLEN]; ib_api_status_t status; ib_member_rec_t mc_req_rec; union { ib_sa_mad_t sa_mad; ib_member_rec_t mcmr; } res; ib_sa_mad_t *sa_mad; ib_member_rec_t *p_mc_res; uint64_t comp_mask = 0; ib_net64_t remote_port_guid = 0x0; cl_qmap_t *p_mgrp_mlid_tbl; osmtest_mgrp_t *p_mgrp; ib_gid_t special_mgid, tmp_mgid, proxy_mgid; ib_net16_t invalid_mlid = 0x0; ib_net16_t max_mlid = cl_hton16(0xFFFE), tmp_mlid; int start_cnt = 0, cnt, middle_cnt = 0, end_cnt = 0; int start_ipoib_cnt = 0, end_ipoib_cnt = 0; int mcg_outside_test_cnt = 0, fail_to_delete_mcg = 0; osmtest_req_context_t context; ib_node_record_t *p_rec; uint32_t num_recs = 0, i; uint8_t mtu_phys = 0, rate_phys = 0; cl_map_t test_created_mlids; /* List of all mlids created in this test */ boolean_t got_error = FALSE; static ib_gid_t good_mgid = { { 0xFF, 0x12, 0xA0, 0x1C, 0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78} }; static ib_gid_t osm_ipoib_mgid = { { 0xff, /* multicast field */ 0x12, /* scope */ 0x40, 0x1b, /* IPv4 signature */ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ 0xff, 0xff, 0xff, 0xee, /* 32 bit IPv4 broadcast address */ }, }; #if 0 static ib_gid_t osm_ts_ipoib_good_mgid = { { 0xff, /* multicast field */ 0x12, /* non-permanent bit,scope */ 0x40, 0x1b, /* IPv4 signature */ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */ }, }; #endif static ib_gid_t osm_ipoib_good_mgid = { { 0xff, /* multicast field */ 0x12, /* non-permanent bit,scope */ 0x40, 0x1b, /* IPv4 signature */ 0xff, 0xff, /* 16 bits of P_Key (to be filled in) */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 bits of zeros */ 0xff, 0xff, 0xff, 0xff, /* 32 bit IPv4 broadcast address */ }, }; static ib_gid_t osm_link_local_mgid = { { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, }; OSM_LOG_ENTER(&p_osmt->log); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "GetTable of all current MCGs...\n"); status = osmt_query_mcast(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02FF " "GetTable of all records has failed!\n"); goto Exit; } /* Initialize the test_created_mgrps map */ cl_map_construct(&test_created_mlids); cl_map_init(&test_created_mlids, 1000); p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; osmt_init_mc_query_rec(p_osmt, &mc_req_rec); sa_mad = &res.sa_mad; p_mc_res = ib_sa_mad_get_payload_ptr(sa_mad); /* Only when we are on single mode check flow - do the count comparison, otherwise skip */ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) { start_cnt = cl_qmap_count(p_mgrp_mlid_tbl); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "(start): " "Number of MC Records found in SA DB is %d\n", start_cnt); } /* This flow is being added due to bug discovered using SilverStorm stack - The bug was initializing MCast with MTU & RATE min values that do not match the subnet capability, even though that OpenSM reponds with the correct value it does not store it in the MCG. We want the check a join request to already existing group (ipoib) without using MTU or RATE then getting response from OpenSM with the correct values then join again with them and get IB_SUCCESS all the way */ /* First validate IPoIB exist in the SA DB */ p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl); /* scan all available multicast groups in the DB and fill in the table */ while (p_mgrp != (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) { /* search for ipoib mgid */ if (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) start_ipoib_cnt++; else { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Non-IPoIB MC Groups exist: mgid=%s\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str)); mcg_outside_test_cnt++; } p_mgrp = (osmtest_mgrp_t *) cl_qmap_next(&p_mgrp->map_item); } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Found %d non-IPoIB MC Groups\n", mcg_outside_test_cnt); if (start_ipoib_cnt) { /* o15-0.2.4 - Check a join request to already created MCG */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Found IPoIB MC Group, so we run SilverStorm Bug Flow...\n"); /* Try to join first like IPoIB of SilverStorm */ memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid, sizeof(ib_gid_t)); /* Request Join */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE; status = osmt_send_mcast_request(p_osmt, 0xff, /* User Defined query Set */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Joining an existing IPoIB multicast group\n"); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Sent Join request with :\n\t\tport_gid=%s, mgid=%s\n" "\t\tjoin state= 0x%x, response is : %s\n", inet_ntop(AF_INET6, mc_req_rec.port_gid.raw, gid_str, sizeof gid_str), inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str2, sizeof gid_str2), (mc_req_rec.scope_state & 0x0F), ib_get_err_str(status)); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B3: " "Failed joining existing IPoIB MCGroup - got %s\n", ib_get_err_str(status)); goto Exit; } /* Check MTU & Rate Value and resend with SA suggested values */ /* Prepare the mc_req_rec for the rest of the flow */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* We simulate the same situation as in SilverStorm - a response with the exact RATE & MTU as the SA responded with. Actually the query has included some more fields but we know that problem was genereated by the RATE */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Received attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n", p_mc_res->mtu, p_mc_res->rate); mc_req_rec.mtu = p_mc_res->mtu; mc_req_rec.rate = p_mc_res->rate; /* Set feasible mtu & rate that will allow check the exact statement of OpenSM */ mtu_phys = p_mc_res->mtu; rate_phys = p_mc_res->rate; memcpy(&mc_req_rec.mgid, &osm_ipoib_good_mgid, sizeof(ib_gid_t)); /* Request Join */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Sending attributes of MCG : \n\t\tMTU=0x%02X, RATE=0x%02X\n", mc_req_rec.mtu, mc_req_rec.rate); status = osmt_send_mcast_request(p_osmt, 0xff, /* User Defined query */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Sent Join request using response values, response is : %s\n", ib_get_err_str(status)); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EF: " "Query as Full Member of already existing " "ipoib group gid %s has failed\n", inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str, sizeof gid_str)); goto Exit; } /* We do not want to leave the MCG since its IPoIB */ } /**************************************************************************/ /* Check Get with invalid mlid */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Get with invalid mlid...\n"); /* Request Get */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); mc_req_rec.mlid = invalid_mlid; comp_mask = IB_MCR_COMPMASK_MLID; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 0xee, /* User Defined query Get */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E0 " "SubnAdmGet with invalid mlid 0x%x succeeded\n", cl_ntoh16(mc_req_rec.mlid)); status = IB_ERROR; goto Exit; } /* Prepare the mc_req_rec for the rest of the flow */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /**************************************************************************/ /* Check Get with invalid port guid */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Get with invalid port guid (0x0) but valid interface ID : 0x%" PRIx64 "...\n", cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id)); /* Request Get */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); memset(&mc_req_rec.port_gid.unicast.interface_id, 0, sizeof(ib_net64_t)); comp_mask = IB_MCR_COMPMASK_GID; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 0xee, /* User Defined query Get */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E4 " "SubnAdmGet with invalid port guid succeeded\n"); status = IB_ERROR; goto Exit; } /* Prepare the mc_req_rec for the rest of the flow */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /**************************************************************************/ /* o15.0.1.3: */ /* - Request Join with insufficient comp_mask */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with insufficient comp mask qkey & pkey (o15.0.1.3)...\n"); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | /* IB_MCR_COMPMASK_QKEY | */ /* IB_MCR_COMPMASK_PKEY | intentionally missed to raise the error */ IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EE: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with insufficient comp mask - sl (15.0.1.3)...\n"); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | /* IB_MCR_COMPMASK_SL | */ IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02ED: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); mc_req_rec.mgid.raw[15] = 0x01; OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with insufficient comp mask - flow label (o15.0.1.3)...\n"); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | /* IB_MCR_COMPMASK_FLOW | intentionally missed to raise the error */ IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EC: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } osmt_init_mc_query_rec(p_osmt, &mc_req_rec); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with insufficient comp mask - tclass (o15.0.1.3)...\n"); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | /* IB_MCR_COMPMASK_TCLASS | Intentionally missed to raise an error */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EA: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } osmt_init_mc_query_rec(p_osmt, &mc_req_rec); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with insufficient comp mask - tclass qkey (o15.0.1.3)...\n"); /* no MGID */ /* memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); */ /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | /* IB_MCR_COMPMASK_QKEY | intentionally missed to raise the error */ IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | /* IB_MCR_COMPMASK_TCLASS | intentionally missed to raise the error */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E9: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } /* o15.0.1.8: */ /* - Request join with unrealistic RATE : get REQ INVALID status */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic rate (o15.0.1.8)...\n"); /* impossible requested rate */ mc_req_rec.rate = IB_MAX_RATE | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0207: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Check Valid value which is unreasonable now */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic rate 300GB (o15.0.1.8)...\n"); /* impossible requested rate */ mc_req_rec.rate = IB_PATH_RECORD_RATE_300_GBS | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0208: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Check Valid value which is unreasonable now */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with less than min rate 2.5GB (o15.0.1.8)...\n"); /* impossible requested rate */ mc_req_rec.rate = IB_PATH_RECORD_RATE_2_5_GBS | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AB: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Checking above max value of MTU which is impossible */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic mtu : \n\t\tmore than 4096 -" " max (o15.0.1.8)...\n"); /* impossible requested mtu */ mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AC: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Checking below min value of MTU which is impossible */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic mtu : \n\t\tless than 256 -" " min (o15.0.1.8)...\n"); /* impossible requested mtu */ mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AD: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic mtu (o15.0.1.8)...\n"); /* impossible requested mtu */ mc_req_rec.mtu = 0x6 | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AE: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } #if 0 /* Currently PacketLifeTime isn't checked in opensm */ /* Check PacketLifeTime as 0 */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create with unrealistic packet life value less than 0 (o15.0.1.8)...\n"); /* impossible requested packet life */ mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_LIFE | IB_MCR_COMPMASK_LIFE_SEL; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR || sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AF: " "Expected REMOTE ERROR IB_SA_MAD_STATUS_REQ_INVALID got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } #endif /* o15.0.1.4: */ /* - Create an MGID by asking for a join with MGID = 0 */ /* providing P_Key, Q_Key, SL, FlowLabel, Tclass. */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=0 skip service level (o15.0.1.4)...\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | /* IB_MCR_COMPMASK_SL | Intentionally missed */ IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A8: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } /* Check that no same MCG in the SMDB */ status = osmt_query_mcast(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02AA: " "Could not get all MC Records in subnet, got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Only when we are on single mode check flow - do the count comparison, otherwise skip */ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) { middle_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "(post false create): " "Number of MC Records found in SA DB is %d\n", middle_cnt); if (middle_cnt != start_cnt) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Got different number of records stored in SA DB (before any creation)\n" "Instead of %d got %d\n", start_cnt, middle_cnt); } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | /* IB_MCR_COMPMASK_QKEY | */ /* IB_MCR_COMPMASK_PKEY | Intentionally missed */ IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A7: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } /* Bad Query o15.0.1.4 */ status = osmt_query_mcast(p_osmt); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=0 skip TClass (o15.0.1.4)...\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | /* IB_MCR_COMPMASK_TCLASS | Intentionally missed */ /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (((ib_net16_t) (sa_mad->status & IB_SMP_STATUS_MASK)) != IB_SA_MAD_STATUS_INSUF_COMPS) OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected IB_SA_MAD_STATUS_INSUF_COMPS got:%s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A6: " "Expected REMOTE ERROR got:%s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=0 valid Set several options :\n\t\t" "First any RATE, Second less than max RATE\n\t\t" "Third above min MTU, Fourth less than max MTU\n\t\t" "Fifth exact MTU & RATE feasible, Sixth exact RATE feasible\n\t\t" "Seventh exact MTU feasible (o15.0.1.4)...\n"); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS; /* all above are required */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A5: " "Failed to create MCG for MGID=0 with higher than minimum RATE - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ mc_req_rec.rate = IB_PATH_RECORD_RATE_60_GBS | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0211: " "Failed to create MCG for MGID=0 with less than highest RATE - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0238: " "Failed to create MCG for MGID=0 with less than highest MTU - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0239: " "Failed to create MCG for MGID=0 with higher than lowest MTU - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ /* Using Exact feasible MTU & RATE */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Using Exact feasible MTU & RATE: " "MTU = 0x%02X, RATE = 0x%02X\n", mtu_phys, rate_phys); mc_req_rec.mtu = mtu_phys; mc_req_rec.rate = rate_phys; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0240: " "Failed to create MCG for MGID=0 with exact MTU & RATE - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ /* Using Exact feasible RATE */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Using Exact feasible RATE: 0x%02X\n", rate_phys); mc_req_rec.rate = rate_phys; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0241: " "Failed to create MCG for MGID=0 with exact RATE - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ /* Using Exact feasible MTU */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Using Exact feasible MTU: 0x%02X\n", mtu_phys); mc_req_rec.mtu = mtu_phys; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0242: " "Failed to create MCG for MGID=0 with exact MTU - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* o15.0.1.5: */ /* - Check the returned MGID is valid. (p 804) */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating resulting MGID (o15.0.1.5)...\n"); /* prefix 0xFF1 Scope 0xA01B */ /* Since we did not directly specified SCOPE in comp mask we should get the comp mask that is link-local scope */ if ((p_mc_res->mgid.multicast.header[0] != 0xFF) || (p_mc_res->mgid.multicast.header[1] != 0x12) || (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) || (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1B)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0209: " "Validating MGID failed. MGID:%s\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str)); status = IB_ERROR; goto Exit; } /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ /* Using feasible GREATER_THAN 0 packet lifitime */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=0 (o15.0.1.4)...\n"); status = osmt_query_mcast(p_osmt); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /* no MGID */ memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); /* Request Join */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_LIFE | IB_MCR_COMPMASK_LIFE_SEL; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0210: " "Failed to create MCG for MGID=0 - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* o15.0.1.6: */ /* - Create a new MCG with valid requested MGID. */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); mc_req_rec.pkey = IB_DEFAULT_PKEY; mc_req_rec.mgid = good_mgid; OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given valid MGID=%s (o15.0.1.6)...\n", inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str, sizeof gid_str)); /* Before creation, need to check that this group doesn't exist */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Verifying that MCGroup with this MGID doesn't exist by trying to Join it (o15.0.1.13)...\n"); ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, /* join */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0301: " "Tried joining group that shouldn't have existed - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Set State to full member to allow group creation */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Now creating group with given valid MGID=%s (o15.0.1.6)...\n", inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str, sizeof gid_str)); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0211: " "Failed to create MCG for MGID=%s (o15.0.1.6) - got %s/%s\n", inet_ntop(AF_INET6, good_mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating resulting MGID (o15.0.1.6)...\n"); /* prefix 0xFF1 Scope 0xA01B */ if ((p_mc_res->mgid.multicast.header[0] != 0xFF) || (p_mc_res->mgid.multicast.header[1] != 0x12) || /* HACK hardcoded scope = 0x02 */ (p_mc_res->mgid.multicast.raw_group_id[0] != 0xA0) || (p_mc_res->mgid.multicast.raw_group_id[1] != 0x1C)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0212: " "Validating MGID failed. MGID:%s\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str)); status = IB_ERROR; goto Exit; } /* - Try to create a new MCG with invalid MGID : get back ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD MGID=0xFA..... (o15.0.1.6)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid.raw[0] = 0xFA; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0213: " "Failed to recognize MGID error for MGID=0xFA - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* - Try again with MGID prefix = 0xA01B (maybe 0x1BA0 little or big ?) */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD MGID=0xFF12A01B..... with link-local scope (o15.0.1.6)...\n"); mc_req_rec.mgid.raw[0] = 0xFF; mc_req_rec.mgid.raw[3] = 0x1B; comp_mask = comp_mask | IB_MCR_COMPMASK_SCOPE; mc_req_rec.scope_state = mc_req_rec.scope_state & 0x2F; /* local scope */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0214: " "Failed to recognize MGID error for A01B with link-local bit (status %s) (rem status %s)\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Change the mgid prefix - get back ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD MGID PREFIX=0xEF... (o15.0.1.6)...\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[0] = 0xEF; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0215: " "Failed to recognize MGID PREFIX error for MGID=0xEF - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Change the scope to reserved - get back VALID REQ */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking local scope with full member \n\t\tand valid mgid %s" " ... (o15.0.1.6)...\n", inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str, sizeof gid_str)); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[1] = 0x1F; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0216: " "Failed to create MCG for MGID=%s - got %s/%s\n", inet_ntop(AF_INET6, good_mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Change the flags to invalid value 0x2 - get back INVALID REQ */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking invalid flags=0xFF 22 ... (o15.0.1.6)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[1] = 0x22; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0217: " "Failed to recognize create with invalid flags value 0x2 - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Change the MGID to link local MGID - get back VALID REQ */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking link local MGID 0xFF02:0:0:0:0:0:0:1 (o15.0.1.6)...\n"); mc_req_rec.mgid = osm_link_local_mgid; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0218: " "Failed to create MCG for MGID=0xFF02:0:0:0:0:0:0:1 - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* o15.0.1.7 - implicitly checked during the prev steps */ /* o15.0.1.8 - implicitly checked during the prev steps */ /* o15.0.1.9 */ /* - Create MCG with Invalid JoinState.FullMember != 1 : get ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking new MGID with invalid join state (o15.0.1.9)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[12] = 0xFF; mc_req_rec.scope_state = 0x22; /* link-local scope, non-member state */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0219: " "Failed to recognize create with JoinState != FullMember - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Lets try a valid join scope state */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking new MGID with valid join state (o15.0.1.9)...\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.scope_state = 0x23; /* link-local scope, non member and full member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0220: " "Failed to create MCG with valid join state 0x3 - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* Lets try another invalid join scope state */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking new MGID with invalid join state (o15.0.1.9)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); /* We have created a new MCG so now we need different mgid when creating group otherwise it will be counted as join request */ mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[12] = 0xFC; mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0221: " "Failed to recognize create with JoinState != FullMember - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Lets try another valid join scope state */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking new MGID creation with valid join state (o15.0.2.3)...\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[12] = 0xFB; memcpy(&special_mgid, &mc_req_rec.mgid, sizeof(ib_gid_t)); mc_req_rec.scope_state = 0x2F; /* link-local scope, Full member with all other bits turned on */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0222: " "Failed to create MCG with valid join state 0xF - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); /* o15.0.1.10 - can't check on a single client .-- obsolete - checked by SilverStorm bug o15-0.2.4, never the less recheck */ /* o15-0.2.4 - Check a join request to already created MCG */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Check o15-0.2.4 statement...\n"); /* Try to join */ memcpy(&mc_req_rec.mgid, &p_mc_res->mgid, sizeof(ib_gid_t)); /* Request Join */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_NON_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE; status = osmt_send_mcast_request(p_osmt, 0x1, /* SubnAdmSet */ &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CC: " "Failed to join MCG with valid req, returned status = %s\n", ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } if ((p_mc_res->scope_state & 0x7) != 0x7) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D0: " "Validating JoinState update failed. " "Expected 0x27 got 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* o15.0.1.11: */ /* - Try to join into a MGID that exists with JoinState=SendOnlyMember - */ /* see that it updates JoinState. What is the routing change? */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n"); mc_req_rec.mgid = good_mgid; /* first, make sure that the group exists */ mc_req_rec.scope_state = 0x21; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CD: " "Failed to create/join as full member - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } mc_req_rec.scope_state = 0x22; /* link-local scope, non-member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D1: " "Failed to update existing MGID - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State update with NonMember (o15.0.1.11)...\n"); if (p_mc_res->scope_state != 0x23) { /* scope is LSB */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CE: " "Validating JoinState update failed. Expected 0x23 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* Try delete current join state then update it with another value */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking JoinState update request should return 0x22 (o15.0.1.11)...\n"); mc_req_rec.rate = IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6; mc_req_rec.mgid = good_mgid; OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Partially delete JoinState (o15.0.1.14)...\n"); /* link-local scope, both non-member bits, so we should not be able to delete) */ mc_req_rec.scope_state = 0x26; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 0, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CF: " "Expected to fail partially update JoinState, " "but got %s\n", ib_get_err_str(status)); status = IB_ERROR; goto Exit; } /* link-local scope, NonMember bit, the FullMember bit should stay */ mc_req_rec.scope_state = 0x22; status = osmt_send_mcast_request(p_osmt, 0, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D3: " "Failed to partially update JoinState : %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } if (p_mc_res->scope_state != 0x21) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02D4: " "Failed to partially update JoinState : " "JoinState = 0x%02X, expected 0x%02X\n", p_mc_res->scope_state, 0x21); status = IB_ERROR; goto Exit; } /* So far successfully delete state - Now change it */ mc_req_rec.mgid = good_mgid; mc_req_rec.scope_state = 0x24; /* link-local scope, send only member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C0: " "Failed to update existing MCG - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State update with Send Only Member (o15.0.1.11)...\n"); if (p_mc_res->scope_state != 0x25) { /* scope is MSB */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C1: " "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* Now try to update value of join state */ mc_req_rec.scope_state = 0x21; /* link-local scope, full member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C2: " "Failed to update existing MGID - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State update with Full Member\n\t\t" "to an existing 0x5 state MCG (o15.0.1.11)...\n"); if (p_mc_res->scope_state != 0x25) { /* scope is LSB */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C3: " "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* Now try to update value of join state */ mc_req_rec.scope_state = 0x22; /* link-local scope, non member */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C4: " "Failed to update existing MGID - got %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State update with Non Member\n\t\t" "to an existing 0x5 state MCG (o15.0.1.11)...\n"); if (p_mc_res->scope_state != 0x27) { /* scope is LSB */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C5: " "Validating JoinState update failed. Expected 0x27 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "DEBUG - Current scope_state value : 0x%02X...\n", p_mc_res->scope_state); /* - We can not check simple join since we have only one tester (for now) */ /* o15.0.1.12: Not Supported */ /* - The SendOnlyNonMem join should have a special treatment in the SA but what is it ? */ /* o15.0.1.13: */ /* - Try joining with rate that does not exist in any MCG - ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = good_mgid; mc_req_rec.rate = IB_PATH_RECORD_RATE_2_5_GBS | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_RATE_SEL | IB_MCR_COMPMASK_RATE; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C6: " "Failed to catch BAD RATE joining an existing MGID: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Try MTU that does not exist in any MCG */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD MTU (higher than max) when connecting to " "existing MGID (o15.0.1.13)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = osm_ipoib_mgid; mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C7: " "Failed to catch BAD RATE (higher than max) joining an existing MGID: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Try another MTU that does not exist in any MCG */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD MTU (less than min) when connecting " "to existing MGID (o15.0.1.13)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = osm_ipoib_mgid; mc_req_rec.mtu = IB_MTU_LEN_256 | IB_PATH_SELECTOR_LESS_THAN << 6; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C8: " "Failed to catch BAD RATE (less than min) joining an existing MGID: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* o15.0.1.14: */ /* - Try partial delete - actually updating the join state. check it. */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking partial JoinState delete request - removing NonMember (o15.0.1.14)...\n"); mc_req_rec.mgid = good_mgid; comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS; /* all above are required */ /* link-local scope, non member (so we should not be able to delete) */ /* but the NonMember bit should be gone */ mc_req_rec.scope_state = 0x22; status = osmt_send_mcast_request(p_osmt, 0, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02C9: " "Fail to partially update JoinState during delete: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State removal of Non Member bit (o15.0.1.14)...\n"); if (p_mc_res->scope_state != 0x25) { /* scope is MSB - now only the full member & send only member have left */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CA: " "Validating JoinState update failed. Expected 0x25 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* Now use the same scope_state and delete all JoinState - leave multicast group since state is 0x0 */ mc_req_rec.scope_state = 0x25; status = osmt_send_mcast_request(p_osmt, 0, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02CB: " "Failed to update JoinState during delete: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Validating Join State update remove (o15.0.1.14)...\n"); if (p_mc_res->scope_state != 0x20) { /* scope is MSB - now only 0x0 so port is removed from MCG */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BF: " "Validating JoinState update failed. Expected 0x20 got: 0x%02X\n", p_mc_res->scope_state); status = IB_ERROR; goto Exit; } /* - Try joining (not full mem) again to see the group was deleted. (should fail) */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Delete by trying to Join deleted group (o15.0.1.13)...\n"); mc_req_rec.scope_state = 0x22; /* use non member - so if no group fail */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, /* join */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status != IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BC: " "Succeeded Joining Deleted Group: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = osm_ipoib_mgid; mc_req_rec.rate = IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6; mc_req_rec.scope_state = 0x21; /* delete full member */ status = osmt_send_mcast_request(p_osmt, 0, /* delete flag */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BD: " "Failed to catch BAD delete from IPoIB: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* Prepare another MCG for the following tests : */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Create given MGID=%s\n\t\t(o15.0.1.4)...\n", inet_ntop(AF_INET6, osm_ipoib_mgid.raw, gid_str, sizeof gid_str)); mc_req_rec.mgid = good_mgid; mc_req_rec.mgid.raw[12] = 0xAA; mc_req_rec.pkt_life = 0 | IB_PATH_SELECTOR_GREATER_THAN << 6; mc_req_rec.scope_state = 0x21; /* Full member */ comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_LIFE | IB_MCR_COMPMASK_LIFE_SEL; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02BE: " "Failed to create MCG for %s - got %s/%s\n", inet_ntop(AF_INET6, good_mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } /* - Try delete with valid join state */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Full Delete of a group (o15.0.1.14)...\n"); mc_req_rec.scope_state = 0x21; /* the FullMember is the current JoinState */ status = osmt_send_mcast_request(p_osmt, 0, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) goto Exit; /* o15.0.1.15: */ /* - Try deletion of the IPoIB MCG and get: ERR_REQ_INVALID */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n"); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); mc_req_rec.mgid = osm_ipoib_mgid; mc_req_rec.rate = IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6; mc_req_rec.scope_state = 0x21; /* delete full member */ status = osmt_send_mcast_request(p_osmt, 0, /* delete flag */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if ((status != IB_REMOTE_ERROR) || (sa_mad->status != IB_SA_MAD_STATUS_REQ_INVALID)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0223: " "Failed to catch BAD delete from IPoIB: %s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /**************************************************************************/ /* Checking join with invalid MTU */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Join with unrealistic mtu : \n" "\t\tFirst create new MCG than try to join it \n" "\t\twith unrealistic MTU greater than 4096 (o15.0.1.8)...\n"); /* First create new mgrp */ mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); mc_req_rec.mtu = IB_MTU_LEN_1024 | IB_PATH_SELECTOR_EXACTLY << 6; memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02EB: " "Failed to create new mgrp\n"); goto Exit; } memcpy(&tmp_mgid, &p_mc_res->mgid, sizeof(ib_gid_t)); osm_dump_mc_record(&p_osmt->log, p_mc_res, OSM_LOG_INFO); /* tmp_mtu = p_mc_res->mtu & 0x3F; */ /* impossible requested mtu always greater than exist in MCG */ mc_req_rec.mtu = IB_MTU_LEN_4096 | IB_PATH_SELECTOR_GREATER_THAN << 6; memcpy(&mc_req_rec.mgid, &tmp_mgid, sizeof(ib_gid_t)); ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_GID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_MTU_SEL | IB_MCR_COMPMASK_MTU; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E4: " "Expected REMOTE ERROR got:%s/%s\n", ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } /* - Try GetTable with PortGUID wildcarded and get back some groups. */ status = osmt_query_mcast(p_osmt); cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "(Before checking Max MCG creation): " "Number of MC Records found in SA DB is %d\n", cnt); /**************************************************************************/ /* Checking join on behalf of remote port gid */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Proxy Join...\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); memset(&context, 0, sizeof(context)); /* * Do a blocking query for all NodeRecords in the subnet. */ status = osmtest_get_all_recs(p_osmt, IB_MAD_ATTR_NODE_RECORD, sizeof(*p_rec), &context); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E5: " "osmtest_get_all_recs failed on getting all node records(%s)\n", ib_get_err_str(status)); goto Exit; } /* * Populate the database with the received records. */ num_recs = context.result.result_cnt; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Received %u records\n", num_recs); for (i = 0; i < num_recs; i++) { p_rec = osmv_get_query_node_rec(context.result.p_result_madw, i); if (p_rec->node_info.port_guid != p_osmt->local_port.port_guid && p_rec->node_info.node_type == IB_NODE_TYPE_CA) { OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "remote port_guid = 0x%" PRIx64 "\n", cl_ntoh64(p_rec->node_info.port_guid)); remote_port_guid = p_rec->node_info.port_guid; i = num_recs; break; } } if (remote_port_guid != 0x0) { mc_req_rec.pkey = IB_DEFAULT_PKEY; ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); mc_req_rec.port_gid.unicast.interface_id = remote_port_guid; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS; /* all above are required */ status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B4: " "Could not join on behalf of remote port 0x%016" PRIx64 " remote status: %s\n", cl_ntoh64(remote_port_guid), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } memcpy(&proxy_mgid, &p_mc_res->mgid, sizeof(ib_gid_t)); /* First try a bad deletion then good one */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Trying deletion of remote port with local port guid\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE; OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_START "\n"); status = osmt_send_mcast_request(p_osmt, 0, /* delete flag */ &mc_req_rec, comp_mask, sa_mad); OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, EXPECTING_ERRORS_END "\n"); if (status == IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02A9: " "Successful deletion of remote port guid with local one MGID : " "%s, Got : %s/%s\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Trying deletion of remote port with the right port guid\n"); osmt_init_mc_query_rec(p_osmt, &mc_req_rec); ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); mc_req_rec.mgid = proxy_mgid; mc_req_rec.port_gid.unicast.interface_id = remote_port_guid; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE; status = osmt_send_mcast_request(p_osmt, 0, /* delete flag */ &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B0: " "Failed to delete mgid with remote port guid MGID : " "%s, Got : %s/%s\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); goto Exit; } } else OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Could not check proxy join since could not found remote port, different from local port\n"); /* prepare init for next check */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /**************************************************************************/ if (p_osmt->opt.mmode > 2) { /* Check invalid Join with max mlid which is more than the Mellanox switches support 0xC000+0x1000 = 0xd000 */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Checking Creation of Maximum avaliable Groups (MulticastFDBCap)...\n"); tmp_mlid = cl_ntoh16(max_mlid) - cnt; while (tmp_mlid > 0) { uint16_t cur_mlid = 0; /* Request Set */ ib_member_set_join_state(&mc_req_rec, IB_MC_REC_STATE_FULL_MEMBER); /* Good Flow - mgid is 0 while giving all required fields for join : P_Key, Q_Key, SL, FlowLabel, Tclass */ mc_req_rec.rate = IB_LINK_WIDTH_ACTIVE_1X | IB_PATH_SELECTOR_GREATER_THAN << 6; mc_req_rec.mlid = max_mlid; memset(&mc_req_rec.mgid, 0, sizeof(ib_gid_t)); comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_PKEY | IB_MCR_COMPMASK_SL | IB_MCR_COMPMASK_FLOW | IB_MCR_COMPMASK_JOIN_STATE | IB_MCR_COMPMASK_TCLASS | /* all above are required */ IB_MCR_COMPMASK_MLID; status = osmt_send_mcast_request(p_osmt, 1, &mc_req_rec, comp_mask, sa_mad); if (status == IB_SUCCESS) { cur_mlid = cl_ntoh16(p_mc_res->mlid); /* Save the mlid created in test_created_mlids map */ OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Created MGID:%s MLID:0x%04X\n", inet_ntop(AF_INET6, p_mc_res->mgid.raw, gid_str, sizeof gid_str), cl_ntoh16(p_mc_res->mlid)); cl_map_insert(&test_created_mlids, cl_ntoh16(p_mc_res->mlid), p_mc_res); } else if (cur_mlid > cl_ntoh16(max_mlid)) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02E1 " "Successful Join with greater mlid than switches support (MulticastFDBCap) 0x%04X\n", cur_mlid); status = IB_ERROR; osm_dump_mc_record(&p_osmt->log, p_mc_res, OSM_LOG_VERBOSE); goto Exit; } else if ((sa_mad->status & IB_SMP_STATUS_MASK) == IB_SA_MAD_STATUS_NO_RESOURCES) /* You can quietly exit the loop since no available mlid in SA DB i.e. reached the maximum valid avalable mlid */ break; tmp_mlid--; } } /* Prepare the mc_req_rec for the rest of the flow */ osmt_init_mc_query_rec(p_osmt, &mc_req_rec); /**************************************************************************/ /* o15.0.1.16: */ /* - Try GetTable with PortGUID wildcarded and get back some groups. */ status = osmt_query_mcast(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B1: " "Failed to query multicast groups: %s\n", ib_get_err_str(status)); goto Exit; } cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "(Before Deletion of all MCG): " "Number of MC Records found in SA DB is %d\n", cnt); /* Delete all MCG that are not of IPoIB */ OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Cleanup all MCG that are not IPoIB...\n"); p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl); /* scan all available multicast groups in the DB and fill in the table */ while (p_mgrp != (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) { /* Only if different from IPoIB Mgid try to delete */ if (!IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) { osmt_init_mc_query_rec(p_osmt, &mc_req_rec); mc_req_rec.mgid = p_mgrp->mcmember_rec.mgid; /* o15-0.1.4 - need to specify the oppsite state for a valid delete */ if (!memcmp(&special_mgid, &p_mgrp->mcmember_rec.mgid, sizeof(special_mgid))) mc_req_rec.scope_state = 0x2F; else mc_req_rec.scope_state = 0x21; comp_mask = IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID | IB_MCR_COMPMASK_JOIN_STATE; OSM_LOG(&p_osmt->log, OSM_LOG_VERBOSE, "Sending request to delete MGID : %s" ", scope_state : 0x%02X\n", inet_ntop(AF_INET6, mc_req_rec.mgid.raw, gid_str, sizeof gid_str), mc_req_rec.scope_state); status = osmt_send_mcast_request(p_osmt, 0, /* delete flag */ &mc_req_rec, comp_mask, sa_mad); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02FF: Failed to delete MGID : %s" " ,\n\t\t it is not our MCG, Status : %s/%s\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), ib_get_err_str(status), ib_get_mad_status_str((ib_mad_t *) sa_mad)); fail_to_delete_mcg++; } } else end_ipoib_cnt++; p_mgrp = (osmtest_mgrp_t *) cl_qmap_next(&p_mgrp->map_item); } status = osmt_query_mcast(p_osmt); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02B2 " "GetTable of all records has failed - got %s\n", ib_get_err_str(status)); goto Exit; } /* If we are in single mode check flow - need to make sure all the multicast groups that are left are not ones created during the flow. */ if (p_osmt->opt.mmode == 1 || p_osmt->opt.mmode == 3) { end_cnt = cl_qmap_count(&p_osmt->exp_subn.mgrp_mlid_tbl); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Status of MC Records in SA DB during the test flow:\n" " Beginning of test\n" " Unrelated to the test: %d\n" " IPoIB MC Records : %d\n" " Total : %d\n" " End of test\n" " Failed to delete : %d\n" " IPoIB MC Records : %d\n" " Total : %d\n", mcg_outside_test_cnt, /* Non-IPoIB that existed at the beginning */ start_ipoib_cnt, /* IPoIB records */ start_cnt, /* Total: IPoIB and MC Records unrelated to the test */ fail_to_delete_mcg, /* Failed to delete at the end */ end_ipoib_cnt, /* IPoIB records */ end_cnt); /* Total MC Records at the end */ /* when we compare num of MCG we should consider an outside source which create other MCGs */ if ((end_cnt - fail_to_delete_mcg - end_ipoib_cnt) != (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt)) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Got different number of non-IPoIB records stored in SA DB\n\t\t" "at Start got %d, at End got %d (IPoIB groups only)\n", (start_cnt - mcg_outside_test_cnt - start_ipoib_cnt), (end_cnt - fail_to_delete_mcg - end_ipoib_cnt)); } p_mgrp_mlid_tbl = &p_osmt->exp_subn.mgrp_mlid_tbl; p_mgrp = (osmtest_mgrp_t *) cl_qmap_head(p_mgrp_mlid_tbl); while (p_mgrp != (osmtest_mgrp_t *) cl_qmap_end(p_mgrp_mlid_tbl)) { uint16_t mlid = (uint16_t) cl_qmap_key((cl_map_item_t *) p_mgrp); OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Found MLID:0x%04X\n", mlid); /* Check if the mlid is in the test_created_mlids. If TRUE, then we didn't delete a MCgroup that was created in this flow. */ if (cl_map_get(&test_created_mlids, mlid) != NULL) { /* This means that we still have an mgrp that we created!! */ OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 02FE: " "Wasn't able to erase mgrp with MGID:%s" " MLID:0x%04X\n", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str), mlid); got_error = TRUE; } else { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Still exists %s MGID:%s\n", (IS_IPOIB_MGID (&p_mgrp->mcmember_rec. mgid)) ? "IPoIB" : "non-IPoIB", inet_ntop(AF_INET6, p_mgrp->mcmember_rec.mgid.raw, gid_str, sizeof gid_str)); } p_mgrp = (osmtest_mgrp_t *) cl_qmap_next(&p_mgrp->map_item); } if (got_error) { __osmt_print_all_multicast_records(p_osmt); status = IB_ERROR; } } Exit: OSM_LOG_EXIT(&p_osmt->log); return status; } opensm-3.3.20/osmtest/osmt_inform.c0000644000205000001450000005327012104655725014224 00000000000000/* * Copyright (c) 2006-2008 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. * */ #ifdef OSM_VENDOR_INTF_MTL /* * Abstract: * Implementation of InformInfo testing flow.. * Top level is osmt_run_inform_info_flow: * osmt_bind_inform_qp * osmt_reg_unreg_inform_info * osmt_send_trap_wait_for_forward * */ #include #include #include #include #include #include #include "osmtest.h" #include "osmt_inform.h" /* * Prepare an asynchronous QP (rcv) for sending inform info and * handling the incoming reports. * */ ib_api_status_t osmt_bind_inform_qp(IN osmtest_t * const p_osmt, OUT osmt_qp_ctx_t * p_qp_ctx) { ib_net64_t port_guid; VAPI_hca_hndl_t hca_hndl; VAPI_hca_id_t hca_id; uint32_t port_num; VAPI_ret_t vapi_ret; IB_MGT_ret_t mgt_ret; uint8_t hca_index; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); port_guid = p_osmt->local_port.port_guid; OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); /* obtain the hca name and port num from the guid */ OSM_LOG(p_log, OSM_LOG_DEBUG, "Finding CA and Port that owns port guid 0x%" PRIx64 "\n", port_guid); mgt_ret = osm_vendor_get_guid_ca_and_port(p_osmt->p_vendor, port_guid, &hca_hndl, &hca_id[0], &hca_index, &port_num); if (mgt_ret != IB_MGT_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0109: " "Unable to obtain CA and port (%d).\n"); status = IB_ERROR; goto Exit; } #define OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY 0x80010000 strncpy(p_qp_ctx->qp_bind_hndl.hca_id, hca_id, sizeof(hca_id)); p_qp_ctx->qp_bind_hndl.hca_hndl = hca_hndl; p_qp_ctx->qp_bind_hndl.port_num = port_num; p_qp_ctx->qp_bind_hndl.max_outs_sq = 10; p_qp_ctx->qp_bind_hndl.max_outs_rq = 10; p_qp_ctx->qp_bind_hndl.qkey = OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY; vapi_ret = osmt_mtl_init_opened_hca(&p_qp_ctx->qp_bind_hndl); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0114: " "Error initializing QP.\n"); status = IB_ERROR; goto Exit; } /* we use the pre-allocated buffers for send and receive : send from buf[0] receive from buf[2] */ p_qp_ctx->p_send_buf = (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + GRH_LEN; p_qp_ctx->p_recv_buf = (uint8_t *) p_qp_ctx->qp_bind_hndl.buf_ptr + 2 * (GRH_LEN + MAD_BLOCK_SIZE); /* Need to clear assigned memory of p_send_buf - before using it to send any data */ memset(p_qp_ctx->p_send_buf, 0, MAD_BLOCK_SIZE); status = IB_SUCCESS; OSM_LOG(p_log, OSM_LOG_DEBUG, "Initialized QP:0x%X in VAPI Mode\n", p_qp_ctx->qp_bind_hndl.qp_id); OSM_LOG(p_log, OSM_LOG_DEBUG, "Binding to IB_MGT SMI\n"); /* we also need a QP0 handle for sending packets */ mgt_ret = IB_MGT_get_handle(hca_id, port_num, IB_MGT_SMI, &(p_qp_ctx->ib_mgt_qp0_handle)); if (IB_MGT_OK != mgt_ret) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0115: " "Error obtaining IB_MGT handle to SMI\n"); status = IB_ERROR; goto Exit; } Exit: OSM_LOG_EXIT(p_log); return status; } /* * Close the QP */ void osmt_unbind_inform_qp(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx) { osm_log_t *p_log = &p_osmt->log; OSM_LOG_ENTER(p_log); osmt_mtl_mad_cleanup(&p_qp_ctx->qp_bind_hndl); IB_MGT_release_handle(p_qp_ctx->ib_mgt_qp0_handle); OSM_LOG(p_log, OSM_LOG_DEBUG, "Unbind QP handles\n"); OSM_LOG_EXIT(&p_osmt->log); } /* * Register/Unregister to receive the given InformInfo * * Uses the qp context to send the inform info mad. * Wait for GetResp(InformInfoResp) * */ ib_api_status_t osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt, IN osmt_qp_ctx_t * p_qp_ctx, IN ib_inform_info_t * p_inform_info, IN uint8_t reg_flag) { ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf); ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); /* SA Payload */ VAPI_ret_t vapi_ret; VAPI_wc_desc_t wc_desc; VAPI_ud_av_hndl_t avh; static VAPI_wr_id_t wrid = 16198; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(&p_osmt->log); /* init the MAD */ ib_mad_init_new((ib_mad_t *) p_sa_mad, IB_MCLASS_SUBN_ADM, (uint8_t) 2, IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0); wrid++; p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO; /* copy the reference inform info */ memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t)); if (reg_flag) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n", p_ii->lid_range_begin, p_ii->lid_range_end, p_ii->g_or_v.generic.trap_num); } else { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n", p_ii->lid_range_begin, p_ii->lid_range_end); } /* set the subscribe bit */ if (reg_flag) { p_ii->subscribe = 1; } else { p_ii->subscribe = 0; /* * we need to set the QPN on the mad if we unsubscribe: * o13-2.1.1 - QPN Field need to be set when unsubscribing. */ ib_inform_info_set_qpn(p_ii, cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id. qp_num)); } osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG); /* --------------------- PREP ------------------------- */ if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1, /* but we need only one mad at a time */ GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: " "Error posting recv bufs\n"); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n"); vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: " "Error Preparing AVH (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n"); if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) { osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf), OSM_LOG_DEBUG); #if 0 for (i = 56; i < 253; i++) { if (i % 8 == 0) { printf("\n %d : ", i); } printf("0x%02X ", p_qp_ctx->p_send_buf[i]); } #endif printf("\n"); } /* --------------------- SEND ------------------------- */ vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1, /* SA is QP1 */ 0, /* SL is 0 */ OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY, avh); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: " "Error sending mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.sq_cq_hndl, &wc_desc, 20, 10000, NULL); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: " "Error getting send completion (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } if (wc_desc.status != VAPI_SUCCESS) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: " "Error on send completion (%s) (%d)\n", VAPI_strerror_sym(wc_desc.status), wc_desc.status); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n"); /* --------------------- RECV ------------------------- */ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.rq_cq_hndl, &wc_desc, 20, 10000, &avh); if (vapi_ret != VAPI_SUCCESS) { if (vapi_ret == VAPI_CQ_EMPTY) { status = IB_TIMEOUT; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: " "Error receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; } goto Exit; } /* check to see if successful - by examination of the subscribe bit */ p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN); if (p_sa_mad->status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n", ib_get_mad_status_str((ib_mad_t *) p_sa_mad)); status = IB_REMOTE_ERROR; goto Exit; } if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n", p_sa_mad->method); status = IB_REMOTE_ERROR; goto Exit; } if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n", cl_ntoh16(p_sa_mad->attr_id)); status = IB_REMOTE_ERROR; goto Exit; } p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad); if (!p_ii->subscribe) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: " "Subscribe/Unsubscribe Failed\n"); status = IB_REMOTE_ERROR; } Exit: OSM_LOG_EXIT(&p_osmt->log); return status; } /* * Send a trap (Subn LID Route) Trap(Notice) through the regular * connection QP connection (targeted at QP0) * * Wait for the trap repress */ ib_api_status_t osmt_send_trap_wait_for_forward(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx) { ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf); ib_mad_notice_attr_t *p_ntc = ib_smp_get_payload_ptr(p_smp); ib_sa_mad_t *p_sa_mad; IB_MGT_ret_t mgt_res; VAPI_ret_t vapi_ret; VAPI_wc_desc_t wc_desc; VAPI_ud_av_hndl_t avh; IB_ud_av_t av; static VAPI_wr_id_t wrid = 2222; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_INFO, "Sending Traps to QP0 of SA LID:0x%X\n", p_osmt->local_port.sm_lid); /* init the MAD */ memset(p_smp, 0, sizeof(ib_smp_t)); ib_mad_init_new((ib_mad_t *) p_smp, IB_MCLASS_SUBN_LID, (uint8_t) 2, IB_MAD_METHOD_TRAP, cl_hton64(wrid), (ib_net16_t) 0, 0); wrid++; p_smp->attr_id = IB_MAD_ATTR_NOTICE; /* prepare the notice */ p_ntc->generic_type = 0x82; /* generic, type = 2 */ ib_notice_set_prod_type_ho(p_ntc, 1); p_ntc->g_or_v.generic.trap_num = cl_hton16(0x26); p_ntc->issuer_lid = cl_hton16(2); /* --------------------- PREP ------------------------- */ if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1, /* we need to receive both trap repress and report */ GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0127: " "Error posting recv bufs\n"); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n"); av.dlid = p_osmt->local_port.sm_lid; av.grh_flag = FALSE; /* EZ: returned in HACK: use constants */ av.static_rate = 0; /* p_mad_addr->static_rate; */ av.src_path_bits = 1; /* p_mad_addr->path_bits; */ av.sl = 0; /* p_mad_addr->addr_type.gsi.service_level; */ OSM_LOG(p_log, OSM_LOG_DEBUG, "av.dlid 0x%X, av.static_rate %d, av.path_bits %d\n", cl_ntoh16(av.dlid), av.static_rate, av.src_path_bits); /* send it */ mgt_res = IB_MGT_send_mad(p_qp_ctx->ib_mgt_qp0_handle, p_smp, /* actual payload */ &av, /* address vector */ wrid, /* casting the mad wrapper pointer for err cb */ p_osmt->opt.transaction_timeout); if (mgt_res != IB_MGT_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0128: " "Error sending mad (%d)\n", mgt_res); status = IB_ERROR; goto Exit; } vapi_ret = osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl, p_osmt->local_port.sm_lid, &avh); if (vapi_ret != VAPI_OK) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0129: " "Error Preparing AVH (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; goto Exit; } OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n"); OSM_LOG(p_log, OSM_LOG_DEBUG, "Trap MAD Sent\n"); /* --------------------- RECV ------------------------- */ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.rq_cq_hndl, &wc_desc, 200, 10000, &avh); if (vapi_ret != VAPI_SUCCESS) { if (vapi_ret == VAPI_CQ_EMPTY) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: " "Timeout receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_TIMEOUT; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: " "Error receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; } goto Exit; } /* check to see if successful - by examination of the subscribe bit */ p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN); if (p_sa_mad->method == IB_MAD_METHOD_REPORT) { if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) { OSM_LOG(p_log, OSM_LOG_INFO, "Received the Report!\n"); status = IB_SUCCESS; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020" "Did not receive a Report(Notice) but attr:%d\n", cl_ntoh16(p_sa_mad->attr_id)); status = IB_ERROR; } } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 1020" "Received an Unexpected Method:%d\n", p_smp->method); status = IB_ERROR; } Exit: OSM_LOG_EXIT(p_log); return status; } /* * Wait for a trap on QPn * */ ib_api_status_t osmt_trap_wait(IN osmtest_t * const p_osmt, IN osmt_qp_ctx_t * p_qp_ctx) { ib_smp_t *p_smp = (ib_smp_t *) (p_qp_ctx->p_send_buf); ib_sa_mad_t *p_sa_mad; VAPI_ret_t vapi_ret; VAPI_wc_desc_t wc_desc; osm_log_t *p_log = &p_osmt->log; ib_api_status_t status = IB_SUCCESS; OSM_LOG_ENTER(p_log); OSM_LOG(p_log, OSM_LOG_INFO, "Waiting for Traps under QP:0x%X of SA LID:0x%X\n", cl_ntoh16(p_osmt->local_port.sm_lid)); /* --------------------- RECV ------------------------- */ vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl, p_qp_ctx->qp_bind_hndl.rq_cq_hndl, &wc_desc, // 200, p_osmt->opt.wait_time * 100, 10000, NULL); if (vapi_ret != VAPI_SUCCESS) { if (vapi_ret == VAPI_CQ_EMPTY) { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0130: " "Timeout receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_TIMEOUT; } else { OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0131: " "Error receiving mad (%s)\n", VAPI_strerror_sym(vapi_ret)); status = IB_ERROR; } goto Exit; } /* check to see if successful - by examination of the subscribe bit */ p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN); if (p_sa_mad->method == IB_MAD_METHOD_REPORT) { if (p_sa_mad->attr_id == IB_MAD_ATTR_NOTICE) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Received the Report!\n"); status = IB_SUCCESS; } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020" "Did not receive a Report(Notice) but attr:%d\n", cl_ntoh16(p_sa_mad->attr_id)); status = IB_ERROR; } } else { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 1020" "Received an Unexpected Method:%d\n", p_smp->method); status = IB_ERROR; } Exit: OSM_LOG_EXIT(p_log); return status; } /* * Initialize an inform info attribute: * Catch all traps in the lid range of the p_osmt * */ ib_api_status_t osmt_init_inform_info(IN osmtest_t * const p_osmt, OUT ib_inform_info_t * p_ii) { memset(p_ii, 0, sizeof(ib_inform_info_t)); /* p_ii->lid_range_begin = cl_hton16(1); */ p_ii->lid_range_begin = 0xFFFF; p_ii->lid_range_end = cl_hton16(p_osmt->max_lid); p_ii->is_generic = 1; /* have to choose */ p_ii->trap_type = 0xFFFF; /* ALL */ p_ii->g_or_v.generic.trap_num = 0xFFFF; /* ALL */ p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */ p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */ return IB_SUCCESS; } ib_api_status_t osmt_init_inform_info_by_trap(IN osmtest_t * const p_osmt, IN ib_net16_t trap_num, OUT ib_inform_info_t * p_ii) { memset(p_ii, 0, sizeof(ib_inform_info_t)); /* p_ii->lid_range_begin = cl_hton16(1); */ p_ii->lid_range_begin = 0xFFFF; p_ii->lid_range_end = cl_hton16(p_osmt->max_lid); p_ii->is_generic = 1; /* have to choose */ p_ii->trap_type = 0xFFFF; /* ALL */ p_ii->g_or_v.generic.trap_num = trap_num; /* ALL */ p_ii->g_or_v.generic.node_type_lsb = 0xFFFF; /* ALL */ p_ii->g_or_v.generic.node_type_msb = 0xFF; /* ALL */ return IB_SUCCESS; } /* * Run a complete inform info test flow: * - try to unregister inform info (should fail) * - register an inform info * - try to unregister inform info (should succeed) * - register an inform info * - send a trap - sleep * - check that a Report(Notice) arrived that matches the sent trap * */ ib_api_status_t osmt_run_inform_info_flow(IN osmtest_t * const p_osmt) { ib_inform_info_t inform_info; ib_api_status_t status; osmt_qp_ctx_t qp_ctx; OSM_LOG_ENTER(&p_osmt->log); /* bind the QP */ status = osmt_bind_inform_qp(p_osmt, &qp_ctx); if (status != IB_SUCCESS) { goto Exit; } /* init the inform info */ osmt_init_inform_info(p_osmt, &inform_info); /* first try to unsubscribe */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0); /* WAS IB_REMOTE_ERROR */ if (status != IB_REMOTE_ERROR) { if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Error during UnSubscribe: (%s)\n", ib_get_err_str(status)); goto Exit; } else { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Expected Failure to UnSubscribe non existing InformInfo\n"); status = IB_ERROR; goto Exit; } } /* send the inform info registration */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1); if (status != IB_SUCCESS) { goto Exit; } /* send a trap through QP0 and wait on QPN */ status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Error during Send Trap and Wait For Report: (%s)\n", ib_get_err_str(status)); goto Exit; } /* try to unsubscribe for cleanup */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Error during UnSubscribe: (%s)\n", ib_get_err_str(status)); goto Exit; } else { if (status == IB_REMOTE_ERROR) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Remote Error during UnSubscribe\n"); status = IB_ERROR; goto Exit; } } Exit: osmt_unbind_inform_qp(p_osmt, &qp_ctx); OSM_LOG_EXIT(&p_osmt->log); return status; } /* * Run a complete inform info test flow: * - try to unregister inform info (should fail) * - register an inform info * - try to unregister inform info (should succeed) * - register an inform info * - send a trap - sleep * - check that a Report(Notice) arrived that match the sent one * */ ib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt) { ib_inform_info_t inform_info; ib_api_status_t status; osmt_qp_ctx_t qp_ctx; OSM_LOG_ENTER(&p_osmt->log); /* bind the QP */ status = osmt_bind_inform_qp(p_osmt, &qp_ctx); if (status != IB_SUCCESS) { goto Exit; } /* init the inform info */ osmt_init_inform_info_by_trap(p_osmt, cl_hton16(64), &inform_info); /* send the inform info registration */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1); if (status != IB_SUCCESS) { goto Exit; } /*--------------------- PREP -------------------------*/ if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1, /* we need to receive the report */ GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: " "Error posting recv bufs for trap 64\n"); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 64\n"); /* init the inform info */ osmt_init_inform_info_by_trap(p_osmt, cl_hton16(65), &inform_info); /* send the inform info registration */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1); if (status != IB_SUCCESS) { goto Exit; } /*--------------------- PREP -------------------------*/ if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1, /* we need to receive the report */ GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) { OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: " "Error posting recv bufs for trap 65\n"); status = IB_ERROR; goto Exit; } OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 65\n"); /* Sleep for x seconds in order to allow external script trap generation */ #if 0 sleep(p_osmt->opt.wait_time); #endif /* wait for a trap on QPN */ status = osmt_trap_wait(p_osmt, &qp_ctx); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Error during Send Trap and Wait For Report: (%s)\n", ib_get_err_str(status)); goto Exit; } /* try to unsubscribe for cleanup */ status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0); if (status != IB_SUCCESS) { OSM_LOG(&p_osmt->log, OSM_LOG_INFO, "Error during UnSubscribe: (%s)\n", ib_get_err_str(status)); goto Exit; } Exit: osmt_unbind_inform_qp(p_osmt, &qp_ctx); OSM_LOG_EXIT(&p_osmt->log); return status; } #endif /* OSM_VENDOR_INTF_MTL */ opensm-3.3.20/osmtest/osmt_mtl_regular_qp.c0000644000205000001450000003043112104655725015741 00000000000000/* * Copyright (c) 2009 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. * */ #ifdef OSM_VENDOR_INTF_MTL /* - Mellanox Confidential and Proprietary - * * Copyright (C) Jul. 2001, Mellanox Technologies Ltd. ALL RIGHTS RESERVED. * * Except as specifically permitted herein, no portion of the information, * including but not limited to object code and source code, may be reproduced, * modified, distributed, republished or otherwise exploited in any form or by * any means for any purpose without the prior written permission of Mellanox * Technologies Ltd. Use of software subject to the terms and conditions * detailed in the file "LICENSE.txt". * * End of legal section ...................................................... * * osmt_mtl_regular_qp.c - * Provide Simple Interface for Sending and Receiving MADS through a regular QP * * Creation date: * * Version: $Id$ * * Authors: * Eitan Zahavi * * Changes: */ #include #include #include #include #include #include #include #include #include #include #include #include /* * Initialize the QP etc. * Given in res: port_num, max_outs_sq, max_outs_rq */ VAPI_ret_t osmt_mtl_get_qp_resources(IN OUT osmt_mtl_mad_res_t * res) { VAPI_ret_t ret; VAPI_hca_port_t hca_port_info; VAPI_qp_init_attr_t qp_init_attr; VAPI_qp_prop_t qp_prop; VAPI_cqe_num_t act_num; /* Get HCA LID */ ret = VAPI_query_hca_port_prop(res->hca_hndl, res->port_num, &hca_port_info); VAPI_CHECK_RET; res->slid = hca_port_info.lid; /* Get a PD */ ret = VAPI_alloc_pd(res->hca_hndl, &(res->pd_hndl)); VAPI_CHECK_RET; /* Create CQ for RQ and SQ *//* TBD - Check we have enough act nums */ ret = VAPI_create_cq(res->hca_hndl, res->max_outs_sq + 1, &(res->sq_cq_hndl), &act_num); VAPI_CHECK_RET; ret = VAPI_create_cq(res->hca_hndl, res->max_outs_rq + 1, &(res->rq_cq_hndl), &act_num); VAPI_CHECK_RET; /* register event handlers for polling(block mode) internal use */ /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->rq_cq_hndl, */ /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->rq_cq_eventh)); */ /* VAPI_CHECK_RET; */ /* ret= EVAPI_set_comp_eventh(res->hca_hndl,res->sq_cq_hndl, */ /* EVAPI_POLL_CQ_UNBLOCK_HANDLER,NULL,&(res->sq_cq_eventh)); */ /* VAPI_CHECK_RET; */ /* Create QP */ qp_init_attr.cap.max_oust_wr_sq = res->max_outs_sq + 1; qp_init_attr.cap.max_oust_wr_rq = res->max_outs_rq + 1; qp_init_attr.cap.max_sg_size_sq = 4; qp_init_attr.cap.max_sg_size_rq = 4; qp_init_attr.pd_hndl = res->pd_hndl; qp_init_attr.rdd_hndl = 0; qp_init_attr.rq_cq_hndl = res->rq_cq_hndl; qp_init_attr.rq_sig_type = VAPI_SIGNAL_ALL_WR; /* That's default for IB */ qp_init_attr.sq_cq_hndl = res->sq_cq_hndl; qp_init_attr.sq_sig_type = VAPI_SIGNAL_REQ_WR; qp_init_attr.ts_type = VAPI_TS_UD; ret = VAPI_create_qp(res->hca_hndl, &qp_init_attr, &(res->qp_hndl), &qp_prop); VAPI_CHECK_RET; res->qp_id.qp_num = qp_prop.qp_num; return (VAPI_OK); } VAPI_ret_t osmt_mtl_qp_init(osmt_mtl_mad_res_t * res) { VAPI_ret_t ret; VAPI_qp_attr_t qp_attr; VAPI_qp_attr_mask_t qp_attr_mask; VAPI_qp_cap_t qp_cap; /* * Change QP to INIT * */ QP_ATTR_MASK_CLR_ALL(qp_attr_mask); qp_attr.qp_state = VAPI_INIT; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); qp_attr.pkey_ix = 0; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PKEY_IX); qp_attr.port = res->port_num; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_PORT); qp_attr.qkey = res->qkey; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QKEY); /* If I do not set this mask, I get an error from HH. QPM should catch it */ ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET; return (ret); } VAPI_ret_t osmt_mtl_qp_2_rtr_rts(osmt_mtl_mad_res_t * res) { VAPI_ret_t ret; VAPI_qp_attr_t qp_attr; VAPI_qp_attr_mask_t qp_attr_mask; VAPI_qp_cap_t qp_cap; /* * Change QP to RTR * */ QP_ATTR_MASK_CLR_ALL(qp_attr_mask); qp_attr.qp_state = VAPI_RTR; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); /* qp_attr.rq_psn = 0; */ /* QP_ATTR_MASK_SET(qp_attr_mask,QP_ATTR_RQ_PSN); */ ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET; /* * Change QP to RTS * */ QP_ATTR_MASK_CLR_ALL(qp_attr_mask); qp_attr.qp_state = VAPI_RTS; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_QP_STATE); qp_attr.sq_psn = 0; QP_ATTR_MASK_SET(qp_attr_mask, QP_ATTR_SQ_PSN); ret = VAPI_modify_qp(res->hca_hndl, res->qp_hndl, &qp_attr, &qp_attr_mask, &qp_cap); VAPI_CHECK_RET; return (ret); } VAPI_ret_t osmt_mtl_mad_create_mr(osmt_mtl_mad_res_t * res) { VAPI_ret_t ret; VAPI_mrw_t mr_in, mr_out; res->buf_size = (MAD_SIZE + GRH_LEN) * (res->max_outs_sq + res->max_outs_rq + 1); /* Register single memory address region for all buffers */ res->buf_ptr = VMALLOC(res->buf_size); if (res->buf_ptr == ((VAPI_virt_addr_t) NULL)) { ret = VAPI_EAGAIN; VAPI_CHECK_RET; } /* Enable local and remote access to memory region */ mr_in.acl = VAPI_EN_LOCAL_WRITE | VAPI_EN_REMOTE_WRITE; mr_in.l_key = 0; mr_in.pd_hndl = res->pd_hndl; mr_in.r_key = 0; mr_in.size = res->buf_size; ASSERT_VOIDP2UINTN(res->buf_ptr); mr_in.start = (VAPI_virt_addr_t) (res->buf_ptr); mr_in.type = VAPI_MR; ret = VAPI_register_mr(res->hca_hndl, &mr_in, &(res->mr_hndl), &mr_out); VAPI_CHECK_RET; res->l_key = mr_out.l_key; return (ret); } VAPI_ret_t osmt_mtl_init_opened_hca(osmt_mtl_mad_res_t * res) { VAPI_ret_t ret; res->pd_hndl = VAPI_INVAL_HNDL; res->rq_cq_hndl = VAPI_INVAL_HNDL; res->sq_cq_hndl = VAPI_INVAL_HNDL; res->sq_cq_eventh = VAPI_INVAL_HNDL; res->rq_cq_eventh = VAPI_INVAL_HNDL; res->qp_hndl = VAPI_INVAL_HNDL; res->mr_hndl = VAPI_INVAL_HNDL; /* * Create QP * */ ret = osmt_mtl_get_qp_resources(res); if (ret != VAPI_OK) { return ret; } /* * Move to init * */ ret = osmt_mtl_qp_init(res); if (ret != VAPI_OK) { return ret; } /* * Initialize memory regions * */ ret = osmt_mtl_mad_create_mr(res); if (ret != VAPI_OK) { return ret; } /* only now move to RTR and RTS */ ret = osmt_mtl_qp_2_rtr_rts(res); if (ret != VAPI_OK) { return ret; } return VAPI_OK; } VAPI_ret_t osmt_mtl_mad_cleanup(osmt_mtl_mad_res_t * res) { if (res->qp_hndl != VAPI_INVAL_HNDL) { VAPI_destroy_qp(res->hca_hndl, res->qp_hndl); } if (res->sq_cq_eventh != VAPI_INVAL_HNDL) { EVAPI_clear_comp_eventh(res->hca_hndl, res->sq_cq_eventh); } if (res->rq_cq_eventh != VAPI_INVAL_HNDL) { EVAPI_clear_comp_eventh(res->hca_hndl, res->rq_cq_eventh); } if (res->rq_cq_hndl != VAPI_INVAL_HNDL) { VAPI_destroy_cq(res->hca_hndl, res->rq_cq_hndl); } if (res->sq_cq_hndl != VAPI_INVAL_HNDL) { VAPI_destroy_cq(res->hca_hndl, res->sq_cq_hndl); } if (res->mr_hndl != VAPI_INVAL_HNDL) { VAPI_deregister_mr(res->hca_hndl, res->mr_hndl); } if (res->pd_hndl != VAPI_INVAL_HNDL) { VAPI_dealloc_pd(res->hca_hndl, res->pd_hndl); } #if 0 /* open/close of HCA should be done system wide - not per application */ if (res->hca_hndl != VAPI_INVAL_HNDL) { VAPI_close_hca(res->hca_hndl); /* TBD: HCA_open/close should be done on a system wide basis */ } #endif return VAPI_OK; } VAPI_ret_t osmt_mtl_create_av(osmt_mtl_mad_res_t * res, int16_t dlid, VAPI_ud_av_hndl_t * avh_p) { VAPI_ud_av_t av; VAPI_ret_t ret; av.dlid = dlid; av.port = res->port_num; av.sl = 0; /* dest->sl; */ av.src_path_bits = 0; /* dest->ee_dlid.dst_path_bits; */ av.static_rate = 0; /* GRH ? */ av.grh_flag = 0; ret = VAPI_create_addr_hndl(res->hca_hndl, res->pd_hndl, &av, avh_p); if (ret != VAPI_OK) { MTL_ERROR1("%s: failed VAPI_create_addr_hndl (%s)\n", __func__, VAPI_strerror_sym(ret)); return ret; } return VAPI_OK; } VAPI_ret_t osmt_mtl_mad_send(osmt_mtl_mad_res_t * res, VAPI_wr_id_t id, void *mad, VAPI_qp_num_t dest_qp, IB_sl_t sl, u_int32_t dest_qkey, VAPI_ud_av_hndl_t avh) { VAPI_sr_desc_t sr; VAPI_sg_lst_entry_t sg_entry; VAPI_ret_t ret; /* building SEND request */ sr.opcode = VAPI_SEND; sr.remote_ah = avh; sr.remote_qp = dest_qp; sr.remote_qkey = dest_qkey; sr.id = id; sr.set_se = FALSE; sr.fence = FALSE; sr.comp_type = VAPI_SIGNALED; sr.sg_lst_len = 1; sr.sg_lst_p = &sg_entry; ASSERT_VOIDP2UINTN(mad); sg_entry.addr = (VAPI_virt_addr_t) (mad); sg_entry.len = MAD_SIZE; sg_entry.lkey = res->l_key; ret = VAPI_post_sr(res->hca_hndl, res->qp_hndl, &sr); if (ret != VAPI_OK) { MTL_ERROR1(__FUNCTION__ ": failed VAPI_post_sr (%s)\n", VAPI_strerror_sym(ret)); return ret; } return VAPI_OK; } int osmt_mtl_mad_post_recv_bufs(osmt_mtl_mad_res_t * res, void *buf_array, u_int32_t num_o_bufs, u_int32_t size, VAPI_wr_id_t start_id) { uint32_t i; void *cur_buf; VAPI_rr_desc_t rr; VAPI_sg_lst_entry_t sg_entry; VAPI_ret_t ret; rr.opcode = VAPI_RECEIVE; rr.comp_type = VAPI_SIGNALED; /* All with CQE (IB compliant) */ rr.sg_lst_len = 1; /* single buffers */ rr.sg_lst_p = &sg_entry; sg_entry.lkey = res->l_key; cur_buf = buf_array; for (i = 0; i < num_o_bufs; i++) { rr.id = start_id + i; /* WQE id used is the index to buffers ptr array */ ASSERT_VOIDP2UINTN(cur_buf); sg_entry.addr = (VAPI_virt_addr_t) cur_buf; sg_entry.len = size; memset(cur_buf, 0x00, size); /* fill with 0 */ ret = VAPI_post_rr(res->hca_hndl, res->qp_hndl, &rr); if (ret != VAPI_OK) { MTL_ERROR1(__FUNCTION__ ": failed posting RQ WQE (%s)\n", VAPI_strerror_sym(ret)); return i; } MTL_DEBUG4(__FUNCTION__ ": posted buf at %p\n", cur_buf); cur_buf += size; } return i; /* num of buffers posted */ } VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca, VAPI_cq_hndl_t cq, VAPI_wc_desc_t * wc_desc_p, u_int32_t max_poll, u_int32_t poll_sleep, VAPI_ud_av_hndl_t * avh_p) { VAPI_ret_t ret = VAPI_CQ_EMPTY; u_int32_t poll_cnt = 0; /* wait for something to arrive */ while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) { ret = VAPI_poll_cq(hca, cq, wc_desc_p); /* don't sleep if we already succeeded) */ if (ret != VAPI_CQ_EMPTY) { break; } usleep(poll_sleep); poll_cnt++; } /* if passed an AVH to destory - do it */ if (avh_p != NULL) { VAPI_destroy_addr_hndl(hca, *avh_p); } if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) { MTL_DEBUG1(__FUNCTION__ ": Failed to get completion on wq after %d polls.\n", max_poll); return VAPI_CQ_EMPTY; } if (ret != VAPI_OK) { MTL_DEBUG1(__FUNCTION__ ": VAPI_poll_cq failed with ret=%s on sq_cq\n", mtl_strerror_sym(ret)); return ret; } if (wc_desc_p->status != VAPI_SUCCESS) { MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n", wc_desc_p->status); } return VAPI_OK; } #endif /* OSM_VENDOR_INTF_MTL */ opensm-3.3.20/osmeventplugin/0000755000205000001450000000000012726325001013145 500000000000000opensm-3.3.20/osmeventplugin/src/0000755000205000001450000000000012726325001013734 500000000000000opensm-3.3.20/osmeventplugin/src/osmeventplugin.c0000644000205000001450000001614512462707723017122 00000000000000/* * Copyright (c) 2013 Mellanox Technologies LTD. All rights reserved. * Copyright (c) 2008 Voltaire, Inc. All rights reserved. * Copyright (c) 2007 The Regents of the University of California. * * 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. * */ #if HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include /** ========================================================================= * This is a simple example plugin which logs some of the events the OSM * generates to this interface. */ #define SAMPLE_PLUGIN_OUTPUT_FILE "/tmp/osm_sample_event_plugin_output" typedef struct _log_events { FILE *log_file; osm_log_t *osmlog; } _log_events_t; /** ========================================================================= */ static void *construct(osm_opensm_t *osm) { _log_events_t *log = malloc(sizeof(*log)); if (!log) return (NULL); log->log_file = fopen(SAMPLE_PLUGIN_OUTPUT_FILE, "a+"); if (!(log->log_file)) { osm_log(&osm->log, OSM_LOG_ERROR, "Sample Event Plugin: Failed to open output file \"%s\"\n", SAMPLE_PLUGIN_OUTPUT_FILE); free(log); return (NULL); } log->osmlog = &osm->log; return ((void *)log); } /** ========================================================================= */ static void destroy(void *_log) { _log_events_t *log = (_log_events_t *) _log; fclose(log->log_file); free(log); } /** ========================================================================= */ static void handle_port_counter(_log_events_t * log, osm_epi_pe_event_t * pc) { if (pc->symbol_err_cnt > 0 || pc->link_err_recover > 0 || pc->link_downed > 0 || pc->rcv_err > 0 || pc->rcv_rem_phys_err > 0 || pc->rcv_switch_relay_err > 0 || pc->xmit_discards > 0 || pc->xmit_constraint_err > 0 || pc->rcv_constraint_err > 0 || pc->link_integrity > 0 || pc->buffer_overrun > 0 || pc->vl15_dropped > 0 || pc->xmit_wait > 0) { fprintf(log->log_file, "Port counter errors for node 0x%" PRIx64 " (%s) port %d\n", pc->port_id.node_guid, pc->port_id.node_name, pc->port_id.port_num); } } /** ========================================================================= */ static void handle_port_counter_ext(_log_events_t * log, osm_epi_dc_event_t * epc) { fprintf(log->log_file, "Recieved Data counters for node 0x%" PRIx64 " (%s) port %d\n", epc->port_id.node_guid, epc->port_id.node_name, epc->port_id.port_num); } /** ========================================================================= */ static void handle_port_select(_log_events_t * log, osm_epi_ps_event_t * ps) { if (ps->xmit_wait > 0) { fprintf(log->log_file, "Port select Xmit Wait counts for node 0x%" PRIx64 " (%s) port %d\n", ps->port_id.node_guid, ps->port_id.node_name, ps->port_id.port_num); } } /** ========================================================================= */ static void handle_trap_event(_log_events_t *log, ib_mad_notice_attr_t *p_ntc) { if (ib_notice_is_generic(p_ntc)) { fprintf(log->log_file, "Generic trap type %d; event %d; from LID %u\n", ib_notice_get_type(p_ntc), cl_ntoh16(p_ntc->g_or_v.generic.trap_num), cl_ntoh16(p_ntc->issuer_lid)); } else { fprintf(log->log_file, "Vendor trap type %d; from LID %u\n", ib_notice_get_type(p_ntc), cl_ntoh16(p_ntc->issuer_lid)); } } /** ========================================================================= */ static void handle_lft_change_event(_log_events_t *log, osm_epi_lft_change_event_t *lft_change) { fprintf(log->log_file, "LFT changed for switch 0x%" PRIx64 " flags 0x%x LFTTop %u block %d\n", cl_ntoh64(osm_node_get_node_guid(lft_change->p_sw->p_node)), lft_change->flags, lft_change->lft_top, lft_change->block_num); } /** ========================================================================= */ static void report(void *_log, osm_epi_event_id_t event_id, void *event_data) { _log_events_t *log = (_log_events_t *) _log; switch (event_id) { case OSM_EVENT_ID_PORT_ERRORS: handle_port_counter(log, (osm_epi_pe_event_t *) event_data); break; case OSM_EVENT_ID_PORT_DATA_COUNTERS: handle_port_counter_ext(log, (osm_epi_dc_event_t *) event_data); break; case OSM_EVENT_ID_PORT_SELECT: handle_port_select(log, (osm_epi_ps_event_t *) event_data); break; case OSM_EVENT_ID_TRAP: handle_trap_event(log, (ib_mad_notice_attr_t *) event_data); break; case OSM_EVENT_ID_SUBNET_UP: fprintf(log->log_file, "Subnet up reported\n"); break; case OSM_EVENT_ID_HEAVY_SWEEP_START: fprintf(log->log_file, "Heavy sweep started\n"); break; case OSM_EVENT_ID_HEAVY_SWEEP_DONE: fprintf(log->log_file, "Heavy sweep completed\n"); break; case OSM_EVENT_ID_UCAST_ROUTING_DONE: fprintf(log->log_file, "Unicast routing completed %d\n", (osm_epi_ucast_routing_flags_t) event_data); break; case OSM_EVENT_ID_STATE_CHANGE: fprintf(log->log_file, "SM state changed\n"); break; case OSM_EVENT_ID_SA_DB_DUMPED: fprintf(log->log_file, "SA DB dump file updated\n"); break; case OSM_EVENT_ID_LFT_CHANGE: handle_lft_change_event(log, (osm_epi_lft_change_event_t *) event_data); break; case OSM_EVENT_ID_MAX: default: osm_log(log->osmlog, OSM_LOG_ERROR, "Unknown event (%d) reported to plugin\n", event_id); } fflush(log->log_file); } /** ========================================================================= * Define the object symbol for loading */ #if OSM_EVENT_PLUGIN_INTERFACE_VER != 2 #error OpenSM plugin interface version missmatch #endif osm_event_plugin_t osm_event_plugin = { OSM_VERSION, construct, destroy, report }; opensm-3.3.20/osmeventplugin/Makefile.am0000644000205000001450000000211412272264654015133 00000000000000 INCLUDES = -I$(srcdir)/../include \ -I$(includedir)/infiniband lib_LTLIBRARIES = libosmeventplugin.la if DEBUG DBGFLAGS = -ggdb -D_DEBUG_ else DBGFLAGS = -g endif libosmeventplugin_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 if HAVE_LD_VERSION_SCRIPT libosmeventplugin_version_script = -Wl,--version-script=$(srcdir)/libosmeventplugin.map else libosmeventplugin_version_script = endif osmeventplugin_api_version=$(shell grep LIBVERSION= $(srcdir)/libosmeventplugin.ver | sed 's/LIBVERSION=//') libosmeventplugin_la_SOURCES = src/osmeventplugin.c libosmeventplugin_la_LDFLAGS = -version-info $(osmeventplugin_api_version) \ -export-dynamic $(libosmeventplugin_version_script) libosmeventplugin_la_LIBADD = -L../complib $(OSMV_LDADD) -losmcomp libosmeventplugin_la_DEPENDENCIES = $(srcdir)/libosmeventplugin.map libosmeventpluginincludedir = $(includedir)/infiniband/complib libosmeventplugininclude_HEADERS = # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmeventplugin.map $(srcdir)/libosmeventplugin.ver opensm-3.3.20/osmeventplugin/Makefile.in0000644000205000001450000005114012726323426015144 00000000000000# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, # Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = osmeventplugin DIST_COMMON = $(libosmeventplugininclude_HEADERS) \ $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/config/libtool.m4 \ $(top_srcdir)/config/ltoptions.m4 \ $(top_srcdir)/config/ltsugar.m4 \ $(top_srcdir)/config/ltversion.m4 \ $(top_srcdir)/config/lt~obsolete.m4 \ $(top_srcdir)/config/osmvsel.m4 $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/include/config.h \ $(top_builddir)/include/opensm/osm_config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(libosmeventpluginincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am_libosmeventplugin_la_OBJECTS = \ libosmeventplugin_la-osmeventplugin.lo libosmeventplugin_la_OBJECTS = $(am_libosmeventplugin_la_OBJECTS) libosmeventplugin_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(libosmeventplugin_la_CFLAGS) $(CFLAGS) \ $(libosmeventplugin_la_LDFLAGS) $(LDFLAGS) -o $@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/opensm depcomp = $(SHELL) $(top_srcdir)/config/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libosmeventplugin_la_SOURCES) DIST_SOURCES = $(libosmeventplugin_la_SOURCES) HEADERS = $(libosmeventplugininclude_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFAULT_EVENT_PLUGIN = @DEFAULT_EVENT_PLUGIN@ DEFAULT_START = @DEFAULT_START@ DEFAULT_STOP = @DEFAULT_STOP@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ NODENAMEMAPFILE = @NODENAMEMAPFILE@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSM_CONFIG_DIR = @OPENSM_CONFIG_DIR@ OPENSM_CONFIG_FILE = @OPENSM_CONFIG_FILE@ OPENSM_CONFIG_SUB_DIR = @OPENSM_CONFIG_SUB_DIR@ OSMV_INCLUDES = @OSMV_INCLUDES@ OSMV_LDADD = @OSMV_LDADD@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PARTITION_CONFIG_FILE = @PARTITION_CONFIG_FILE@ PATH_SEPARATOR = @PATH_SEPARATOR@ PER_MOD_LOGGING_FILE = @PER_MOD_LOGGING_FILE@ PREFIX_ROUTES_FILE = @PREFIX_ROUTES_FILE@ QOS_POLICY_FILE = @QOS_POLICY_FILE@ RANLIB = @RANLIB@ RDMA_SERVICE = @RDMA_SERVICE@ RELEASE = @RELEASE@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TARBALL = @TARBALL@ TORUS2QOS_CONF_FILE = @TORUS2QOS_CONF_FILE@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ _LEX_ = @_LEX_@ _YACC_ = @_YACC_@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = -I$(srcdir)/../include \ -I$(includedir)/infiniband lib_LTLIBRARIES = libosmeventplugin.la @DEBUG_FALSE@DBGFLAGS = -g @DEBUG_TRUE@DBGFLAGS = -ggdb -D_DEBUG_ libosmeventplugin_la_CFLAGS = -Wall -Wwrite-strings $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1 @HAVE_LD_VERSION_SCRIPT_FALSE@libosmeventplugin_version_script = @HAVE_LD_VERSION_SCRIPT_TRUE@libosmeventplugin_version_script = -Wl,--version-script=$(srcdir)/libosmeventplugin.map osmeventplugin_api_version = $(shell grep LIBVERSION= $(srcdir)/libosmeventplugin.ver | sed 's/LIBVERSION=//') libosmeventplugin_la_SOURCES = src/osmeventplugin.c libosmeventplugin_la_LDFLAGS = -version-info $(osmeventplugin_api_version) \ -export-dynamic $(libosmeventplugin_version_script) libosmeventplugin_la_LIBADD = -L../complib $(OSMV_LDADD) -losmcomp libosmeventplugin_la_DEPENDENCIES = $(srcdir)/libosmeventplugin.map libosmeventpluginincludedir = $(includedir)/infiniband/complib libosmeventplugininclude_HEADERS = # headers are distributed as part of the include dir EXTRA_DIST = $(srcdir)/libosmeventplugin.map $(srcdir)/libosmeventplugin.ver all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign osmeventplugin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign osmeventplugin/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done libosmeventplugin.la: $(libosmeventplugin_la_OBJECTS) $(libosmeventplugin_la_DEPENDENCIES) $(libosmeventplugin_la_LINK) -rpath $(libdir) $(libosmeventplugin_la_OBJECTS) $(libosmeventplugin_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libosmeventplugin_la-osmeventplugin.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libosmeventplugin_la-osmeventplugin.lo: src/osmeventplugin.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmeventplugin_la_CFLAGS) $(CFLAGS) -MT libosmeventplugin_la-osmeventplugin.lo -MD -MP -MF $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Tpo -c -o libosmeventplugin_la-osmeventplugin.lo `test -f 'src/osmeventplugin.c' || echo '$(srcdir)/'`src/osmeventplugin.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Tpo $(DEPDIR)/libosmeventplugin_la-osmeventplugin.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='src/osmeventplugin.c' object='libosmeventplugin_la-osmeventplugin.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libosmeventplugin_la_CFLAGS) $(CFLAGS) -c -o libosmeventplugin_la-osmeventplugin.lo `test -f 'src/osmeventplugin.c' || echo '$(srcdir)/'`src/osmeventplugin.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-libosmeventpluginincludeHEADERS: $(libosmeventplugininclude_HEADERS) @$(NORMAL_INSTALL) test -z "$(libosmeventpluginincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libosmeventpluginincludedir)" @list='$(libosmeventplugininclude_HEADERS)'; test -n "$(libosmeventpluginincludedir)" || list=; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libosmeventpluginincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libosmeventpluginincludedir)" || exit $$?; \ done uninstall-libosmeventpluginincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(libosmeventplugininclude_HEADERS)'; test -n "$(libosmeventpluginincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ test -n "$$files" || exit 0; \ echo " ( cd '$(DESTDIR)$(libosmeventpluginincludedir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(libosmeventpluginincludedir)" && rm -f $$files ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libosmeventpluginincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-libosmeventpluginincludeHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES \ uninstall-libosmeventpluginincludeHEADERS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libosmeventpluginincludeHEADERS \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-libLTLIBRARIES \ uninstall-libosmeventpluginincludeHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: opensm-3.3.20/osmeventplugin/libosmeventplugin.map0000644000205000001450000000007012104655725017340 00000000000000OSMPMDB_1.0 { global: osm_event_plugin; local: *; }; opensm-3.3.20/osmeventplugin/libosmeventplugin.ver0000644000205000001450000000052412104655725017363 00000000000000# In this file we track the current API version # of the vendor interface (and libraries) # The version is built of the following # tree numbers: # API_REV:RUNNING_REV:AGE # API_REV - advance on any added API # RUNNING_REV - advance any change to the vendor files # AGE - number of backward versions the API still supports LIBVERSION=1:2:0