--- /dev/null
+##### Begin svn/gen1/trunk/src/userspace/osm/README.opensm-build
+
+# How to Build the OpenSM Subnet Manager
+# ----------------------------------------
+
+# This file is arranged as a shell script so you can paste or execute
+# it. This is for building from the SVN source at openib.org.
+
+# 1. Complete steps outlined in README.kernel-build.
+# 2. Complete steps outlined in README.user-build.
+
+# set TOP to wherever you've checked out the openib repository.
+TOP=/usr/src/openib
+
+export TSHOME=$TOP/src/linux-kernel/infiniband/include/
+export MTHOME=$TOP/src/userspace/hw/mellanox-hca/mthome/
+
+# Add util dir to path for makedepend
+export PATH=$TOP/src/userspace/osm/util:$PATH
+
+cd $TOP/src/userspace/osm
+make VENDOR=ts
+
+##### end
\ No newline at end of file
--- /dev/null
+Support new HOQ value for the ports feeding HCA ports
+
+Support Static Lid assignment with a flag for specifying a file with guid to lid.
+
+Support PKey comp in Path Record
+Support SL comp in Path Record
+
+Support VL traversal in Path Record - compute the SL accordingly
+ Make it a runtime option, So we do not pay the price if no SL are used.
+
+Support a fast Path Record mode - if the fabric is totally uniform in rate and
+ MTU. No need to traverse the path at all...
+
+Improve the MinHop routing algorithm such that it only calc the min hops
+for switches, then
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+/*
+ * Abstract:
+ * Windows-specific definitions
+ *
+ * Environment:
+ * Windows
+ *
+ * $Revision: $
+ */
+
+#ifndef _CONFIG_h_
+#define _CONFIG_h_
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <io.h>
+
+#define chmod(a,b) _chmod(a,b)
+#define S_IRUSR _S_IREAD
+#define S_IWUSR _S_IWRITE
+
+#define snprintf _snprintf
+#define fileno _fileno
+
+#define stat _stat
+#define fstat(a,b) fstat_alias((a),(b))
+
+inline int
+fstat_alias(int filedes, struct _stat *buf)
+{
+ return _fstat(filedes, buf);
+}
+
+#endif /*_CONFIG_h_ */
+
+
+
+
--- /dev/null
+DIRS=\
+ libvendor \
+ libopensm \
+ opensm
+
--- /dev/null
+OpenSM Partition Management
+---------------------------
+
+Roadmap:
+Phase 1 - provide partition management at the EndPort (HCA, Router and Switch
+ Port 0) level with no routing affects.
+Phase 2 - routing engine should take partitions into account.
+
+Phase 1 functionality:
+
+Supported Policy:
+
+1. EndPort partition groups are to be defined by listing the
+ PortGUIDs as full and limited members.
+
+2. Each partition group might be assigned an explicit P_Key (only the 15
+ LSB bits are valid) or the SM should assign it randomly.
+
+3. A flag should control the generation of IPoIB broadcast group for
+ that partition. Extra optional MGIDs can be provided to be setup (on
+ top of the IPoIB broadcast group).
+
+4. A global flag "Disconnect Unconfigured EndPorts": If TRUE prevents
+ EndPorts that are not explicitly defined as part of any partition
+ (thus "unconfigured") to communicate with any other EndPort. Otherwise, it
+ will let these EndPorts send packets to all other EndPorts.
+
+Functionality:
+
+1. The policy should be updated:
+ - during SM bringup
+ - after kill -HUP
+ - through SNMP (once it is supported)
+
+2. Partition tables will be updated on full sweep (new port/trap etc).
+ As a first step, the policy feasibility should be
+ verified. Feasibility could be limited by the EndPorts supports for
+ number of partitions, etc. Unrealizable policy should be reported
+ and extra rules ignored after providing error messages.
+
+3. Each EndPort will be assigned P_Keys as follows:
+
+ a. Default partition group limited membership as defined by rule #4 below.
+ (only the SM port will get 0xffff).
+
+ b. P_Keys for all partition groups it is part of as defined in
+ the policy.
+
+ c. P_Key update will preserve index for the existing P_Keys on the
+ port. If port has limited resources that will require reuse of,
+ on index a message will be provided and some of the settings will be
+ ommitted. P_Key indexes will not change under any circumstances.
+
+4. Each Switch Leaf Port (a switch port that is connected to an
+ EndPort) should be configured according to the same rules that
+ apply to the EndPort connected to that switch port.
+ This actually enables unauthorized port isolation (with future
+ usage of M_Key and ProtectBits).
+
+5. Policy entries matching a non EndPort will be flagged as
+ erroneous in the log file and ignored.
+
+6. At the end of the P_Key setting phase, a check for successful
+ setting should be made.
+ Errors should be clearly logged and cause a new sweep.
+
+7. Each partition that is marked to support IPoIB should define a
+ broadcast MGRP. If the partition does not support IPoIB, it should
+ define a dummy MGRP with parameters blocking IPoIB drivers from
+ registering to it.
+
+Phase 2 functionality:
+
+The partition policy should be considered during the routing such that
+links are associated with particular partition or a set of
+partitions. Policy should be enhanced to provide hints for how to do
+that (correlating to QoS too). The exact algorithm is TBD.
+
+
--- /dev/null
+Current OpenSM Routing
+1/2/07
+
+OpenSM offers three 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. 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.
+
+OpenSM now also offers 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 ports 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 when neither UPDN or the file method are
+specified.
+
+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 <equalize-ignore-guids-file>
+-ignore-guids <equalize-ignore-guids-file>
+ 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.
+
+
+UPDN Algorithm Usage
+
+Activation through OpenSM
+
+Use '-R updn' option (instead of old '-u') to activate the UPDN algorithm.
+Use `-a <guid_list_file>' 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).
+
+
+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 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.
+Fat-tree algorithm supports topologies that comply 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.
+*ports that are connected to the same remote switch are referenced as
+'port group'.
+
+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.
+
+The algorithm also dumps CA ordering file (osm-ftree-ca-order.dump) in the
+same directory where the OpenSM log resides. This ordering file provides the
+CA order that may be used to create efficient communication pattern, that
+will match the routing tables.
+
+
+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.
+
--- /dev/null
+Modular Routine Engine
+
+Modular routing engine structure has been added to allow
+for ease of "plugging" new routing modules.
+
+Currently, only unicast callbacks are supported. Multicast
+can be added later.
+
+One of existing routing modules 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 dump 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 dump 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 dump file (in order
+ to disable this GUIDs may be removed from the dump file or zeroed)
+
+The dump file format is compatible with output of 'ibroute' util and for
+whole fabric may be generated with script like this:
+
+ for sw_lid in `ibswitches | awk '{print $NF}'` ; do
+ ibroute $sw_lid
+ done > /path/to/dump_file
+
+, or using DR paths:
+
+ for sw_dr in `ibnetdiscover -v \
+ | sed -ne '/^DR path .* switch /s/^DR path \[\(.*\)\].*$/\1/p' \
+ | sed -e 's/\]\[/,/g' \
+ | sort -u` ; do
+ ibroute -D ${sw_dr}
+ done > /path/to/dump_file
+
+This script is dump_lfts.sh
+
+In order to activate new module use:
+
+ opensm -R file -U /path/to/dump_file
+
+If the dump_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 dump
+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 dump 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'.
+
+NOTE: ibroute has been updated (for switch management ports) to support this.
+Also, lmc was added to switch management ports. ibroute needs to be r7855 or
+later from the trunk.
+
+
--- /dev/null
+ OpenSM Release Notes 2.0.5
+ ============================
+
+Version: OpenFabrics Enterprise Distribution (OFED) 1.1
+Repo: https://openib.org/svn/gen2/branches/1.1/src/userspace/management/osm
+Version: 9535 (openib-2.0.5)
+Date: October 2006
+
+1 Overview
+----------
+This document describes the contents of the OpenSM OFED 1.1 release.
+OpenSM is an InfiniBand compliant Subnet Manager and Administration,
+and runs on top of OpenIB. The OpenSM version for this release
+is openib-2.0.5
+
+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 Major Bug Fixes
+5 Main Verification Flows
+6 Qualified software stacks and devices
+
+1.1 Major New Features
+
+* Partition manager:
+ The partition manager provides a means to setup multiple partitions
+ by providing a partition policy file. For details please read the
+ doc/partition-config.txt or the opensm man page.
+
+* Basic QoS Manager:
+ Provides a uniform configuration of the entire fabric with values defined
+ in the OpenSM options file. The options support different settings for
+ CAs, Switches, and Routers. Note that this is disabled by default and
+ using -Q enables QoS fabric setup.
+
+* Loading pre-routes from a file:
+ A new routing module enables loading pre-routes from a file.
+ To use this option you should use the command line options:
+ "-R file --U <your routing file>" or
+ "--routing_engine file --ucast_file <your routing file>"
+ For more information refer to the file doc/modular-routing.txt
+ or the opensm man page.
+
+* SA MultiPathRecord support:
+ The SA can now handle requests for multiple PathRecords in one query.
+ This includes methods SA GetMulti/GetMultiResp and dual sided RMPP.
+
+* PPC64 is now QAed and supported
+
+* Support LMC > 0 for Switch Enhanced Port 0:
+ Allows enhanced switch port 0 (ESP0) to have a non zero
+ LMC. Use the configured subnet wide LMC for this. Modifications were
+ necessary to the LID assignment and routing to support this.
+ Also, added an option to the configuration to use LMC configured for
+ subnet for enhanced switch port 0 or set it to 0 even if a non zero
+ LMC is configured for the subnet. The default is currently the
+ latter option. The new configuration option is: lmc_esp0
+
+1.2 Minor New Features:
+
+* IPoIB broadcast group configuration:
+ It is now possible to control the IPoIB broadcast group parameters
+ (MTU, rate, SL) through the partitions configuration file.
+
+* Limiting OpenSM log file size:
+ By providing the command line option: "-L <size in MB>" or
+ "--log_limit <size in MB>" the user can limit the generated log
+ file size. When specified, the log file will be truncated upon reaching
+ this limit.
+
+* Favor 1K MTU for Tavor (MT23108) HCA
+ In cases where a PathRecord or MultiPathRecord is queried and the
+ requestor does not specify the MTU or does specify it in a way
+ that allows for MTU to be 1K and one of the path ends in a Tavor,
+ limit the MTU to 1K max.
+
+* Man pages:
+ Added opensm.8 and osmtest.8
+
+* Leaf VL stall count control:
+ A new parameter (leaf_vl_stall_count) for controlling the number of
+ sequential packets dropped on a switch port driving a HCA/TCA/Router
+ that cause the port to enter the VLStalled state was added to the
+ options file.
+
+* SM Polling/Handover defaults changed
+ The default SMInfo polling retries was decreased from 18 to 4
+ which reduces the default handover time from 3 min to 40 seconds.
+
+1.3 Library API Changes
+
+* cl_mem* APIs deprecated in complib:
+ These functions are now considered as deprecated and should be
+ replaced by direct calls to malloc, free, memset, etc.
+
+* osm_log_init_v2 API added in libopensm:
+ Supports providing the new option for log file truncation.
+
+1.4 Software Dependencies
+
+OpenSM depends on the installation of either OFED 1.1, OFED 1.0,
+OpenIB gen2 (e.g. IBG2 distribution), OpenIB gen1 (e.g. IBGD
+distribution), or Mellanox VAPI stacks. The qualified driver versions
+are provided in Table 2, "Qualified IB Stacks".
+
+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).
+
+* No "port down" event handling:
+ Changing the switch port through which OpenSM connects to the IB
+ fabric may cause incorrect operation. Please restart OpenSM whenever
+ such a connectivity change is made.
+
+* Changing connections during SM operation:
+ Under some conditions the SM can get confused by a change in
+ cabling (moving a cable from one switch port to the other) and
+ momentarily see this as having the same GUID appear connected
+ to two different IB ports. Under some conditions, when the SM fails to
+ get the corresponding change event it might mistakenly report this case
+ as a "duplicated GUID" case and abort. It is advisable to double-check
+ the syslog after each such change in connectivity and restart
+ OpenSM if it has exited.
+
+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-24.1.1.5 and C14-62.1.1.22 (Initialization):
+ GUIDInfo - SM should enable assigning Port GUIDInfo.
+
+* 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:P_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 Major Bug Fixes
+-----------------
+
+The following is a list of bugs that were fixed. Note that other less critical
+or visible bugs were also fixed.
+
+* "Broken" fabric (duplicated port GUIDs) handling improved
+ Replace assert with a real check to handle invalid physical port
+ in osm_node_info_rcv.c which could occur on a broken fabric
+
+* SA client synchronous request failed but status returned was IB_SUCCESS
+ even if there was no response.
+ There was a missing setting of the status in the synchronous case.
+
+* Memory leak fixes:
+ 1. In libvendor/osm_vendor_ibumad.c:osm_vendor_get_all_port_attr
+ 2. In libvendor/osm_vendor_ibumad_sa.c:__osmv_sa_mad_rcv_cb
+ 3. On receiving SMInfo SA request from a node that does not share a
+ partition, the response mad was allocated but never free'd
+ as it was never sent.
+
+* Set(InformInfo) OpenSM Deadlock:
+ When receiving a request with unknown LID
+
+* PathRecord to inconsistent multicast destination:
+ Fix the return error when multicast destination is not consistently
+ indicated.
+
+* Remove double calculation of reversible path
+ In osm_sa_path_record.c:__osm_pr_rcv_get_lid_pair_path a PathRecord
+ query used to double check if the path is reversible
+
+* Some PathRecord log messages use "net order":
+ Fix GUID net to host conversion in some osm_log messages
+
+* DR/LID routed SMPs direction bit handling:
+ osm_resp.c:osm_resp_make_resp_smp, set direction bit only if direct
+ routed class. This bug caused two issues:
+ 1. Get/Set responses always had direction bit set.
+ 2. Trap represses never had direction bit set.
+ The direction bit needs setting in direct routed responses and it
+ doesn't exist in LID routed responses.
+ osm_sm_mad_ctrl.c: did not detect the "direction bit" correctly.
+
+* OpenSM crash due to transaction lookup (interop with Cisco stack)
+ When a wire TID that maps to internal TID of zero (after applying
+ mask) was received the lookup of the transaction was successful.
+ The stale transaction pointed to "free'd" memory.
+
+* Better handling for Path/MultiPath requests for raw traffic
+
+* Wrong ProducerType provided in Notice Reports:
+ When formating an SM generated report, the ProducerType was using
+ CL_NTOH32 which can not be used to format a 24bit network order number.
+
+* OpenSM break on PPC64
+ complib: Fixed memory corruption in cl_pool.c:cl_qcpool_init. This
+ affected big endian 64-bit architectures only.
+
+* Illegal Set(InformInfo) was wrongly successful in updating the SMDB
+ osm_sa_informinfo.c: In osm_infr_rcv_process_set_method, if sending
+ error, don't call osm_infr_rcv_process_set_method
+
+* RMPP queries of InformInfoRecord fail
+ ib_types.h: Pad ib_inform_info_record_t to be modulo 8 in size so
+ that attribute offset is calculated properly
+
+* Returning "invalid request" rather than "unsupported method/attribute"
+ In these cases, a noncompliant response was being provided.
+
+* Noncompliant response for SubnAdmGet(PortInfoRecord) with no match
+ osm_pir_rcv_process, now returns "SA no records error" for SubnAdmGet
+ with 0 records found
+
+* Noncompliant non base LID returned by some queries:
+ The following attributes used to return the request LID rather than
+ its base LID in responses: PKeyTableRecord, GUIDInfoRecord,
+ SLtoVLMappingTableRecord, VLArbitrationTableRecord, LinkRecord
+
+* Noncompliant SubnAdmGet and SubnAdmGetTable:
+ Mixing of error codes in case of no records or multiple records
+ fixed for the attributes:
+ LinearForwardingTableRecord, GUIDInfoRecord,
+ VLArbitrationTableRecord, LinkRecord, PathRecord
+
+* segfault in InformInfo flows
+ Under stress concurrent Set/Delete/Get flows. Fixed by adding
+ missing lock.
+
+* SA queries containing LID out if range did not return ERR_REQ_INVALID
+
+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 Qualification
+----------------
+
+Table 2 - Qualified IB Stacks
+=============================
+
+Stack | Version
+-----------------------------------------|--------------------------
+OFED | 1.1
+OFED | 1.0
+OpenIB Gen2 (IBG2 distribution) | 1.0
+OpenIB Gen1 (IBGD distribution) | 1.8.0
+VAPI (Mellanox InfiniBand HCA Driver) | 3.2 and later
+
+Table 3 - Qualified Devices and Corresponding Firmware
+======================================================
+
+Mellanox
+Device | FW versions
+--------|-----------------------------------------------------------
+MT43132 | InfiniScale - fw-43132 5.2.0 (and later)
+MT47396 | InfiniScale III - fw-47396 0.5.0 (and later)
+MT23108 | InfiniHost - fw-23108 3.3.2 (and later)
+MT25204 | InfiniHost III Lx - fw-25204 1.0.1i (and later)
+MT25208 | InfiniHost III Ex (InfiniHost Mode) - fw-25208 4.6.2 (and later)
+MT25208 | InfiniHost III Ex (MemFree Mode) - fw-25218 5.0.1 (and later)
+
+QLogic/PathScale
+Device | Note
+--------|-----------------------------------------------------------
+iPath | QHT6040 (PathScale InfiniPath HT-460)
+iPath | QHT6140 (PathScale InfiniPath HT-465)
+iPath | QLE6140 (PathScale InfiniPath PE-880)
+
+Note: 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.
+
--- /dev/null
+Trivial low level QoS configuration proposition
+===============================================
+
+Basically there is 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 - High priority VL Arbitration table (IBA 7.6.9) template
+ qos_vlarb_high - Low 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 the 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_<type>_"
+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
+
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
--- /dev/null
+!if $(FREEBUILD)\r
+TARGETNAME=ibtrapgen\r
+!else\r
+TARGETNAME=ibtrapgend\r
+!endif\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+ main.c \\r
+ ibtrapgen.c\r
+\r
+\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+ $(LIBPATH)\*\ibal.lib \\r
+ $(LIBPATH)\*\complib.lib \\r
+ $(TARGETPATH)\*\osmv_ibal.lib \\r
+ $(TARGETPATH)\*\opensm_ibal.lib\r
+!else\r
+ $(LIBPATH)\*\ibald.lib \\r
+ $(LIBPATH)\*\complibd.lib \\r
+ $(TARGETPATH)\*\osmv_ibald.lib \\r
+ $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+ $(OSM_HOME)\include; \\r
+ $(OSM_HOME); \\r
+ $(WINIBHOME)\inc; \\r
+ $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+\r
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+/*
+ * Abstract:
+ * Implementation of ibtrapgen_t.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include "ibtrapgen.h"
+
+#define GUID_ARRAY_SIZE 64
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ This function initializes the main object, the log and the Osm Vendor
+*/
+ib_api_status_t
+ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+ IN ibtrapgen_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ )
+{
+ ib_api_status_t status;
+
+ /* just making sure - cleanup the static global obj */
+ cl_memclr( p_ibtrapgen, sizeof( *p_ibtrapgen ) );
+
+ /* construct and init the log */
+ p_ibtrapgen->p_log = (osm_log_t *)cl_malloc(sizeof(osm_log_t));
+ osm_log_construct( p_ibtrapgen->p_log );
+ status = osm_log_init( p_ibtrapgen->p_log, p_opt->force_log_flush,
+ 0x0001, p_opt->log_file,FALSE );
+ if( status != IB_SUCCESS )
+ return ( status );
+
+ osm_log_set_level( p_ibtrapgen->p_log, log_flags );
+
+ /* finaly can declare we are here ... */
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+ "ibtrapgen_init: [\n" );
+
+ /* assign all the opts */
+ p_ibtrapgen->p_opt = p_opt;
+
+ /* initialize the osm vendor service object */
+ p_ibtrapgen->p_vendor = osm_vendor_new( p_ibtrapgen->p_log,
+ p_opt->transaction_timeout );
+
+ if( p_ibtrapgen->p_vendor == NULL )
+ {
+ status = IB_INSUFFICIENT_RESOURCES;
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_init: ERR 0001: "
+ "Unable to allocate vendor object" );
+ goto Exit;
+ }
+
+ /* all mads (actually wrappers) are taken and returned to a pool */
+ osm_mad_pool_construct( &p_ibtrapgen->mad_pool );
+ status = osm_mad_pool_init(
+ &p_ibtrapgen->mad_pool, p_ibtrapgen->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_FUNCS,
+ "ibtrapgen_init: ]\n" );
+ return ( status );
+}
+
+/****f* opensm: SM/__ibtrapgen_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_rcv_callback(
+ IN osm_madw_t *p_madw,
+ IN void *bind_context,
+ IN osm_madw_t *p_req_madw )
+{
+ ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_rcv_callback );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_VERBOSE,
+ "__ibtrapgen_rcv_callback: Got callback\n",
+ cl_ntoh64(p_madw->p_mad->trans_id) );
+
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/****f* opensm: SM/__ibtrapgen_send_err_cb
+ * NAME
+ * __ibtrapgen_send_err_cb
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__ibtrapgen_send_err_cb(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ ibtrapgen_t* p_ibtrapgen = (ibtrapgen_t*)bind_context;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, __ibtrapgen_send_err_callback );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "__ibtrapgen_send_err_cb: ERR 0011: "
+ "MAD completed in error (%s).\n",
+ ib_get_err_str( p_madw->status ) );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "__ibtrapgen_send_err_cb: ERR 0012: "
+ "We shouldn't be here!! TID:0x%016" PRIx64 ".\n",
+ cl_ntoh64(p_madw->p_mad->trans_id) );
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen )
+{
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+ osm_bind_info_t bind_info;
+ uint8_t i;
+
+ OSM_LOG_ENTER( p_ibtrapgen->p_log, ibtrapgen_bind );
+
+ /*
+ * Call the transport layer for a list of local port
+ * GUID values.
+ */
+ status = osm_vendor_get_all_port_attr( p_ibtrapgen->p_vendor,
+ attr_array, &num_ports );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0002: "
+ "Failure getting local port attributes (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ /* make sure the requested port exists */
+ if ( p_ibtrapgen->p_opt->port_num > num_ports )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0003: "
+ "Given port number out of range %u > %u\n",
+ p_ibtrapgen->p_opt->port_num , num_ports );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+
+ for ( i = 0 ; i < num_ports ; i++ )
+ {
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_INFO,
+ "ibtrapgen_bind: Found port number:%u "
+ " with GUID:0x%016" PRIx64 "\n",
+ i, cl_ntoh64(attr_array[i].port_guid) );
+ }
+ /* check if the port is active */
+/* if (attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state < 4) */
+/* { */
+/* osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR, */
+/* "ibtrapgen_bind: ERR 0004: " */
+/* "Given port number link state is not active: %s.\n", */
+/* ib_get_port_state_str( */
+/* attr_array[p_ibtrapgen->p_opt->port_num - 1].link_state ) */
+/* ); */
+/* status = IB_NOT_FOUND; */
+/* goto Exit; */
+/* } */
+
+ p_ibtrapgen->port_guid = attr_array[p_ibtrapgen->p_opt->port_num - 1].port_guid;
+ /* save sm_lid as we need it when sending the Trap (dest lid)*/
+ p_ibtrapgen->p_opt->sm_lid = attr_array[p_ibtrapgen->p_opt->port_num - 1].sm_lid;
+
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+ "ibtrapgen_bind: Port Num:%u "
+ "GUID:0x%016"PRIx64"\n",
+ p_ibtrapgen->p_opt->port_num,
+ p_ibtrapgen->port_guid );
+
+ /* ok finaly bind the sa interface to this port */
+ /* TODO - BIND LIKE THE osm_sm_mad_ctrl does */
+ bind_info.class_version = 1;
+ bind_info.is_report_processor = TRUE;
+ bind_info.is_responder = TRUE;
+ bind_info.is_trap_processor = TRUE;
+ bind_info.mad_class = IB_MCLASS_SUBN_LID;
+ bind_info.port_guid = p_ibtrapgen->port_guid;
+ bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE;
+ bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE;
+
+ osm_log(p_ibtrapgen->p_log, OSM_LOG_DEBUG,
+ "ibtrapgen_bind: Trying to bind to GUID:0x%016"PRIx64"\n",
+ bind_info.port_guid );
+
+ p_ibtrapgen->h_bind = osm_vendor_bind( p_ibtrapgen->p_vendor,
+ &bind_info,
+ &p_ibtrapgen->mad_pool,
+ __ibtrapgen_rcv_callback,
+ __ibtrapgen_send_err_cb,
+ p_ibtrapgen );
+
+ if( p_ibtrapgen->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ibtrapgen->p_log, OSM_LOG_ERROR,
+ "ibtrapgen_bind: ERR 0005: "
+ "Unable to bind to SA\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ibtrapgen->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen )
+{
+ if( p_ibtrapgen->p_vendor )
+ {
+ osm_vendor_delete( &p_ibtrapgen->p_vendor );
+ }
+
+ osm_log_destroy( p_ibtrapgen->p_log );
+ cl_free( p_ibtrapgen->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+
+ib_api_status_t
+ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen )
+{
+ osm_madw_t* p_report_madw;
+ ib_mad_notice_attr_t* p_report_ntc;
+ ib_mad_t* p_mad;
+ ib_smp_t* p_smp_mad;
+ osm_mad_addr_t mad_addr;
+ static atomic32_t trap_fwd_trans_id = 0x02DAB000;
+ ib_api_status_t status;
+ osm_log_t *p_log = p_ibtrapgen->p_log;
+ uint16_t i;
+
+ OSM_LOG_ENTER( p_log, ibtrapgen_run );
+
+ osm_log( p_log, OSM_LOG_INFO,
+ "ibtrapgen_run: "
+ "Sending trap:%u from LID:0x%X %u times\n",
+ p_ibtrapgen->p_opt->trap_num,
+ p_ibtrapgen->p_opt->lid,
+ p_ibtrapgen->p_opt->number );
+
+ printf("-V- SM lid is : 0x%04X\n",cl_ntoh16(p_ibtrapgen->p_opt->sm_lid));
+ mad_addr.dest_lid = (p_ibtrapgen->p_opt->sm_lid);
+ /* ??? - what is path_bits? What should be the value here?? */
+ mad_addr.path_bits = 0;
+ /* ??? - what is static_rate? What should be the value here?? */
+ mad_addr.static_rate = 0;
+
+ mad_addr.addr_type.smi.source_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ mad_addr.addr_type.smi.port_num = p_ibtrapgen->p_opt->src_port;
+
+ for (i = 1 ; i <= p_ibtrapgen->p_opt->number ; i++ )
+ {
+ p_report_madw = osm_mad_pool_get( &p_ibtrapgen->mad_pool,
+ p_ibtrapgen->h_bind,
+ MAD_BLOCK_SIZE,
+ &mad_addr );
+
+ if( !p_report_madw )
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "ibtrapgen_run: ERR 00020: "
+ "osm_mad_pool_get failed.\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_report_madw->resp_expected = FALSE;
+
+ /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+ p_mad = osm_madw_get_mad_ptr( p_report_madw );
+ ib_mad_init_new(p_mad,
+ IB_MCLASS_SUBN_LID,
+ 1,
+ IB_MAD_METHOD_TRAP,
+ cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+ IB_MAD_ATTR_NOTICE,
+ 0);
+
+ p_smp_mad = osm_madw_get_smp_ptr( p_report_madw );
+
+ /* The payload is analyzed as mad notice attribute */
+ p_report_ntc = (ib_mad_notice_attr_t*)(ib_smp_get_payload_ptr(p_smp_mad));
+
+ cl_memclr( p_report_ntc, sizeof(*p_report_ntc) );
+ p_report_ntc->generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type(p_report_ntc, 2); /* A switch generator */
+ p_report_ntc->g_or_v.generic.trap_num = cl_hton16(p_ibtrapgen->p_opt->trap_num);
+ p_report_ntc->issuer_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ if (p_ibtrapgen->p_opt->trap_num == 128)
+ {
+ p_report_ntc->data_details.ntc_128.sw_lid = cl_hton16(p_ibtrapgen->p_opt->lid);
+ }
+ else
+ {
+ p_report_ntc->data_details.ntc_129_131.lid =
+ cl_hton16(p_ibtrapgen->p_opt->lid);
+ p_report_ntc->data_details.ntc_129_131.port_num =
+ p_ibtrapgen->p_opt->src_port;
+ }
+
+ status = osm_vendor_send(p_report_madw->h_bind, p_report_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "ibtrapgen_run: ERR 0021: "
+ "osm_vendor_send. status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+ osm_log(p_log, OSM_LOG_INFO,
+ "ibtrapgen_run: "
+ "Sent trap number:%u out of:%u\n",
+ i,
+ p_ibtrapgen->p_opt->number );
+ /* sleep according to rate time. The usleep is in usec - need to revert
+ the milisecs to usecs. */
+ usleep(p_ibtrapgen->p_opt->rate*1000);
+ }
+
+ Exit:
+ // sleep(3);
+ OSM_LOG_EXIT( p_log );
+ return(status);
+}
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ * Declaration of ibtrapgen_t.
+ * This object represents the ibtrapgen object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#ifndef _IBTRAPGEN_H_
+#define _IBTRAPGEN_H_
+
+#include <complib/cl_qmap.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+
+/****h* Trap_Generator_App/Ibtrapgen
+ * NAME
+ * Ibtrapgen
+ *
+ * DESCRIPTION
+ * The Ibtrapgen object create/join and leave multicast group.
+ *
+ * AUTHOR
+ * Yael Kalka, Mellanox.
+ *
+ *********/
+
+/****s* Trap_Generator_App/ibtrapgen_opt_t
+ * NAME
+ * ibtrapgen_opt_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen options structure. This structure contains the various
+ * specific configuration parameters for ibtrapgen.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen_opt
+{
+ uint8_t trap_num;
+ uint16_t number;
+ uint16_t rate;
+ uint16_t lid;
+ uint16_t sm_lid;
+ uint8_t src_port;
+ uint8_t port_num;
+ uint32_t transaction_timeout;
+ boolean_t force_log_flush;
+ char *log_file;
+} ibtrapgen_opt_t;
+/*
+ * FIELDS
+ *
+ * trap_num
+ * Trap number to generate.
+ *
+ * number
+ * Number of times trap should be generated.
+ *
+ * rate
+ * Rate of trap generation (in miliseconds)
+ *
+ * lid
+ * Lid from which the trap should be generated.
+ *
+ * src_port
+ * Source port from which the trap should be generated.
+ *
+ * port_num
+ * Port num used for communicating with the SA.
+ *
+ * SEE ALSO
+ *********/
+
+/****s* Trap Generator App/ibtrapgen_t
+ * NAME
+ * ibtrapgen_t
+ *
+ * DESCRIPTION
+ * Ibtrapgen structure.
+ *
+ * This object should be treated as opaque and should
+ * be manipulated only through the provided functions.
+ *
+ * SYNOPSYS
+ */
+typedef struct _ibtrapgen
+{
+ osm_log_t *p_log;
+ struct _osm_vendor *p_vendor;
+ osm_bind_handle_t h_bind;
+ osm_mad_pool_t mad_pool;
+
+ ibtrapgen_opt_t *p_opt;
+ ib_net64_t port_guid;
+} ibtrapgen_t;
+/*
+ * FIELDS
+ * p_log
+ * Log facility used by all Ibtrapgen 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
+ *
+ * p_opt
+ * ibtrapgen options structure
+ *
+ * guid
+ * guid for the port over which ibtrapgen is running.
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_destroy
+ * NAME
+ * ibtrapgen_destroy
+ *
+ * DESCRIPTION
+ * The ibtrapgen_destroy function destroys an ibtrapgen object, releasing
+ * all resources.
+ *
+ * SYNOPSIS
+ */
+void ibtrapgen_destroy( IN ibtrapgen_t * p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to a Trap_Generator_App object to destroy.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ *
+ * NOTES
+ * Performs any necessary cleanup of the specified Trap_Generator_App object.
+ * Further operations should not be attempted on the destroyed object.
+ * This function should only be called after a call to ibtrapgen_init.
+ *
+ * SEE ALSO
+ * ibtrapgen_init
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_init
+ * NAME
+ * ibtrapgen_init
+ *
+ * DESCRIPTION
+ * The ibtrapgen_init function initializes a Trap_Generator_App object for use.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_init( IN ibtrapgen_t * const p_ibtrapgen,
+ IN ibtrapgen_opt_t * const p_opt,
+ IN const osm_log_level_t log_flags
+ );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_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 Trap_Generator_App object was initialized successfully.
+ *
+ * NOTES
+ * Allows calling other Trap_Generator_App methods.
+ *
+ * SEE ALSO
+ * ibtrapgen object, ibtrapgen_construct, ibtrapgen_destroy
+ *********/
+
+
+/****f* Trap_Generator_App/ibtrapgen_bind
+ * NAME
+ * ibtrapgen_bind
+ *
+ * DESCRIPTION
+ * Binds ibtrapgen to a local port.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_bind( IN ibtrapgen_t * p_ibtrapgen );
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS if OK
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+/****f* Trap_Generator_App/ibtrapgen_run
+ * NAME
+ * ibtrapgen_run
+ *
+ * DESCRIPTION
+ * Runs the ibtrapgen flow: Creation of traps.
+ *
+ * SYNOPSIS
+ */
+ib_api_status_t ibtrapgen_run( IN ibtrapgen_t * const p_ibtrapgen );
+
+/*
+ * PARAMETERS
+ * p_ibtrapgen
+ * [in] Pointer to an ibtrapgen_t object.
+ *
+ * RETURN VALUES
+ * IB_SUCCESS on success
+ *
+ * NOTES
+ *
+ * SEE ALSO
+ *********/
+
+#endif /* */
--- /dev/null
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ This software program is available to you under a choice of one of two
+ licenses. You may choose to be licensed under either the GNU General Public
+ License (GPL) Version 2, June 1991, available at
+ http://www.fsf.org/copyleft/gpl.html, or the Intel BSD + Patent License,
+ the text of which follows:
+
+ "Recipient" has requested a license and Intel Corporation ("Intel")
+ is willing to grant a license for the software entitled
+ InfiniBand(tm) System Software (the "Software") being provided by
+ Intel Corporation.
+
+ The following definitions apply to this License:
+
+ "Licensed Patents" means patent claims licensable by Intel Corporation which
+ are necessarily infringed by the use or sale of the Software alone or when
+ combined with the operating system referred to below.
+
+ "Recipient" means the party to whom Intel delivers this Software.
+ "Licensee" means Recipient and those third parties that receive a license to
+ any operating system available under the GNU Public License version 2.0 or
+ later.
+
+ Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+
+ The license is provided to Recipient and Recipient's Licensees under the
+ following terms.
+
+ Redistribution and use in source and binary forms of the Software, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+ Redistributions of source code of the Software may retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ Redistributions in binary form of the Software may reproduce the above
+ copyright notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ Neither the name of Intel Corporation nor the names of its contributors shall
+ be used to endorse or promote products derived from this Software without
+ specific prior written permission.
+
+ Intel hereby grants Recipient and Licensees a non-exclusive, worldwide,
+ royalty-free patent license under Licensed Patents to make, use, sell, offer
+ to sell, import and otherwise transfer the Software, if any, in source code
+ and object code form. This license shall include changes to the Software that
+ are error corrections or other minor changes to the Software that do not add
+ functionality or features when the Software is incorporated in any version of
+ a operating system that has been distributed under the GNU General Public
+ License 2.0 or later. This patent license shall apply to the combination of
+ the Software and any operating system licensed under the GNU Public License
+ version 2.0 or later if, at the time Intel provides the Software to
+ Recipient, such addition of the Software to the then publicly
+ available versions of such operating system available under the GNU
+ Public License version 2.0 or later (whether in gold, beta or alpha
+ form) causes such combination to be covered by the Licensed
+ Patents. The patent license shall not apply to any other
+ combinations which include the Software. No hardware per se is
+ licensed hereunder.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ --------------------------------------------------------------------------*/
+
+
+/*
+ * Abstract:
+ * Command line interface for ibtrapgen.
+ * Parse and fill in the options and call the actual code.
+ * Implemented in ibtrapgen:
+ * Initialize the ibmgrp object (and log)
+ * Bind ibmgrp to the requested IB port.
+ * Run the actual command
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifndef __WIN__
+#include <getopt.h>
+#endif
+#include <complib/cl_debug.h>
+#include <errno.h>
+#include "ibtrapgen.h"
+
+#define DEFAULT_RETRY_COUNT 3
+#define DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+ibtrapgen_is_debug()
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage( )
+{
+ printf( "\n------- ibtrapgen - Usage and options ----------------------\n" );
+ printf( "Usage: one of the following optional flows:\n" );
+ printf(" ibtrapgen -t|--trap_num <TRAP_NUM> -n|--number <NUM_TRAP_CREATIONS>\n"
+ " -r|--rate <TRAP_RATE> -l|--lid <LIDADDR> \n"
+ " -s|--src_port <SOURCE_PORT> -p|--port_num <PORT_NUM>\n" );
+ printf( "\nOptions:\n" );
+ printf( "-t <TRAP_NUM>\n"
+ "--trap_num <TRAP_NUM>\n"
+ " This option specifies the number of the trap to generate.\n"
+ " Valid values are 128-131.\n" );
+ printf( "-n <NUM_TRAP_CREATIONS>\n"
+ "--number <NUM_TRAP_CREATIONS>\n"
+ " This option specifies the number of times to generate this trap.\n"
+ " If not specified - default to 1.\n" );
+ printf( "-r <TRAP_RATE>\n"
+ "--rate <TRAP_RATE>\n"
+ " This option specifies the rate of the trap generation.\n"
+ " What is the time period between one generation and another?\n"
+ " The value is given in miliseconds. \n"
+ " If the number of trap creations is 1 - this value is ignored.\n" );
+ printf( "-l <LIDADDR>\n"
+ "--lid <LIDADDR>\n"
+ " This option specifies the lid address from where the trap should\n"
+ " be generated.\n" );
+ printf( "-s <SOURCE_PORT>\n"
+ "--src_port <SOURCE_PORT>\n"
+ " This option specifies the port number from which the trap should\n"
+ " be generated. If trap number is 128 - this value is ignored (since\n"
+ " trap 128 is not sent with a specific port number)\n" );
+ printf( "-p <port num>\n"
+ "--port_num <port num>\n"
+ " This is the port number used for communicating with\n"
+ " the SA.\n" );
+ printf( "-h\n"
+ "--help\n" " Display this usage info then exit.\n\n" );
+ printf( "-o\n"
+ "--out_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( "-x <flags>\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 -x, ibtrapgen defaults to ERROR + INFO (0x3).\n"
+ " Specifying -x 0 disables all messages.\n"
+ " Specifying -x 0xFF enables all messages (see -V).\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ Converts a GID string of the format 0xPPPPPPPPPPPPPPPP:GGGGGGGGGGGGGGGG
+ to a gid type
+*/
+int
+str2gid(
+ IN char *str,
+ OUT ib_gid_t *p_gid
+ );
+
+int
+str2gid(
+ IN char *str,
+ OUT ib_gid_t *p_gid
+ )
+{
+ ib_gid_t temp;
+ char buf[38];
+ char *p_prefix, *p_guid;
+
+ CL_ASSERT(p_gid);
+
+ strcpy(buf, str);
+ p_prefix = buf;
+ /*p_guid = index(buf, ':');*/
+ p_guid = strchr( buf, ':' );
+
+ if (! p_guid)
+ {
+ printf("Wrong format for gid %s\n", buf);
+ return 1;
+ }
+
+ *p_guid = '\0';
+ p_guid++;
+
+ errno = 0;
+ temp.unicast.prefix = cl_hton64(strtoull(p_prefix, NULL, 0));
+ if (errno) {
+ printf("Wrong format for gid prefix:%s (got %u)\n",
+ p_prefix, errno);
+ return 1;
+ }
+
+ temp.unicast.interface_id = cl_hton64(strtoull(p_guid, NULL, 16));
+ if (errno) {
+ printf("Wrong format for gid guid:%s\n", p_guid);
+ return 1;
+ }
+
+ *p_gid = temp;
+ return 0;
+}
+void OsmReportState(IN const char *p_str)
+{
+}
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+ char *argv[] )
+{
+ static ibtrapgen_t ibtrapgen;
+ ibtrapgen_opt_t opt = { 0 };
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+ uint32_t next_option;
+ const char *const short_option = "t:n:r:s:l:p:o:vVh";
+
+ /*
+ * 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[] = {
+ {"trap_num", 1, NULL, 't'},
+ {"number", 1, NULL, 'n'},
+ {"rate", 1, NULL, 'r'},
+ {"lid", 1, NULL, 'l'},
+ {"src_port", 1, NULL, 's'},
+ {"port_num", 1, NULL, 'p'},
+ {"help", 0, NULL, 'h'},
+ {"verbose", 0, NULL, 'v'},
+ {"out_log_file", 1, NULL, 'o'},
+ {"vf", 1, NULL, 'x'},
+ {"V", 0, NULL, 'V'},
+
+ {NULL, 0, NULL, 0} /* Required at end of array */
+ };
+
+
+ opt.trap_num = 0;
+ opt.number = 1; /* This is the default value */
+ opt.rate = 0;
+ opt.lid = 0;
+ opt.src_port = 0;
+ opt.port_num = 0;
+ opt.log_file = NULL;
+ opt.force_log_flush = FALSE;
+ opt.transaction_timeout = DEFAULT_TRANS_TIMEOUT_MILLISEC;
+
+ do
+ {
+ next_option = getopt_long_only( argc, argv, short_option,
+ long_option, NULL );
+
+ switch ( next_option )
+ {
+ case 't':
+ /*
+ * Define the trap number
+ */
+ opt.trap_num = (uint8_t)atoi( optarg );
+ if ((opt.trap_num < 128) || (opt.trap_num > 131))
+ {
+ printf( "-E- Given trap number is illegal! \n"
+ " Supportes generation of traps 128-131.\n" );
+ exit(1);
+ }
+ printf( "-I- Trap Number = %u\n", opt.trap_num );
+ break;
+
+ case 'n':
+ /*
+ * Define the number of occurences
+ */
+ opt.number = (uint16_t)atoi( optarg );
+
+ printf( "-I- Number Trap Occurences = %u\n", opt.number );
+ break;
+
+ case 'r':
+ /*
+ * Define the rate of the trap
+ */
+ opt.rate = (uint16_t)atoi( optarg );
+
+ printf( "-I- Trap Rate = %u miliseconds\n", opt.rate );
+ break;
+
+
+ case 'l':
+ /*
+ * Define the source lid of the trap
+ */
+ opt.lid = (uint16_t)strtoul( optarg , NULL , 16);
+
+ printf( "-I- Trap Lid = 0x%04X\n", opt.lid );
+ break;
+
+ case 's':
+ /*
+ * Define the source port number of the trap
+ */
+ opt.src_port = (uint8_t)atoi( optarg );
+
+ printf( "-I- Trap Port Number = %u\n", opt.src_port );
+ break;
+
+ case 'p':
+ /*
+ * Specifies port guid with which to bind.
+ */
+ opt.port_num = (uint8_t)atoi( optarg );
+ printf( "-I- Port Num:%u\n", opt.port_num );
+ break;
+
+ case 'o':
+ opt.log_file = optarg;
+ printf("-I- Log File:%s\n", opt.log_file );
+ break;
+
+ case 'v':
+ /*
+ * Increases log verbosity.
+ */
+ log_flags = ( log_flags << 1 ) | 1;
+ printf( "-I- Verbose 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( "-I- Enabling maximum log verbosity\n" );
+ break;
+
+ case 'h':
+ show_usage( );
+ return 0;
+
+ case 'x':
+ log_flags = strtol( optarg, NULL, 0 );
+ printf( "-I- Verbose option -vf (log flags = 0x%X)\n",
+ log_flags );
+ break;
+
+ case -1:
+ /* printf( "Done with args\n" ); */
+ break;
+
+ default: /* something wrong */
+ abort( );
+ }
+
+ }
+ while( next_option != -1 );
+
+ /* Check for mandatory options */
+ if (opt.trap_num == 0)
+ {
+ printf( "-E- Missing trap number.\n" );
+ exit(1);
+ }
+ if (opt.lid == 0)
+ {
+ printf( "-E- Missing lid.\n" );
+ exit(1);
+ }
+ if (opt.src_port == 0 && opt.trap_num >= 129 && opt.trap_num <= 131)
+ {
+ /* for trap 129-131 should be given source port number */
+ printf( "-E- source port number.\n" );
+ exit(1);
+ }
+ if (opt.port_num == 0)
+ {
+ printf( "-E- Missing port number.\n" );
+ exit(1);
+ }
+ if (opt.rate == 0 && opt.number > 1)
+ {
+ /* for number of traps greater than 1 need to give the rate for the
+ trap generation. */
+ printf( "-E- Missing rate.\n" );
+ exit(1);
+ }
+
+
+ /* init the main object and sub objects (log and osm vendor) */
+ status = ibtrapgen_init( &ibtrapgen, &opt, ( osm_log_level_t ) log_flags );
+ if( status != IB_SUCCESS )
+ {
+ printf("-E- fail to init ibtrapgen.\n");
+ goto Exit;
+ }
+
+ /* bind to a specific port */
+ status = ibtrapgen_bind( &ibtrapgen );
+ if (status != IB_SUCCESS) exit(status);
+
+ /* actual work */
+ status = ibtrapgen_run( &ibtrapgen );
+ if (status != IB_SUCCESS)
+ {
+ printf("IBTRAPGEN: FAIL\n");
+ }
+ else
+ {
+ printf("IBTRAPGEN: PASS\n");
+ }
+
+ //ibtrapgen_destroy( &ibtrapgen );
+
+ Exit:
+ exit ( status );
+}
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: cl_byteswap.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * provides byteswapping utilities. Basic fuctions are obtained from platform
+ * specific implementations from ibyteswap_osd.h.
+ *
+ * Environment:
+ * All
+ */
+
+
+#ifndef _CL_BYTESWAP_H_
+#define _CL_BYTESWAP_H_
+
+
+#include <complib/cl_memory.h>
+#include <complib/cl_byteswap_osd.h>
+
+
+/****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 ibyteswap_osd.h provides the following macros.
+ * __LITTLE_ENDIAN
+ * __BIG_ENDIAN
+ * __BYTE_ORDER
+ *
+ * If the platform provides byte swapping functions, ibyteswap_osd.h also
+ * provides the following macros.
+ * ntoh16, hton16
+ * ntoh32, hton32
+ * ntoh64, hton64
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#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
+*********/
+#undef cl_ntoh16
+#undef cl_hton16
+#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
+*********/
+#undef cl_ntoh32
+#undef cl_hton32
+#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) & CL_CONST64(0x00000000000000FF)) << 56) | \
+ (((uint64_t)(x) & CL_CONST64(0x000000000000FF00)) << 40) | \
+ (((uint64_t)(x) & CL_CONST64(0x0000000000FF0000)) << 24) | \
+ (((uint64_t)(x) & CL_CONST64(0x00000000FF000000)) << 8 ) | \
+ (((uint64_t)(x) & CL_CONST64(0x000000FF00000000)) >> 8 ) | \
+ (((uint64_t)(x) & CL_CONST64(0x0000FF0000000000)) >> 24) | \
+ (((uint64_t)(x) & CL_CONST64(0x00FF000000000000)) >> 40) | \
+ (((uint64_t)(x) & CL_CONST64(0xFF00000000000000)) >> 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
+*********/
+#undef cl_ntoh64
+#undef cl_hton64
+#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
+*/
+CL_INLINE void CL_API
+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 )
+ cl_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
+*********/
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* _CL_BYTESWAP_H_ */
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of dispatcher abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_threadpool.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_ptr_vector.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* 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_) */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of event wheel abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.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* 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;
+ osm_log_t *p_log;
+} 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.
+*
+* p_log
+* Pointer to opensm log object.
+*
+* 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,
+ IN osm_log_t *p_log);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* 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 osm_log_t *p_log,
+ IN cl_spinlock_t *p_external_lock);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* 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_) */
+
--- /dev/null
+/*
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 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.
+ *
+ * $Id: cl_signal_osd.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+/*
+ * Abstract:
+ * Declaration of Signal Handler Registration
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.3 $
+ */
+
+
+#ifndef _CL_SIG_HDL_H_
+#define _CL_SIG_HDL_H_
+
+#include <signal.h>
+
+/****h* Component Library/Signal Handler
+* NAME
+* Signal Handler Registration
+*
+* DESCRIPTION
+* The Signal Handler Registration allows to register a callback on the case of incoming signal
+*
+* SEE ALSO
+*********/
+/* TODO : Required when calling signal function in windows*/
+typedef void (__cdecl *cl_sig_hdl)(
+ IN int sig);
+/* Prototypes */
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+* cl_reg_sig_hdl
+*
+* DESCRIPTION
+* Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+
+static inline void
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl);
+
+
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+* cl_sig_mask_sigint
+*
+* DESCRIPTION
+* Mask the kill signal
+*
+* SYNOPSIS
+*/
+
+static inline void
+cl_sig_mask_sigint(void);
+
+
+
+
+/****f* Component Library: Signal Handler/cl_reg_sig_hdl
+* NAME
+* cl_reg_sig_hdl
+*
+* DESCRIPTION
+* Register the handler for the given signal
+*
+* SYNOPSIS
+*/
+static inline void
+cl_reg_sig_hdl(int sig, cl_sig_hdl pfn_sig_hdl) {
+ signal(sig,pfn_sig_hdl);
+ }
+/*
+*********/
+
+/****f* Component Library: Signal Handler/cl_mask_sigint
+* NAME
+* cl_sig_mask_sigint
+*
+* DESCRIPTION
+* Mask the kill signal
+*
+* SYNOPSIS
+*/
+static inline void
+cl_sig_mask_sigint(void)
+{
+
+}
+/*
+*********/
+
+#endif /* _CL_SIG_HDL_H_ */
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: ib_types.h 1925 2009-02-04 15:11:30Z tzachid $\r
+ */\r
+\r
+\r
+\r
+#if !defined(__IB_TYPES_H__)\r
+#define __IB_TYPES_H__\r
+\r
+#include <string.h>\r
+#include <complib/cl_types.h>\r
+#include <complib/cl_byteswap.h>\r
+\r
+#ifdef __cplusplus\r
+# define BEGIN_C_DECLS extern "C" {\r
+# define END_C_DECLS }\r
+#else /* !__cplusplus */\r
+# define BEGIN_C_DECLS\r
+# define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+#if defined( WIN32 ) || defined( _WIN64 )\r
+ #if defined( EXPORT_AL_SYMBOLS )\r
+ #define OSM_EXPORT __declspec(dllexport)\r
+ #else\r
+ #define OSM_EXPORT __declspec(dllimport)\r
+ #endif\r
+ #define OSM_API __stdcall\r
+ #define OSM_CDECL __cdecl\r
+#else\r
+ #define OSM_EXPORT extern\r
+ #define OSM_API\r
+ #define OSM_CDECL\r
+ #define __ptr64\r
+#endif\r
+\r
+\r
+#define IB_CONCAT(str1, str2) str1##str2\r
+\r
+#define TO_LONG_PTR(type,member_name) \\r
+ union { type member_name; uint64_t IB_CONCAT(member_name,_padding) ; }\r
+\r
+\r
+\r
+/****h* IBA Base/Constants\r
+* NAME\r
+* Constants\r
+*\r
+* DESCRIPTION\r
+* The following constants are used throughout the IBA code base.\r
+*\r
+* Definitions are from the InfiniBand Architecture Specification v1.2\r
+*\r
+*********/\r
+\r
+/****d* IBA Base: Constants/MAD_BLOCK_SIZE\r
+* NAME\r
+* MAD_BLOCK_SIZE\r
+*\r
+* DESCRIPTION\r
+* Size of a non-RMPP MAD datagram.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_BLOCK_SIZE 256\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_RMPP_HDR_SIZE\r
+* NAME\r
+* MAD_RMPP_HDR_SIZE\r
+*\r
+* DESCRIPTION\r
+* Size of an RMPP header, including the common MAD header.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_RMPP_HDR_SIZE 36\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_RMPP_DATA_SIZE\r
+* NAME\r
+* MAD_RMPP_DATA_SIZE\r
+*\r
+* DESCRIPTION\r
+* Size of an RMPP transaction data section.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_RMPP_DATA_SIZE (MAD_BLOCK_SIZE - MAD_RMPP_HDR_SIZE)\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/MAD_BLOCK_GRH_SIZE\r
+* NAME\r
+* MAD_BLOCK_GRH_SIZE\r
+*\r
+* DESCRIPTION\r
+* Size of a MAD datagram, including the GRH.\r
+*\r
+* SOURCE\r
+*/\r
+#define MAD_BLOCK_GRH_SIZE 296\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_PERMISSIVE\r
+* NAME\r
+* IB_LID_PERMISSIVE\r
+*\r
+* DESCRIPTION\r
+* Permissive LID\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_PERMISSIVE 0xFFFF\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_PKEY\r
+* NAME\r
+* IB_DEFAULT_PKEY\r
+*\r
+* DESCRIPTION\r
+* P_Key value for the default partition.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_PKEY 0xFFFF\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_QP1_WELL_KNOWN_Q_KEY\r
+* NAME\r
+* IB_QP1_WELL_KNOWN_Q_KEY\r
+*\r
+* DESCRIPTION\r
+* Well-known Q_Key for QP1 privileged mode access (15.4.2).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_QP1_WELL_KNOWN_Q_KEY CL_NTOH32(0x80010000)\r
+/*********/\r
+\r
+#define IB_QP0 0\r
+#define IB_QP1 CL_NTOH32(1)\r
+\r
+#define IB_QP_PRIVILEGED_Q_KEY CL_NTOH32(0x80000000)\r
+\r
+/****d* IBA Base: Constants/IB_LID_UCAST_START\r
+* NAME\r
+* IB_LID_UCAST_START\r
+*\r
+* DESCRIPTION\r
+* Lowest valid unicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_UCAST_START_HO 0x0001\r
+#define IB_LID_UCAST_START (CL_HTON16(IB_LID_UCAST_START_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_UCAST_END\r
+* NAME\r
+* IB_LID_UCAST_END\r
+*\r
+* DESCRIPTION\r
+* Highest valid unicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_UCAST_END_HO 0xBFFF\r
+#define IB_LID_UCAST_END (CL_HTON16(IB_LID_UCAST_END_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_MCAST_START\r
+* NAME\r
+* IB_LID_MCAST_START\r
+*\r
+* DESCRIPTION\r
+* Lowest valid multicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_MCAST_START_HO 0xC000\r
+#define IB_LID_MCAST_START (CL_HTON16(IB_LID_MCAST_START_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_LID_MCAST_END\r
+* NAME\r
+* IB_LID_MCAST_END\r
+*\r
+* DESCRIPTION\r
+* Highest valid multicast LID value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LID_MCAST_END_HO 0xFFFE\r
+#define IB_LID_MCAST_END (CL_HTON16(IB_LID_MCAST_END_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_SUBNET_PREFIX\r
+* NAME\r
+* IB_DEFAULT_SUBNET_PREFIX\r
+*\r
+* DESCRIPTION\r
+* Default subnet GID prefix.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_SUBNET_PREFIX (CL_HTON64(0xFE80000000000000ULL))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_NUM_PORTS_MAX\r
+* NAME\r
+* IB_NODE_NUM_PORTS_MAX\r
+*\r
+* DESCRIPTION\r
+* Maximum number of ports in a single node (14.2.5.7).\r
+* SOURCE\r
+*/\r
+#define IB_NODE_NUM_PORTS_MAX 0xFE\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_INVALID_PORT_NUM\r
+* NAME\r
+* IB_INVALID_PORT_NUM\r
+*\r
+* DESCRIPTION\r
+* Value used to indicate an invalid port number (14.2.5.10).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_INVALID_PORT_NUM 0xFF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_SUBNET_PATH_HOPS_MAX\r
+* NAME\r
+* IB_SUBNET_PATH_HOPS_MAX\r
+*\r
+* DESCRIPTION\r
+* Maximum number of directed route switch hops in a subnet (14.2.1.2).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SUBNET_PATH_HOPS_MAX 64\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_MAX_BLOCKS\r
+* NAME\r
+* IB_PKEY_MAX_BLOCKS\r
+*\r
+* DESCRIPTION\r
+* Maximum number of PKEY blocks (14.2.5.7).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_MAX_BLOCKS 2048\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_MAX_BLOCK_ID\r
+* NAME\r
+* IB_MCAST_MAX_BLOCK_ID\r
+*\r
+* DESCRIPTION\r
+* Maximum number of Multicast port mask blocks\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_MAX_BLOCK_ID 511\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_ID_MASK_HO\r
+* NAME\r
+* IB_MCAST_BLOCK_ID_MASK_HO\r
+*\r
+* DESCRIPTION\r
+* Mask (host order) to recover the Multicast block ID.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_BLOCK_ID_MASK_HO 0x000001FF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_BLOCK_SIZE\r
+* NAME\r
+* IB_MCAST_BLOCK_SIZE\r
+*\r
+* DESCRIPTION\r
+* Number of port mask entries in a multicast forwarding table block.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_BLOCK_SIZE 32\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_MASK_SIZE\r
+* NAME\r
+* IB_MCAST_MASK_SIZE\r
+*\r
+* DESCRIPTION\r
+* Number of port mask bits in each entry in the multicast forwarding table.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_MASK_SIZE 16\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MASK_HO\r
+* NAME\r
+* IB_MCAST_POSITION_MASK_HO\r
+*\r
+* DESCRIPTION\r
+* Mask (host order) to recover the multicast block position.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_MASK_HO 0xF0000000\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_MAX\r
+* NAME\r
+* IB_MCAST_POSITION_MAX\r
+*\r
+* DESCRIPTION\r
+* Maximum value for the multicast block position.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_MAX 0xF\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_MCAST_POSITION_SHIFT\r
+* NAME\r
+* IB_MCAST_POSITION_SHIFT\r
+*\r
+* DESCRIPTION\r
+* Shift value to normalize the multicast block position value.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCAST_POSITION_SHIFT 28\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_ENTRIES_MAX\r
+* NAME\r
+* IB_PKEY_ENTRIES_MAX\r
+*\r
+* DESCRIPTION\r
+* Maximum number of PKEY entries per port (14.2.5.7).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_ENTRIES_MAX (IB_PKEY_MAX_BLOCKS * IB_NUM_PKEY_ELEMENTS_IN_BLOCK)\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_BASE_MASK\r
+* NAME\r
+* IB_PKEY_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+* Masks for the base P_Key value given a P_Key Entry.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_BASE_MASK (CL_HTON16(0x7FFF))\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_PKEY_TYPE_MASK\r
+* NAME\r
+* IB_PKEY_TYPE_MASK\r
+*\r
+* DESCRIPTION\r
+* Masks for the P_Key membership type given a P_Key Entry.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PKEY_TYPE_MASK (CL_NTOH16(0x8000))\r
+/*********/\r
+\r
+/****d* IBA Base: Constants/IB_DEFAULT_PARTIAL_PKEY\r
+* NAME\r
+* IB_DEFAULT_PARTIAL_PKEY \r
+*\r
+* DESCRIPTION\r
+* 0x7FFF in network order\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_DEFAULT_PARTIAL_PKEY (CL_HTON16(0x7FFF))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_LID\r
+* NAME\r
+* IB_MCLASS_SUBN_LID\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Subnet Manager LID routed (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_LID 0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_DIR\r
+* NAME\r
+* IB_MCLASS_SUBN_DIR\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Subnet Manager directed route (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_DIR 0x81\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SUBN_ADM\r
+* NAME\r
+* IB_MCLASS_SUBN_ADM\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Subnet Administration (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SUBN_ADM 0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_PERF\r
+* NAME\r
+* IB_MCLASS_PERF\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Performance Manager (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_PERF 0x04\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_BM\r
+* NAME\r
+* IB_MCLASS_BM\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Baseboard Manager (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_BM 0x05\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_DEV_MGMT\r
+* NAME\r
+* IB_MCLASS_DEV_MGMT\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Device Management (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_DEV_MGMT 0x06\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_COMM_MGMT\r
+* NAME\r
+* IB_MCLASS_COMM_MGMT\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Communication Management (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_COMM_MGMT 0x07\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_SNMP\r
+* NAME\r
+* IB_MCLASS_SNMP\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, SNMP Tunneling (13.4.4)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_SNMP 0x08\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MIN\r
+* NAME\r
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Vendor Specific Low Range Start\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_LOW_RANGE_MIN 0x09\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+* NAME\r
+* IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Vendor Specific Low Range End\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_LOW_RANGE_MAX 0x0f\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_DEV_ADM\r
+* NAME\r
+* IB_MCLASS_DEV_ADM\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Device Administration\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_DEV_ADM 0x10\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_BIS\r
+* NAME\r
+* IB_MCLASS_BIS\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, BIS\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_BIS 0x12\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MIN\r
+* NAME\r
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Vendor Specific High Range Start\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MIN 0x30\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+* NAME\r
+* IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+*\r
+* DESCRIPTION\r
+* Subnet Management Class, Vendor Specific High Range End\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MCLASS_VENDOR_HIGH_RANGE_MAX 0x4f\r
+/**********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific_low\r
+* NAME\r
+* ib_class_is_vendor_specific_low\r
+*\r
+* DESCRIPTION\r
+* Indicates if the Class Code if a vendor specific class from \r
+* the low range\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_class_is_vendor_specific_low(\r
+ IN const uint8_t class_code )\r
+{\r
+ return( (class_code >= IB_MCLASS_VENDOR_LOW_RANGE_MIN) &&\r
+ (class_code <= IB_MCLASS_VENDOR_LOW_RANGE_MAX) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* class_code\r
+* [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+* TRUE if the class is in the Low range of Vendor Specific MADs \r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* IB_MCLASS_VENDOR_LOW_RANGE_MIN, IB_MCLASS_VENDOR_LOW_RANGE_MAX\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific_high\r
+* NAME\r
+* ib_class_is_vendor_specific_high\r
+*\r
+* DESCRIPTION\r
+* Indicates if the Class Code if a vendor specific class from \r
+* the high range\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_class_is_vendor_specific_high(\r
+ IN const uint8_t class_code )\r
+{\r
+ return( (class_code >= IB_MCLASS_VENDOR_HIGH_RANGE_MIN) &&\r
+ (class_code <= IB_MCLASS_VENDOR_HIGH_RANGE_MAX) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* class_code\r
+* [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+* TRUE if the class is in the High range of Vendor Specific MADs \r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* IB_MCLASS_VENDOR_HIGH_RANGE_MIN, IB_MCLASS_VENDOR_HIGH_RANGE_MAX\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_class_is_vendor_specific\r
+* NAME\r
+* ib_class_is_vendor_specific\r
+*\r
+* DESCRIPTION\r
+* Indicates if the Class Code if a vendor specific class\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_class_is_vendor_specific(\r
+ IN const uint8_t class_code )\r
+{\r
+ return( ib_class_is_vendor_specific_low(class_code) ||\r
+ ib_class_is_vendor_specific_high(class_code) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* class_code\r
+* [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+* TRUE if the class is a Vendor Specific MAD\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_class_is_vendor_specific_low, ib_class_is_vendor_specific_high\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_is_rmpp\r
+* NAME\r
+* ib_class_is_rmpp\r
+*\r
+* DESCRIPTION\r
+* Indicates if the Class Code supports RMPP\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_class_is_rmpp(\r
+ IN const uint8_t class_code )\r
+{\r
+ return( (class_code == IB_MCLASS_SUBN_ADM) ||\r
+ (class_code == IB_MCLASS_DEV_MGMT) ||\r
+ (class_code == IB_MCLASS_DEV_ADM) ||\r
+ (class_code == IB_MCLASS_BIS) ||\r
+ ib_class_is_vendor_specific_high( class_code ) ); \r
+}\r
+/*\r
+* PARAMETERS\r
+* class_code\r
+* [in] The Management Datagram Class Code\r
+*\r
+* RETURN VALUE\r
+* TRUE if the class supports RMPP\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+*********/\r
+\r
+/*\r
+ * MAD methods\r
+ */\r
+\r
+/****d* IBA Base: Constants/IB_MAX_METHOD\r
+* NAME\r
+* IB_MAX_METHOD\r
+*\r
+* DESCRIPTION\r
+* Total number of methods available to a class, not including the R-bit.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAX_METHODS 128\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_RESP_MASK\r
+* NAME\r
+* IB_MAD_METHOD_RESP_MASK\r
+*\r
+* DESCRIPTION\r
+* Response mask to extract 'R' bit from the method field. (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_RESP_MASK 0x80\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET\r
+* NAME\r
+* IB_MAD_METHOD_GET\r
+*\r
+* DESCRIPTION\r
+* Get() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GET 0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_SET\r
+* NAME\r
+* IB_MAD_METHOD_SET\r
+*\r
+* DESCRIPTION\r
+* Set() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_SET 0x02\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GET_RESP\r
+* NAME\r
+* IB_MAD_METHOD_GET_RESP\r
+*\r
+* DESCRIPTION\r
+* GetResp() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GET_RESP 0x81\r
+/**********/\r
+\r
+#define IB_MAD_METHOD_DELETE 0x15\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE\r
+* NAME\r
+* IB_MAD_METHOD_GETTABLE\r
+*\r
+* DESCRIPTION\r
+* SubnAdmGetTable() Method (15.2.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GETTABLE 0x12\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_GETTABLE_RESP\r
+* NAME\r
+* IB_MAD_METHOD_GETTABLE_RESP\r
+*\r
+* DESCRIPTION\r
+* SubnAdmGetTableResp() Method (15.2.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_GETTABLE_RESP 0x92\r
+\r
+/**********/\r
+\r
+#define IB_MAD_METHOD_GETTRACETABLE 0x13\r
+#define IB_MAD_METHOD_GETMULTI 0x14\r
+#define IB_MAD_METHOD_GETMULTI_RESP 0x94\r
+\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_SEND\r
+* NAME\r
+* IB_MAD_METHOD_SEND\r
+*\r
+* DESCRIPTION\r
+* Send() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_SEND 0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP\r
+* NAME\r
+* IB_MAD_METHOD_TRAP\r
+*\r
+* DESCRIPTION\r
+* Trap() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_TRAP 0x05\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT\r
+* NAME\r
+* IB_MAD_METHOD_REPORT\r
+*\r
+* DESCRIPTION\r
+* Report() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_REPORT 0x06\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_REPORT_RESP\r
+* NAME\r
+* IB_MAD_METHOD_REPORT_RESP\r
+*\r
+* DESCRIPTION\r
+* ReportResp() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_REPORT_RESP 0x86\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_METHOD_TRAP_REPRESS\r
+* NAME\r
+* IB_MAD_METHOD_TRAP_REPRESS\r
+*\r
+* DESCRIPTION\r
+* TrapRepress() Method (13.4.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_METHOD_TRAP_REPRESS 0x07\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_BUSY\r
+* NAME\r
+* IB_MAD_STATUS_BUSY\r
+*\r
+* DESCRIPTION\r
+* Temporarily busy, MAD discarded (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_BUSY (CL_HTON16(0x0001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_REDIRECT\r
+* NAME\r
+* IB_MAD_STATUS_REDIRECT\r
+*\r
+* DESCRIPTION\r
+* QP Redirection required (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_REDIRECT (CL_HTON16(0x0002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_CLASS_VER\r
+* NAME\r
+* IB_MAD_STATUS_UNSUP_CLASS_VER\r
+*\r
+* DESCRIPTION\r
+* Unsupported class version (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_CLASS_VER (CL_HTON16(0x0004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD\r
+* NAME\r
+* IB_MAD_STATUS_UNSUP_METHOD\r
+*\r
+* DESCRIPTION\r
+* Unsupported method (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_METHOD (CL_HTON16(0x0008))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_UNSUP_METHOD_ATTR\r
+* NAME\r
+* IB_MAD_STATUS_UNSUP_METHOD_ATTR\r
+*\r
+* DESCRIPTION\r
+* Unsupported method/attribute combination (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_UNSUP_METHOD_ATTR (CL_HTON16(0x000C))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_STATUS_INVALID_FIELD\r
+* NAME\r
+* IB_MAD_STATUS_INVALID_FIELD\r
+*\r
+* DESCRIPTION\r
+* Attribute contains one or more invalid fields (13.4.7)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_STATUS_INVALID_FIELD (CL_HTON16(0x001C))\r
+/**********/\r
+\r
+#define IB_MAD_STATUS_CLASS_MASK (CL_HTON16(0xFF00))\r
+\r
+#define IB_SA_MAD_STATUS_SUCCESS (CL_HTON16(0x0000))\r
+#define IB_SA_MAD_STATUS_NO_RESOURCES (CL_HTON16(0x0100))\r
+#define IB_SA_MAD_STATUS_REQ_INVALID (CL_HTON16(0x0200))\r
+#define IB_SA_MAD_STATUS_NO_RECORDS (CL_HTON16(0x0300))\r
+#define IB_SA_MAD_STATUS_TOO_MANY_RECORDS (CL_HTON16(0x0400))\r
+#define IB_SA_MAD_STATUS_INVALID_GID (CL_HTON16(0x0500))\r
+#define IB_SA_MAD_STATUS_INSUF_COMPS (CL_HTON16(0x0600))\r
+\r
+#define IB_DM_MAD_STATUS_NO_IOC_RESP (CL_HTON16(0x0100))\r
+#define IB_DM_MAD_STATUS_NO_SVC_ENTRIES (CL_HTON16(0x0200))\r
+#define IB_DM_MAD_STATUS_IOC_FAILURE (CL_HTON16(0x8000))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_CLASS_PORT_INFO\r
+* NAME\r
+* IB_MAD_ATTR_CLASS_PORT_INFO\r
+*\r
+* DESCRIPTION\r
+* ClassPortInfo attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_CLASS_PORT_INFO (CL_NTOH16(0x0001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NOTICE\r
+* NAME\r
+* IB_MAD_ATTR_NOTICE\r
+*\r
+* DESCRIPTION\r
+* Notice attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NOTICE (CL_NTOH16(0x0002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO\r
+* NAME\r
+* IB_MAD_ATTR_INFORM_INFO\r
+*\r
+* DESCRIPTION\r
+* InformInfo attribute (13.4.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_INFORM_INFO (CL_NTOH16(0x0003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_DESC\r
+* NAME\r
+* IB_MAD_ATTR_NODE_DESC\r
+*\r
+* DESCRIPTION\r
+* NodeDescription attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_DESC (CL_NTOH16(0x0010))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_CTRL\r
+* NAME\r
+* IB_MAD_ATTR_PORT_SMPL_CTRL\r
+*\r
+* DESCRIPTION\r
+* NodeDescription attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_SMPL_CTRL (CL_NTOH16(0x0010))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_INFO\r
+* NAME\r
+* IB_MAD_ATTR_NODE_INFO\r
+*\r
+* DESCRIPTION\r
+* NodeInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_INFO (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_SMPL_RSLT\r
+* NAME\r
+* IB_MAD_ATTR_PORT_SMPL_RSLT\r
+*\r
+* DESCRIPTION\r
+* NodeInfo attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_SMPL_RSLT (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO\r
+* NAME\r
+* IB_MAD_ATTR_SWITCH_INFO\r
+*\r
+* DESCRIPTION\r
+* SwitchInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SWITCH_INFO (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_CNTRS\r
+* NAME\r
+* IB_MAD_ATTR_PORT_CNTRS\r
+*\r
+* DESCRIPTION\r
+* SwitchInfo attribute (16.1.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_CNTRS (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUID_INFO\r
+* NAME\r
+* IB_MAD_ATTR_GUID_INFO\r
+*\r
+* DESCRIPTION\r
+* GUIDInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_GUID_INFO (CL_NTOH16(0x0014))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORT_INFO\r
+* NAME\r
+* IB_MAD_ATTR_PORT_INFO\r
+*\r
+* DESCRIPTION\r
+* PortInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORT_INFO (CL_NTOH16(0x0015))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_P_KEY_TABLE\r
+* NAME\r
+* IB_MAD_ATTR_P_KEY_TABLE\r
+*\r
+* DESCRIPTION\r
+* PartitionTable attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_P_KEY_TABLE (CL_NTOH16(0x0016))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_TABLE\r
+* NAME\r
+* IB_MAD_ATTR_SLVL_TABLE\r
+*\r
+* DESCRIPTION\r
+* SL VL Mapping Table attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SLVL_TABLE (CL_NTOH16(0x0017))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VL_ARBITRATION\r
+* NAME\r
+* IB_MAD_ATTR_VL_ARBITRATION\r
+*\r
+* DESCRIPTION\r
+* VL Arbitration Table attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VL_ARBITRATION (CL_NTOH16(0x0018))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LIN_FWD_TBL\r
+* NAME\r
+* IB_MAD_ATTR_LIN_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+* Switch linear forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LIN_FWD_TBL (CL_NTOH16(0x0019))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_RND_FWD_TBL\r
+* NAME\r
+* IB_MAD_ATTR_RND_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+* Switch random forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_RND_FWD_TBL (CL_NTOH16(0x001A))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCAST_FWD_TBL\r
+* NAME\r
+* IB_MAD_ATTR_MCAST_FWD_TBL\r
+*\r
+* DESCRIPTION\r
+* Switch multicast forwarding table\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MCAST_FWD_TBL (CL_NTOH16(0x001B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_NODE_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_NODE_RECORD\r
+*\r
+* DESCRIPTION\r
+* NodeRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_NODE_RECORD (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PORTINFO_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_PORTINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+* PortInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PORTINFO_RECORD (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SWITCH_INFO_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SWITCH_INFO_RECORD\r
+*\r
+* DESCRIPTION\r
+* SwitchInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SWITCH_INFO_RECORD (CL_NTOH16(0x0014))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LINK_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_LINK_RECORD\r
+*\r
+* DESCRIPTION\r
+* LinkRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LINK_RECORD (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SM_INFO\r
+* NAME\r
+* IB_MAD_ATTR_SM_INFO\r
+*\r
+* DESCRIPTION\r
+* SMInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SM_INFO (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SMINFO_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SMINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+* SMInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SMINFO_RECORD (CL_NTOH16(0x0018))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_GUIDINFO_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_GUIDINFO_RECORD\r
+*\r
+* DESCRIPTION\r
+* GuidInfoRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_GUIDINFO_RECORD (CL_NTOH16(0x0030))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VENDOR_DIAG\r
+* NAME\r
+* IB_MAD_ATTR_VENDOR_DIAG\r
+*\r
+* DESCRIPTION\r
+* VendorDiag attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VENDOR_DIAG (CL_NTOH16(0x0030))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LED_INFO\r
+* NAME\r
+* IB_MAD_ATTR_LED_INFO\r
+*\r
+* DESCRIPTION\r
+* LedInfo attribute (14.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LED_INFO (CL_NTOH16(0x0031))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SERVICE_RECORD\r
+*\r
+* DESCRIPTION\r
+* ServiceRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SERVICE_RECORD (CL_NTOH16(0x0031))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_LFT_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_LFT_RECORD\r
+*\r
+* DESCRIPTION\r
+* LinearForwardingTableRecord attribute (15.2.5.6)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_LFT_RECORD (CL_NTOH16(0x0015))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MFT_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_MFT_RECORD\r
+*\r
+* DESCRIPTION\r
+* MulticastForwardingTableRecord attribute (15.2.5.8)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MFT_RECORD (CL_NTOH16(0x0017))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PKEYTBL_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_PKEYTBL_RECORD\r
+*\r
+* DESCRIPTION\r
+* PKEY Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PKEY_TBL_RECORD (CL_NTOH16(0x0033))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PATH_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_PATH_RECORD\r
+*\r
+* DESCRIPTION\r
+* PathRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PATH_RECORD (CL_NTOH16(0x0035))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_VLARB_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_VLARB_RECORD\r
+*\r
+* DESCRIPTION\r
+* VL Arbitration Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_VLARB_RECORD (CL_NTOH16(0x0036))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SLVL_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SLVL_RECORD\r
+*\r
+* DESCRIPTION\r
+* SLtoVL Mapping Table Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SLVL_RECORD (CL_NTOH16(0x0013))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MCMEMBER_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_MCMEMBER_RECORD\r
+*\r
+* DESCRIPTION\r
+* MCMemberRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MCMEMBER_RECORD (CL_NTOH16(0x0038))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TRACE_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_TRACE_RECORD\r
+*\r
+* DESCRIPTION\r
+* TraceRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TRACE_RECORD (CL_NTOH16(0x0039))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_MULTIPATH_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_MULTIPATH_RECORD\r
+*\r
+* DESCRIPTION\r
+* MultiPathRecord attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_MULTIPATH_RECORD (CL_NTOH16(0x003A))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+*\r
+* DESCRIPTION\r
+* Service Association Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_NTOH16(0x003B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_INFORM_INFO_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_INFORM_INFO_RECORD\r
+*\r
+* DESCRIPTION\r
+* InformInfo Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_INFORM_INFO_RECORD (CL_NTOH16(0x00F3))\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_UNIT_INFO\r
+* NAME\r
+* IB_MAD_ATTR_IO_UNIT_INFO\r
+*\r
+* DESCRIPTION\r
+* IOUnitInfo attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_IO_UNIT_INFO (CL_NTOH16(0x0010))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_IO_CONTROLLER_PROFILE\r
+* NAME\r
+* IB_MAD_ATTR_IO_CONTROLLER_PROFILE\r
+*\r
+* DESCRIPTION\r
+* IOControllerProfile attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_IO_CONTROLLER_PROFILE (CL_NTOH16(0x0011))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SERVICE_ENTRIES\r
+* NAME\r
+* IB_MAD_ATTR_SERVICE_ENTRIES\r
+*\r
+* DESCRIPTION\r
+* ServiceEntries attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SERVICE_ENTRIES (CL_NTOH16(0x0012))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT\r
+* NAME\r
+* IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+* DiagnosticTimeout attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_DIAGNOSTIC_TIMEOUT (CL_NTOH16(0x0020))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_PREPARE_TO_TEST\r
+* NAME\r
+* IB_MAD_ATTR_PREPARE_TO_TEST\r
+*\r
+* DESCRIPTION\r
+* PrepareToTest attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_PREPARE_TO_TEST (CL_NTOH16(0x0021))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_ONCE\r
+* NAME\r
+* IB_MAD_ATTR_TEST_DEVICE_ONCE\r
+*\r
+* DESCRIPTION\r
+* TestDeviceOnce attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TEST_DEVICE_ONCE (CL_NTOH16(0x0022))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_TEST_DEVICE_LOOP\r
+* NAME\r
+* IB_MAD_ATTR_TEST_DEVICE_LOOP\r
+*\r
+* DESCRIPTION\r
+* TestDeviceLoop attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_TEST_DEVICE_LOOP (CL_NTOH16(0x0023))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_DIAG_CODE\r
+* NAME\r
+* IB_MAD_ATTR_DIAG_CODE\r
+*\r
+* DESCRIPTION\r
+* DiagCode attribute (16.3.3)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_DIAG_CODE (CL_NTOH16(0x0024))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+* NAME\r
+* IB_MAD_ATTR_SVC_ASSOCIATION_RECORD\r
+*\r
+* DESCRIPTION\r
+* Service Association Record attribute (15.2.5)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MAD_ATTR_SVC_ASSOCIATION_RECORD (CL_NTOH16(0x003B))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_CA\r
+* NAME\r
+* IB_NODE_TYPE_CA\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_CA 0x01\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_SWITCH\r
+* NAME\r
+* IB_NODE_TYPE_SWITCH\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_SWITCH 0x02\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NODE_TYPE_ROUTER\r
+* NAME\r
+* IB_NODE_TYPE_ROUTER\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NODE_TYPE_ROUTER 0x03\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_CA\r
+* NAME\r
+* IB_NOTICE_NODE_TYPE_CA\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_CA (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SWITCH\r
+* NAME\r
+* IB_NOTICE_NODE_TYPE_SWITCH\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_SWITCH (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_ROUTER\r
+* NAME\r
+* IB_NOTICE_NODE_TYPE_ROUTER\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2)\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_ROUTER (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_NOTICE_NODE_TYPE_SUBN_MGMT\r
+* NAME\r
+* IB_NOTICE_NODE_TYPE_SUBN_MGMT\r
+*\r
+* DESCRIPTION\r
+* Encoded generic node type used in MAD attributes (13.4.8.2).\r
+* Note that this value is not defined for the NodeType field\r
+* of the NodeInfo attribute (14.2.5.3).\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_NOTICE_NODE_TYPE_SUBN_MGMT (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MTU_LEN_TYPE\r
+* NAME\r
+* IB_MTU_LEN_TYPE\r
+*\r
+* DESCRIPTION\r
+* Encoded path MTU.\r
+* 1: 256\r
+* 2: 512\r
+* 3: 1024\r
+* 4: 2048\r
+* 5: 4096\r
+* others: reserved\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MTU_LEN_256 1\r
+#define IB_MTU_LEN_512 2\r
+#define IB_MTU_LEN_1024 3\r
+#define IB_MTU_LEN_2048 4\r
+#define IB_MTU_LEN_4096 5\r
+\r
+#define IB_MIN_MTU IB_MTU_LEN_256\r
+#define IB_MAX_MTU IB_MTU_LEN_4096\r
+\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_SELECTOR_TYPE\r
+* NAME\r
+* IB_PATH_SELECTOR_TYPE\r
+*\r
+* DESCRIPTION\r
+* Path selector.\r
+* 0: greater than specified\r
+* 1: less than specified\r
+* 2: exactly the specified\r
+* 3: largest available\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_SELECTOR_GREATER_THAN 0\r
+#define IB_PATH_SELECTOR_LESS_THAN 1\r
+#define IB_PATH_SELECTOR_EXACTLY 2\r
+#define IB_PATH_SELECTOR_LARGEST 3\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_NOTACTIVE\r
+* NAME\r
+* IB_SMINFO_STATE_NOTACTIVE\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_NOTACTIVE 0\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_DISCOVERING\r
+* NAME\r
+* IB_SMINFO_STATE_DISCOVERING\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_DISCOVERING 1\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_STANDBY\r
+* NAME\r
+* IB_SMINFO_STATE_STANDBY\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_STANDBY 2\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_MASTER\r
+* NAME\r
+* IB_SMINFO_STATE_MASTER\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_MASTER 3\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_SL_MASK\r
+* NAME\r
+* IB_PATH_REC_SL_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the sl field for path record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_SL_MASK 0x000F\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SL_MASK\r
+* NAME\r
+* IB_MILTIPATH_REC_SL_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the sl field for MultiPath record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_SL_MASK 0x000F\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_QOS_CLASS_MASK\r
+* NAME\r
+* IB_PATH_REC_QOS_CLASS_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the QoS class field for path record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_QOS_CLASS_MASK 0xFFF0\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_QOS_CLASS_MASK\r
+* NAME\r
+* IB_MULTIPATH_REC_QOS_CLASS_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the QoS class field for MultiPath record\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_QOS_CLASS_MASK 0xFFF0\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_SELECTOR_MASK\r
+* NAME\r
+* IB_PATH_REC_SELECTOR_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the selector field for path record MTU, rate,\r
+* and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_SELECTOR_MASK 0xC0\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_SELECTOR_MASK\r
+* NAME\r
+* IB_MULTIPATH_REC_SELECTOR_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the selector field for multipath record MTU, rate,\r
+* and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_SELECTOR_MASK 0xC0\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_PATH_REC_BASE_MASK\r
+* NAME\r
+* IB_PATH_REC_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the base value field for path record MTU, rate,\r
+* and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_PATH_REC_BASE_MASK 0x3F\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_MULTIPATH_REC_BASE_MASK\r
+* NAME\r
+* IB_MULTIPATH_REC_BASE_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask for the base value field for multipath record MTU, rate,\r
+* and packet lifetime.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_MULTIPATH_REC_BASE_MASK 0x3F\r
+/**********/\r
+\r
+/****h* IBA Base/Type Definitions\r
+* NAME\r
+* Type Definitions\r
+*\r
+* DESCRIPTION\r
+* Definitions are from the InfiniBand Architecture Specification v1.2\r
+*\r
+*********/\r
+\r
+/****d* IBA Base: Types/ib_net16_t\r
+* NAME\r
+* ib_net16_t\r
+*\r
+* DESCRIPTION\r
+* Defines the network ordered type for 16-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint16_t ib_net16_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_net32_t\r
+* NAME\r
+* ib_net32_t\r
+*\r
+* DESCRIPTION\r
+* Defines the network ordered type for 32-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint32_t ib_net32_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_net64_t\r
+* NAME\r
+* ib_net64_t\r
+*\r
+* DESCRIPTION\r
+* Defines the network ordered type for 64-bit values.\r
+*\r
+* SOURCE\r
+*/\r
+typedef uint64_t ib_net64_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Types/ib_gid_prefix_t\r
+* NAME\r
+* ib_gid_prefix_t\r
+*\r
+* DESCRIPTION\r
+*\r
+* SOURCE\r
+*/\r
+typedef ib_net64_t ib_gid_prefix_t;\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/ib_link_states_t\r
+* NAME\r
+* ib_link_states_t\r
+*\r
+* DESCRIPTION\r
+* Defines the link states of a port.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_LINK_NO_CHANGE 0\r
+#define IB_LINK_DOWN 1\r
+#define IB_LINK_INIT 2\r
+#define IB_LINK_ARMED 3\r
+#define IB_LINK_ACTIVE 4\r
+#define IB_LINK_ACT_DEFER 5\r
+/**********/\r
+\r
+static const char* const __ib_node_type_str[] =\r
+{\r
+ "UNKNOWN",\r
+ "Channel Adapter",\r
+ "Switch",\r
+ "Router",\r
+ "Subnet Management"\r
+};\r
+\r
+/****f* IBA Base: Types/ib_get_node_type_str\r
+* NAME\r
+* ib_get_node_type_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified node type.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char* OSM_API\r
+ib_get_node_type_str(\r
+ IN uint32_t node_type )\r
+{\r
+ if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )\r
+ node_type = 0;\r
+ return( __ib_node_type_str[node_type] );\r
+}\r
+/*\r
+* PARAMETERS\r
+* node_type\r
+* [in] Encoded node type as returned in the NodeInfo attribute.\r
+\r
+* RETURN VALUES\r
+* Pointer to the node type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_node_info_t\r
+*********/\r
+\r
+static const char* const __ib_port_state_str[] =\r
+{\r
+ "No State Change (NOP)",\r
+ "DOWN",\r
+ "INIT",\r
+ "ARMED",\r
+ "ACTIVE",\r
+ "ACTDEFER",\r
+ "UNKNOWN"\r
+};\r
+\r
+/****f* IBA Base: Types/ib_get_port_state_str\r
+* NAME\r
+* ib_get_port_state_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char* OSM_API\r
+ib_get_port_state_str(\r
+ IN uint8_t port_state )\r
+{\r
+ if( port_state > IB_LINK_ACTIVE )\r
+ port_state = IB_LINK_ACTIVE + 1;\r
+ return( __ib_port_state_str[port_state] );\r
+}\r
+/*\r
+* PARAMETERS\r
+* node_type\r
+* [in] Encoded port state as returned in the PortInfo attribute.\r
+\r
+* RETURN VALUES\r
+* Pointer to the port state string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_get_port_state_from_str\r
+* NAME\r
+* ib_get_port_state_from_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_get_port_state_from_str(\r
+ IN char* p_port_state_str )\r
+{\r
+ if( !strncmp(p_port_state_str,"No State Change (NOP)", 12) )\r
+ return(0);\r
+ else if( !strncmp(p_port_state_str, "DOWN", 4) )\r
+ return(1);\r
+ else if( !strncmp(p_port_state_str, "INIT", 4) )\r
+ return(2);\r
+ else if( !strncmp(p_port_state_str, "ARMED" , 5) )\r
+ return(3);\r
+ else if( !strncmp(p_port_state_str, "ACTIVE", 6) )\r
+ return(4);\r
+ else if( !strncmp(p_port_state_str, "ACTDEFER", 8) )\r
+ return(5);\r
+ return(6);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_port_state_str\r
+* [in] A string matching one returned by ib_get_port_state_str\r
+*\r
+* RETURN VALUES\r
+* The appropriate code.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_port_info_t\r
+*********/\r
+\r
+/****d* IBA Base: Constants/Join States\r
+* NAME\r
+* Join States\r
+*\r
+* DESCRIPTION\r
+* Defines the join state flags for multicast group management.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_JOIN_STATE_FULL 1\r
+#define IB_JOIN_STATE_NON 2\r
+#define IB_JOIN_STATE_SEND_ONLY 4\r
+/**********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_get_base\r
+* NAME\r
+* ib_pkey_get_base\r
+*\r
+* DESCRIPTION\r
+* Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net16_t OSM_API\r
+ib_pkey_get_base(\r
+ IN const ib_net16_t pkey )\r
+{\r
+ return( (ib_net16_t)(pkey & IB_PKEY_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* pkey\r
+* [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+* Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_is_full_member\r
+* NAME\r
+* ib_pkey_is_full_member\r
+*\r
+* DESCRIPTION\r
+* Indicates if the port is a full member of the parition.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_pkey_is_full_member(\r
+ IN const ib_net16_t pkey )\r
+{\r
+ return( (pkey & IB_PKEY_TYPE_MASK) == IB_PKEY_TYPE_MASK );\r
+}\r
+/*\r
+* PARAMETERS\r
+* pkey\r
+* [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+* TRUE if the port is a full member of the partition.\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_pkey_get_base, ib_net16_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_pkey_is_invalid\r
+* NAME\r
+* ib_pkey_is_invalid\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the given P_Key is an invalid P_Key\r
+* C10-116: the CI shall regard a P_Key as invalid if its low-order\r
+* 15 bits are all zero...\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_pkey_is_invalid(\r
+ IN const ib_net16_t pkey )\r
+{\r
+ if (ib_pkey_get_base(pkey) == 0x0000)\r
+ return TRUE;\r
+\r
+ return FALSE;\r
+}\r
+/*\r
+* PARAMETERS\r
+* pkey\r
+* [in] P_Key value\r
+*\r
+* RETURN VALUE\r
+* Returns the base P_Key value with the membership bit stripped.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* IBA Base: Types/ib_gid_t\r
+* NAME\r
+* ib_gid_t\r
+*\r
+* DESCRIPTION\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef union _ib_gid\r
+{\r
+ uint8_t raw[16];\r
+ struct _ib_gid_unicast\r
+ {\r
+ ib_gid_prefix_t prefix;\r
+ ib_net64_t interface_id;\r
+\r
+ } PACK_SUFFIX unicast;\r
+\r
+ struct _ib_gid_multicast\r
+ {\r
+ uint8_t header[2];\r
+ uint8_t raw_group_id[14];\r
+\r
+ } PACK_SUFFIX multicast;\r
+\r
+} PACK_SUFFIX ib_gid_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* raw\r
+* GID represented as an unformated byte array.\r
+*\r
+* unicast\r
+* Typical unicast representation with subnet prefix and\r
+* port GUID.\r
+*\r
+* multicast\r
+* Representation for multicast use.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_multicast\r
+* NAME\r
+* ib_gid_is_multicast\r
+*\r
+* DESCRIPTION\r
+* Returns a boolean indicating whether a GID is a multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_gid_is_multicast(\r
+ IN const ib_gid_t* p_gid )\r
+{\r
+ return( p_gid->raw[0] == 0xFF );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_get_scope\r
+* NAME\r
+* ib_gid_get_scope\r
+*\r
+* DESCRIPTION\r
+* Returns scope of (assumed) multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_mgid_get_scope(\r
+ IN const ib_gid_t* p_gid )\r
+{\r
+ return( p_gid->raw[1] & 0x0F );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_set_scope\r
+* NAME\r
+* ib_gid_set_scope\r
+*\r
+* DESCRIPTION\r
+* Sets scope of (assumed) multicast GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_mgid_set_scope(\r
+ IN ib_gid_t* const p_gid,\r
+ IN const uint8_t scope )\r
+{\r
+ p_gid->raw[1] &= 0xF0;\r
+ p_gid->raw[1] |= scope & 0x0F;\r
+}\r
+\r
+/****f* IBA Base: Types/ib_gid_set_default\r
+* NAME\r
+* ib_gid_set_default\r
+*\r
+* DESCRIPTION\r
+* Sets a GID to the default value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_gid_set_default(\r
+ IN ib_gid_t* const p_gid,\r
+ IN const ib_net64_t interface_id )\r
+{\r
+ p_gid->unicast.prefix = IB_DEFAULT_SUBNET_PREFIX;\r
+ p_gid->unicast.interface_id = interface_id;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_gid\r
+* [in] Pointer to the GID object.\r
+*\r
+* interface_id\r
+* [in] Manufacturer assigned EUI64 value of a port.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_get_subnet_prefix\r
+* NAME\r
+* ib_gid_get_subnet_prefix\r
+*\r
+* DESCRIPTION\r
+* Gets the subnet prefix from a GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t OSM_API\r
+ib_gid_get_subnet_prefix(\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ return( p_gid->unicast.prefix );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_gid\r
+* [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+* 64-bit subnet prefix value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_link_local\r
+* NAME\r
+* ib_gid_is_link_local\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the unicast GID scoping indicates link local,\r
+* FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_gid_is_link_local(\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ return( ( ib_gid_get_subnet_prefix( p_gid ) &\r
+ CL_HTON64( 0xFFC0000000000000ULL ) ) == IB_DEFAULT_SUBNET_PREFIX );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_gid\r
+* [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the unicast GID scoping indicates link local,\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_is_site_local\r
+* NAME\r
+* ib_gid_is_site_local\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the unicast GID scoping indicates site local,\r
+* FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_gid_is_site_local(\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ return( ( ib_gid_get_subnet_prefix( p_gid ) &\r
+ CL_HTON64( 0xFFFFFFFFFFFF0000ULL ) ) == CL_HTON64( 0xFEC0000000000000ULL ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_gid\r
+* [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the unicast GID scoping indicates site local,\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_gid_get_guid\r
+* NAME\r
+* ib_gid_get_guid\r
+*\r
+* DESCRIPTION\r
+* Gets the guid from a GID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t OSM_API\r
+ib_gid_get_guid(\r
+ IN const ib_gid_t* const p_gid )\r
+{\r
+ return( p_gid->unicast.interface_id );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_gid\r
+* [in] Pointer to the GID object.\r
+*\r
+* RETURN VALUES\r
+* 64-bit GUID value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_path_rec_t\r
+* NAME\r
+* ib_path_rec_t\r
+*\r
+* DESCRIPTION\r
+* Path records encapsulate the properties of a given\r
+* route between two end-points on a subnet.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_path_rec\r
+{\r
+ ib_net64_t service_id;\r
+ ib_gid_t dgid;\r
+ ib_gid_t sgid;\r
+ ib_net16_t dlid;\r
+ ib_net16_t slid;\r
+ ib_net32_t hop_flow_raw;\r
+ uint8_t tclass;\r
+ uint8_t num_path; \r
+ ib_net16_t pkey;\r
+ ib_net16_t qos_class_sl;\r
+ uint8_t mtu;\r
+ uint8_t rate;\r
+ uint8_t pkt_life;\r
+ uint8_t preference;\r
+ uint8_t resv2[6];\r
+\r
+} PACK_SUFFIX ib_path_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* resv0\r
+* Reserved bytes.\r
+*\r
+* dgid\r
+* GID of destination port.\r
+*\r
+* sgid\r
+* GID of source port.\r
+*\r
+* dlid\r
+* LID of destination port.\r
+*\r
+* slid\r
+* LID of source port.\r
+*\r
+* hop_flow_raw\r
+* Global routing parameters: hop count, flow label and raw bit.\r
+*\r
+* tclass\r
+* Another global routing parameter.\r
+*\r
+* num_path\r
+* Reversible path - 1 bit to say if path is reversible.\r
+* num_path [6:0] In queries, maximum number of paths to return.\r
+* In responses, undefined.\r
+*\r
+* pkey\r
+* Partition key (P_Key) to use on this path.\r
+*\r
+* resv1\r
+* Reserved byte.\r
+*\r
+* sl\r
+* Service level to use on this path.\r
+*\r
+* mtu\r
+* MTU and MTU selector fields to use on this path\r
+*\r
+* rate\r
+* Rate and rate selector fields to use on this path.\r
+*\r
+* pkt_life\r
+* Packet lifetime\r
+*\r
+* preference\r
+* Indicates the relative merit of this path versus other path\r
+* records returned from the SA. Lower numbers are better.\r
+*\r
+* resv2\r
+* Reserved bytes.\r
+* SEE ALSO\r
+*********/\r
+\r
+/* Path Record Component Masks */\r
+#define IB_PR_COMPMASK_DGID (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_PR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_PR_COMPMASK_DLID (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_PR_COMPMASK_SLID (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_PR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_PR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_PR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_PR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_PR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_PR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_PR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_PR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_PR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_PR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_PR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_PR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_PR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_PR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_PR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_PR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<21))\r
+\r
+/* Link Record Component Masks */\r
+#define IB_LR_COMPMASK_FROM_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_LR_COMPMASK_FROM_PORT (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_LR_COMPMASK_TO_PORT (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_LR_COMPMASK_TO_LID (CL_HTON64(((uint64_t)1)<<3))\r
+\r
+/* VL Arbitration Record Masks */\r
+#define IB_VLA_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_VLA_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_VLA_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* SLtoVL Mapping Record Masks */\r
+#define IB_SLVL_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SLVL_COMPMASK_IN_PORT (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SLVL_COMPMASK_OUT_PORT (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* P_Key Table Record Masks */\r
+#define IB_PKEY_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_PKEY_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_PKEY_COMPMASK_PORT (CL_HTON64(((uint64_t)1)<<2))\r
+\r
+/* Switch Info Record Masks */\r
+#define IB_SWIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SWIR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1))\r
+\r
+/* LFT Record Masks */\r
+#define IB_LFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_LFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<1))\r
+\r
+/* MFT Record Masks */\r
+#define IB_MFTR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MFTR_COMPMASK_POSITION (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MFTR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MFTR_COMPMASK_BLOCK (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MFTR_COMPMASK_RESERVED2 (CL_HTON64(((uint64_t)1)<<4))\r
+\r
+/* NodeInfo Record Masks */\r
+#define IB_NR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_NR_COMPMASK_RESERVED1 (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_NR_COMPMASK_BASEVERSION (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_NR_COMPMASK_CLASSVERSION (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_NR_COMPMASK_NODETYPE (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_NR_COMPMASK_NUMPORTS (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_NR_COMPMASK_SYSIMAGEGUID (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_NR_COMPMASK_NODEGUID (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_NR_COMPMASK_PORTGUID (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_NR_COMPMASK_PARTCAP (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_NR_COMPMASK_DEVID (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_NR_COMPMASK_REV (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_NR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_NR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_NR_COMPMASK_NODEDESC (CL_HTON64(((uint64_t)1)<<14))\r
+\r
+/* Service Record Component Masks Sec 15.2.5.14 Ver 1.1*/\r
+#define IB_SR_COMPMASK_SID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SR_COMPMASK_SGID (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SR_COMPMASK_SPKEY (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_SR_COMPMASK_RES1 (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_SR_COMPMASK_SLEASE (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_SR_COMPMASK_SKEY (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_SR_COMPMASK_SNAME (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_SR_COMPMASK_SDATA8_0 (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_SR_COMPMASK_SDATA8_1 (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_SR_COMPMASK_SDATA8_2 (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_SR_COMPMASK_SDATA8_3 (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_SR_COMPMASK_SDATA8_4 (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_SR_COMPMASK_SDATA8_5 (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_SR_COMPMASK_SDATA8_6 (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_SR_COMPMASK_SDATA8_7 (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_SR_COMPMASK_SDATA8_8 (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_SR_COMPMASK_SDATA8_9 (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_SR_COMPMASK_SDATA8_10 (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_SR_COMPMASK_SDATA8_11 (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_SR_COMPMASK_SDATA8_12 (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_SR_COMPMASK_SDATA8_13 (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_SR_COMPMASK_SDATA8_14 (CL_HTON64(((uint64_t)1)<<21))\r
+#define IB_SR_COMPMASK_SDATA8_15 (CL_HTON64(((uint64_t)1)<<22))\r
+#define IB_SR_COMPMASK_SDATA16_0 (CL_HTON64(((uint64_t)1)<<23))\r
+#define IB_SR_COMPMASK_SDATA16_1 (CL_HTON64(((uint64_t)1)<<24))\r
+#define IB_SR_COMPMASK_SDATA16_2 (CL_HTON64(((uint64_t)1)<<25))\r
+#define IB_SR_COMPMASK_SDATA16_3 (CL_HTON64(((uint64_t)1)<<26))\r
+#define IB_SR_COMPMASK_SDATA16_4 (CL_HTON64(((uint64_t)1)<<27))\r
+#define IB_SR_COMPMASK_SDATA16_5 (CL_HTON64(((uint64_t)1)<<28))\r
+#define IB_SR_COMPMASK_SDATA16_6 (CL_HTON64(((uint64_t)1)<<29))\r
+#define IB_SR_COMPMASK_SDATA16_7 (CL_HTON64(((uint64_t)1)<<30))\r
+#define IB_SR_COMPMASK_SDATA32_0 (CL_HTON64(((uint64_t)1)<<31))\r
+#define IB_SR_COMPMASK_SDATA32_1 (CL_HTON64(((uint64_t)1)<<32))\r
+#define IB_SR_COMPMASK_SDATA32_2 (CL_HTON64(((uint64_t)1)<<33))\r
+#define IB_SR_COMPMASK_SDATA32_3 (CL_HTON64(((uint64_t)1)<<34))\r
+#define IB_SR_COMPMASK_SDATA64_0 (CL_HTON64(((uint64_t)1)<<35))\r
+#define IB_SR_COMPMASK_SDATA64_1 (CL_HTON64(((uint64_t)1)<<36))\r
+\r
+/* Port Info Record Component Masks */\r
+#define IB_PIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_PIR_COMPMASK_PORTNUM (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_PIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_PIR_COMPMASK_MKEY (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_PIR_COMPMASK_GIDPRE (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_PIR_COMPMASK_BASELID (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_PIR_COMPMASK_SMLID (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_PIR_COMPMASK_CAPMASK (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_PIR_COMPMASK_DIAGCODE (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_PIR_COMPMASK_MKEYLEASEPRD (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_PIR_COMPMASK_LOCALPORTNUM (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_PIR_COMPMASK_LINKWIDTHENABLED (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_PIR_COMPMASK_LNKWIDTHSUPPORT (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_PIR_COMPMASK_LNKWIDTHACTIVE (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_PIR_COMPMASK_LNKSPEEDSUPPORT (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_PIR_COMPMASK_PORTSTATE (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_PIR_COMPMASK_PORTPHYSTATE (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_PIR_COMPMASK_LINKDWNDFLTSTATE (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_PIR_COMPMASK_MKEYPROTBITS (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_PIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_PIR_COMPMASK_LMC (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_PIR_COMPMASK_LINKSPEEDACTIVE (CL_HTON64(((uint64_t)1)<<21))\r
+#define IB_PIR_COMPMASK_LINKSPEEDENABLE (CL_HTON64(((uint64_t)1)<<22))\r
+#define IB_PIR_COMPMASK_NEIGHBORMTU (CL_HTON64(((uint64_t)1)<<23))\r
+#define IB_PIR_COMPMASK_MASTERSMSL (CL_HTON64(((uint64_t)1)<<24))\r
+#define IB_PIR_COMPMASK_VLCAP (CL_HTON64(((uint64_t)1)<<25))\r
+#define IB_PIR_COMPMASK_INITTYPE (CL_HTON64(((uint64_t)1)<<26))\r
+#define IB_PIR_COMPMASK_VLHIGHLIMIT (CL_HTON64(((uint64_t)1)<<27))\r
+#define IB_PIR_COMPMASK_VLARBHIGHCAP (CL_HTON64(((uint64_t)1)<<28))\r
+#define IB_PIR_COMPMASK_VLARBLOWCAP (CL_HTON64(((uint64_t)1)<<29))\r
+#define IB_PIR_COMPMASK_INITTYPEREPLY (CL_HTON64(((uint64_t)1)<<30))\r
+#define IB_PIR_COMPMASK_MTUCAP (CL_HTON64(((uint64_t)1)<<31))\r
+#define IB_PIR_COMPMASK_VLSTALLCNT (CL_HTON64(((uint64_t)1)<<32))\r
+#define IB_PIR_COMPMASK_HOQLIFE (CL_HTON64(((uint64_t)1)<<33))\r
+#define IB_PIR_COMPMASK_OPVLS (CL_HTON64(((uint64_t)1)<<34))\r
+#define IB_PIR_COMPMASK_PARENFIN (CL_HTON64(((uint64_t)1)<<35))\r
+#define IB_PIR_COMPMASK_PARENFOUT (CL_HTON64(((uint64_t)1)<<36))\r
+#define IB_PIR_COMPMASK_FILTERRAWIN (CL_HTON64(((uint64_t)1)<<37))\r
+#define IB_PIR_COMPMASK_FILTERRAWOUT (CL_HTON64(((uint64_t)1)<<38))\r
+#define IB_PIR_COMPMASK_MKEYVIO (CL_HTON64(((uint64_t)1)<<39))\r
+#define IB_PIR_COMPMASK_PKEYVIO (CL_HTON64(((uint64_t)1)<<40))\r
+#define IB_PIR_COMPMASK_QKEYVIO (CL_HTON64(((uint64_t)1)<<41))\r
+#define IB_PIR_COMPMASK_GUIDCAP (CL_HTON64(((uint64_t)1)<<42))\r
+#define IB_PIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<43))\r
+#define IB_PIR_COMPMASK_SUBNTO (CL_HTON64(((uint64_t)1)<<44))\r
+#define IB_PIR_COMPMASK_RESV4 (CL_HTON64(((uint64_t)1)<<45))\r
+#define IB_PIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<46))\r
+#define IB_PIR_COMPMASK_LOCALPHYERR (CL_HTON64(((uint64_t)1)<<47))\r
+#define IB_PIR_COMPMASK_OVERRUNERR (CL_HTON64(((uint64_t)1)<<48))\r
+\r
+/* Multicast Member Record Component Masks */\r
+#define IB_MCR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MCR_COMPMASK_MGID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MCR_COMPMASK_PORT_GID (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MCR_COMPMASK_QKEY (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MCR_COMPMASK_MLID (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MCR_COMPMASK_MTU_SEL (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_MCR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_MCR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_MCR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_MCR_COMPMASK_RATE_SEL (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_MCR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_MCR_COMPMASK_LIFE_SEL (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_MCR_COMPMASK_LIFE (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_MCR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_MCR_COMPMASK_FLOW (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_MCR_COMPMASK_HOP (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_MCR_COMPMASK_SCOPE (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_MCR_COMPMASK_JOIN_STATE (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_MCR_COMPMASK_PROXY (CL_HTON64(((uint64_t)1)<<17))\r
+\r
+/* GUID Info Record Component Masks */\r
+#define IB_GIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_GIR_COMPMASK_BLOCKNUM (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_GIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_GIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_GIR_COMPMASK_GID0 (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_GIR_COMPMASK_GID1 (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_GIR_COMPMASK_GID2 (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_GIR_COMPMASK_GID3 (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_GIR_COMPMASK_GID4 (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_GIR_COMPMASK_GID5 (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_GIR_COMPMASK_GID6 (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_GIR_COMPMASK_GID7 (CL_HTON64(((uint64_t)1)<<11))\r
+\r
+/* MultiPath Record Component Masks */\r
+#define IB_MPR_COMPMASK_RAWTRAFFIC (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_MPR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_MPR_COMPMASK_FLOWLABEL (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_MPR_COMPMASK_HOPLIMIT (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_MPR_COMPMASK_TCLASS (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_MPR_COMPMASK_REVERSIBLE (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_MPR_COMPMASK_NUMBPATH (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_MPR_COMPMASK_PKEY (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_MPR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_MPR_COMPMASK_SL (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_MPR_COMPMASK_MTUSELEC (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_MPR_COMPMASK_MTU (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_MPR_COMPMASK_RATESELEC (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_MPR_COMPMASK_RATE (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_MPR_COMPMASK_PKTLIFETIMESELEC (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_MPR_COMPMASK_PKTLIFETIME (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_MPR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<16))\r
+#define IB_MPR_COMPMASK_INDEPSELEC (CL_HTON64(((uint64_t)1)<<17))\r
+#define IB_MPR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<18))\r
+#define IB_MPR_COMPMASK_SGIDCOUNT (CL_HTON64(((uint64_t)1)<<19))\r
+#define IB_MPR_COMPMASK_DGIDCOUNT (CL_HTON64(((uint64_t)1)<<20))\r
+#define IB_MPR_COMPMASK_RESV4 (CL_HTON64(((uint64_t)1)<<21))\r
+\r
+/* SMInfo Record Component Masks */\r
+#define IB_SMIR_COMPMASK_LID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_SMIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_SMIR_COMPMASK_GUID (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_SMIR_COMPMASK_SMKEY (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_SMIR_COMPMASK_ACTCOUNT (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_SMIR_COMPMASK_PRIORITY (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_SMIR_COMPMASK_SMSTATE (CL_HTON64(((uint64_t)1)<<6))\r
+\r
+/* InformInfo Record Component Masks */\r
+#define IB_IIR_COMPMASK_SUBSCRIBERGID (CL_HTON64(((uint64_t)1)<<0))\r
+#define IB_IIR_COMPMASK_ENUM (CL_HTON64(((uint64_t)1)<<1))\r
+#define IB_IIR_COMPMASK_RESV0 (CL_HTON64(((uint64_t)1)<<2))\r
+#define IB_IIR_COMPMASK_GID (CL_HTON64(((uint64_t)1)<<3))\r
+#define IB_IIR_COMPMASK_LIDRANGEBEGIN (CL_HTON64(((uint64_t)1)<<4))\r
+#define IB_IIR_COMPMASK_LIDRANGEEND (CL_HTON64(((uint64_t)1)<<5))\r
+#define IB_IIR_COMPMASK_RESV1 (CL_HTON64(((uint64_t)1)<<6))\r
+#define IB_IIR_COMPMASK_ISGENERIC (CL_HTON64(((uint64_t)1)<<7))\r
+#define IB_IIR_COMPMASK_SUBSCRIBE (CL_HTON64(((uint64_t)1)<<8))\r
+#define IB_IIR_COMPMASK_TYPE (CL_HTON64(((uint64_t)1)<<9))\r
+#define IB_IIR_COMPMASK_TRAPNUMB (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_IIR_COMPMASK_DEVICEID (CL_HTON64(((uint64_t)1)<<10))\r
+#define IB_IIR_COMPMASK_QPN (CL_HTON64(((uint64_t)1)<<11))\r
+#define IB_IIR_COMPMASK_RESV2 (CL_HTON64(((uint64_t)1)<<12))\r
+#define IB_IIR_COMPMASK_RESPTIME (CL_HTON64(((uint64_t)1)<<13))\r
+#define IB_IIR_COMPMASK_RESV3 (CL_HTON64(((uint64_t)1)<<14))\r
+#define IB_IIR_COMPMASK_PRODTYPE (CL_HTON64(((uint64_t)1)<<15))\r
+#define IB_IIR_COMPMASK_VENDID (CL_HTON64(((uint64_t)1)<<15))\r
+\r
+/****f* IBA Base: Types/ib_path_rec_init_local\r
+* NAME\r
+* ib_path_rec_init_local\r
+*\r
+* DESCRIPTION\r
+* Initializes a subnet local path record.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_path_rec_init_local(\r
+ IN ib_path_rec_t* const p_rec,\r
+ IN ib_gid_t* const p_dgid,\r
+ IN ib_gid_t* const p_sgid,\r
+ IN ib_net16_t dlid,\r
+ IN ib_net16_t slid,\r
+ IN uint8_t num_path,\r
+ IN ib_net16_t pkey,\r
+ IN uint8_t sl,\r
+ IN uint8_t mtu_selector,\r
+ IN uint8_t mtu,\r
+ IN uint8_t rate_selector,\r
+ IN uint8_t rate,\r
+ IN uint8_t pkt_life_selector,\r
+ IN uint8_t pkt_life,\r
+ IN uint8_t preference )\r
+{\r
+ p_rec->dgid = *p_dgid;\r
+ p_rec->sgid = *p_sgid;\r
+ p_rec->dlid = dlid;\r
+ p_rec->slid = slid;\r
+ p_rec->num_path = num_path;\r
+ p_rec->pkey = pkey;\r
+ /* Lower 4 bits of path rec's SL are reserved. */\r
+ p_rec->qos_class_sl = cl_ntoh16( sl );\r
+ p_rec->mtu = (uint8_t)((mtu & IB_PATH_REC_BASE_MASK) |\r
+ (uint8_t)(mtu_selector << 6));\r
+ p_rec->rate = (uint8_t)((rate & IB_PATH_REC_BASE_MASK) |\r
+ (uint8_t)(rate_selector << 6));\r
+ p_rec->pkt_life = (uint8_t)((pkt_life & IB_PATH_REC_BASE_MASK) |\r
+ (uint8_t)(pkt_life_selector << 6));\r
+ p_rec->preference = preference;\r
+\r
+ /* Clear global routing fields for local path records */\r
+ p_rec->hop_flow_raw = 0;\r
+ p_rec->tclass = 0;\r
+\r
+ *((uint64_t*)p_rec->service_id) = 0;\r
+ *((uint32_t*)p_rec->resv2) = 0;\r
+ *((uint16_t*)p_rec->resv2 + 2) = 0;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* dgid\r
+* [in] GID of destination port.\r
+*\r
+* sgid\r
+* [in] GID of source port.\r
+*\r
+* dlid\r
+* [in] LID of destination port.\r
+*\r
+* slid\r
+* [in] LID of source port.\r
+*\r
+* num_path\r
+* [in] Reversible path - 1 bit to say if path is reversible.\r
+* num_path [6:0] In queries, maximum number of paths to return.\r
+* In responses, undefined.\r
+*\r
+* pkey\r
+* [in] Partition key (P_Key) to use on this path.\r
+*\r
+* sl\r
+* [in] Service level to use on this path. Lower 4-bits are valid.\r
+*\r
+* mtu_selector\r
+* [in] Encoded MTU selector value to use on this path\r
+*\r
+* mtu\r
+* [in] Encoded MTU to use on this path\r
+*\r
+* rate_selector\r
+* [in] Encoded rate selector value to use on this path.\r
+*\r
+* rate\r
+* [in] Encoded rate to use on this path.\r
+*\r
+* pkt_life_selector\r
+* [in] Encoded Packet selector value lifetime for this path.\r
+*\r
+* pkt_life\r
+* [in] Encoded Packet lifetime for this path.\r
+*\r
+* preference\r
+* [in] Indicates the relative merit of this path versus other path\r
+* records returned from the SA. Lower numbers are better.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_num_path\r
+* NAME\r
+* ib_path_rec_num_path\r
+*\r
+* DESCRIPTION\r
+* Get max number of paths to return.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_num_path(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( p_rec->num_path &0x7F );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Maximum number of paths to return for each unique SGID_DGID combination.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_sl\r
+* NAME\r
+* ib_path_rec_sl\r
+*\r
+* DESCRIPTION\r
+* Get path service level.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_sl(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((cl_ntoh16( p_rec->qos_class_sl )) & 0xF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* SL.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_set_qos_class\r
+* NAME\r
+* ib_path_rec_set_qos_class\r
+*\r
+* DESCRIPTION\r
+* Set path QoS class.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_path_rec_set_qos_class(IN ib_path_rec_t * const p_rec,\r
+ IN const uint16_t qos_class)\r
+{\r
+ p_rec->qos_class_sl =\r
+ (p_rec->qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) |\r
+ cl_hton16(qos_class << 4);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* qos_class\r
+* [in] QoS class to set.\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_qos_class\r
+* NAME\r
+* ib_path_rec_qos_class\r
+*\r
+* DESCRIPTION\r
+* Get QoS class.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint16_t OSM_API\r
+ib_path_rec_qos_class(IN const ib_path_rec_t * const p_rec)\r
+{\r
+ return (cl_ntoh16(p_rec->qos_class_sl) >> 4);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* QoS class of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_path_rec_mtu\r
+* NAME\r
+* ib_path_rec_mtu\r
+*\r
+* DESCRIPTION\r
+* Get encoded path MTU.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_mtu(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->mtu & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path MTU.\r
+* 1: 256\r
+* 2: 512\r
+* 3: 1024\r
+* 4: 2048\r
+* 5: 4096\r
+* others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_mtu_sel\r
+* NAME\r
+* ib_path_rec_mtu_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded path MTU selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_mtu_sel(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->mtu & IB_PATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path MTU selector value (for queries).\r
+* 0: greater than MTU specified\r
+* 1: less than MTU specified\r
+* 2: exactly the MTU specified\r
+* 3: largest MTU available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_rate\r
+* NAME\r
+* ib_path_rec_rate\r
+*\r
+* DESCRIPTION\r
+* Get encoded path rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_rate(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->rate & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path rate.\r
+* 2: 2.5 Gb/sec.\r
+* 3: 10 Gb/sec.\r
+* 4: 30 Gb/sec.\r
+* 5: 5 Gb/sec.\r
+* 6: 20 Gb/sec.\r
+* 7: 40 Gb/sec.\r
+* 8: 60 Gb/sec.\r
+* 9: 80 Gb/sec.\r
+* 10: 120 Gb/sec.\r
+* others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_rate_sel\r
+* NAME\r
+* ib_path_rec_rate_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded path rate selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_rate_sel(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->rate & IB_PATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path rate selector value (for queries).\r
+* 0: greater than rate specified\r
+* 1: less than rate specified\r
+* 2: exactly the rate specified\r
+* 3: largest rate available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_pkt_life\r
+* NAME\r
+* ib_path_rec_pkt_life\r
+*\r
+* DESCRIPTION\r
+* Get encoded path pkt_life.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_pkt_life(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->pkt_life & IB_PATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path pkt_life = 4.096 µsec * 2 ** PacketLifeTime.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_pkt_life_sel\r
+* NAME\r
+* ib_path_rec_pkt_life_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded path pkt_lifetime selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_pkt_life_sel(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->pkt_life & IB_PATH_REC_SELECTOR_MASK) >> 6 ));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path pkt_lifetime selector value (for queries).\r
+* 0: greater than rate specified\r
+* 1: less than rate specified\r
+* 2: exactly the rate specified\r
+* 3: smallest packet lifetime available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_flow_lbl\r
+* NAME\r
+* ib_path_rec_flow_lbl\r
+*\r
+* DESCRIPTION\r
+* Get flow label.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint32_t OSM_API\r
+ib_path_rec_flow_lbl(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( ((cl_ntoh32(p_rec->hop_flow_raw) >> 8) & 0x000FFFFF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Flow label of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_rec_hop_limit\r
+* NAME\r
+* ib_path_rec_hop_limit\r
+*\r
+* DESCRIPTION\r
+* Get hop limit.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_rec_hop_limit(\r
+ IN const ib_path_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->hop_flow_raw & 0x000000FF ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the path record object.\r
+*\r
+* RETURN VALUES\r
+* Hop limit of the path record.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_path_rec_t\r
+*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_CAP_TRAP\r
+* NAME\r
+* IB_CLASS_CAP_TRAP\r
+*\r
+* DESCRIPTION\r
+* ClassPortInfo CapabilityMask bits. This bit will be set\r
+* if the class supports Trap() MADs (13.4.8.1).\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t, IB_CLASS_CAP_GETSET\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_CAP_TRAP 0x0001\r
+/*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_CAP_GETSET\r
+* NAME\r
+* IB_CLASS_CAP_GETSET\r
+*\r
+* DESCRIPTION\r
+* ClassPortInfo CapabilityMask bits. This bit will be set\r
+* if the class supports Get(Notice) and Set(Notice) MADs (13.4.8.1).\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t, IB_CLASS_CAP_TRAP\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_CAP_GETSET 0x0002\r
+/*********/\r
+\r
+/****s* IBA Base: Constants/IB_CLASS_RESP_TIME_MASK\r
+* NAME\r
+* IB_CLASS_RESP_TIME_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask bits to extract the reponse time value from the\r
+* resp_time_val field of ib_class_port_info_t.\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_CLASS_RESP_TIME_MASK 0x1F\r
+/*********/\r
+/****s* IBA Base: Types/ib_class_port_info_t\r
+* NAME\r
+* ib_class_port_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined ClassPortInfo attribute (13.4.8.1)\r
+* route between two end-points on a subnet.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_class_port_info\r
+{\r
+ uint8_t base_ver;\r
+ uint8_t class_ver;\r
+ ib_net16_t cap_mask;\r
+ ib_net32_t cap_mask2_resp_time;\r
+ ib_gid_t redir_gid;\r
+ ib_net32_t redir_tc_sl_fl;\r
+ ib_net16_t redir_lid;\r
+ ib_net16_t redir_pkey;\r
+ ib_net32_t redir_qp;\r
+ ib_net32_t redir_qkey;\r
+ ib_gid_t trap_gid;\r
+ ib_net32_t trap_tc_sl_fl;\r
+ ib_net16_t trap_lid;\r
+ ib_net16_t trap_pkey;\r
+ ib_net32_t trap_hop_qp;\r
+ ib_net32_t trap_qkey;\r
+\r
+} PACK_SUFFIX ib_class_port_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* base_ver\r
+* Maximum supported MAD Base Version.\r
+*\r
+* class_ver\r
+* Maximum supported management class version.\r
+*\r
+* cap_mask\r
+* Supported capabilities of this management class.\r
+*\r
+* cap_mask2_resp_time\r
+* Maximum expected response time and additional\r
+* supported capabilities of this management class.\r
+*\r
+* redr_gid\r
+* GID to use for redirection, or zero\r
+*\r
+* recdir_tc_sl_fl\r
+* Traffic class, service level and flow label the requester\r
+* should use if the service is redirected.\r
+*\r
+* redir_lid\r
+* LID used for redirection, or zero\r
+*\r
+* redir_pkey\r
+* P_Key used for redirection\r
+*\r
+* redir_qp\r
+* QP number used for redirection\r
+*\r
+* redir_qkey\r
+* Q_Key associated with the redirected QP. This shall be the\r
+* well known Q_Key value.\r
+*\r
+* trap_gid\r
+* GID value used for trap messages from this service.\r
+*\r
+* trap_tc_sl_fl\r
+* Traffic class, service level and flow label used for\r
+* trap messages originated by this service.\r
+*\r
+* trap_lid\r
+* LID used for trap messages, or zero\r
+*\r
+* trap_pkey\r
+* P_Key used for trap messages\r
+*\r
+* trap_hop_qp\r
+* Hop limit (upper 8 bits) and QP number used for trap messages\r
+*\r
+* trap_qkey\r
+* Q_Key associated with the trap messages QP.\r
+*\r
+* SEE ALSO\r
+* IB_CLASS_CAP_GETSET, IB_CLASS_CAP_TRAP\r
+*\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_set_resp_time_val\r
+* NAME\r
+* ib_class_set_resp_time_val\r
+*\r
+* DESCRIPTION\r
+* Set maximum expected response time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_class_set_resp_time_val(IN ib_class_port_info_t * const p_cpi,\r
+ IN const uint8_t val)\r
+{\r
+ p_cpi->cap_mask2_resp_time =\r
+ (p_cpi->cap_mask2_resp_time & CL_HTON32(~IB_CLASS_RESP_TIME_MASK)) |\r
+ cl_hton32(val & IB_CLASS_RESP_TIME_MASK);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_cpi\r
+* [in] Pointer to the class port info object.\r
+*\r
+* val\r
+* [in] Response time value to set.\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_resp_time_val\r
+* NAME\r
+* ib_class_resp_time_val\r
+*\r
+* DESCRIPTION\r
+* Get response time value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_class_resp_time_val(IN ib_class_port_info_t * const p_cpi)\r
+{\r
+ return (uint8_t)(cl_ntoh32(p_cpi->cap_mask2_resp_time) &\r
+ IB_CLASS_RESP_TIME_MASK);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_cpi\r
+* [in] Pointer to the class port info object.\r
+*\r
+* RETURN VALUES\r
+* Response time value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_set_cap_mask2\r
+* NAME\r
+* ib_class_set_cap_mask2\r
+*\r
+* DESCRIPTION\r
+* Set ClassPortInfo:CapabilityMask2.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_class_set_cap_mask2(IN ib_class_port_info_t * const p_cpi,\r
+ IN const uint32_t cap_mask2)\r
+{\r
+ p_cpi->cap_mask2_resp_time = (p_cpi->cap_mask2_resp_time &\r
+ CL_HTON32(IB_CLASS_RESP_TIME_MASK)) |\r
+ cl_hton32(cap_mask2 << 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_cpi\r
+* [in] Pointer to the class port info object.\r
+*\r
+* cap_mask2\r
+* [in] CapabilityMask2 value to set.\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_class_cap_mask2\r
+* NAME\r
+* ib_class_cap_mask2\r
+*\r
+* DESCRIPTION\r
+* Get ClassPortInfo:CapabilityMask2.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint32_t OSM_API\r
+ib_class_cap_mask2(IN const ib_class_port_info_t * const p_cpi)\r
+{\r
+ return (cl_ntoh32(p_cpi->cap_mask2_resp_time) >> 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_cpi\r
+* [in] Pointer to the class port info object.\r
+*\r
+* RETURN VALUES\r
+* CapabilityMask2 of the ClassPortInfo.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_class_port_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_sm_info_t\r
+* NAME\r
+* ib_sm_info_t\r
+*\r
+* DESCRIPTION\r
+* SMInfo structure (14.2.5.13).\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sm_info\r
+{\r
+ ib_net64_t guid;\r
+ ib_net64_t sm_key;\r
+ ib_net32_t act_count;\r
+ uint8_t pri_state;\r
+\r
+} PACK_SUFFIX ib_sm_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* guid\r
+* Port GUID for this SM.\r
+*\r
+* sm_key\r
+* SM_Key of this SM.\r
+*\r
+* act_count\r
+* Activity counter used as a heartbeat.\r
+*\r
+* pri_state\r
+* Priority and State information\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_sminfo_get_priority\r
+* NAME\r
+* ib_sminfo_get_priority\r
+*\r
+* DESCRIPTION\r
+* Returns the priority value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_sminfo_get_priority(\r
+ IN const ib_sm_info_t* const p_smi )\r
+{\r
+ return( (uint8_t)((p_smi->pri_state & 0xF0)>>4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smi\r
+* [in] Pointer to the SMInfo Attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the priority value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_sminfo_get_state\r
+* NAME\r
+* ib_sminfo_get_state\r
+*\r
+* DESCRIPTION\r
+* Returns the state value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_sminfo_get_state(\r
+ IN const ib_sm_info_t* const p_smi )\r
+{\r
+ return( (uint8_t)(p_smi->pri_state & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smi\r
+* [in] Pointer to the SMInfo Attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the state value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_mad_t\r
+* NAME\r
+* ib_mad_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined MAD header (13.4.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mad\r
+{\r
+ uint8_t base_ver;\r
+ uint8_t mgmt_class;\r
+ uint8_t class_ver;\r
+ uint8_t method;\r
+ ib_net16_t status;\r
+ ib_net16_t class_spec;\r
+ ib_net64_t trans_id;\r
+ ib_net16_t attr_id;\r
+ ib_net16_t resv;\r
+ ib_net32_t attr_mod;\r
+} PACK_SUFFIX ib_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* base_ver\r
+* MAD base format.\r
+*\r
+* mgmt_class\r
+* Class of operation.\r
+*\r
+* class_ver\r
+* Version of MAD class-specific format.\r
+*\r
+* method\r
+* Method to perform, including 'R' bit.\r
+*\r
+* status\r
+* Status of operation.\r
+*\r
+* class_spec\r
+* Reserved for subnet management.\r
+*\r
+* trans_id\r
+* Transaction ID.\r
+*\r
+* attr_id\r
+* Attribute ID.\r
+*\r
+* resv\r
+* Reserved field.\r
+*\r
+* attr_mod\r
+* Attribute modifier.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****s* IBA Base: Types/ib_rmpp_mad_t\r
+* NAME\r
+* ib_rmpp_mad_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined MAD RMPP header (13.6.2.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_rmpp_mad\r
+{\r
+ ib_mad_t common_hdr;\r
+\r
+ uint8_t rmpp_version;\r
+ uint8_t rmpp_type;\r
+ uint8_t rmpp_flags;\r
+ uint8_t rmpp_status;\r
+\r
+ ib_net32_t seg_num;\r
+ ib_net32_t paylen_newwin;\r
+\r
+} PACK_SUFFIX ib_rmpp_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+\r
+/****f* IBA Base: Types/ib_mad_init_new\r
+* NAME\r
+* ib_mad_init_new\r
+*\r
+* DESCRIPTION\r
+* Initializes a MAD common header.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_mad_init_new(\r
+ IN ib_mad_t* const p_mad,\r
+ IN const uint8_t mgmt_class,\r
+ IN const uint8_t class_ver,\r
+ IN const uint8_t method,\r
+ IN const ib_net64_t trans_id,\r
+ IN const ib_net16_t attr_id,\r
+ IN const ib_net32_t attr_mod )\r
+{\r
+ CL_ASSERT( p_mad );\r
+ p_mad->base_ver = 1;\r
+ p_mad->mgmt_class = mgmt_class;\r
+ p_mad->class_ver = class_ver;\r
+ p_mad->method = method;\r
+ p_mad->status = 0;\r
+ p_mad->class_spec = 0;\r
+ p_mad->trans_id = trans_id;\r
+ p_mad->attr_id = attr_id;\r
+ p_mad->resv = 0;\r
+ p_mad->attr_mod = attr_mod;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_mad\r
+* [in] Pointer to the MAD common header.\r
+*\r
+* mgmt_class\r
+* [in] Class of operation.\r
+*\r
+* class_ver\r
+* [in] Version of MAD class-specific format.\r
+*\r
+* method\r
+* [in] Method to perform, including 'R' bit.\r
+*\r
+* trans_Id\r
+* [in] Transaction ID.\r
+*\r
+* attr_id\r
+* [in] Attribute ID.\r
+*\r
+* attr_mod\r
+* [in] Attribute modifier.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_mad_init_response\r
+* NAME\r
+* ib_mad_init_response\r
+*\r
+* DESCRIPTION\r
+* Initializes a MAD common header as a response.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_mad_init_response(\r
+ IN const ib_mad_t* const p_req_mad,\r
+ IN ib_mad_t* const p_mad,\r
+ IN const ib_net16_t status )\r
+{\r
+ CL_ASSERT( p_req_mad );\r
+ CL_ASSERT( p_mad );\r
+ *p_mad = *p_req_mad;\r
+ p_mad->status = status;\r
+ if( p_mad->method == IB_MAD_METHOD_SET )\r
+ p_mad->method = IB_MAD_METHOD_GET;\r
+ p_mad->method |= IB_MAD_METHOD_RESP_MASK;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_req_mad\r
+* [in] Pointer to the MAD common header in the original request MAD.\r
+*\r
+* p_mad\r
+* [in] Pointer to the MAD common header to initialize.\r
+*\r
+* status\r
+* [in] MAD Status value to return;\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+* p_req_mad and p_mad may point to the same MAD.\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_mad_is_response\r
+* NAME\r
+* ib_mad_is_response\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the MAD is a response ('R' bit set),\r
+* FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_mad_is_response(\r
+ IN const ib_mad_t* const p_mad )\r
+{\r
+ CL_ASSERT( p_mad );\r
+ return( (p_mad->method & IB_MAD_METHOD_RESP_MASK) ==\r
+ IB_MAD_METHOD_RESP_MASK );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_mad\r
+* [in] Pointer to the MAD.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the MAD is a response ('R' bit set),\r
+* FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+#define IB_RMPP_TYPE_DATA 1\r
+#define IB_RMPP_TYPE_ACK 2\r
+#define IB_RMPP_TYPE_STOP 3\r
+#define IB_RMPP_TYPE_ABORT 4\r
+\r
+#define IB_RMPP_NO_RESP_TIME 0x1F\r
+#define IB_RMPP_FLAG_ACTIVE 0x01\r
+#define IB_RMPP_FLAG_FIRST 0x02\r
+#define IB_RMPP_FLAG_LAST 0x04\r
+\r
+#define IB_RMPP_STATUS_SUCCESS 0\r
+#define IB_RMPP_STATUS_RESX 1 /* resources exhausted */\r
+#define IB_RMPP_STATUS_T2L 118 /* time too long */\r
+#define IB_RMPP_STATUS_BAD_LEN 119 /* incon. last and payload len */\r
+#define IB_RMPP_STATUS_BAD_SEG 120 /* incon. first and segment no */\r
+#define IB_RMPP_STATUS_BADT 121 /* bad rmpp type */\r
+#define IB_RMPP_STATUS_W2S 122 /* newwindowlast too small */\r
+#define IB_RMPP_STATUS_S2B 123 /* segment no too big */\r
+#define IB_RMPP_STATUS_BAD_STATUS 124 /* illegal status */\r
+#define IB_RMPP_STATUS_UNV 125 /* unsupported version */\r
+#define IB_RMPP_STATUS_TMR 126 /* too many retries */\r
+#define IB_RMPP_STATUS_UNSPEC 127 /* unspecified */\r
+\r
+/****f* IBA Base: Types/ib_rmpp_is_flag_set\r
+* NAME\r
+* ib_rmpp_is_flag_set\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the MAD has the given RMPP flag set.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_rmpp_is_flag_set(\r
+ IN const ib_rmpp_mad_t* const p_rmpp_mad,\r
+ IN const uint8_t flag )\r
+{\r
+ CL_ASSERT( p_rmpp_mad );\r
+ return( (p_rmpp_mad->rmpp_flags & flag) == flag );\r
+}\r
+/*\r
+* PARAMETERS\r
+* ib_rmpp_mad_t\r
+* [in] Pointer to a MAD with an RMPP header.\r
+*\r
+* flag\r
+* [in] The RMPP flag being examined.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the MAD has the given RMPP flag set.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_mad_t, ib_rmpp_mad_t\r
+*********/\r
+\r
+static inline void OSM_API\r
+ib_rmpp_set_resp_time(\r
+ IN ib_rmpp_mad_t* const p_rmpp_mad,\r
+ IN const uint8_t resp_time )\r
+{\r
+ CL_ASSERT( p_rmpp_mad );\r
+ p_rmpp_mad->rmpp_flags |= (resp_time << 3);\r
+}\r
+\r
+\r
+static inline uint8_t OSM_API\r
+ib_rmpp_get_resp_time(\r
+ IN const ib_rmpp_mad_t* const p_rmpp_mad )\r
+{\r
+ CL_ASSERT( p_rmpp_mad );\r
+ return( (uint8_t)(p_rmpp_mad->rmpp_flags >> 3) );\r
+}\r
+\r
+/****d* IBA Base: Constants/IB_SMP_DIRECTION\r
+* NAME\r
+* IB_SMP_DIRECTION\r
+*\r
+* DESCRIPTION\r
+* The Direction bit for directed route SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMP_DIRECTION_HO 0x8000\r
+#define IB_SMP_DIRECTION (CL_HTON16(IB_SMP_DIRECTION_HO))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMP_STATUS_MASK\r
+* NAME\r
+* IB_SMP_STATUS_MASK\r
+*\r
+* DESCRIPTION\r
+* Mask value for extracting status from a directed route SMP.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMP_STATUS_MASK_HO 0x7FFF\r
+#define IB_SMP_STATUS_MASK (CL_HTON16(IB_SMP_STATUS_MASK_HO))\r
+/**********/\r
+\r
+/****s* IBA Base: Types/ib_smp_t\r
+* NAME\r
+* ib_smp_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined SMP. (14.2.1.2)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_SMP_DATA_SIZE 64\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_smp\r
+{\r
+ uint8_t base_ver;\r
+ uint8_t mgmt_class;\r
+ uint8_t class_ver;\r
+ uint8_t method;\r
+ ib_net16_t status;\r
+ uint8_t hop_ptr;\r
+ uint8_t hop_count;\r
+ ib_net64_t trans_id;\r
+ ib_net16_t attr_id;\r
+ ib_net16_t resv;\r
+ ib_net32_t attr_mod;\r
+ ib_net64_t m_key;\r
+ ib_net16_t dr_slid;\r
+ ib_net16_t dr_dlid;\r
+ uint32_t resv1[7];\r
+ uint8_t data[IB_SMP_DATA_SIZE];\r
+ uint8_t initial_path[IB_SUBNET_PATH_HOPS_MAX];\r
+ uint8_t return_path[IB_SUBNET_PATH_HOPS_MAX];\r
+\r
+} PACK_SUFFIX ib_smp_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* base_ver\r
+* MAD base format.\r
+*\r
+* mgmt_class\r
+* Class of operation.\r
+*\r
+* class_ver\r
+* Version of MAD class-specific format.\r
+*\r
+* method\r
+* Method to perform, including 'R' bit.\r
+*\r
+* status\r
+* Status of operation.\r
+*\r
+* hop_ptr\r
+* Hop pointer for directed route MADs.\r
+*\r
+* hop_count\r
+* Hop count for directed route MADs.\r
+*\r
+* trans_Id\r
+* Transaction ID.\r
+*\r
+* attr_id\r
+* Attribute ID.\r
+*\r
+* resv\r
+* Reserved field.\r
+*\r
+* attr_mod\r
+* Attribute modifier.\r
+*\r
+* m_key\r
+* Management key value.\r
+*\r
+* dr_slid\r
+* Directed route source LID.\r
+*\r
+* dr_dlid\r
+* Directed route destination LID.\r
+*\r
+* resv0\r
+* Reserved for 64 byte alignment.\r
+*\r
+* data\r
+* MAD data payload.\r
+*\r
+* initial_path\r
+* Outbound port list.\r
+*\r
+* return_path\r
+* Inbound port list.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_get_status\r
+* NAME\r
+* ib_smp_get_status\r
+*\r
+* DESCRIPTION\r
+* Returns the SMP status value in network order.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net16_t OSM_API\r
+ib_smp_get_status(\r
+ IN const ib_smp_t* const p_smp )\r
+{\r
+ return( (ib_net16_t)(p_smp->status & IB_SMP_STATUS_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+* Returns the SMP status value in network order.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_is_response\r
+* NAME\r
+* ib_smp_is_response\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the SMP is a response MAD, FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_smp_is_response(\r
+ IN const ib_smp_t* const p_smp )\r
+{\r
+ return( ib_mad_is_response( (const ib_mad_t*)p_smp ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the SMP is a response MAD, FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_is_d\r
+* NAME\r
+* ib_smp_is_d\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the SMP 'D' (direction) bit is set.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_smp_is_d(\r
+ IN const ib_smp_t* const p_smp )\r
+{\r
+ return( (p_smp->status & IB_SMP_DIRECTION) == IB_SMP_DIRECTION );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the SMP 'D' (direction) bit is set.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_smp_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_init_new\r
+* NAME\r
+* ib_smp_init_new\r
+*\r
+* DESCRIPTION\r
+* Initializes a MAD common header.\r
+*\r
+* TODO\r
+* This is too big for inlining, but leave it here for now\r
+* since there is not yet another convient spot.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_smp_init_new(\r
+ IN ib_smp_t* const p_smp,\r
+ IN const uint8_t method,\r
+ IN const ib_net64_t trans_id,\r
+ IN const ib_net16_t attr_id,\r
+ IN const ib_net32_t attr_mod,\r
+ IN const uint8_t hop_count,\r
+ IN const ib_net64_t m_key,\r
+ IN const uint8_t* path_out,\r
+ IN const ib_net16_t dr_slid,\r
+ IN const ib_net16_t dr_dlid )\r
+{\r
+ CL_ASSERT( p_smp );\r
+ CL_ASSERT( hop_count < IB_SUBNET_PATH_HOPS_MAX );\r
+ p_smp->base_ver = 1;\r
+ p_smp->mgmt_class = IB_MCLASS_SUBN_DIR;\r
+ p_smp->class_ver = 1;\r
+ p_smp->method = method;\r
+ p_smp->status = 0;\r
+ p_smp->hop_ptr = 0;\r
+ p_smp->hop_count = hop_count;\r
+ p_smp->trans_id = trans_id;\r
+ p_smp->attr_id = attr_id;\r
+ p_smp->resv = 0;\r
+ p_smp->attr_mod = attr_mod;\r
+ p_smp->m_key = m_key;\r
+ p_smp->dr_slid = dr_slid;\r
+ p_smp->dr_dlid = dr_dlid;\r
+\r
+ memset( p_smp->resv1, 0,\r
+ sizeof(p_smp->resv1) +\r
+ sizeof(p_smp->data) +\r
+ sizeof(p_smp->initial_path) +\r
+ sizeof(p_smp->return_path) );\r
+\r
+ /* copy the path */\r
+ memcpy( &p_smp->initial_path, path_out,\r
+ sizeof( p_smp->initial_path ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SMP packet.\r
+*\r
+* method\r
+* [in] Method to perform, including 'R' bit.\r
+*\r
+* trans_Id\r
+* [in] Transaction ID.\r
+*\r
+* attr_id\r
+* [in] Attribute ID.\r
+*\r
+* attr_mod\r
+* [in] Attribute modifier.\r
+*\r
+* hop_count\r
+* [in] Number of hops in the path.\r
+*\r
+* m_key\r
+* [in] Management key for this SMP.\r
+*\r
+* path_out\r
+* [in] Port array for outbound path.\r
+*\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+* Payload area is initialized to zero.\r
+*\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_smp_get_payload_ptr\r
+* NAME\r
+* ib_smp_get_payload_ptr\r
+*\r
+* DESCRIPTION\r
+* Gets a pointer to the SMP payload area.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void* OSM_API\r
+ib_smp_get_payload_ptr(\r
+ IN const ib_smp_t* const p_smp )\r
+{\r
+ return( (void*)p_smp->data );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SMP packet.\r
+*\r
+* RETURN VALUES\r
+* Pointer to SMP payload area.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_node_info_t\r
+* NAME\r
+* ib_node_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined NodeInfo. (14.2.5.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_info\r
+{\r
+ uint8_t base_version;\r
+ uint8_t class_version;\r
+ uint8_t node_type;\r
+ uint8_t num_ports;\r
+ ib_net64_t sys_guid;\r
+ ib_net64_t node_guid;\r
+ ib_net64_t port_guid;\r
+ ib_net16_t partition_cap;\r
+ ib_net16_t device_id;\r
+ ib_net32_t revision;\r
+ ib_net32_t port_num_vendor_id;\r
+\r
+} PACK_SUFFIX ib_node_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_sa_mad_t\r
+* NAME\r
+* ib_sa_mad_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined SA MAD format. (15.2.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_SA_DATA_SIZE 200\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sa_mad\r
+{\r
+ uint8_t base_ver;\r
+ uint8_t mgmt_class;\r
+ uint8_t class_ver;\r
+ uint8_t method;\r
+ ib_net16_t status;\r
+ ib_net16_t resv;\r
+ ib_net64_t trans_id;\r
+ ib_net16_t attr_id;\r
+ ib_net16_t resv1;\r
+ ib_net32_t attr_mod;\r
+\r
+ uint8_t rmpp_version;\r
+ uint8_t rmpp_type;\r
+ uint8_t rmpp_flags;\r
+ uint8_t rmpp_status;\r
+\r
+ ib_net32_t seg_num;\r
+ ib_net32_t paylen_newwin;\r
+\r
+ ib_net64_t sm_key;\r
+\r
+ ib_net16_t attr_offset;\r
+ ib_net16_t resv3;\r
+\r
+ ib_net64_t comp_mask;\r
+\r
+ uint8_t data[IB_SA_DATA_SIZE];\r
+} PACK_SUFFIX ib_sa_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/**********/\r
+#define IB_SA_MAD_HDR_SIZE (sizeof(ib_sa_mad_t) - IB_SA_DATA_SIZE)\r
+\r
+static inline uint32_t OSM_API\r
+ib_get_attr_size(\r
+ IN const ib_net16_t attr_offset )\r
+{\r
+ return( ((uint32_t)cl_ntoh16( attr_offset )) << 3 );\r
+}\r
+\r
+static inline ib_net16_t OSM_API\r
+ib_get_attr_offset(\r
+ IN const uint32_t attr_size )\r
+{\r
+ return( cl_hton16( (uint16_t)(attr_size >> 3) ) );\r
+}\r
+\r
+/****f* IBA Base: Types/ib_sa_mad_get_payload_ptr\r
+* NAME\r
+* ib_sa_mad_get_payload_ptr\r
+*\r
+* DESCRIPTION\r
+* Gets a pointer to the SA MAD's payload area.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void* OSM_API\r
+ib_sa_mad_get_payload_ptr(\r
+ IN const ib_sa_mad_t* const p_sa_mad )\r
+{\r
+ return( (void*)p_sa_mad->data );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_smp\r
+* [in] Pointer to the SA MAD packet.\r
+*\r
+* RETURN VALUES\r
+* Pointer to SA MAD payload area.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+#define IB_NODE_INFO_PORT_NUM_MASK (CL_NTOH32(0xFF000000))\r
+#define IB_NODE_INFO_VEND_ID_MASK (CL_NTOH32(0x00FFFFFF))\r
+#if CPU_LE\r
+ #define IB_NODE_INFO_PORT_NUM_SHIFT 0\r
+#else\r
+ #define IB_NODE_INFO_PORT_NUM_SHIFT 24\r
+#endif\r
+\r
+/****f* IBA Base: Types/ib_node_info_get_local_port_num\r
+* NAME\r
+* ib_node_info_get_local_port_num\r
+*\r
+* DESCRIPTION\r
+* Gets a the local port number from the NodeInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_node_info_get_local_port_num(\r
+ IN const ib_node_info_t* const p_ni )\r
+{\r
+ return( (uint8_t)(( p_ni->port_num_vendor_id &\r
+ IB_NODE_INFO_PORT_NUM_MASK )\r
+ >> IB_NODE_INFO_PORT_NUM_SHIFT ));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ni\r
+* [in] Pointer to a NodeInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Local port number that returned the attribute.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_node_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_node_info_get_vendor_id\r
+* NAME\r
+* ib_node_info_get_vendor_id\r
+*\r
+* DESCRIPTION\r
+* Gets the VendorID from the NodeInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_node_info_get_vendor_id(\r
+ IN const ib_node_info_t* const p_ni )\r
+{\r
+ return( (ib_net32_t)( p_ni->port_num_vendor_id &\r
+ IB_NODE_INFO_VEND_ID_MASK ) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ni\r
+* [in] Pointer to a NodeInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* VendorID that returned the attribute.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_node_info_t\r
+*********/\r
+\r
+#define IB_NODE_DESCRIPTION_SIZE 64\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_desc\r
+{\r
+ // Node String is an array of UTF-8 character that\r
+ // describes the node in text format\r
+ // Note that this string is NOT NULL TERMINATED!\r
+ uint8_t description[IB_NODE_DESCRIPTION_SIZE];\r
+\r
+} PACK_SUFFIX ib_node_desc_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_node_record_t\r
+{\r
+ ib_net16_t lid;\r
+ ib_net16_t resv;\r
+ ib_node_info_t node_info;\r
+ ib_node_desc_t node_desc;\r
+ uint8_t pad[4];\r
+\r
+} PACK_SUFFIX ib_node_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IBA Base: Types/ib_port_info_t\r
+* NAME\r
+* ib_port_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined PortInfo. (14.2.5.6)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_port_info\r
+{\r
+ ib_net64_t m_key;\r
+ ib_net64_t subnet_prefix;\r
+ ib_net16_t base_lid;\r
+ ib_net16_t master_sm_base_lid;\r
+ ib_net32_t capability_mask;\r
+ ib_net16_t diag_code;\r
+ ib_net16_t m_key_lease_period;\r
+ uint8_t local_port_num;\r
+ uint8_t link_width_enabled;\r
+ uint8_t link_width_supported;\r
+ uint8_t link_width_active;\r
+ uint8_t state_info1; /* LinkSpeedSupported and PortState */\r
+ uint8_t state_info2; /* PortPhysState and LinkDownDefaultState */\r
+ uint8_t mkey_lmc;\r
+ uint8_t link_speed; /* LinkSpeedEnabled and LinkSpeedActive */\r
+ uint8_t mtu_smsl;\r
+ uint8_t vl_cap; /* VLCap and InitType */\r
+ uint8_t vl_high_limit;\r
+ uint8_t vl_arb_high_cap;\r
+ uint8_t vl_arb_low_cap;\r
+ uint8_t mtu_cap;\r
+ uint8_t vl_stall_life;\r
+ uint8_t vl_enforce;\r
+ ib_net16_t m_key_violations;\r
+ ib_net16_t p_key_violations;\r
+ ib_net16_t q_key_violations;\r
+ uint8_t guid_cap;\r
+ uint8_t subnet_timeout; /* cli_rereg(1b), resrv(\r
+2b), timeout(5b) */\r
+ uint8_t resp_time_value;\r
+ uint8_t error_threshold;\r
+\r
+} PACK_SUFFIX ib_port_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_PORT_STATE_MASK 0x0F\r
+#define IB_PORT_LMC_MASK 0x07\r
+#define IB_PORT_LMC_MAX 0x07\r
+#define IB_PORT_MPB_MASK 0xC0\r
+#define IB_PORT_MPB_SHIFT 6\r
+#define IB_PORT_LINK_SPEED_SHIFT 4\r
+#define IB_PORT_LINK_SPEED_SUPPORTED_MASK 0xF0\r
+#define IB_PORT_LINK_SPEED_ACTIVE_MASK 0xF0\r
+#define IB_PORT_LINK_SPEED_ENABLED_MASK 0x0F\r
+#define IB_PORT_PHYS_STATE_MASK 0xF0\r
+#define IB_PORT_PHYS_STATE_SHIFT 4\r
+#define IB_PORT_LNKDWNDFTSTATE_MASK 0x0F\r
+\r
+#define IB_PORT_CAP_RESV0 (CL_NTOH32(0x00000001))\r
+#define IB_PORT_CAP_IS_SM (CL_NTOH32(0x00000002))\r
+#define IB_PORT_CAP_HAS_NOTICE (CL_NTOH32(0x00000004))\r
+#define IB_PORT_CAP_HAS_TRAP (CL_NTOH32(0x00000008))\r
+#define IB_PORT_CAP_HAS_IPD (CL_NTOH32(0x00000010))\r
+#define IB_PORT_CAP_HAS_AUTO_MIG (CL_NTOH32(0x00000020))\r
+#define IB_PORT_CAP_HAS_SL_MAP (CL_NTOH32(0x00000040))\r
+#define IB_PORT_CAP_HAS_NV_MKEY (CL_NTOH32(0x00000080))\r
+#define IB_PORT_CAP_HAS_NV_PKEY (CL_NTOH32(0x00000100))\r
+#define IB_PORT_CAP_HAS_LED_INFO (CL_NTOH32(0x00000200))\r
+#define IB_PORT_CAP_SM_DISAB (CL_NTOH32(0x00000400))\r
+#define IB_PORT_CAP_HAS_SYS_IMG_GUID (CL_NTOH32(0x00000800))\r
+#define IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP (CL_NTOH32(0x00001000))\r
+#define IB_PORT_CAP_RESV13 (CL_NTOH32(0x00002000))\r
+#define IB_PORT_CAP_RESV14 (CL_NTOH32(0x00004000))\r
+#define IB_PORT_CAP_RESV15 (CL_NTOH32(0x00008000))\r
+#define IB_PORT_CAP_HAS_COM_MGT (CL_NTOH32(0x00010000))\r
+#define IB_PORT_CAP_HAS_SNMP (CL_NTOH32(0x00020000))\r
+#define IB_PORT_CAP_REINIT (CL_NTOH32(0x00040000))\r
+#define IB_PORT_CAP_HAS_DEV_MGT (CL_NTOH32(0x00080000))\r
+#define IB_PORT_CAP_HAS_VEND_CLS (CL_NTOH32(0x00100000))\r
+#define IB_PORT_CAP_HAS_DR_NTC (CL_NTOH32(0x00200000))\r
+#define IB_PORT_CAP_HAS_CAP_NTC (CL_NTOH32(0x00400000))\r
+#define IB_PORT_CAP_HAS_BM (CL_NTOH32(0x00800000))\r
+#define IB_PORT_CAP_HAS_LINK_RT_LATENCY (CL_NTOH32(0x01000000))\r
+#define IB_PORT_CAP_HAS_CLIENT_REREG (CL_NTOH32(0x02000000))\r
+#define IB_PORT_CAP_RESV26 (CL_NTOH32(0x04000000))\r
+#define IB_PORT_CAP_RESV27 (CL_NTOH32(0x08000000))\r
+#define IB_PORT_CAP_RESV28 (CL_NTOH32(0x10000000))\r
+#define IB_PORT_CAP_RESV29 (CL_NTOH32(0x20000000))\r
+#define IB_PORT_CAP_RESV30 (CL_NTOH32(0x40000000))\r
+#define IB_PORT_CAP_RESV31 (CL_NTOH32(0x80000000))\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_port_state\r
+* NAME\r
+* ib_port_info_get_port_state\r
+*\r
+* DESCRIPTION\r
+* Returns the port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_port_state(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->state_info1 & IB_PORT_STATE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Port state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_port_state\r
+* NAME\r
+* ib_port_info_set_port_state\r
+*\r
+* DESCRIPTION\r
+* Sets the port state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_port_state(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t port_state )\r
+{\r
+ p_pi->state_info1 = (uint8_t)((p_pi->state_info1 & 0xF0) | port_state );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* port_state\r
+* [in] Port state value to set.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_vl_cap\r
+* NAME\r
+* ib_port_info_get_vl_cap\r
+*\r
+* DESCRIPTION\r
+* Gets the VL Capability of a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_vl_cap(\r
+ IN const ib_port_info_t* const p_pi)\r
+{\r
+ return((p_pi->vl_cap >> 4) & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* VL_CAP field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_init_type\r
+* NAME\r
+* ib_port_info_get_init_type\r
+*\r
+* DESCRIPTION\r
+* Gets the init type of a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_init_type(\r
+ IN const ib_port_info_t* const p_pi)\r
+{\r
+ return (uint8_t) (p_pi->vl_cap & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* InitType field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_op_vls\r
+* NAME\r
+* ib_port_info_get_op_vls\r
+*\r
+* DESCRIPTION\r
+* Gets the operational VLs on a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_op_vls(\r
+ IN const ib_port_info_t* const p_pi)\r
+{\r
+ return((p_pi->vl_enforce >> 4) & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* OP_VLS field\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_op_vls\r
+* NAME\r
+* ib_port_info_set_op_vls\r
+*\r
+* DESCRIPTION\r
+* Sets the operational VLs on a port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_op_vls(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t op_vls )\r
+{\r
+ p_pi->vl_enforce = (uint8_t)((p_pi->vl_enforce & 0x0F) | (op_vls << 4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* op_vls\r
+* [in] Encoded operation VLs value.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_state_no_change\r
+* NAME\r
+* ib_port_info_set_state_no_change\r
+*\r
+* DESCRIPTION\r
+* Sets the port state fields to the value for "no change".\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_state_no_change(\r
+ IN ib_port_info_t* const p_pi )\r
+{\r
+ ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );\r
+ p_pi->state_info2 = 0;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_sup\r
+* NAME\r
+* ib_port_info_get_link_speed_sup\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the link speed supported.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_link_speed_sup(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->state_info1 &\r
+ IB_PORT_LINK_SPEED_SUPPORTED_MASK) >>\r
+ IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the encoded value for the link speed supported.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_speed_sup\r
+* NAME\r
+* ib_port_info_set_link_speed_sup\r
+*\r
+* DESCRIPTION\r
+* Given an integer of the supported link speed supported.\r
+* Set the appropriate bits in state_info1\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_link_speed_sup(\r
+ IN uint8_t const speed,\r
+ IN ib_port_info_t* p_pi )\r
+{\r
+ p_pi->state_info1 =\r
+ ( ~IB_PORT_LINK_SPEED_SUPPORTED_MASK & p_pi->state_info1 ) |\r
+ ( IB_PORT_LINK_SPEED_SUPPORTED_MASK &\r
+ (speed << IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* speed\r
+* [in] Supported Speeds Code.\r
+*\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* This function does not return a value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_port_phys_state\r
+* NAME\r
+* ib_port_info_get_port_phys_state\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the port physical state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_port_phys_state(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->state_info2 &\r
+ IB_PORT_PHYS_STATE_MASK) >>\r
+ IB_PORT_PHYS_STATE_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the encoded value for the port physical state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_port_phys_state\r
+* NAME\r
+* ib_port_info_set_port_phys_state\r
+*\r
+* DESCRIPTION\r
+* Given an integer of the port physical state,\r
+* Set the appropriate bits in state_info2\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_port_phys_state(\r
+ IN uint8_t const phys_state,\r
+ IN ib_port_info_t* p_pi )\r
+{\r
+ p_pi->state_info2 =\r
+ ( ~IB_PORT_PHYS_STATE_MASK & p_pi->state_info2 ) |\r
+ ( IB_PORT_PHYS_STATE_MASK &\r
+ (phys_state << IB_PORT_PHYS_STATE_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* phys_state\r
+* [in] port physical state.\r
+*\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* This function does not return a value.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_down_def_state\r
+* NAME\r
+* ib_port_info_get_link_down_def_state\r
+*\r
+* DESCRIPTION\r
+* Returns the link down default state.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_link_down_def_state(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->state_info2 & IB_PORT_LNKDWNDFTSTATE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* link down default state of the port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_down_def_state\r
+* NAME\r
+* ib_port_info_set_link_down_def_state\r
+*\r
+* DESCRIPTION\r
+* Sets the link down default state of the port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_link_down_def_state(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t link_dwn_state )\r
+{\r
+ p_pi->state_info2 = (uint8_t)((p_pi->state_info2 & 0xF0) | link_dwn_state );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* link_dwn_state\r
+* [in] Link down default state of the port.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_active\r
+* NAME\r
+* ib_port_info_get_link_speed_active\r
+*\r
+* DESCRIPTION\r
+* Returns the Link Speed Active value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_link_speed_active(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->link_speed &\r
+ IB_PORT_LINK_SPEED_ACTIVE_MASK) >>\r
+ IB_PORT_LINK_SPEED_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the link speed active value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+#define IB_LINK_WIDTH_ACTIVE_1X 1\r
+#define IB_LINK_WIDTH_ACTIVE_4X 2\r
+#define IB_LINK_WIDTH_ACTIVE_12X 8\r
+#define IB_LINK_SPEED_ACTIVE_2_5 1\r
+#define IB_LINK_SPEED_ACTIVE_5 2\r
+#define IB_LINK_SPEED_ACTIVE_10 4\r
+\r
+/* following v1 ver1.2 p901 */\r
+#define IB_PATH_RECORD_RATE_2_5_GBS 2\r
+#define IB_PATH_RECORD_RATE_10_GBS 3\r
+#define IB_PATH_RECORD_RATE_30_GBS 4\r
+#define IB_PATH_RECORD_RATE_5_GBS 5\r
+#define IB_PATH_RECORD_RATE_20_GBS 6\r
+#define IB_PATH_RECORD_RATE_40_GBS 7\r
+#define IB_PATH_RECORD_RATE_60_GBS 8\r
+#define IB_PATH_RECORD_RATE_80_GBS 9\r
+#define IB_PATH_RECORD_RATE_120_GBS 10\r
+\r
+#define IB_MIN_RATE IB_PATH_RECORD_RATE_2_5_GBS\r
+#define IB_MAX_RATE IB_PATH_RECORD_RATE_120_GBS \r
+\r
+/****f* IBA Base: Types/ib_port_info_compute_rate\r
+* NAME\r
+* ib_port_info_compute_rate\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the path rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_compute_rate(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ uint8_t rate = 0;\r
+\r
+ switch (ib_port_info_get_link_speed_active(p_pi))\r
+ {\r
+ case IB_LINK_SPEED_ACTIVE_2_5:\r
+ switch (p_pi->link_width_active)\r
+ {\r
+ case IB_LINK_WIDTH_ACTIVE_1X:\r
+ rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+ break;\r
+ \r
+ case IB_LINK_WIDTH_ACTIVE_4X:\r
+ rate = IB_PATH_RECORD_RATE_10_GBS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_12X:\r
+ rate = IB_PATH_RECORD_RATE_30_GBS;\r
+ break;\r
+\r
+ default:\r
+ rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+ break;\r
+ }\r
+ break;\r
+ case IB_LINK_SPEED_ACTIVE_5:\r
+ switch (p_pi->link_width_active)\r
+ {\r
+ case IB_LINK_WIDTH_ACTIVE_1X:\r
+ rate = IB_PATH_RECORD_RATE_5_GBS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_4X:\r
+ rate = IB_PATH_RECORD_RATE_20_GBS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_12X:\r
+ rate = IB_PATH_RECORD_RATE_60_GBS;\r
+ break;\r
+\r
+ default:\r
+ rate = IB_PATH_RECORD_RATE_5_GBS;\r
+ break;\r
+ }\r
+ break;\r
+ case IB_LINK_SPEED_ACTIVE_10:\r
+ switch (p_pi->link_width_active)\r
+ {\r
+ case IB_LINK_WIDTH_ACTIVE_1X:\r
+ rate = IB_PATH_RECORD_RATE_10_GBS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_4X:\r
+ rate = IB_PATH_RECORD_RATE_40_GBS;\r
+ break;\r
+\r
+ case IB_LINK_WIDTH_ACTIVE_12X:\r
+ rate =IB_PATH_RECORD_RATE_120_GBS;\r
+ break;\r
+\r
+ default:\r
+ rate = IB_PATH_RECORD_RATE_10_GBS;\r
+ break;\r
+ }\r
+ break;\r
+ default:\r
+ rate = IB_PATH_RECORD_RATE_2_5_GBS;\r
+ break;\r
+ }\r
+\r
+ return rate;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the encoded value for the link speed supported.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_path_get_ipd\r
+* NAME\r
+* ib_path_get_ipd\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the inter packet delay.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_path_get_ipd(\r
+ IN uint8_t local_link_width_supported,\r
+ IN uint8_t path_rec_rate )\r
+{\r
+ uint8_t ipd = 0;\r
+\r
+ switch(local_link_width_supported)\r
+ {\r
+ /* link_width_supported = 1: 1x */\r
+ case 1:\r
+ break;\r
+\r
+ /* link_width_supported = 3: 1x or 4x */\r
+ case 3:\r
+ switch(path_rec_rate & 0x3F)\r
+ {\r
+ case IB_PATH_RECORD_RATE_2_5_GBS:\r
+ ipd = 3;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
+ /* link_width_supported = 11: 1x or 4x or 12x */\r
+ case 11:\r
+ switch(path_rec_rate & 0x3F)\r
+ {\r
+ case IB_PATH_RECORD_RATE_2_5_GBS:\r
+ ipd = 11;\r
+ break;\r
+ case IB_PATH_RECORD_RATE_10_GBS:\r
+ ipd = 2;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return ipd;\r
+}\r
+/*\r
+* PARAMETERS\r
+* local_link_width_supported\r
+* [in] link with supported for this port\r
+*\r
+* path_rec_rate\r
+* [in] rate field of the path record\r
+*\r
+* RETURN VALUES\r
+* Returns the ipd\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_mtu_cap\r
+* NAME\r
+* ib_port_info_get_mtu_cap\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the maximum MTU supported by this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_mtu_cap(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->mtu_cap & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_neighbor_mtu\r
+* NAME\r
+* ib_port_info_get_neighbor_mtu\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the neighbor MTU at this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_neighbor_mtu(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->mtu_smsl & 0xF0) >> 4) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the encoded value for the neighbor MTU at this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_neighbor_mtu\r
+* NAME\r
+* ib_port_info_set_neighbor_mtu\r
+*\r
+* DESCRIPTION\r
+* Sets the Neighbor MTU value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_neighbor_mtu(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t mtu )\r
+{\r
+ CL_ASSERT( mtu <= 5 );\r
+ CL_ASSERT( mtu != 0 );\r
+ p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0x0F) | (mtu << 4));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* mtu\r
+* [in] Encoded MTU value to set\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_master_smsl\r
+* NAME\r
+* ib_port_info_get_master_smsl\r
+*\r
+* DESCRIPTION\r
+* Returns the encoded value for the Master SMSL at this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_master_smsl(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return (uint8_t) (p_pi->mtu_smsl & 0x0F); \r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the encoded value for the Master SMSL at this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_master_smsl\r
+* NAME\r
+* ib_port_info_set_master_smsl\r
+*\r
+* DESCRIPTION\r
+* Sets the Master SMSL value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_master_smsl(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t smsl )\r
+{\r
+ p_pi->mtu_smsl = (uint8_t)((p_pi->mtu_smsl & 0xF0) | smsl );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* mtu\r
+* [in] Encoded Master SMSL value to set\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_timeout\r
+* NAME\r
+* ib_port_info_set_timeout\r
+*\r
+* DESCRIPTION\r
+* Sets the encoded subnet timeout value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_timeout(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t timeout )\r
+{\r
+ CL_ASSERT( timeout <= 0x1F );\r
+ p_pi->subnet_timeout =\r
+ (uint8_t)(\r
+ (p_pi->subnet_timeout & 0x80) | (timeout & 0x1F));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* timeout\r
+* [in] Encoded timeout value to set\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_client_rereg\r
+* NAME\r
+* ib_port_info_set_client_rereg\r
+*\r
+* DESCRIPTION\r
+* Sets the encoded client reregistration bit value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_client_rereg(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t client_rereg )\r
+{\r
+ CL_ASSERT( client_rereg <= 0x1 );\r
+ p_pi->subnet_timeout =\r
+ (uint8_t)(\r
+ (p_pi->subnet_timeout & 0x1F) | ((client_rereg << 7) & 0x80));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* client_rereg\r
+* [in] Client reregistration value to set (either 1 or 0).\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_timeout\r
+* NAME\r
+* ib_port_info_get_timeout\r
+*\r
+* DESCRIPTION\r
+* Gets the encoded subnet timeout value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_timeout(\r
+ IN ib_port_info_t const* p_pi )\r
+{\r
+ return(p_pi->subnet_timeout & 0x1F );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* The encoded timeout value\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_client_rereg\r
+* NAME\r
+* ib_port_info_get_client_rereg\r
+*\r
+* DESCRIPTION\r
+* Gets the encoded client reregistration bit value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_client_rereg(\r
+ IN ib_port_info_t const* p_pi )\r
+{\r
+ return ( (p_pi->subnet_timeout & 0x80 ) >> 7);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Client reregistration value (either 1 or 0).\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_hoq_lifetime\r
+* NAME\r
+* ib_port_info_set_hoq_lifetime\r
+*\r
+* DESCRIPTION\r
+* Sets the Head of Queue Lifetime for which a packet can live in the head \r
+* of VL queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_hoq_lifetime(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t hoq_life )\r
+{\r
+ p_pi->vl_stall_life = (uint8_t)((hoq_life & 0x1f) |\r
+ (p_pi->vl_stall_life & 0xe0));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* hoq_life\r
+* [in] Encoded lifetime value to set\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_hoq_lifetime\r
+* NAME\r
+* ib_port_info_get_hoq_lifetime\r
+*\r
+* DESCRIPTION\r
+* Gets the Head of Queue Lifetime for which a packet can live in the head \r
+* of VL queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_hoq_lifetime(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->vl_stall_life & 0x1f) );\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Encoded lifetime value\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_vl_stall_count\r
+* NAME\r
+* ib_port_info_set_vl_stall_count\r
+*\r
+* DESCRIPTION\r
+* Sets the VL Stall Count which define the number of contiguous \r
+* HLL (hoq) drops that will put the VL into stalled mode.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_vl_stall_count(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t vl_stall_count )\r
+{\r
+ p_pi->vl_stall_life = (uint8_t)((p_pi->vl_stall_life & 0x1f) |\r
+ ((vl_stall_count << 5) & 0xe0));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* vl_stall_count \r
+* [in] value to set\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_vl_stall_count\r
+* NAME\r
+* ib_port_info_get_vl_stall_count\r
+*\r
+* DESCRIPTION\r
+* Gets the VL Stall Count which define the number of contiguous \r
+* HLL (hoq) drops that will put the VL into stalled mode\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_vl_stall_count(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->vl_stall_life & 0xe0) >> 5);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* vl stall count\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_lmc\r
+* NAME\r
+* ib_port_info_get_lmc\r
+*\r
+* DESCRIPTION\r
+* Returns the LMC value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_lmc(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->mkey_lmc & IB_PORT_LMC_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_lmc\r
+* NAME\r
+* ib_port_info_set_lmc\r
+*\r
+* DESCRIPTION\r
+* Sets the LMC value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_lmc(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t lmc )\r
+{\r
+ CL_ASSERT( lmc <= IB_PORT_LMC_MAX );\r
+ p_pi->mkey_lmc = (uint8_t)((p_pi->mkey_lmc & 0xF8) | lmc);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* lmc\r
+* [in] LMC value to set, must be less than 7.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_link_speed_enabled\r
+* NAME\r
+* ib_port_info_get_link_speed_enabled\r
+*\r
+* DESCRIPTION\r
+* Returns the link speed enabled value assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_link_speed_enabled(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)(p_pi->link_speed & IB_PORT_LINK_SPEED_ENABLED_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Port state.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_link_speed_enabled\r
+* NAME\r
+* ib_port_info_set_link_speed_enabled\r
+*\r
+* DESCRIPTION\r
+* Sets the link speed enabled value in the PortInfo attribute.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_link_speed_enabled(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN const uint8_t link_speed_enabled )\r
+{\r
+ p_pi->link_speed = (uint8_t)((p_pi->link_speed & 0xF0) | link_speed_enabled );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* link_speed_enabled\r
+* [in] link speed enabled value to set.\r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_mpb\r
+* NAME\r
+* ib_port_info_get_mpb\r
+*\r
+* DESCRIPTION\r
+* Returns the M_Key protect bits assigned to this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_mpb(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return( (uint8_t)((p_pi->mkey_lmc & IB_PORT_MPB_MASK) >>\r
+ IB_PORT_MPB_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ni\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the M_Key protect bits assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_mpb\r
+* NAME\r
+* ib_port_info_set_mpb\r
+*\r
+* DESCRIPTION\r
+* Set the M_Key protect bits of this port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_mpb(\r
+ IN ib_port_info_t* p_pi,\r
+ IN uint8_t mpb )\r
+{\r
+ p_pi->mkey_lmc =\r
+ (~IB_PORT_MPB_MASK & p_pi->mkey_lmc) |\r
+ ( IB_PORT_MPB_MASK & (mpb << IB_PORT_MPB_SHIFT) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* mpb\r
+* [in] M_Key protect bits\r
+* p_ni\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_local_phy_err_thd\r
+* NAME\r
+* ib_port_info_get_local_phy_err_thd\r
+*\r
+* DESCRIPTION\r
+* Returns the Phy Link Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_local_phy_err_thd(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return (uint8_t)( (p_pi->error_threshold & 0xF0) >> 4);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the Phy Link error threshold assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_get_overrun_err_thd\r
+* NAME\r
+* ib_port_info_get_local_overrun_err_thd\r
+*\r
+* DESCRIPTION\r
+* Returns the Credits Overrun Errors Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_port_info_get_overrun_err_thd(\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ return (uint8_t)(p_pi->error_threshold & 0x0F);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the Credits Overrun errors threshold assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_port_info_set_phy_and_overrun_err_thd\r
+* NAME\r
+* ib_port_info_set_phy_and_overrun_err_thd\r
+*\r
+* DESCRIPTION\r
+* Sets the Phy Link and Credits Overrun Errors Threshold\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_port_info_set_phy_and_overrun_err_thd(\r
+ IN ib_port_info_t* const p_pi,\r
+ IN uint8_t phy_threshold,\r
+ IN uint8_t overrun_threshold )\r
+{\r
+ p_pi->error_threshold = \r
+ (uint8_t)( ((phy_threshold & 0x0F) << 4) | (overrun_threshold & 0x0F) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_pi\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* phy_threshold\r
+* [in] Physical Link Errors Threshold above which Trap 129 is generated \r
+*\r
+* overrun_threshold\r
+* [in] Credits overrun Errors Threshold above which Trap 129 is generated \r
+*\r
+* RETURN VALUES\r
+* None.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+typedef uint8_t ib_svc_name_t[64];\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_service_record\r
+{\r
+ ib_net64_t service_id;\r
+ ib_gid_t service_gid;\r
+ ib_net16_t service_pkey;\r
+ ib_net16_t resv;\r
+ ib_net32_t service_lease;\r
+ uint8_t service_key[16];\r
+ ib_svc_name_t service_name;\r
+ uint8_t service_data8[16];\r
+ ib_net16_t service_data16[8];\r
+ ib_net32_t service_data32[4];\r
+ ib_net64_t service_data64[2];\r
+\r
+} PACK_SUFFIX ib_service_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_portinfo_record\r
+{\r
+ ib_net16_t lid;\r
+ uint8_t port_num;\r
+ uint8_t resv;\r
+ ib_port_info_t port_info;\r
+ uint8_t pad[6];\r
+\r
+} PACK_SUFFIX ib_portinfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_link_record\r
+{\r
+ ib_net16_t from_lid;\r
+ uint8_t from_port_num;\r
+ uint8_t to_port_num;\r
+ ib_net16_t to_lid;\r
+ uint8_t pad[2];\r
+\r
+} PACK_SUFFIX ib_link_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_sminfo_record\r
+{\r
+ ib_net16_t lid;\r
+ uint16_t resv0;\r
+ ib_sm_info_t sm_info;\r
+ uint8_t pad[7];\r
+\r
+} PACK_SUFFIX ib_sminfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****s* IBA Base: Types/ib_lft_record_t\r
+* NAME\r
+* ib_lft_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined LinearForwardingTableRecord (15.2.5.6)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_lft_record\r
+{\r
+ ib_net16_t lid;\r
+ ib_net16_t block_num;\r
+ uint32_t resv0;\r
+ uint8_t lft[64];\r
+} PACK_SUFFIX ib_lft_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_mft_record_t\r
+* NAME\r
+* ib_mft_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined MulticastForwardingTableRecord (15.2.5.8)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mft_record\r
+{\r
+ ib_net16_t lid;\r
+ ib_net16_t position_block_num;\r
+ uint32_t resv0;\r
+ ib_net16_t mft[IB_MCAST_BLOCK_SIZE];\r
+} PACK_SUFFIX ib_mft_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_switch_info_t\r
+* NAME\r
+* ib_switch_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined SwitchInfo. (14.2.5.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_switch_info\r
+{\r
+ ib_net16_t lin_cap;\r
+ ib_net16_t rand_cap;\r
+ ib_net16_t mcast_cap;\r
+ ib_net16_t lin_top;\r
+ uint8_t def_port;\r
+ uint8_t def_mcast_pri_port;\r
+ uint8_t def_mcast_not_port;\r
+ uint8_t life_state;\r
+ ib_net16_t lids_per_port;\r
+ ib_net16_t enforce_cap;\r
+ uint8_t flags;\r
+\r
+} PACK_SUFFIX ib_switch_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_switch_info_record\r
+{\r
+ ib_net16_t lid;\r
+ uint16_t resv0;\r
+ ib_switch_info_t switch_info;\r
+ uint8_t pad[3];\r
+\r
+} PACK_SUFFIX ib_switch_info_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#define IB_SWITCH_PSC 0x04\r
+\r
+/****f* IBA Base: Types/ib_switch_info_get_state_change\r
+* NAME\r
+* ib_switch_info_get_state_change\r
+*\r
+* DESCRIPTION\r
+* Returns the value of the state change flag.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_switch_info_get_state_change(\r
+ IN const ib_switch_info_t* const p_si )\r
+{\r
+ return( (p_si->life_state & IB_SWITCH_PSC) == IB_SWITCH_PSC );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_si\r
+* [in] Pointer to a SwitchInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the value of the state change flag.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_switch_info_clear_state_change\r
+* NAME\r
+* ib_switch_info_clear_state_change\r
+*\r
+* DESCRIPTION\r
+* Clears the switch's state change bit.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_switch_info_clear_state_change(\r
+ IN ib_switch_info_t* const p_si )\r
+{\r
+ p_si->life_state = (uint8_t)(p_si->life_state & 0xFB);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ni\r
+* [in] Pointer to a PortInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns the LMC value assigned to this port.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_switch_info_is_enhanced_port0\r
+* NAME\r
+* ib_switch_info_is_enhanced_port0\r
+*\r
+* DESCRIPTION\r
+* Returns TRUE if the enhancedPort0 bit is on (meaning the switch\r
+* port zero supports enhanced functions).\r
+* Returns FALSE otherwise.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_switch_info_is_enhanced_port0(\r
+ IN const ib_switch_info_t* const p_si )\r
+{\r
+ return( (p_si->flags & 0x08) == 0x08 );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_si\r
+* [in] Pointer to a SwitchInfo attribute.\r
+*\r
+* RETURN VALUES\r
+* Returns TRUE if the switch supports enhanced port 0. FALSE otherwise.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_guid_info_t\r
+* NAME\r
+* ib_guid_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined GuidInfo. (14.2.5.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define GUID_TABLE_MAX_ENTRIES 8\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_guid_info\r
+{\r
+ ib_net64_t guid[GUID_TABLE_MAX_ENTRIES];\r
+\r
+} PACK_SUFFIX ib_guid_info_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_guidinfo_record\r
+{\r
+ ib_net16_t lid;\r
+ uint8_t block_num;\r
+ uint8_t resv;\r
+ uint32_t reserved;\r
+ ib_guid_info_t guid_info;\r
+} PACK_SUFFIX ib_guidinfo_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+#define IB_MULTIPATH_MAX_GIDS 11 /* Support max that can fit into first MAD (for now) */\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_multipath_rec_t\r
+{\r
+ ib_net32_t hop_flow_raw;\r
+ uint8_t tclass;\r
+ uint8_t num_path;\r
+ ib_net16_t pkey;\r
+ uint8_t resv0;\r
+ uint8_t sl;\r
+ uint8_t mtu;\r
+ uint8_t rate;\r
+ uint8_t pkt_life;\r
+ uint8_t resv1;\r
+ uint8_t independence; /* formerly resv2 */\r
+ uint8_t sgid_count;\r
+ uint8_t dgid_count;\r
+ uint8_t resv3[7];\r
+ ib_gid_t gids[IB_MULTIPATH_MAX_GIDS];\r
+} PACK_SUFFIX ib_multipath_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* hop_flow_raw\r
+* Global routing parameters: hop count, flow label and raw bit.\r
+*\r
+* tclass\r
+* Another global routing parameter.\r
+*\r
+* num_path\r
+* Reversible path - 1 bit to say if path is reversible.\r
+* num_path [6:0] In queries, maximum number of paths to return.\r
+* In responses, undefined.\r
+*\r
+* pkey\r
+* Partition key (P_Key) to use on this path.\r
+*\r
+* sl\r
+* Service level to use on this path.\r
+*\r
+* mtu\r
+* MTU and MTU selector fields to use on this path\r
+* rate\r
+* Rate and rate selector fields to use on this path.\r
+*\r
+* pkt_life\r
+* Packet lifetime\r
+*\r
+* preference\r
+* Indicates the relative merit of this path versus other path\r
+* records returned from the SA. Lower numbers are better.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_num_path\r
+* NAME\r
+* ib_multipath_rec_num_path\r
+*\r
+* DESCRIPTION\r
+* Get max number of paths to return.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_num_path(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( p_rec->num_path &0x7F );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Maximum number of paths to return for each unique SGID_DGID combination.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_sl\r
+* NAME\r
+* ib_multipath_rec_sl\r
+*\r
+* DESCRIPTION\r
+* Get multipath service level.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_sl(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((cl_ntoh16( p_rec->sl )) & 0xF) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* SL.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_mtu\r
+* NAME\r
+* ib_multipath_rec_mtu\r
+*\r
+* DESCRIPTION\r
+* Get encoded path MTU.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_mtu(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->mtu & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path MTU.\r
+* 1: 256\r
+* 2: 512\r
+* 3: 1024\r
+* 4: 2048\r
+* 5: 4096\r
+* others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_mtu_sel\r
+* NAME\r
+* ib_multipath_rec_mtu_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded multipath MTU selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_mtu_sel(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->mtu & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path MTU selector value (for queries).\r
+* 0: greater than MTU specified\r
+* 1: less than MTU specified\r
+* 2: exactly the MTU specified\r
+* 3: largest MTU available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_rate\r
+* NAME\r
+* ib_multipath_rec_rate\r
+*\r
+* DESCRIPTION\r
+* Get encoded multipath rate.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_rate(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->rate & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded multipath rate.\r
+* 2: 2.5 Gb/sec.\r
+* 3: 10 Gb/sec.\r
+* 4: 30 Gb/sec.\r
+* others: reserved\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_rate_sel\r
+* NAME\r
+* ib_multipath_rec_rate_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded multipath rate selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_rate_sel(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->rate & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path rate selector value (for queries).\r
+* 0: greater than rate specified\r
+* 1: less than rate specified\r
+* 2: exactly the rate specified\r
+* 3: largest rate available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life\r
+* NAME\r
+* ib_multipath_rec_pkt_life\r
+*\r
+* DESCRIPTION\r
+* Get encoded multipath pkt_life.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_pkt_life(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)(p_rec->pkt_life & IB_MULTIPATH_REC_BASE_MASK) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded multipath pkt_life = 4.096 µsec * 2 ** PacketLifeTime.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_multipath_rec_pkt_life_sel\r
+* NAME\r
+* ib_multipath_rec_pkt_life_sel\r
+*\r
+* DESCRIPTION\r
+* Get encoded multipath pkt_lifetime selector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_multipath_rec_pkt_life_sel(\r
+ IN const ib_multipath_rec_t* const p_rec )\r
+{\r
+ return( (uint8_t)((p_rec->pkt_life & IB_MULTIPATH_REC_SELECTOR_MASK) >> 6 ));\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_rec\r
+* [in] Pointer to the multipath record object.\r
+*\r
+* RETURN VALUES\r
+* Encoded path pkt_lifetime selector value (for queries).\r
+* 0: greater than rate specified\r
+* 1: less than rate specified\r
+* 2: exactly the rate specified\r
+* 3: smallest packet lifetime available\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_multipath_rec_t\r
+*********/\r
+\r
+#define IB_NUM_PKEY_ELEMENTS_IN_BLOCK 32\r
+/****s* IBA Base: Types/ib_pkey_table_t\r
+* NAME\r
+* ib_pkey_table_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined PKey table. (14.2.5.7)\r
+*\r
+* SYNOPSIS\r
+*/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_pkey_table\r
+{\r
+ ib_net16_t pkey_entry[IB_NUM_PKEY_ELEMENTS_IN_BLOCK];\r
+\r
+} PACK_SUFFIX ib_pkey_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_pkey_table_record_t\r
+* NAME\r
+* ib_pkey_table_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined P_Key Table Record for SA Query. (15.2.5.11)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_pkey_table_record\r
+{\r
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0\r
+ uint16_t block_num;\r
+ uint8_t port_num; // for switch: port number, for CA: reserved\r
+ uint8_t reserved1;\r
+ uint16_t reserved2;\r
+ ib_pkey_table_t pkey_tbl;\r
+\r
+} PACK_SUFFIX ib_pkey_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_DROP_VL 15\r
+#define IB_MAX_NUM_VLS 16\r
+/****s* IBA Base: Types/ib_slvl_table_t\r
+* NAME\r
+* ib_slvl_table_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined SL2VL Mapping Table Attribute. (14.2.5.8)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_slvl_table\r
+{\r
+ uint8_t raw_vl_by_sl[IB_MAX_NUM_VLS/2];\r
+} PACK_SUFFIX ib_slvl_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_slvl_table_record_t\r
+* NAME\r
+* ib_slvl_table_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined SL to VL Mapping Table Record for SA Query. (15.2.5.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_slvl_table_record\r
+{\r
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0\r
+ uint8_t in_port_num; // reserved for CAs\r
+ uint8_t out_port_num; // reserved for CAs\r
+ uint32_t resv;\r
+ ib_slvl_table_t slvl_tbl;\r
+\r
+} PACK_SUFFIX ib_slvl_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****f* IBA Base: Types/ib_slvl_table_set\r
+* NAME\r
+* ib_slvl_table_set\r
+*\r
+* DESCRIPTION\r
+* Set slvl table entry.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_slvl_table_set(\r
+ IN ib_slvl_table_t* p_slvl_tbl,\r
+ IN uint8_t sl_index,\r
+ IN uint8_t vl )\r
+{\r
+ uint8_t idx = sl_index/2;\r
+ CL_ASSERT(vl <= 15);\r
+ CL_ASSERT(sl_index <= 15);\r
+\r
+ if (sl_index%2)\r
+ {\r
+ /* this is an odd sl. Need to update the ls bits */\r
+ p_slvl_tbl->raw_vl_by_sl[idx] = ( p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0 ) | vl ;\r
+ }\r
+ else\r
+ {\r
+ /* this is an even sl. Need to update the ms bits */\r
+ p_slvl_tbl->raw_vl_by_sl[idx] = ( vl << 4 ) | ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );\r
+ }\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_slvl_tbl\r
+* [in] pointer to ib_slvl_table_t object.\r
+*\r
+* sl_index\r
+* [in] the sl index in the table to be updated.\r
+*\r
+* vl\r
+* [in] the vl value to update for that sl.\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_slvl_table_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_slvl_table_get\r
+* NAME\r
+* ib_slvl_table_get\r
+*\r
+* DESCRIPTION\r
+* Get slvl table entry.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_slvl_table_get(\r
+ IN const ib_slvl_table_t* p_slvl_tbl,\r
+ IN uint8_t sl_index )\r
+{\r
+ uint8_t idx = sl_index/2;\r
+ CL_ASSERT(sl_index <= 15);\r
+\r
+ if (sl_index%2)\r
+ {\r
+ /* this is an odd sl. Need to return the ls bits. */\r
+ return ( p_slvl_tbl->raw_vl_by_sl[idx] & 0x0F );\r
+ }\r
+ else\r
+ {\r
+ /* this is an even sl. Need to return the ms bits. */\r
+ return ( (p_slvl_tbl->raw_vl_by_sl[idx] & 0xF0) >> 4 );\r
+ }\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_slvl_tbl\r
+* [in] pointer to ib_slvl_table_t object.\r
+*\r
+* sl_index\r
+* [in] the sl index in the table whose value should be returned.\r
+*\r
+* RETURN VALUES\r
+* vl for the requested sl_index.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_slvl_table_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_element_t\r
+* NAME\r
+* ib_vl_arb_element_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined VL Arbitration Table Element. (14.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_element\r
+{\r
+ uint8_t vl;\r
+ uint8_t weight;\r
+} PACK_SUFFIX ib_vl_arb_element_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+#define IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK 32\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_table_t\r
+* NAME\r
+* ib_vl_arb_table_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined VL Arbitration Table. (14.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_table\r
+{\r
+ ib_vl_arb_element_t vl_entry[IB_NUM_VL_ARB_ELEMENTS_IN_BLOCK];\r
+} PACK_SUFFIX ib_vl_arb_table_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/****s* IBA Base: Types/ib_vl_arb_table_record_t\r
+* NAME\r
+* ib_vl_arb_table_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined VL Arbitration Table Record for SA Query. (15.2.5.9)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_vl_arb_table_record\r
+{\r
+ ib_net16_t lid; // for CA: lid of port, for switch lid of port 0\r
+ uint8_t port_num;\r
+ uint8_t block_num;\r
+ uint32_t reserved;\r
+ ib_vl_arb_table_t vl_arb_tbl;\r
+} PACK_SUFFIX ib_vl_arb_table_record_t;\r
+#include <complib/cl_packoff.h>\r
+/************/\r
+\r
+/*\r
+ * Global route header information received with unreliable datagram messages\r
+ */\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_grh\r
+{\r
+ ib_net32_t ver_class_flow;\r
+ uint16_t resv1;\r
+ uint8_t resv2;\r
+ uint8_t hop_limit;\r
+ ib_gid_t src_gid;\r
+ ib_gid_t dest_gid;\r
+} PACK_SUFFIX ib_grh_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_grh_get_ver_class_flow\r
+* NAME\r
+* ib_grh_get_ver_class_flow\r
+*\r
+* DESCRIPTION\r
+* Get encoded version, traffic class and flow label in grh\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_grh_get_ver_class_flow(\r
+ IN const ib_net32_t ver_class_flow,\r
+ OUT uint8_t* const p_ver,\r
+ OUT uint8_t* const p_tclass,\r
+ OUT uint32_t* const p_flow_lbl )\r
+{\r
+ ib_net32_t tmp_ver_class_flow;\r
+\r
+ if (p_ver)\r
+ *p_ver = (uint8_t)(ver_class_flow & 0x0f);\r
+\r
+ tmp_ver_class_flow = ver_class_flow >> 4;\r
+\r
+ if (p_tclass)\r
+ *p_tclass = (uint8_t)(tmp_ver_class_flow & 0xff);\r
+\r
+ tmp_ver_class_flow = tmp_ver_class_flow >> 8;\r
+\r
+ if (p_flow_lbl)\r
+ *p_flow_lbl = tmp_ver_class_flow & 0xfffff;\r
+}\r
+/*\r
+* PARAMETERS\r
+* ver_class_flow\r
+* [in] the version, traffic class and flow label info.\r
+*\r
+* RETURN VALUES\r
+* p_ver\r
+* [out] pointer to the version info.\r
+*\r
+* p_tclass\r
+* [out] pointer to the traffic class info.\r
+*\r
+* p_flow_lbl\r
+* [out] pointer to the flow label info\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_grh_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_grh_set_ver_class_flow\r
+* NAME\r
+* ib_grh_set_ver_class_flow\r
+*\r
+* DESCRIPTION\r
+* Set encoded version, traffic class and flow label in grh\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_grh_set_ver_class_flow(\r
+ IN const uint8_t ver,\r
+ IN const uint8_t tclass,\r
+ IN const uint32_t flow_lbl )\r
+{\r
+ ib_net32_t ver_class_flow;\r
+\r
+ ver_class_flow = flow_lbl;\r
+ ver_class_flow = ver_class_flow << 8;\r
+ ver_class_flow = ver_class_flow | tclass;\r
+ ver_class_flow = ver_class_flow << 4;\r
+ ver_class_flow = ver_class_flow | ver;\r
+ return (ver_class_flow);\r
+}\r
+/*\r
+* PARAMETERS\r
+* ver\r
+* [in] the version info.\r
+*\r
+* tclass\r
+* [in] the traffic class info.\r
+*\r
+* flow_lbl\r
+* [in] the flow label info\r
+*\r
+* RETURN VALUES\r
+* ver_class_flow\r
+* [out] the version, traffic class and flow label info.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_grh_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_member_rec_t\r
+* NAME\r
+* ib_member_rec_t\r
+*\r
+* DESCRIPTION\r
+* Multicast member record, used to create, join, and leave multicast\r
+* groups.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_member_rec\r
+{\r
+ ib_gid_t mgid;\r
+ ib_gid_t port_gid;\r
+ ib_net32_t qkey;\r
+ ib_net16_t mlid;\r
+ uint8_t mtu;\r
+ uint8_t tclass;\r
+ ib_net16_t pkey;\r
+ uint8_t rate;\r
+ uint8_t pkt_life;\r
+ ib_net32_t sl_flow_hop;\r
+ uint8_t scope_state;\r
+ uint8_t proxy_join:1;\r
+ uint8_t reserved[2];\r
+ uint8_t pad[4];\r
+\r
+} PACK_SUFFIX ib_member_rec_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* mgid\r
+* Multicast GID address for this multicast group.\r
+*\r
+* port_gid\r
+* Valid GID of the endpoint joining this multicast group.\r
+*\r
+* qkey\r
+* Q_Key to be sued by this multicast group.\r
+*\r
+* mlid\r
+* Multicast LID for this multicast group.\r
+*\r
+* mtu\r
+* MTU and MTU selector fields to use on this path\r
+*\r
+* tclass\r
+* Another global routing parameter.\r
+*\r
+* pkey\r
+* Partition key (P_Key) to use for this member.\r
+*\r
+* rate\r
+* Rate and rate selector fields to use on this path.\r
+*\r
+* pkt_life\r
+* Packet lifetime\r
+*\r
+* sl_flow_hop\r
+* Global routing parameters: service level, hop count, and flow label.\r
+*\r
+* scope_state\r
+* MGID scope and JoinState of multicast request.\r
+*\r
+* proxy_join\r
+* Enables others in the Partition to proxy add/remove from the group\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_get_sl_flow_hop\r
+* NAME\r
+* ib_member_get_sl_flow_hop\r
+*\r
+* DESCRIPTION\r
+* Get encoded sl, flow label, and hop limit\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_member_get_sl_flow_hop(\r
+ IN const ib_net32_t sl_flow_hop,\r
+ OUT uint8_t* const p_sl,\r
+ OUT uint32_t* const p_flow_lbl,\r
+ OUT uint8_t* const p_hop )\r
+{\r
+ uint32_t tmp;\r
+\r
+ tmp = cl_ntoh32(sl_flow_hop);\r
+ if (p_hop)\r
+ *p_hop = (uint8_t)tmp;\r
+ tmp >>= 8;\r
+\r
+ if (p_flow_lbl)\r
+ *p_flow_lbl = (uint32_t)(tmp & 0xfffff);\r
+ tmp >>= 20;\r
+\r
+ if (p_sl)\r
+ *p_sl = (uint8_t)tmp;\r
+}\r
+/*\r
+* PARAMETERS\r
+* sl_flow_hop\r
+* [in] the sl, flow label, and hop limit of MC Group\r
+*\r
+* RETURN VALUES\r
+* p_sl\r
+* [out] pointer to the service level\r
+*\r
+* p_flow_lbl\r
+* [out] pointer to the flow label info\r
+*\r
+* p_hop\r
+* [out] pointer to the hop count limit.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_sl_flow_hop\r
+* NAME\r
+* ib_member_set_sl_flow_hop\r
+*\r
+* DESCRIPTION\r
+* Set encoded sl, flow label, and hop limit\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_member_set_sl_flow_hop(\r
+ IN const uint8_t sl,\r
+ IN const uint32_t flow_label,\r
+ IN const uint8_t hop_limit )\r
+{\r
+ uint32_t tmp;\r
+\r
+ tmp = (sl << 28) | ((flow_label & 0xfffff) << 8) | hop_limit;\r
+ return cl_hton32(tmp);\r
+}\r
+/*\r
+* PARAMETERS\r
+* sl\r
+* [in] the service level.\r
+*\r
+* flow_lbl\r
+* [in] the flow label info\r
+*\r
+* hop_limit\r
+* [in] the hop limit.\r
+*\r
+* RETURN VALUES\r
+* sl_flow_hop\r
+* [out] the encoded sl, flow label, and hop limit\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_get_scope_state\r
+* NAME\r
+* ib_member_get_scope_state\r
+*\r
+* DESCRIPTION\r
+* Get encoded MGID scope and JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_member_get_scope_state(\r
+ IN const uint8_t scope_state,\r
+ OUT uint8_t* const p_scope,\r
+ OUT uint8_t* const p_state )\r
+{\r
+ uint8_t tmp_scope_state;\r
+\r
+ if (p_state)\r
+ *p_state = (uint8_t)(scope_state & 0x0f);\r
+\r
+ tmp_scope_state = scope_state >> 4;\r
+\r
+ if (p_scope)\r
+ *p_scope = (uint8_t)(tmp_scope_state & 0x0f);\r
+\r
+}\r
+/*\r
+* PARAMETERS\r
+* scope_state\r
+* [in] the scope and state\r
+*\r
+* RETURN VALUES\r
+* p_scope\r
+* [out] pointer to the MGID scope\r
+*\r
+* p_state\r
+* [out] pointer to the join state\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_scope_state\r
+* NAME\r
+* ib_member_set_scope_state\r
+*\r
+* DESCRIPTION\r
+* Set encoded version, MGID scope and JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_member_set_scope_state(\r
+ IN const uint8_t scope,\r
+ IN const uint8_t state )\r
+{\r
+ uint8_t scope_state;\r
+\r
+ scope_state = scope;\r
+ scope_state = scope_state << 4;\r
+ scope_state = scope_state | state;\r
+ return (scope_state);\r
+}\r
+/*\r
+* PARAMETERS\r
+* scope\r
+* [in] the MGID scope\r
+*\r
+* state\r
+* [in] the JoinState\r
+*\r
+* RETURN VALUES\r
+* scope_state\r
+* [out] the encoded one\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_member_rec_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_member_set_join_state\r
+* NAME\r
+* ib_member_set_join_state\r
+*\r
+* DESCRIPTION\r
+* Set JoinState\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_member_set_join_state(\r
+ IN OUT ib_member_rec_t *p_mc_rec,\r
+ IN const uint8_t state )\r
+{\r
+ /* keep the scope as it is */\r
+ p_mc_rec->scope_state = (p_mc_rec->scope_state & 0xF0) | (0x0f & state);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_mc_rec\r
+* [in] pointer to the member record\r
+*\r
+* state\r
+* [in] the JoinState\r
+*\r
+* RETURN VALUES\r
+* NONE\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_member_rec_t\r
+*********/\r
+\r
+/*\r
+ * Join State Codes:\r
+ */\r
+#define IB_MC_REC_STATE_FULL_MEMBER 0x01\r
+#define IB_MC_REC_STATE_NON_MEMBER 0x02\r
+#define IB_MC_REC_STATE_SEND_ONLY_MEMBER 0x04\r
+\r
+/*\r
+ * Generic MAD notice types\r
+ */\r
+#define IB_NOTICE_TYPE_FATAL 0x00\r
+#define IB_NOTICE_TYPE_URGENT 0x01\r
+#define IB_NOTICE_TYPE_SECURITY 0x02\r
+#define IB_NOTICE_TYPE_SUBN_MGMT 0x03\r
+#define IB_NOTICE_TYPE_INFO 0x04\r
+#define IB_NOTICE_TYPE_EMPTY 0x7F\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_mad_notice_attr // Total Size calc Accumulated\r
+{\r
+ uint8_t generic_type; // 1 1\r
+ \r
+ union _notice_g_or_v\r
+ {\r
+ struct _notice_generic // 5 6\r
+ {\r
+ uint8_t prod_type_msb;\r
+ ib_net16_t prod_type_lsb;\r
+ ib_net16_t trap_num;\r
+ } PACK_SUFFIX generic;\r
+ \r
+ struct _notice_vend\r
+ {\r
+ uint8_t vend_id_msb;\r
+ ib_net16_t vend_id_lsb;\r
+ ib_net16_t dev_id;\r
+ } PACK_SUFFIX vend;\r
+ } g_or_v;\r
+ \r
+ ib_net16_t issuer_lid; // 2 8\r
+ ib_net16_t toggle_count; // 2 10\r
+ \r
+ union _data_details // 54 64\r
+ {\r
+ struct _raw_data\r
+ {\r
+ uint8_t details[54];\r
+ } PACK_SUFFIX raw_data;\r
+\r
+ struct _ntc_64_67\r
+ {\r
+ uint8_t res[6];\r
+ ib_gid_t gid; // the Node or Multicast Group that came in/out\r
+ } PACK_SUFFIX ntc_64_67;\r
+\r
+ struct _ntc_128 {\r
+ ib_net16_t sw_lid; // the sw lid of which link state changed\r
+ } PACK_SUFFIX ntc_128;\r
+ \r
+ struct _ntc_129_131 {\r
+ ib_net16_t pad;\r
+ ib_net16_t lid; // lid and port number of the violation\r
+ uint8_t port_num;\r
+ } PACK_SUFFIX ntc_129_131;\r
+ \r
+ struct _ntc_144 {\r
+ ib_net16_t pad1;\r
+ ib_net16_t lid; // lid where capability mask changed\r
+ ib_net16_t pad2;\r
+ ib_net32_t new_cap_mask; // new capability mask\r
+ } PACK_SUFFIX ntc_144;\r
+\r
+ struct _ntc_145 {\r
+ ib_net16_t pad1;\r
+ ib_net16_t lid; // lid where sys guid changed\r
+ ib_net16_t pad2;\r
+ ib_net64_t new_sys_guid; // new system image guid\r
+ } PACK_SUFFIX ntc_145;\r
+\r
+ struct _ntc_256 { // total: 54\r
+ ib_net16_t pad1; // 2\r
+ ib_net16_t lid; // 2\r
+ ib_net16_t pad2; // 2\r
+ uint8_t method; // 1\r
+ uint8_t pad3; // 1\r
+ ib_net16_t attr_id; // 2\r
+ ib_net32_t attr_mod; // 4\r
+ ib_net64_t mkey; // 8\r
+ uint8_t dr_slid; // 1\r
+ uint8_t dr_trunc_hop; // 1\r
+ uint8_t dr_rtn_path[30]; // 30\r
+ } PACK_SUFFIX ntc_256;\r
+\r
+ struct _ntc_257_258 // violation of p/q_key // 49\r
+ {\r
+ ib_net16_t pad1; // 2\r
+ ib_net16_t lid1; // 2\r
+ ib_net16_t lid2; // 2\r
+ ib_net32_t key; // 2\r
+ uint8_t sl; // 1\r
+ ib_net32_t qp1; // 4\r
+ ib_net32_t qp2; // 4\r
+ ib_gid_t gid1; // 16\r
+ ib_gid_t gid2; // 16\r
+ } PACK_SUFFIX ntc_257_258;\r
+\r
+ struct _ntc_259 // p/q_key violation with sw info 53\r
+ {\r
+ ib_net16_t data_valid; // 2\r
+ ib_net16_t lid1; // 2\r
+ ib_net16_t lid2; // 2\r
+ ib_net32_t key; // 4\r
+ uint8_t sl; // 1\r
+ ib_net32_t qp1; // 4\r
+ uint8_t qp2_msb; // 1\r
+ ib_net16_t qp2_lsb; // 2\r
+ ib_gid_t gid1; // 16\r
+ ib_gid_t gid2; // 16\r
+ ib_net16_t sw_lid; // 2\r
+ uint8_t port_no; // 1\r
+ } PACK_SUFFIX ntc_259;\r
+\r
+ } data_details;\r
+\r
+ ib_gid_t issuer_gid; // 16 80\r
+\r
+} PACK_SUFFIX ib_mad_notice_attr_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_notice_is_generic\r
+* NAME\r
+* ib_notice_is_generic\r
+*\r
+* DESCRIPTION\r
+* Check if the notice is generic\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline boolean_t OSM_API\r
+ib_notice_is_generic(\r
+ IN const ib_mad_notice_attr_t *p_ntc )\r
+{\r
+ return (p_ntc->generic_type & 0x80);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+* TRUE if mad is generic\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_type\r
+* NAME\r
+* ib_notice_get_type\r
+*\r
+* DESCRIPTION\r
+* Get the notice type\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_notice_get_type(\r
+ IN const ib_mad_notice_attr_t *p_ntc )\r
+{\r
+ return p_ntc->generic_type & 0x7f;\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+* TRUE if mad is generic\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_prod_type\r
+* NAME\r
+* ib_notice_get_prod_type\r
+*\r
+* DESCRIPTION\r
+* Get the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_notice_get_prod_type(\r
+ IN const ib_mad_notice_attr_t *p_ntc )\r
+{\r
+ uint32_t pt;\r
+\r
+ pt = cl_ntoh16(p_ntc->g_or_v.generic.prod_type_lsb) |\r
+ (p_ntc->g_or_v.generic.prod_type_msb << 16);\r
+ return cl_hton32(pt);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+* The producer type\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_prod_type\r
+* NAME\r
+* ib_notice_set_prod_type\r
+*\r
+* DESCRIPTION\r
+* Set the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_notice_set_prod_type(\r
+ IN ib_mad_notice_attr_t *p_ntc,\r
+ IN ib_net32_t prod_type_val )\r
+{\r
+ uint32_t ptv = cl_ntoh32(prod_type_val);\r
+ p_ntc->g_or_v.generic.prod_type_lsb = cl_hton16((uint16_t)(ptv & 0x0000ffff));\r
+ p_ntc->g_or_v.generic.prod_type_msb = (uint8_t)( (ptv & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* prod_type\r
+* [in] The producer Type code\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_prod_type_ho\r
+* NAME\r
+* ib_notice_set_prod_type_ho\r
+*\r
+* DESCRIPTION\r
+* Set the notice Producer Type of Generic Notice given Host Order\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_notice_set_prod_type_ho(\r
+ IN ib_mad_notice_attr_t *p_ntc,\r
+ IN uint32_t prod_type_val_ho )\r
+{\r
+ p_ntc->g_or_v.generic.prod_type_lsb = \r
+ cl_hton16( (uint16_t)(prod_type_val_ho & 0x0000ffff) );\r
+ p_ntc->g_or_v.generic.prod_type_msb = \r
+ (uint8_t)( (prod_type_val_ho & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* prod_type\r
+* [in] The producer Type code in host order\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_get_vend_id\r
+* NAME\r
+* ib_notice_get_vend_id\r
+*\r
+* DESCRIPTION\r
+* Get the Vendor Id of Vendor type Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_notice_get_vend_id(\r
+ IN const ib_mad_notice_attr_t *p_ntc )\r
+{\r
+ uint32_t vi;\r
+\r
+ vi = cl_ntoh16(p_ntc->g_or_v.vend.vend_id_lsb) |\r
+ (p_ntc->g_or_v.vend.vend_id_msb << 16);\r
+ return cl_hton32(vi);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* RETURN VALUES\r
+* The Vendor Id of Vendor type Notice\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_vend_id\r
+* NAME\r
+* ib_notice_set_vend_id\r
+*\r
+* DESCRIPTION\r
+* Set the notice Producer Type of Generic Notice\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_notice_set_vend_id(\r
+ IN ib_mad_notice_attr_t *p_ntc,\r
+ IN ib_net32_t vend_id )\r
+{\r
+ uint32_t vi = cl_ntoh32(vend_id);\r
+ p_ntc->g_or_v.vend.vend_id_lsb = cl_hton16((uint16_t)(vi & 0x0000ffff));\r
+ p_ntc->g_or_v.vend.vend_id_msb = (uint8_t)((vi & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* vend_id\r
+* [in] The producer Type code\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_notice_set_vend_id_ho\r
+* NAME\r
+* ib_notice_set_vend_id_ho\r
+*\r
+* DESCRIPTION\r
+* Set the notice Producer Type of Generic Notice given a host order value\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_notice_set_vend_id_ho(\r
+ IN ib_mad_notice_attr_t *p_ntc,\r
+ IN uint32_t vend_id_ho )\r
+{\r
+ p_ntc->g_or_v.vend.vend_id_lsb = \r
+ cl_hton16((uint16_t)(vend_id_ho & 0x0000ffff));\r
+ p_ntc->g_or_v.vend.vend_id_msb =\r
+ (uint8_t)((vend_id_ho & 0x00ff0000) >> 16);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ntc\r
+* [in] Pointer to the notice MAD attribute\r
+*\r
+* vend_id_ho\r
+* [in] The producer Type code in host order\r
+*\r
+* RETURN VALUES\r
+* None\r
+*\r
+* SEE ALSO\r
+* ib_mad_notice_attr_t\r
+*********/\r
+\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_inform_info\r
+{\r
+ ib_gid_t gid;\r
+ ib_net16_t lid_range_begin;\r
+ ib_net16_t lid_range_end;\r
+ ib_net16_t reserved1;\r
+ uint8_t is_generic;\r
+ uint8_t subscribe;\r
+ ib_net16_t trap_type;\r
+ union _inform_g_or_v\r
+ {\r
+ struct _inform_generic\r
+ {\r
+ ib_net16_t trap_num;\r
+ ib_net32_t qpn_resp_time_val;\r
+ uint8_t reserved2;\r
+ uint8_t node_type_msb;\r
+ ib_net16_t node_type_lsb;\r
+ } PACK_SUFFIX generic;\r
+ \r
+ struct _inform_vend\r
+ {\r
+ ib_net16_t dev_id;\r
+ ib_net32_t qpn_resp_time_val;\r
+ uint8_t reserved2;\r
+ uint8_t vendor_id_msb;\r
+ ib_net16_t vendor_id_lsb;\r
+ } PACK_SUFFIX vend;\r
+ \r
+ } PACK_SUFFIX g_or_v;\r
+ \r
+} PACK_SUFFIX ib_inform_info_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_qpn_resp_time\r
+* NAME\r
+* ib_inform_info_get_qpn_resp_time\r
+*\r
+* DESCRIPTION\r
+* Get QPN of the inform info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_inform_info_get_qpn_resp_time(\r
+ IN const ib_net32_t qpn_resp_time_val,\r
+ OUT ib_net32_t* const p_qpn,\r
+ OUT uint8_t* const p_resp_time_val )\r
+{\r
+ uint32_t tmp = cl_ntoh32(qpn_resp_time_val);\r
+\r
+ if (p_qpn)\r
+ *p_qpn = cl_hton32((tmp & 0xffffff00) >> 8);\r
+ \r
+ if (p_resp_time_val)\r
+ *p_resp_time_val = (uint8_t)(tmp & 0x0000001f);\r
+}\r
+/*\r
+* PARAMETERS\r
+* qpn_resp_time_val\r
+* [in] the qpn and resp time val from the mad\r
+*\r
+* RETURN VALUES\r
+* p_qpn\r
+* [out] pointer to the qpn\r
+*\r
+* p_state\r
+* [out] pointer to the resp time val\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_set_qpn\r
+* NAME\r
+* ib_inform_info_set_qpn\r
+*\r
+* DESCRIPTION\r
+* Set the QPN of the inform info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline void OSM_API\r
+ib_inform_info_set_qpn(\r
+ IN ib_inform_info_t *p_ii,\r
+ IN ib_net32_t const qpn)\r
+{\r
+ uint32_t tmp = cl_ntoh32(p_ii->g_or_v.generic.qpn_resp_time_val);\r
+\r
+ p_ii->g_or_v.generic.qpn_resp_time_val = \r
+ cl_hton32(\r
+ (tmp & 0x000000ff) |\r
+ ((cl_ntoh32(qpn) << 8) & 0xffffff00)\r
+ );\r
+}\r
+/*\r
+* PARAMETERS\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_prod_type\r
+* NAME\r
+* ib_inform_info_get_prod_type\r
+*\r
+* DESCRIPTION\r
+* Get Producer Type of the Inform Info\r
+* 13.4.8.3 InformInfo\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_inform_info_get_prod_type(IN const ib_inform_info_t * p_inf)\r
+{\r
+ uint32_t nt;\r
+\r
+ nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |\r
+ (p_inf->g_or_v.generic.node_type_msb << 16);\r
+ return cl_hton32(nt);\r
+}\r
+\r
+/*\r
+* PARAMETERS\r
+* p_inf\r
+* [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+* The producer type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_node_type\r
+* NAME\r
+* ib_inform_info_get_node_type\r
+*\r
+* DESCRIPTION\r
+* Get Node Type of the Inform Info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_inform_info_get_node_type(\r
+ IN const ib_inform_info_t *p_inf)\r
+{\r
+ uint32_t nt;\r
+\r
+ nt = cl_ntoh16(p_inf->g_or_v.generic.node_type_lsb) |\r
+ (p_inf->g_or_v.generic.node_type_msb << 16);\r
+ return cl_hton32(nt);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_inf\r
+* [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+* The node type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_inform_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_inform_info_get_vend_id\r
+* NAME\r
+* ib_inform_info_get_vend_id\r
+*\r
+* DESCRIPTION\r
+* Get Node Type of the Inform Info\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net32_t OSM_API\r
+ib_inform_info_get_vend_id(\r
+ IN const ib_inform_info_t *p_inf)\r
+{\r
+ uint32_t vi;\r
+\r
+ vi = cl_ntoh16(p_inf->g_or_v.vend.vendor_id_lsb) |\r
+ (p_inf->g_or_v.vend.vendor_id_msb << 16);\r
+ return cl_hton32(vi);\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_inf\r
+* [in] pointer to an inform info\r
+*\r
+* RETURN VALUES\r
+* The node type\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_inform_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_inform_info_record_t\r
+* NAME\r
+* ib_inform_info_record_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined InformInfo Record. (15.2.5.12)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_inform_info_record\r
+{\r
+ ib_gid_t subscriber_gid;\r
+ ib_net16_t subscriber_enum;\r
+ uint8_t reserved[6];\r
+ ib_inform_info_t inform_info;\r
+ uint8_t pad[4];\r
+} PACK_SUFFIX ib_inform_info_record_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/****d* IBA Base: Types/DM_SVC_NAME\r
+* NAME\r
+* DM_SVC_NAME\r
+*\r
+* DESCRIPTION\r
+* IBA defined Device Management service name (16.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define DM_SVC_NAME "DeviceManager.IBTA"\r
+/*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_dm_mad_t\r
+* NAME\r
+* ib_dm_mad_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined Device Management MAD (16.3.1)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_dm_mad\r
+{\r
+ ib_mad_t header;\r
+ uint8_t resv[40];\r
+\r
+#define IB_DM_DATA_SIZE 192\r
+ uint8_t data[IB_DM_DATA_SIZE];\r
+\r
+} PACK_SUFFIX ib_dm_mad_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* header\r
+* Common MAD header.\r
+*\r
+* resv\r
+* Reserved.\r
+*\r
+* data\r
+* Device Management payload. The structure and content of this field\r
+* depend upon the method, attr_id, and attr_mod fields in the header.\r
+*\r
+* SEE ALSO\r
+* ib_mad_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_iou_info_t\r
+* NAME\r
+* ib_iou_info_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined IO Unit information structure (16.3.3.3)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_iou_info\r
+{\r
+ ib_net16_t change_id;\r
+ uint8_t max_controllers;\r
+ uint8_t diag_rom;\r
+\r
+#define IB_DM_CTRL_LIST_SIZE 128\r
+\r
+ uint8_t controller_list[IB_DM_CTRL_LIST_SIZE];\r
+#define IOC_NOT_INSTALLED 0x0\r
+#define IOC_INSTALLED 0x1\r
+// Reserved values 0x02-0xE\r
+#define SLOT_DOES_NOT_EXIST 0xF\r
+\r
+} PACK_SUFFIX ib_iou_info_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* change_id\r
+* Value incremented, with rollover, by any change to the controller_list.\r
+*\r
+* max_controllers\r
+* Number of slots in controller_list.\r
+*\r
+* diag_rom\r
+* A byte containing two fields: DiagDeviceID and OptionROM.\r
+* These fields may be read using the ib_iou_info_diag_dev_id\r
+* and ib_iou_info_option_rom functions.\r
+*\r
+* controller_list\r
+* A series of 4-bit nibbles, with each nibble representing a slot\r
+* in the IO Unit. Individual nibbles may be read using the\r
+* ioc_at_slot function.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t, ib_iou_info_diag_dev_id, ib_iou_info_option_rom, ioc_at_slot\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_iou_info_diag_dev_id\r
+* NAME\r
+* ib_iou_info_diag_dev_id\r
+*\r
+* DESCRIPTION\r
+* Returns the DiagDeviceID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_iou_info_diag_dev_id(\r
+ IN const ib_iou_info_t* const p_iou_info )\r
+{\r
+ return( (uint8_t)(p_iou_info->diag_rom >> 6 & 1) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_iou_info\r
+* [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+* DiagDeviceID field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_iou_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ib_iou_info_option_rom\r
+* NAME\r
+* ib_iou_info_option_rom\r
+*\r
+* DESCRIPTION\r
+* Returns the OptionROM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ib_iou_info_option_rom(\r
+ IN const ib_iou_info_t* const p_iou_info )\r
+{\r
+ return( (uint8_t)(p_iou_info->diag_rom >> 7) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_iou_info\r
+* [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+* OptionROM field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_iou_info_t\r
+*********/\r
+\r
+/****f* IBA Base: Types/ioc_at_slot\r
+* NAME\r
+* ioc_at_slot\r
+*\r
+* DESCRIPTION\r
+* Returns the IOC value at the specified slot.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t OSM_API\r
+ioc_at_slot(\r
+ IN const ib_iou_info_t* const p_iou_info,\r
+ IN uint8_t slot )\r
+{\r
+ if( slot >= IB_DM_CTRL_LIST_SIZE ) return SLOT_DOES_NOT_EXIST;\r
+ else return (int8_t)\r
+ ( (slot%2) ?\r
+ ((p_iou_info->controller_list[slot/2] & 0xf0) >> 4 ):\r
+ (p_iou_info->controller_list[slot/2] & 0x0f) );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_iou_info\r
+* [in] Pointer to the IO Unit information structure.\r
+*\r
+* slot\r
+* [in] Pointer to the IO Unit information structure.\r
+*\r
+* RETURN VALUES\r
+* OptionROM field of the IO Unit information.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_iou_info_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_ioc_profile_t\r
+* NAME\r
+* ib_ioc_profile_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined IO Controller profile structure (16.3.3.4)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_ioc_profile\r
+{\r
+ ib_net64_t ioc_guid;\r
+\r
+ ib_net32_t vend_id;\r
+\r
+ ib_net32_t dev_id;\r
+ ib_net16_t dev_ver;\r
+ ib_net16_t resv2;\r
+\r
+ ib_net32_t subsys_vend_id;\r
+ ib_net32_t subsys_id;\r
+\r
+ ib_net16_t io_class;\r
+ ib_net16_t io_subclass;\r
+ ib_net16_t protocol;\r
+ ib_net16_t protocol_ver;\r
+\r
+ ib_net32_t resv3;\r
+ ib_net16_t send_msg_depth;\r
+ uint8_t resv4;\r
+ uint8_t rdma_read_depth;\r
+ ib_net32_t send_msg_size;\r
+ ib_net32_t rdma_size;\r
+\r
+ uint8_t ctrl_ops_cap;\r
+#define CTRL_OPS_CAP_ST 0x01\r
+#define CTRL_OPS_CAP_SF 0x02\r
+#define CTRL_OPS_CAP_RT 0x04\r
+#define CTRL_OPS_CAP_RF 0x08\r
+#define CTRL_OPS_CAP_WT 0x10\r
+#define CTRL_OPS_CAP_WF 0x20\r
+#define CTRL_OPS_CAP_AT 0x40\r
+#define CTRL_OPS_CAP_AF 0x80\r
+\r
+ uint8_t resv5;\r
+\r
+ uint8_t num_svc_entries;\r
+#define MAX_NUM_SVC_ENTRIES 0xff\r
+\r
+ uint8_t resv6[9];\r
+\r
+#define CTRL_ID_STRING_LEN 64\r
+ char id_string[CTRL_ID_STRING_LEN];\r
+\r
+} PACK_SUFFIX ib_ioc_profile_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* ioc_guid\r
+* An EUI-64 GUID used to uniquely identify the IO controller.\r
+*\r
+* vend_id\r
+* IO controller vendor ID, IEEE format.\r
+*\r
+* dev_id\r
+* A number assigned by the vendor to identify the type of controller.\r
+*\r
+* dev_ver\r
+* A number assigned by the vendor to identify the divice version.\r
+*\r
+* subsys_vend_id\r
+* ID of the vendor of the enclosure, if any, in which the IO controller\r
+* resides in IEEE format; otherwise zero.\r
+*\r
+* subsys_id\r
+* A number identifying the subsystem where the controller resides.\r
+*\r
+* io_class\r
+* 0x0000 - 0xfffe = reserved for IO classes encompased by InfiniBand\r
+* Architecture. 0xffff = Vendor specific.\r
+*\r
+* io_subclass\r
+* 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand\r
+* Architecture. 0xffff = Vendor specific. This shall be set to 0xfff\r
+* if the io_class component is 0xffff.\r
+*\r
+* protocol\r
+* 0x0000 - 0xfffe = reserved for IO subclasses encompased by InfiniBand\r
+* Architecture. 0xffff = Vendor specific. This shall be set to 0xfff\r
+* if the io_class component is 0xffff.\r
+*\r
+* protocol_ver\r
+* Protocol specific.\r
+*\r
+* send_msg_depth\r
+* Maximum depth of the send message queue.\r
+*\r
+* rdma_read_depth\r
+* Maximum depth of the per-channel RDMA read queue.\r
+*\r
+* send_msg_size\r
+* Maximum size of send messages.\r
+*\r
+* ctrl_ops_cap\r
+* Supported operation types of this IO controller. A bit set to one\r
+* for affirmation of supported capability.\r
+*\r
+* num_svc_entries\r
+* Number of entries in the service entries table.\r
+*\r
+* id_string\r
+* UTF-8 encoded string for identifying the controller to an operator.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t\r
+*********/\r
+\r
+static inline uint32_t OSM_API\r
+ib_ioc_profile_get_vend_id(\r
+ IN const ib_ioc_profile_t* const p_ioc_profile )\r
+{\r
+ return( cl_ntoh32(p_ioc_profile->vend_id) >> 8 );\r
+}\r
+\r
+\r
+static inline void OSM_API\r
+ib_ioc_profile_set_vend_id(\r
+ IN ib_ioc_profile_t* const p_ioc_profile,\r
+ IN const uint32_t vend_id )\r
+{\r
+ p_ioc_profile->vend_id = (cl_hton32(vend_id) << 8);\r
+}\r
+\r
+/****s* IBA Base: Types/ib_svc_entry_t\r
+* NAME\r
+* ib_svc_entry_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined IO Controller service entry structure (16.3.3.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_svc_entry\r
+{\r
+#define MAX_SVC_ENTRY_NAME_LEN 40\r
+ char name[MAX_SVC_ENTRY_NAME_LEN];\r
+\r
+ ib_net64_t id;\r
+\r
+} PACK_SUFFIX ib_svc_entry_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* name\r
+* UTF-8 encoded, null-terminated name of the service.\r
+*\r
+* id\r
+* An identifier of the associated Service.\r
+*\r
+* SEE ALSO\r
+* ib_svc_entries_t\r
+*********/\r
+\r
+/****s* IBA Base: Types/ib_svc_entries_t\r
+* NAME\r
+* ib_svc_entries_t\r
+*\r
+* DESCRIPTION\r
+* IBA defined IO Controller service entry array (16.3.3.5)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_svc_entries\r
+{\r
+#define SVC_ENTRY_COUNT 4\r
+ ib_svc_entry_t service_entry[SVC_ENTRY_COUNT];\r
+\r
+} PACK_SUFFIX ib_svc_entries_t;\r
+#include <complib/cl_packoff.h>\r
+/*\r
+* FIELDS\r
+* service_entry\r
+* An array of IO controller service entries.\r
+*\r
+* SEE ALSO\r
+* ib_dm_mad_t, ib_svc_entry_t\r
+*********/\r
+\r
+static inline void OSM_API\r
+ib_dm_get_slot_lo_hi(\r
+ IN const ib_net32_t slot_lo_hi,\r
+ OUT uint8_t *const p_slot,\r
+ OUT uint8_t *const p_lo,\r
+ OUT uint8_t *const p_hi )\r
+{\r
+ ib_net32_t tmp_slot_lo_hi = CL_NTOH32( slot_lo_hi );\r
+\r
+ if( p_slot )\r
+ *p_slot = (uint8_t)( ( tmp_slot_lo_hi >> 16 ) & 0x0f );\r
+\r
+ if( p_hi )\r
+ *p_hi = (uint8_t)( ( tmp_slot_lo_hi >> 8 ) & 0xff );\r
+\r
+ if( p_lo )\r
+ *p_lo = (uint8_t)( ( tmp_slot_lo_hi >> 0 ) & 0xff );\r
+}\r
+\r
+/*\r
+ * IBA defined information describing an I/O controller\r
+ */\r
+#include <complib/cl_packon.h>\r
+typedef struct _ib_ioc_info\r
+{\r
+ ib_net64_t module_guid;\r
+ ib_net64_t iou_guid;\r
+ ib_ioc_profile_t ioc_profile;\r
+ ib_net64_t access_key;\r
+ uint16_t initiators_conf;\r
+ uint8_t resv[38];\r
+\r
+} PACK_SUFFIX ib_ioc_info_t;\r
+#include <complib/cl_packoff.h>\r
+\r
+/*\r
+ * Defines known Communication management class versions\r
+ */\r
+#define IB_MCLASS_CM_VER_2 2\r
+#define IB_MCLASS_CM_VER_1 1\r
+\r
+/*\r
+ * Defines the size of user available data in communication management MADs\r
+ */\r
+#define IB_REQ_CM_RDMA_PDATA_SIZE 56\r
+#define IB_REQ_PDATA_SIZE_VER2 92\r
+#define IB_MRA_PDATA_SIZE_VER2 222\r
+#define IB_REJ_PDATA_SIZE_VER2 148\r
+#define IB_REP_PDATA_SIZE_VER2 196\r
+#define IB_RTU_PDATA_SIZE_VER2 224\r
+#define IB_LAP_PDATA_SIZE_VER2 168\r
+#define IB_APR_PDATA_SIZE_VER2 148\r
+#define IB_DREQ_PDATA_SIZE_VER2 220\r
+#define IB_DREP_PDATA_SIZE_VER2 224\r
+#define IB_SIDR_REQ_PDATA_SIZE_VER2 216\r
+#define IB_SIDR_REP_PDATA_SIZE_VER2 136\r
+\r
+#define IB_REQ_PDATA_SIZE_VER1 92\r
+#define IB_MRA_PDATA_SIZE_VER1 222\r
+#define IB_REJ_PDATA_SIZE_VER1 148\r
+#define IB_REP_PDATA_SIZE_VER1 204\r
+#define IB_RTU_PDATA_SIZE_VER1 224\r
+#define IB_LAP_PDATA_SIZE_VER1 168\r
+#define IB_APR_PDATA_SIZE_VER1 151\r
+#define IB_DREQ_PDATA_SIZE_VER1 220\r
+#define IB_DREP_PDATA_SIZE_VER1 224\r
+#define IB_SIDR_REQ_PDATA_SIZE_VER1 216\r
+#define IB_SIDR_REP_PDATA_SIZE_VER1 140\r
+\r
+#define IB_ARI_SIZE 72 // redefine\r
+#define IB_APR_INFO_SIZE 72\r
+\r
+/****d* Access Layer/ib_rej_status_t\r
+* NAME\r
+* ib_rej_status_t\r
+*\r
+* DESCRIPTION\r
+* Rejection reasons.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef ib_net16_t ib_rej_status_t;\r
+/*\r
+* SEE ALSO\r
+* ib_cm_rej, ib_cm_rej_rec_t\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_REJ_INSUF_QP CL_HTON16(1)\r
+#define IB_REJ_INSUF_EEC CL_HTON16(2)\r
+#define IB_REJ_INSUF_RESOURCES CL_HTON16(3)\r
+#define IB_REJ_TIMEOUT CL_HTON16(4)\r
+#define IB_REJ_UNSUPPORTED CL_HTON16(5)\r
+#define IB_REJ_INVALID_COMM_ID CL_HTON16(6)\r
+#define IB_REJ_INVALID_COMM_INSTANCE CL_HTON16(7)\r
+#define IB_REJ_INVALID_SID CL_HTON16(8)\r
+#define IB_REJ_INVALID_XPORT CL_HTON16(9)\r
+#define IB_REJ_STALE_CONN CL_HTON16(10)\r
+#define IB_REJ_RDC_NOT_EXIST CL_HTON16(11)\r
+#define IB_REJ_INVALID_GID CL_HTON16(12)\r
+#define IB_REJ_INVALID_LID CL_HTON16(13)\r
+#define IB_REJ_INVALID_SL CL_HTON16(14)\r
+#define IB_REJ_INVALID_TRAFFIC_CLASS CL_HTON16(15)\r
+#define IB_REJ_INVALID_HOP_LIMIT CL_HTON16(16)\r
+#define IB_REJ_INVALID_PKT_RATE CL_HTON16(17)\r
+#define IB_REJ_INVALID_ALT_GID CL_HTON16(18)\r
+#define IB_REJ_INVALID_ALT_LID CL_HTON16(19)\r
+#define IB_REJ_INVALID_ALT_SL CL_HTON16(20)\r
+#define IB_REJ_INVALID_ALT_TRAFFIC_CLASS CL_HTON16(21)\r
+#define IB_REJ_INVALID_ALT_HOP_LIMIT CL_HTON16(22)\r
+#define IB_REJ_INVALID_ALT_PKT_RATE CL_HTON16(23)\r
+#define IB_REJ_PORT_REDIRECT CL_HTON16(24)\r
+#define IB_REJ_INVALID_MTU CL_HTON16(26)\r
+#define IB_REJ_INSUFFICIENT_RESP_RES CL_HTON16(27)\r
+#define IB_REJ_USER_DEFINED CL_HTON16(28)\r
+#define IB_REJ_INVALID_RNR_RETRY CL_HTON16(29)\r
+#define IB_REJ_DUPLICATE_LOCAL_COMM_ID CL_HTON16(30)\r
+#define IB_REJ_INVALID_CLASS_VER CL_HTON16(31)\r
+#define IB_REJ_INVALID_FLOW_LBL CL_HTON16(32)\r
+#define IB_REJ_INVALID_ALT_FLOW_LBL CL_HTON16(33)\r
+\r
+#define IB_REJ_SERVICE_HANDOFF CL_HTON16(65535)\r
+/******/\r
+\r
+/****d* Access Layer/ib_apr_status_t\r
+* NAME\r
+* ib_apr_status_t\r
+*\r
+* DESCRIPTION\r
+* Automatic path migration status information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t ib_apr_status_t;\r
+/*\r
+* SEE ALSO\r
+* ib_cm_apr, ib_cm_apr_rec_t\r
+*\r
+* SOURCE\r
+ */\r
+#define IB_AP_SUCCESS 0\r
+#define IB_AP_INVALID_COMM_ID 1\r
+#define IB_AP_UNSUPPORTED 2\r
+#define IB_AP_REJECT 3\r
+#define IB_AP_REDIRECT 4\r
+#define IB_AP_IS_CURRENT 5\r
+#define IB_AP_INVALID_QPN_EECN 6\r
+#define IB_AP_INVALID_LID 7\r
+#define IB_AP_INVALID_GID 8\r
+#define IB_AP_INVALID_FLOW_LBL 9\r
+#define IB_AP_INVALID_TCLASS 10\r
+#define IB_AP_INVALID_HOP_LIMIT 11\r
+#define IB_AP_INVALID_PKT_RATE 12\r
+#define IB_AP_INVALID_SL 13\r
+/******/\r
+\r
+/****d* Access Layer/ib_cm_cap_mask_t\r
+* NAME\r
+* ib_cm_cap_mask_t\r
+*\r
+* DESCRIPTION\r
+* Capability mask values in ClassPortInfo.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define IB_CM_RELIABLE_CONN_CAPABLE CL_HTON16(9)\r
+#define IB_CM_RELIABLE_DGRM_CAPABLE CL_HTON16(10)\r
+#define IB_CM_RDGRM_CAPABLE CL_HTON16(11)\r
+#define IB_CM_UNRELIABLE_CONN_CAPABLE CL_HTON16(12)\r
+#define IB_CM_SIDR_CAPABLE CL_HTON16(13)\r
+/*\r
+* SEE ALSO\r
+* ib_cm_rep, ib_class_port_info_t\r
+*\r
+* SOURCE\r
+*\r
+*******/\r
+\r
+/*\r
+ * Service ID resolution status\r
+ */\r
+typedef uint16_t ib_sidr_status_t;\r
+#define IB_SIDR_SUCCESS 0\r
+#define IB_SIDR_UNSUPPORTED 1\r
+#define IB_SIDR_REJECT 2\r
+#define IB_SIDR_NO_QP 3\r
+#define IB_SIDR_REDIRECT 4\r
+#define IB_SIDR_UNSUPPORTED_VER 5\r
+\r
+/*\r
+ * The following definitions are shared between the Access Layer and VPD\r
+ */\r
+\r
+\r
+typedef struct _ib_ca* ib_ca_handle_t ;\r
+typedef struct _ib_pd* ib_pd_handle_t ;\r
+typedef struct _ib_rdd* ib_rdd_handle_t;\r
+typedef struct _ib_mr* ib_mr_handle_t;\r
+typedef struct _ib_mw* ib_mw_handle_t;\r
+typedef struct _ib_qp* ib_qp_handle_t;\r
+typedef struct _ib_eec* ib_eec_handle_t;\r
+typedef struct _ib_cq* ib_cq_handle_t;\r
+typedef struct _ib_av* ib_av_handle_t;\r
+typedef struct _ib_mcast* ib_mcast_handle_t;\r
+/* Currently for windows branch, use the extended version of ib special verbs struct \r
+ in order to be compliant with Infinicon ib_types; later we'll change it to support \r
+ OpenSM ib_types.h */\r
+\r
+#ifndef WIN32\r
+/****d* Access Layer/ib_api_status_t\r
+* NAME\r
+* ib_api_status_t\r
+*\r
+* DESCRIPTION\r
+* Function return codes indicating the success or failure of an API call.\r
+* Note that success is indicated by the return value IB_SUCCESS, which\r
+* is always zero.\r
+*\r
+* NOTES\r
+* IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call\r
+* in the pre-ioctl step itself.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_api_status_t\r
+{\r
+ IB_SUCCESS,\r
+ IB_INSUFFICIENT_RESOURCES,\r
+ IB_INSUFFICIENT_MEMORY,\r
+ IB_INVALID_PARAMETER,\r
+ IB_INVALID_SETTING,\r
+ IB_NOT_FOUND,\r
+ IB_TIMEOUT,\r
+ IB_CANCELED,\r
+ IB_INTERRUPTED,\r
+ IB_INVALID_PERMISSION,\r
+ IB_UNSUPPORTED,\r
+ IB_OVERFLOW,\r
+ IB_MAX_MCAST_QPS_REACHED,\r
+ IB_INVALID_QP_STATE,\r
+ IB_INVALID_EEC_STATE,\r
+ IB_INVALID_APM_STATE,\r
+ IB_INVALID_PORT_STATE,\r
+ IB_INVALID_STATE,\r
+ IB_RESOURCE_BUSY,\r
+ IB_INVALID_PKEY,\r
+ IB_INVALID_LKEY,\r
+ IB_INVALID_RKEY,\r
+ IB_INVALID_MAX_WRS,\r
+ IB_INVALID_MAX_SGE,\r
+ IB_INVALID_CQ_SIZE,\r
+ IB_INVALID_SERVICE_TYPE,\r
+ IB_INVALID_GID,\r
+ IB_INVALID_LID,\r
+ IB_INVALID_GUID,\r
+ IB_INVALID_GUID_MASK,\r
+ IB_INVALID_CA_HANDLE,\r
+ IB_INVALID_AV_HANDLE,\r
+ IB_INVALID_CQ_HANDLE,\r
+ IB_INVALID_EEC_HANDLE,\r
+ IB_INVALID_QP_HANDLE,\r
+ IB_INVALID_PD_HANDLE,\r
+ IB_INVALID_MR_HANDLE,\r
+ IB_INVALID_MW_HANDLE,\r
+ IB_INVALID_RDD_HANDLE,\r
+ IB_INVALID_MCAST_HANDLE,\r
+ IB_INVALID_CALLBACK,\r
+ IB_INVALID_AL_HANDLE, /* InfiniBand Access Layer */\r
+ IB_INVALID_HANDLE, /* InfiniBand Access Layer */\r
+ IB_ERROR, /* InfiniBand Access Layer */\r
+ IB_REMOTE_ERROR, /* Infiniband Access Layer */\r
+ IB_VERBS_PROCESSING_DONE, /* See Notes above */\r
+ IB_INVALID_WR_TYPE,\r
+ IB_QP_IN_TIMEWAIT,\r
+ IB_EE_IN_TIMEWAIT,\r
+ IB_INVALID_PORT,\r
+ IB_NOT_DONE,\r
+ IB_UNKNOWN_ERROR /* ALWAYS LAST ENUM VALUE! */\r
+\r
+} ib_api_status_t;\r
+/*****/\r
+\r
+OSM_EXPORT const char* ib_error_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_err_str\r
+* NAME\r
+* ib_get_err_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified status value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char* OSM_API\r
+ib_get_err_str(\r
+ IN ib_api_status_t status )\r
+{\r
+ if( status > IB_UNKNOWN_ERROR )\r
+ status = IB_UNKNOWN_ERROR;\r
+ return( ib_error_str[status] );\r
+}\r
+/*\r
+* PARAMETERS\r
+* status\r
+* [in] status value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Verbs/ib_async_event_t\r
+* NAME\r
+* ib_async_event_t -- Async event types\r
+*\r
+* DESCRIPTION\r
+* This type indicates the reason the async callback was called.\r
+* The context in the ib_event_rec_t indicates the resource context\r
+* that associated with the callback. For example, for IB_AE_CQ_ERROR\r
+* the context provided during the ib_create_cq is returned in the event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_async_event_t\r
+{\r
+ IB_AE_SQ_ERROR = 1,\r
+ IB_AE_SQ_DRAINED,\r
+ IB_AE_RQ_ERROR,\r
+ IB_AE_CQ_ERROR,\r
+ IB_AE_QP_FATAL,\r
+ IB_AE_QP_COMM,\r
+ IB_AE_QP_APM,\r
+ IB_AE_EEC_FATAL,\r
+ IB_AE_EEC_COMM,\r
+ IB_AE_EEC_APM,\r
+ IB_AE_LOCAL_FATAL,\r
+ IB_AE_PKEY_TRAP,\r
+ IB_AE_QKEY_TRAP,\r
+ IB_AE_MKEY_TRAP,\r
+ IB_AE_PORT_TRAP,\r
+ IB_AE_SYSIMG_GUID_TRAP,\r
+ IB_AE_BUF_OVERRUN,\r
+ IB_AE_LINK_INTEGRITY,\r
+ IB_AE_FLOW_CTRL_ERROR,\r
+ IB_AE_BKEY_TRAP,\r
+ IB_AE_QP_APM_ERROR,\r
+ IB_AE_EEC_APM_ERROR,\r
+ IB_AE_WQ_REQ_ERROR,\r
+ IB_AE_WQ_ACCESS_ERROR,\r
+ IB_AE_PORT_ACTIVE,\r
+ IB_AE_PORT_DOWN,\r
+ IB_AE_UNKNOWN /* ALWAYS LAST ENUM VALUE */\r
+\r
+} ib_async_event_t;\r
+/*\r
+* VALUES\r
+* IB_AE_SQ_ERROR\r
+* An error occurred when accessing the send queue of the QP or EEC.\r
+* This event is optional.\r
+*\r
+* IB_AE_SQ_DRAINED\r
+* The send queue of the specified QP has completed the outstanding\r
+* messages in progress when the state change was requested and, if\r
+* applicable, has received all acknowledgements for those messages.\r
+*\r
+* IB_AE_RQ_ERROR\r
+* An error occurred when accessing the receive queue of the QP or EEC.\r
+* This event is optional.\r
+*\r
+* IB_AE_CQ_ERROR\r
+* An error occurred when writing an entry to the CQ.\r
+*\r
+* IB_AE_QP_FATAL\r
+* A catastrophic error occurred while accessing or processing the\r
+* work queue that prevents reporting of completions.\r
+*\r
+* IB_AE_QP_COMM\r
+* The first packet has arrived for the receive work queue where the\r
+* QP is still in the RTR state.\r
+*\r
+* IB_AE_QP_APM\r
+* If alternate path migration is supported, this event indicates that\r
+* the QP connection has migrated to the alternate path.\r
+*\r
+* IB_AE_EEC_FATAL\r
+* If reliable datagram service is supported, this event indicates that\r
+* a catastrophic error occurred while accessing or processing the EEC\r
+* that prevents reporting of completions.\r
+*\r
+* IB_AE_EEC_COMM\r
+* If reliable datagram service is supported, this event indicates that\r
+* the first packet has arrived for the receive work queue where the\r
+* EEC is still in the RTR state.\r
+*\r
+* IB_AE_EEC_APM\r
+* If reliable datagram service and alternate path migration is supported,\r
+* this event indicates that the EEC connection has migrated to the\r
+* alternate path.\r
+*\r
+* IB_AE_LOCAL_FATAL\r
+* A catastrophic HCA error occurred which cannot be attributed to any\r
+* resource; behavior is indeterminate.\r
+*\r
+* IB_AE_PKEY_TRAP\r
+* A PKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_QKEY_TRAP\r
+* A QKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_MKEY_TRAP\r
+* An MKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_PORT_TRAP\r
+* A port capability change was detected. This event is optional.\r
+*\r
+* IB_AE_SYSIMG_GUID_TRAP\r
+* If the system image GUID is supported, this event indicates that the\r
+* system image GUID of this HCA has been changed. This event is\r
+* optional.\r
+*\r
+* IB_AE_BUF_OVERRUN\r
+* The number of consecutive flow control update periods with at least\r
+* one overrun error in each period has exceeded the threshold specified\r
+* in the port info attributes. This event is optional.\r
+*\r
+* IB_AE_LINK_INTEGRITY\r
+* The detection of excessively frequent local physical errors has\r
+* exceeded the threshold specified in the port info attributes. This\r
+* event is optional.\r
+*\r
+* IB_AE_FLOW_CTRL_ERROR\r
+* An HCA watchdog timer monitoring the arrival of flow control updates\r
+* has expired without receiving an update. This event is optional.\r
+*\r
+* IB_AE_BKEY_TRAP\r
+* An BKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_QP_APM_ERROR\r
+* If alternate path migration is supported, this event indicates that\r
+* an incoming path migration request to this QP was not accepted.\r
+*\r
+* IB_AE_EEC_APM_ERROR\r
+* If reliable datagram service and alternate path migration is supported,\r
+* this event indicates that an incoming path migration request to this\r
+* EEC was not accepted.\r
+*\r
+* IB_AE_WQ_REQ_ERROR\r
+* An OpCode violation was detected at the responder.\r
+*\r
+* IB_AE_WQ_ACCESS_ERROR\r
+* An access violation was detected at the responder.\r
+*\r
+* IB_AE_PORT_ACTIVE\r
+* If the port active event is supported, this event is generated\r
+* when the link becomes active: IB_LINK_ACTIVE.\r
+*\r
+* IB_AE_PORT_DOWN\r
+* The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,\r
+* IB_LINK_DOWN.\r
+*\r
+* IB_AE_UNKNOWN\r
+* An unknown error occurred which cannot be attributed to any\r
+* resource; behavior is indeterminate.\r
+*\r
+*****/\r
+\r
+OSM_EXPORT const char* ib_async_event_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_async_event_str\r
+* NAME\r
+* ib_get_async_event_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified asynchronous event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char* OSM_API\r
+ib_get_async_event_str(\r
+ IN ib_async_event_t event )\r
+{\r
+ if( event > IB_AE_UNKNOWN )\r
+ event = IB_AE_UNKNOWN;\r
+ return( ib_async_event_str[event] );\r
+}\r
+/*\r
+* PARAMETERS\r
+* event\r
+* [in] event value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the asynchronous event description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* Verbs/ib_event_rec_t\r
+* NAME\r
+* ib_event_rec_t -- Async event notification record\r
+*\r
+* DESCRIPTION\r
+* When an async event callback is made, this structure is passed to indicate\r
+* the type of event, the source of event that caused it, and the context\r
+* associated with this event.\r
+*\r
+* context -- Context of the resource that caused the event.\r
+* -- ca_context if this is a port/adapter event.\r
+* -- qp_context if the source is a QP event\r
+* -- cq_context if the source is a CQ event.\r
+* -- ee_context if the source is an EE event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_event_rec\r
+{\r
+ void *context;\r
+ ib_async_event_t type;\r
+\r
+ /* HCA vendor specific event information. */\r
+ uint64_t vendor_specific;\r
+\r
+ /* The following structures are valid only for trap types. */\r
+ union _trap\r
+ {\r
+ struct\r
+ {\r
+ uint16_t lid;\r
+ ib_net64_t port_guid;\r
+ uint8_t port_num;\r
+\r
+ /*\r
+ * The following structure is valid only for\r
+ * P_KEY, Q_KEY, and M_KEY violation traps.\r
+ */\r
+ struct\r
+ {\r
+ uint8_t sl;\r
+ uint16_t src_lid;\r
+ uint16_t dest_lid;\r
+ union _key\r
+ {\r
+ uint16_t pkey;\r
+ uint32_t qkey;\r
+ uint64_t mkey;\r
+ } key;\r
+ uint32_t src_qp;\r
+ uint32_t dest_qp;\r
+ ib_gid_t src_gid;\r
+ ib_gid_t dest_gid;\r
+\r
+ } violation;\r
+\r
+ } info;\r
+\r
+ ib_net64_t sysimg_guid;\r
+\r
+ } trap;\r
+\r
+} ib_event_rec_t;\r
+/*******/\r
+\r
+/****d* Access Layer/ib_atomic_t\r
+* NAME\r
+* ib_atomic_t\r
+*\r
+* DESCRIPTION\r
+* Indicates atomicity levels supported by an adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_atomic_t\r
+{\r
+ IB_ATOMIC_NONE,\r
+ IB_ATOMIC_LOCAL,\r
+ IB_ATOMIC_GLOBAL\r
+\r
+} ib_atomic_t;\r
+/*\r
+* VALUES\r
+* IB_ATOMIC_NONE\r
+* Atomic operations not supported.\r
+*\r
+* IB_ATOMIC_LOCAL\r
+* Atomic operations guaranteed between QPs of a single CA.\r
+*\r
+* IB_ATOMIC_GLOBAL\r
+* Atomic operations are guaranteed between CA and any other entity\r
+* in the system.\r
+*****/\r
+\r
+/****s* Access Layer/ib_port_cap_t\r
+* NAME\r
+* ib_port_cap_t\r
+*\r
+* DESCRIPTION\r
+* Indicates which management agents are currently available on the specified\r
+* port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_cap\r
+{\r
+ boolean_t cm;\r
+ boolean_t snmp;\r
+ boolean_t dev_mgmt;\r
+ boolean_t vend;\r
+ boolean_t sm;\r
+ boolean_t sm_disable;\r
+ boolean_t qkey_ctr;\r
+ boolean_t pkey_ctr;\r
+ boolean_t notice;\r
+ boolean_t trap;\r
+ boolean_t apm;\r
+ boolean_t slmap;\r
+ boolean_t pkey_nvram;\r
+ boolean_t mkey_nvram;\r
+ boolean_t sysguid;\r
+ boolean_t dr_notice;\r
+ boolean_t boot_mgmt;\r
+ boolean_t capm_notice;\r
+ boolean_t reinit;\r
+ boolean_t ledinfo;\r
+ boolean_t port_active;\r
+\r
+} ib_port_cap_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_init_type_t\r
+* NAME\r
+* ib_init_type_t\r
+*\r
+* DESCRIPTION\r
+* If supported by the HCA, the type of initialization requested by\r
+* this port before SM moves it to the active or armed state. If the\r
+* SM implements reinitialization, it shall set these bits to indicate\r
+* the type of initialization performed prior to activating the port.\r
+* Otherwise, these bits shall be set to 0.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t ib_init_type_t;\r
+#define IB_INIT_TYPE_NO_LOAD 0x01\r
+#define IB_INIT_TYPE_PRESERVE_CONTENT 0x02\r
+#define IB_INIT_TYPE_PRESERVE_PRESENCE 0x04\r
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE 0x08\r
+/*****/\r
+\r
+/****s* Access Layer/ib_port_attr_mod_t\r
+* NAME\r
+* ib_port_attr_mod_t\r
+*\r
+* DESCRIPTION\r
+* Port attributes that may be modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr_mod\r
+{\r
+ ib_port_cap_t cap;\r
+ uint16_t pkey_ctr;\r
+ uint16_t qkey_ctr;\r
+\r
+ ib_init_type_t init_type;\r
+ ib_net64_t system_image_guid;\r
+\r
+} ib_port_attr_mod_t;\r
+/*\r
+* SEE ALSO\r
+* ib_port_cap_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_port_attr_t\r
+* NAME\r
+* ib_port_attr_t\r
+*\r
+* DESCRIPTION\r
+* Information about a port on a given channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr\r
+{\r
+ ib_net64_t port_guid;\r
+ uint8_t port_num;\r
+ uint8_t mtu;\r
+ uint64_t max_msg_size;\r
+ ib_net16_t lid;\r
+ uint8_t lmc;\r
+\r
+ /*\r
+ * LinkWidthSupported as defined in PortInfo. Required to calculate\r
+ * inter-packet delay (a.k.a. static rate).\r
+ */\r
+ uint8_t link_width_supported;\r
+\r
+ uint16_t max_vls;\r
+\r
+ ib_net16_t sm_lid;\r
+ uint8_t sm_sl;\r
+ uint8_t link_state;\r
+\r
+ ib_init_type_t init_type_reply; /* Optional */\r
+\r
+ /*\r
+ * subnet_timeout:\r
+ * The maximum expected subnet propagation delay to reach any port on\r
+ * the subnet. This value also determines the rate at which traps can\r
+ * be generated from this node.\r
+ *\r
+ * timeout = 4.096 microseconds * 2^subnet_timeout\r
+ */\r
+ uint8_t subnet_timeout;\r
+\r
+ ib_port_cap_t cap;\r
+ uint16_t pkey_ctr;\r
+ uint16_t qkey_ctr;\r
+\r
+ uint16_t num_gids;\r
+ uint16_t num_pkeys;\r
+ /*\r
+ * Pointers at the end of the structure to allow doing a simple\r
+ * memory comparison of contents up to the first pointer.\r
+ */\r
+ ib_gid_t *p_gid_table;\r
+ ib_net16_t *p_pkey_table;\r
+\r
+} ib_port_attr_t;\r
+/*\r
+* SEE ALSO\r
+* uint8_t, ib_port_cap_t, ib_link_states_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_ca_attr_t\r
+* NAME\r
+* ib_ca_attr_t\r
+*\r
+* DESCRIPTION\r
+* Information about a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ca_attr\r
+{\r
+ ib_net64_t ca_guid;\r
+\r
+ uint32_t vend_id;\r
+ uint16_t dev_id;\r
+ uint16_t revision;\r
+ uint64_t fw_ver;\r
+\r
+ /*\r
+ * Total size of the ca attributes in bytes\r
+ */\r
+ uint32_t size;\r
+ uint32_t max_qps;\r
+ uint32_t max_wrs;\r
+\r
+ uint32_t max_sges;\r
+ uint32_t max_rd_sges;\r
+\r
+ uint32_t max_cqs;\r
+ uint32_t max_cqes;\r
+\r
+ uint32_t max_pds;\r
+\r
+ uint32_t init_regions;\r
+ uint64_t init_region_size;\r
+\r
+ uint32_t init_windows;\r
+ uint64_t max_addr_handles;\r
+\r
+ uint32_t max_partitions;\r
+\r
+ ib_atomic_t atomicity;\r
+\r
+ uint8_t max_qp_resp_res;\r
+ uint8_t max_eec_resp_res;\r
+ uint8_t max_resp_res;\r
+\r
+ uint8_t max_qp_init_depth;\r
+ uint8_t max_eec_init_depth;\r
+\r
+ uint32_t max_eecs;\r
+ uint32_t max_rdds;\r
+\r
+ uint32_t max_ipv6_qps;\r
+ uint32_t max_ether_qps;\r
+\r
+ uint32_t max_mcast_grps;\r
+ uint32_t max_mcast_qps;\r
+ uint32_t max_qps_per_mcast_grp;\r
+ uint32_t max_fmr;\r
+ uint32_t max_map_per_fmr;\r
+\r
+ /*\r
+ * local_ack_delay:\r
+ * Specifies the maximum time interval between the local CA receiving\r
+ * a message and the transmission of the associated ACK or NAK.\r
+ *\r
+ * timeout = 4.096 microseconds * 2^local_ack_delay\r
+ */\r
+ uint8_t local_ack_delay;\r
+\r
+ boolean_t bad_pkey_ctr_support;\r
+ boolean_t bad_qkey_ctr_support;\r
+ boolean_t raw_mcast_support;\r
+ boolean_t apm_support;\r
+ boolean_t av_port_check;\r
+ boolean_t change_primary_port;\r
+ boolean_t modify_wr_depth;\r
+ boolean_t current_qp_state_support;\r
+ boolean_t shutdown_port_capability;\r
+ boolean_t init_type_support;\r
+ boolean_t port_active_event_support;\r
+ boolean_t system_image_guid_support;\r
+ boolean_t hw_agents;\r
+\r
+ ib_net64_t system_image_guid;\r
+\r
+ uint32_t num_page_sizes;\r
+ uint8_t num_ports;\r
+\r
+ uint32_t *p_page_size;\r
+ ib_port_attr_t *p_port_attr;\r
+\r
+} ib_ca_attr_t;\r
+/*\r
+* FIELDS\r
+* ca_guid\r
+* GUID for this adapter.\r
+*\r
+* vend_id\r
+* IEEE vendor ID for this adapter\r
+*\r
+* dev_id\r
+* Device ID of this adapter. (typically from PCI device ID)\r
+*\r
+* revision\r
+* Revision ID of this adapter\r
+*\r
+* fw_ver\r
+* Device Firmware version.\r
+*\r
+* size\r
+* Total size in bytes for the HCA attributes. This size includes total\r
+* size required for all the variable members of the structure. If a\r
+* vendor requires to pass vendor specific fields beyond this structure,\r
+* the HCA vendor can choose to report a larger size. If a vendor is\r
+* reporting extended vendor specific features, they should also provide\r
+* appropriate access functions to aid with the required interpretation.\r
+*\r
+* max_qps\r
+* Maximum number of QP's supported by this HCA.\r
+*\r
+* max_wrs\r
+* Maximum number of work requests supported by this HCA.\r
+*\r
+* max_sges\r
+* Maximum number of scatter gather elements supported per work request.\r
+*\r
+* max_rd_sges\r
+* Maximum number of scatter gather elements supported for READ work\r
+* requests for a Reliable Datagram QP. This value must be zero if RD\r
+* service is not supported.\r
+*\r
+* max_cqs\r
+* Maximum number of Completion Queues supported.\r
+*\r
+* max_cqes\r
+* Maximum number of CQ elements supported per CQ.\r
+*\r
+* max_pds\r
+* Maximum number of protection domains supported.\r
+*\r
+* init_regions\r
+* Initial number of memory regions supported. These are only informative\r
+* values. HCA vendors can extended and grow these limits on demand.\r
+*\r
+* init_region_size\r
+* Initial limit on the size of the registered memory region.\r
+*\r
+* init_windows\r
+* Initial number of window entries supported.\r
+*\r
+* max_addr_handles\r
+* Maximum number of address handles supported.\r
+*\r
+* max_partitions\r
+* Maximum number of partitions supported.\r
+*\r
+* atomicity\r
+* Indicates level of atomic operations supported by this HCA.\r
+*\r
+* max_qp_resp_res\r
+* max_eec_resp_res\r
+* Maximum limit on number of responder resources for incoming RDMA\r
+* operations, on QPs and EEC's respectively.\r
+*\r
+* max_resp_res\r
+* Maximum number of responder resources per HCA, with this HCA used as\r
+* the target.\r
+*\r
+* max_qp_init_depth\r
+* max_eec_init_depth\r
+* Maximimum initiator depth per QP or EEC for initiating RDMA reads and\r
+* atomic operations.\r
+*\r
+* max_eecs\r
+* Maximimum number of EEC's supported by the HCA.\r
+*\r
+* max_rdds\r
+* Maximum number of Reliable datagram domains supported.\r
+*\r
+* max_ipv6_qps\r
+* max_ether_qps\r
+* Maximum number of IPV6 and raw ether QP's supported by this HCA.\r
+*\r
+* max_mcast_grps\r
+* Maximum number of multicast groups supported.\r
+*\r
+* max_mcast_qps\r
+* Maximum number of QP's that can support multicast operations.\r
+*\r
+* max_qps_per_mcast_grp\r
+* Maximum number of multicast QP's per multicast group.\r
+*\r
+* local_ack_delay\r
+* Specifies the maximum time interval between the local CA receiving\r
+* a message and the transmission of the associated ACK or NAK.\r
+* timeout = 4.096 microseconds * 2^local_ack_delay\r
+*\r
+* bad_pkey_ctr_support\r
+* bad_qkey_ctr_support\r
+* Indicates support for the bad pkey and qkey counters.\r
+*\r
+* raw_mcast_support\r
+* Indicates support for raw packet multicast.\r
+*\r
+* apm_support\r
+* Indicates support for Automatic Path Migration.\r
+*\r
+* av_port_check\r
+* Indicates ability to check port number in address handles.\r
+*\r
+* change_primary_port\r
+* Indicates ability to change primary port for a QP or EEC during a\r
+* SQD->RTS transition.\r
+*\r
+* modify_wr_depth\r
+* Indicates ability to modify QP depth during a modify QP operation.\r
+* Check the verb specification for permitted states.\r
+*\r
+* current_qp_state_support\r
+* Indicates ability of the HCA to support the current QP state modifier\r
+* during a modify QP operation.\r
+*\r
+* shutdown_port_capability\r
+* Shutdown port capability support indicator.\r
+*\r
+* init_type_support\r
+* Indicates init_type_reply and ability to set init_type is supported.\r
+*\r
+* port_active_event_support\r
+* Port active event support indicator.\r
+*\r
+* system_image_guid_support\r
+* System image GUID support indicator.\r
+*\r
+* hw_agents\r
+* Indicates SMA is implemented in HW.\r
+*\r
+* system_image_guid\r
+* Optional system image GUID. This field is valid only if the\r
+* system_image_guid_support flag is set.\r
+*\r
+* num_page_sizes\r
+* Indicates support for different page sizes supported by the HCA.\r
+* The variable size array can be obtained from p_page_size.\r
+*\r
+* num_ports\r
+* Number of physical ports supported on this HCA.\r
+*\r
+* p_page_size\r
+* Array holding different page size supported.\r
+*\r
+* p_port_attr\r
+* Array holding port attributes.\r
+*\r
+* NOTES\r
+* This structure contains the attributes of a channel adapter. Users must\r
+* call ib_copy_ca_attr to copy the contents of this structure to a new\r
+* memory region.\r
+*\r
+* SEE ALSO\r
+* ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr\r
+*****/\r
+\r
+/****f* Access layer/ib_copy_ca_attr\r
+* NAME\r
+* ib_copy_ca_attr\r
+*\r
+* DESCRIPTION\r
+* Copies CA attributes.\r
+*\r
+* SYNOPSIS\r
+*/\r
+ib_ca_attr_t*\r
+ib_copy_ca_attr(\r
+ IN ib_ca_attr_t* const p_dest,\r
+ IN const ib_ca_attr_t* const p_src );\r
+/*\r
+* PARAMETERS\r
+* p_dest\r
+* Pointer to the buffer that is the destination of the copy.\r
+*\r
+* p_src\r
+* Pointer to the CA attributes to copy.\r
+*\r
+* RETURN VALUE\r
+* Pointer to the copied CA attributes.\r
+*\r
+* NOTES\r
+* The buffer pointed to by the p_dest parameter must be at least the size\r
+* specified in the size field of the buffer pointed to by p_src.\r
+*\r
+* SEE ALSO\r
+* ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr\r
+*****/\r
+\r
+/****s* Access Layer/ib_av_attr_t\r
+* NAME\r
+* ib_av_attr_t\r
+*\r
+* DESCRIPTION\r
+* IBA address vector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_av_attr\r
+{\r
+ uint8_t port_num;\r
+\r
+ uint8_t sl;\r
+ ib_net16_t dlid;\r
+\r
+ boolean_t grh_valid;\r
+ ib_grh_t grh;\r
+ uint8_t static_rate;\r
+ uint8_t path_bits;\r
+\r
+ struct _av_conn\r
+ {\r
+ uint8_t path_mtu;\r
+ uint8_t local_ack_timeout;\r
+ uint8_t seq_err_retry_cnt;\r
+ uint8_t rnr_retry_cnt;\r
+\r
+ } conn;\r
+\r
+} ib_av_attr_t;\r
+/*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_type_t\r
+* NAME\r
+* ib_qp_type_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of queue pair being created.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_qp_type\r
+{\r
+ IB_QPT_RELIABLE_CONN = 0, /* Matches CM REQ transport type */\r
+ IB_QPT_UNRELIABLE_CONN = 1, /* Matches CM REQ transport type */\r
+ IB_QPT_RELIABLE_DGRM = 2, /* Matches CM REQ transport type */\r
+ IB_QPT_UNRELIABLE_DGRM,\r
+ IB_QPT_QP0,\r
+ IB_QPT_QP1,\r
+ IB_QPT_RAW_IPV6,\r
+ IB_QPT_RAW_ETHER,\r
+ IB_QPT_MAD, /* InfiniBand Access Layer */\r
+ IB_QPT_QP0_ALIAS, /* InfiniBand Access Layer */\r
+ IB_QPT_QP1_ALIAS /* InfiniBand Access Layer */\r
+\r
+} ib_qp_type_t;\r
+/*\r
+* VALUES\r
+* IB_QPT_RELIABLE_CONN\r
+* Reliable, connected queue pair.\r
+*\r
+* IB_QPT_UNRELIABLE_CONN\r
+* Unreliable, connected queue pair.\r
+*\r
+* IB_QPT_RELIABLE_DGRM\r
+* Reliable, datagram queue pair.\r
+*\r
+* IB_QPT_UNRELIABLE_DGRM\r
+* Unreliable, datagram queue pair.\r
+*\r
+* IB_QPT_QP0\r
+* Queue pair 0.\r
+*\r
+* IB_QPT_QP1\r
+* Queue pair 1.\r
+*\r
+* IB_QPT_RAW_DGRM\r
+* Raw datagram queue pair.\r
+*\r
+* IB_QPT_RAW_IPV6\r
+* Raw IP version 6 queue pair.\r
+*\r
+* IB_QPT_RAW_ETHER\r
+* Raw Ethernet queue pair.\r
+*\r
+* IB_QPT_MAD\r
+* Unreliable, datagram queue pair that will send and receive management\r
+* datagrams with assistance from the access layer.\r
+*\r
+* IB_QPT_QP0_ALIAS\r
+* Alias to queue pair 0. Aliased QPs can only be created on an aliased\r
+* protection domain.\r
+*\r
+* IB_QPT_QP1_ALIAS\r
+* Alias to queue pair 1. Aliased QPs can only be created on an aliased\r
+* protection domain.\r
+*****/\r
+\r
+/****d* Access Layer/ib_access_t\r
+* NAME\r
+* ib_access_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of access is permitted on resources such as QPs,\r
+* memory regions and memory windows.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_access_t;\r
+#define IB_AC_RDMA_READ 0x00000001\r
+#define IB_AC_RDMA_WRITE 0x00000002\r
+#define IB_AC_ATOMIC 0x00000004\r
+#define IB_AC_LOCAL_WRITE 0x00000008\r
+#define IB_AC_MW_BIND 0x00000010\r
+/*\r
+* NOTES\r
+* Users may combine access rights using a bit-wise or operation to specify\r
+* additional access. For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants\r
+* RDMA read and write access.\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_state_t\r
+* NAME\r
+* ib_qp_state_t\r
+*\r
+* DESCRIPTION\r
+* Indicates or sets the state of a queue pair. The current state of a queue\r
+* pair is returned through the ib_qp_query call and set via the\r
+* ib_qp_modify call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_qp_state_t;\r
+#define IB_QPS_RESET 0x00000001\r
+#define IB_QPS_INIT 0x00000002\r
+#define IB_QPS_RTR 0x00000004\r
+#define IB_QPS_RTS 0x00000008\r
+#define IB_QPS_SQD 0x00000010\r
+#define IB_QPS_SQD_DRAINING 0x00000030\r
+#define IB_QPS_SQD_DRAINED 0x00000050\r
+#define IB_QPS_SQERR 0x00000080\r
+#define IB_QPS_ERROR 0x00000100\r
+#define IB_QPS_TIME_WAIT 0xDEAD0000 /* InfiniBand Access Layer */\r
+/*****/\r
+\r
+/****d* Access Layer/ib_apm_state_t\r
+* NAME\r
+* ib_apm_state_t\r
+*\r
+* DESCRIPTION\r
+* The current automatic path migration state of a queue pair\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_apm_state\r
+{\r
+ IB_APM_MIGRATED = 1,\r
+ IB_APM_REARM,\r
+ IB_APM_ARMED\r
+\r
+} ib_apm_state_t;\r
+/*****/\r
+\r
+/****s* Access Layer/ib_qp_create_t\r
+* NAME\r
+* ib_qp_create_t\r
+*\r
+* DESCRIPTION\r
+* Attributes used to initialize a queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_create\r
+{\r
+ ib_qp_type_t qp_type;\r
+\r
+TO_LONG_PTR( struct _ib_rdd* , h_rdd) ; \r
+\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+ uint32_t sq_sge;\r
+ uint32_t rq_sge;\r
+\r
+TO_LONG_PTR( ib_cq_handle_t , h_sq_cq) ; \r
+TO_LONG_PTR( ib_cq_handle_t , h_rq_cq) ; \r
+\r
+ boolean_t sq_signaled;\r
+\r
+} ib_qp_create_t;\r
+/*\r
+* FIELDS\r
+* type\r
+* Specifies the type of queue pair to create.\r
+*\r
+* h_rdd\r
+* A handle to a reliable datagram domain to associate with the queue\r
+* pair. This field is ignored if the queue pair is not a reliable\r
+* datagram type queue pair.\r
+*\r
+* sq_depth\r
+* Indicates the requested maximum number of work requests that may be\r
+* outstanding on the queue pair's send queue. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* rq_depth\r
+* Indicates the requested maximum number of work requests that may be\r
+* outstanding on the queue pair's receive queue. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* sq_sge\r
+* Indicates the maximum number scatter-gather elements that may be\r
+* given in a send work request. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* rq_sge\r
+* Indicates the maximum number scatter-gather elements that may be\r
+* given in a receive work request. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* h_sq_cq\r
+* A handle to the completion queue that will be used to report send work\r
+* request completions. This handle must be NULL if the type is\r
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+* h_rq_cq\r
+* A handle to the completion queue that will be used to report receive\r
+* work request completions. This handle must be NULL if the type is\r
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+* sq_signaled\r
+* A flag that is used to indicate whether the queue pair will signal\r
+* an event upon completion of a send work request. If set to\r
+* TRUE, send work requests will always generate a completion\r
+* event. If set to FALSE, a completion event will only be\r
+* generated if the send_opt field of the send work request has the\r
+* IB_SEND_OPT_SIGNALED flag set.\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t, ib_qp_attr_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_qp_attr_t\r
+* NAME\r
+* ib_qp_attr_t\r
+*\r
+* DESCRIPTION\r
+* Queue pair attributes returned through ib_query_qp.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_attr\r
+{\r
+TO_LONG_PTR( struct _ib_pd* , h_pd) ; \r
+ ib_qp_type_t qp_type;\r
+ ib_access_t access_ctrl;\r
+ uint16_t pkey_index;\r
+\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+ uint32_t sq_sge;\r
+ uint32_t rq_sge;\r
+ uint8_t init_depth;\r
+ uint8_t resp_res;\r
+\r
+TO_LONG_PTR( ib_cq_handle_t , h_sq_cq) ; \r
+TO_LONG_PTR( ib_cq_handle_t , h_rq_cq) ; \r
+TO_LONG_PTR( struct _ib_rdd* , h_rdd) ; \r
+\r
+ boolean_t sq_signaled;\r
+\r
+ ib_qp_state_t state;\r
+ ib_net32_t num;\r
+ ib_net32_t dest_num;\r
+ ib_net32_t qkey;\r
+\r
+ ib_net32_t sq_psn;\r
+ ib_net32_t rq_psn;\r
+\r
+ uint8_t primary_port;\r
+ uint8_t alternate_port;\r
+ ib_av_attr_t primary_av;\r
+ ib_av_attr_t alternate_av;\r
+ ib_apm_state_t apm_state;\r
+\r
+} ib_qp_attr_t;\r
+/*\r
+* FIELDS\r
+* h_pd\r
+* This is a handle to a protection domain associated with the queue\r
+* pair, or NULL if the queue pair is type IB_QPT_RELIABLE_DGRM.\r
+*\r
+* NOTES\r
+* Other fields are defined by the Infiniband specification.\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_qp_opts_t\r
+* NAME\r
+* ib_qp_opts_t\r
+*\r
+* DESCRIPTION\r
+* Optional fields supplied in the modify QP operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_qp_opts_t;\r
+#define IB_MOD_QP_ALTERNATE_AV 0x00000001\r
+#define IB_MOD_QP_PKEY 0x00000002\r
+#define IB_MOD_QP_APM_STATE 0x00000004\r
+#define IB_MOD_QP_PRIMARY_AV 0x00000008\r
+#define IB_MOD_QP_RNR_NAK_TIMEOUT 0x00000010\r
+#define IB_MOD_QP_RESP_RES 0x00000020\r
+#define IB_MOD_QP_INIT_DEPTH 0x00000040\r
+#define IB_MOD_QP_PRIMARY_PORT 0x00000080\r
+#define IB_MOD_QP_ACCESS_CTRL 0x00000100\r
+#define IB_MOD_QP_QKEY 0x00000200\r
+#define IB_MOD_QP_SQ_DEPTH 0x00000400\r
+#define IB_MOD_QP_RQ_DEPTH 0x00000800\r
+#define IB_MOD_QP_CURRENT_STATE 0x00001000\r
+#define IB_MOD_QP_RETRY_CNT 0x00002000\r
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT 0x00004000\r
+#define IB_MOD_QP_RNR_RETRY_CNT 0x00008000\r
+/*\r
+* SEE ALSO\r
+* ib_qp_mod_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_qp_mod_t\r
+* NAME\r
+* ib_qp_mod_t\r
+*\r
+* DESCRIPTION\r
+* Information needed to change the state of a queue pair through the\r
+* ib_modify_qp call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_mod\r
+{\r
+ ib_qp_state_t req_state;\r
+\r
+ union _qp_state\r
+ {\r
+ struct _qp_reset\r
+ {\r
+ /*\r
+ * Time, in milliseconds, that the QP needs to spend in\r
+ * the time wait state before being reused.\r
+ */\r
+ uint32_t timewait;\r
+\r
+ } reset;\r
+\r
+ struct _qp_init\r
+ {\r
+ ib_qp_opts_t opts;\r
+ uint8_t primary_port;\r
+ ib_net32_t qkey;\r
+ uint16_t pkey_index;\r
+ ib_access_t access_ctrl;\r
+\r
+ } init;\r
+\r
+ struct _qp_rtr\r
+ {\r
+ ib_net32_t rq_psn;\r
+ ib_net32_t dest_qp;\r
+ ib_av_attr_t primary_av;\r
+ uint8_t resp_res;\r
+\r
+ ib_qp_opts_t opts;\r
+ ib_av_attr_t alternate_av;\r
+ ib_net32_t qkey;\r
+ uint16_t pkey_index;\r
+ ib_access_t access_ctrl;\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+ uint8_t rnr_nak_timeout;\r
+\r
+ } rtr;\r
+\r
+ struct _qp_rts\r
+ {\r
+ ib_net32_t sq_psn;\r
+ uint8_t retry_cnt;\r
+ uint8_t rnr_retry_cnt;\r
+ uint8_t rnr_nak_timeout;\r
+ uint8_t local_ack_timeout;\r
+ uint8_t init_depth;\r
+\r
+ ib_qp_opts_t opts;\r
+ ib_qp_state_t current_state;\r
+ ib_net32_t qkey;\r
+ ib_access_t access_ctrl;\r
+ uint8_t resp_res;\r
+\r
+ ib_av_attr_t primary_av;\r
+ ib_av_attr_t alternate_av;\r
+\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+\r
+ ib_apm_state_t apm_state;\r
+ uint8_t primary_port;\r
+ uint16_t pkey_index;\r
+\r
+ } rts;\r
+\r
+ struct _qp_sqd\r
+ {\r
+ boolean_t sqd_event;\r
+\r
+ } sqd;\r
+\r
+ } state;\r
+\r
+} ib_qp_mod_t;\r
+/*\r
+* SEE ALSO\r
+* ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_eec_attr_t\r
+* NAME\r
+* ib_eec_attr_t\r
+*\r
+* DESCRIPTION\r
+* Information about an end-to-end context.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_eec_attr\r
+{\r
+ ib_qp_state_t state;\r
+TO_LONG_PTR( struct _ib_rdd* , h_rdd) ; \r
+ ib_net32_t local_eecn;\r
+\r
+ ib_net32_t sq_psn;\r
+ ib_net32_t rq_psn;\r
+ uint8_t primary_port;\r
+ uint16_t pkey_index;\r
+ uint32_t resp_res;\r
+ ib_net32_t remote_eecn;\r
+ uint32_t init_depth;\r
+ uint32_t dest_num; // ??? What is this?\r
+ ib_av_attr_t primary_av;\r
+ ib_av_attr_t alternate_av;\r
+ ib_apm_state_t apm_state;\r
+\r
+} ib_eec_attr_t;\r
+/*\r
+* SEE ALSO\r
+* ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_eec_opts_t\r
+* NAME\r
+* ib_eec_opts_t\r
+*\r
+* DESCRIPTION\r
+* Optional fields supplied in the modify EEC operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_eec_opts_t;\r
+#define IB_MOD_EEC_ALTERNATE_AV 0x00000001\r
+#define IB_MOD_EEC_PKEY 0x00000002\r
+#define IB_MOD_EEC_APM_STATE 0x00000004\r
+#define IB_MOD_EEC_PRIMARY_AV 0x00000008\r
+#define IB_MOD_EEC_RNR 0x00000010\r
+#define IB_MOD_EEC_RESP_RES 0x00000020\r
+#define IB_MOD_EEC_OUTSTANDING 0x00000040\r
+#define IB_MOD_EEC_PRIMARY_PORT 0x00000080\r
+/*\r
+* NOTES\r
+*\r
+*\r
+*****/\r
+\r
+/****s* Access Layer/ib_eec_mod_t\r
+* NAME\r
+* ib_eec_mod_t\r
+*\r
+* DESCRIPTION\r
+* Information needed to change the state of an end-to-end context through\r
+* the ib_modify_eec function.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_eec_mod\r
+{\r
+ ib_qp_state_t req_state;\r
+\r
+ union _eec_state\r
+ {\r
+ struct _eec_init\r
+ {\r
+ uint8_t primary_port;\r
+ uint16_t pkey_index;\r
+\r
+ } init;\r
+\r
+ struct _eec_rtr\r
+ {\r
+ ib_net32_t rq_psn;\r
+ ib_net32_t remote_eecn;\r
+ ib_av_attr_t primary_av;\r
+ uint8_t resp_res;\r
+\r
+ ib_eec_opts_t opts;\r
+ ib_av_attr_t alternate_av;\r
+ uint16_t pkey_index;\r
+\r
+ } rtr;\r
+\r
+ struct _eec_rts\r
+ {\r
+ ib_net32_t sq_psn;\r
+ uint8_t retry_cnt;\r
+ uint8_t rnr_retry_cnt;\r
+ uint8_t local_ack_timeout;\r
+ uint8_t init_depth;\r
+\r
+ ib_eec_opts_t opts;\r
+ ib_av_attr_t alternate_av;\r
+ ib_apm_state_t apm_state;\r
+\r
+ ib_av_attr_t primary_av;\r
+ uint16_t pkey_index;\r
+ uint8_t primary_port;\r
+\r
+ } rts;\r
+\r
+ struct _eec_sqd\r
+ {\r
+ boolean_t sqd_event;\r
+\r
+ } sqd;\r
+\r
+ } state;\r
+\r
+} ib_eec_mod_t;\r
+/*\r
+* SEE ALSO\r
+* ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_wr_type_t\r
+* NAME\r
+* ib_wr_type_t\r
+*\r
+* DESCRIPTION\r
+* Identifies the type of work request posted to a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wr_type_t\r
+{\r
+ WR_SEND = 1,\r
+ WR_RDMA_WRITE,\r
+ WR_RDMA_READ,\r
+ WR_COMPARE_SWAP,\r
+ WR_FETCH_ADD\r
+\r
+} ib_wr_type_t;\r
+/*****/\r
+\r
+/****s* Access Layer/ib_local_ds_t\r
+* NAME\r
+* ib_local_ds_t\r
+*\r
+* DESCRIPTION\r
+* Local data segment information referenced by send and receive work\r
+* requests. This is used to specify local data buffers used as part of a\r
+* work request.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_local_ds\r
+{\r
+ void *vaddr;\r
+ uint32_t length;\r
+ uint32_t lkey;\r
+\r
+} ib_local_ds_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_send_opt_t\r
+* NAME\r
+* ib_send_opt_t\r
+*\r
+* DESCRIPTION\r
+* Optional flags used when posting send work requests. These flags\r
+* indicate specific processing for the send operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_send_opt_t;\r
+#define IB_SEND_OPT_IMMEDIATE 0x00000001\r
+#define IB_SEND_OPT_FENCE 0x00000002\r
+#define IB_SEND_OPT_SIGNALED 0x00000004\r
+#define IB_SEND_OPT_SOLICITED 0x00000008\r
+#define IB_SEND_OPT_INLINE 0x00000010\r
+#define IB_SEND_OPT_LOCAL 0x00000020\r
+#define IB_SEND_OPT_VEND_MASK 0xFFFF0000\r
+/*\r
+* VALUES\r
+* The following flags determine the behavior of a work request when\r
+* posted to the send side.\r
+*\r
+* IB_SEND_OPT_IMMEDIATE\r
+* Send immediate data with the given request.\r
+*\r
+* IB_SEND_OPT_FENCE\r
+* The operation is fenced. Complete all pending send operations\r
+* before processing this request.\r
+*\r
+* IB_SEND_OPT_SIGNALED\r
+* If the queue pair is configured for signaled completion, then\r
+* generate a completion queue entry when this request completes.\r
+*\r
+* IB_SEND_OPT_SOLICITED\r
+* Set the solicited bit on the last packet of this request.\r
+*\r
+* IB_SEND_OPT_INLINE\r
+* Indicates that the requested send data should be copied into a VPD\r
+* owned data buffer. This flag permits the user to issue send operations\r
+* without first needing to register the buffer(s) associated with the\r
+* send operation. Verb providers that support this operation may place\r
+* vendor specific restrictions on the size of send operation that may\r
+* be performed as inline.\r
+*\r
+*\r
+* IB_SEND_OPT_LOCAL\r
+* Indicates that a sent MAD request should be given to the local VPD for\r
+* processing. MADs sent using this option are not placed on the wire.\r
+* This send option is only valid for MAD send operations.\r
+*\r
+*\r
+* IB_SEND_OPT_VEND_MASK\r
+* This mask indicates bits reserved in the send options that may be used\r
+* by the verbs provider to indicate vendor specific options. Bits set\r
+* in this area of the send options are ignored by the Access Layer, but\r
+* may have specific meaning to the underlying VPD.\r
+*\r
+*****/\r
+\r
+/****s* Access Layer/ib_send_wr_t\r
+* NAME\r
+* ib_send_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a work request to the send queue of a queue\r
+* pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_send_wr\r
+{\r
+ struct _ib_send_wr *p_next;\r
+ uint64_t wr_id;\r
+ ib_wr_type_t wr_type;\r
+ ib_send_opt_t send_opt;\r
+ uint32_t num_ds;\r
+ ib_local_ds_t *ds_array;\r
+ ib_net32_t immediate_data;\r
+\r
+ union _send_dgrm\r
+ {\r
+ struct _send_ud\r
+ {\r
+ ib_net32_t remote_qp;\r
+ ib_net32_t remote_qkey;\r
+TO_LONG_PTR( ib_av_handle_t , h_av) ; \r
+\r
+ } ud;\r
+\r
+ struct _send_rd\r
+ {\r
+ ib_net32_t remote_qp;\r
+ ib_net32_t remote_qkey;\r
+ ib_net32_t eecn;\r
+\r
+ } rd;\r
+\r
+ struct _send_raw_ether\r
+ {\r
+ ib_net16_t dest_lid;\r
+ uint8_t path_bits;\r
+ uint8_t sl;\r
+ uint8_t max_static_rate;\r
+ ib_net16_t ether_type;\r
+\r
+ } raw_ether;\r
+\r
+ struct _send_raw_ipv6\r
+ {\r
+ ib_net16_t dest_lid;\r
+ uint8_t path_bits;\r
+ uint8_t sl;\r
+ uint8_t max_static_rate;\r
+\r
+ } raw_ipv6;\r
+\r
+ } dgrm;\r
+\r
+ struct _send_remote_ops\r
+ {\r
+ uint64_t vaddr;\r
+ uint32_t rkey;\r
+\r
+ ib_net64_t atomic1;\r
+ ib_net64_t atomic2;\r
+\r
+ } remote_ops;\r
+\r
+} ib_send_wr_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work requests together. This permits multiple\r
+* work requests to be posted to a queue pair through a single function\r
+* call. This value is set to NULL to mark the end of the chain.\r
+*\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* wr_type\r
+* The type of work request being submitted to the send queue.\r
+*\r
+* send_opt\r
+* Optional send control parameters.\r
+*\r
+* num_ds\r
+* Number of local data segments specified by this work request.\r
+*\r
+* ds_array\r
+* A reference to an array of local data segments used by the send\r
+* operation.\r
+*\r
+* immediate_data\r
+* 32-bit field sent as part of a message send or RDMA write operation.\r
+* This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE\r
+* has been set.\r
+*\r
+* dgrm.ud.remote_qp\r
+* Identifies the destination queue pair of an unreliable datagram send\r
+* operation.\r
+*\r
+* dgrm.ud.remote_qkey\r
+* The qkey for the destination queue pair.\r
+*\r
+* dgrm.ud.h_av\r
+* An address vector that specifies the path information used to route\r
+* the outbound datagram to the destination queue pair.\r
+*\r
+* dgrm.rd.remote_qp\r
+* Identifies the destination queue pair of a reliable datagram send\r
+* operation.\r
+*\r
+* dgrm.rd.remote_qkey\r
+* The qkey for the destination queue pair.\r
+*\r
+* dgrm.rd.eecn\r
+* The local end-to-end context number to use with the reliable datagram\r
+* send operation.\r
+*\r
+* dgrm.raw_ether.dest_lid\r
+* The destination LID that will receive this raw ether send.\r
+*\r
+* dgrm.raw_ether.path_bits\r
+* path bits...\r
+*\r
+* dgrm.raw_ether.sl\r
+* service level...\r
+*\r
+* dgrm.raw_ether.max_static_rate\r
+* static rate...\r
+*\r
+* dgrm.raw_ether.ether_type\r
+* ether type...\r
+*\r
+* dgrm.raw_ipv6.dest_lid\r
+* The destination LID that will receive this raw ether send.\r
+*\r
+* dgrm.raw_ipv6.path_bits\r
+* path bits...\r
+*\r
+* dgrm.raw_ipv6.sl\r
+* service level...\r
+*\r
+* dgrm.raw_ipv6.max_static_rate\r
+* static rate...\r
+*\r
+* remote_ops.vaddr\r
+* The registered virtual memory address of the remote memory to access\r
+* with an RDMA or atomic operation.\r
+*\r
+* remote_ops.rkey\r
+* The rkey associated with the specified remote vaddr. This data must\r
+* be presented exactly as obtained from the remote node. No swapping\r
+* of data must be performed.\r
+*\r
+* atomic1\r
+* The first operand for an atomic operation.\r
+*\r
+* atomic2\r
+* The second operand for an atomic operation.\r
+*\r
+* NOTES\r
+* The format of data sent over the fabric is user-defined and is considered\r
+* opaque to the access layer. The sole exception to this are MADs posted\r
+* to a MAD QP service. MADs are expected to match the format defined by\r
+* the Infiniband specification and must be in network-byte order when posted\r
+* to the MAD QP service.\r
+*\r
+* SEE ALSO\r
+* ib_wr_type_t, ib_local_ds_t, ib_send_opt_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_recv_wr_t\r
+* NAME\r
+* ib_recv_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a work request to the receive queue of a queue\r
+* pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_recv_wr\r
+{\r
+ struct _ib_recv_wr *p_next;\r
+ uint64_t wr_id;\r
+ uint32_t num_ds;\r
+ ib_local_ds_t *ds_array;\r
+} ib_recv_wr_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work requests together. This permits multiple\r
+* work requests to be posted to a queue pair through a single function\r
+* call. This value is set to NULL to mark the end of the chain.\r
+*\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* num_ds\r
+* Number of local data segments specified by this work request.\r
+*\r
+* ds_array\r
+* A reference to an array of local data segments used by the send\r
+* operation.\r
+*\r
+* SEE ALSO\r
+* ib_local_ds_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_bind_wr_t\r
+* NAME\r
+* ib_bind_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a memory window bind work request to the send\r
+* queue of a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_bind_wr\r
+{\r
+ uint64_t wr_id;\r
+ ib_send_opt_t send_opt;\r
+\r
+TO_LONG_PTR( struct _ib_mr* , h_mr) ; \r
+ ib_access_t access_ctrl;\r
+ uint32_t current_rkey;\r
+\r
+ ib_local_ds_t local_ds;\r
+\r
+} ib_bind_wr_t;\r
+/*\r
+* FIELDS\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* send_opt\r
+* Optional send control parameters.\r
+*\r
+* h_mr\r
+* Handle to the memory region to which this window is being bound.\r
+*\r
+* access_ctrl\r
+* Access rights for this memory window.\r
+*\r
+* current_rkey\r
+* The current rkey assigned to this window for remote access.\r
+*\r
+* local_ds\r
+* A reference to a local data segment used by the bind operation.\r
+*\r
+* SEE ALSO\r
+* ib_send_opt_t, ib_access_t, ib_local_ds_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_wc_status_t\r
+* NAME\r
+* ib_wc_status_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the status of a completed work request. These VALUES are\r
+* returned to the user when retrieving completions. Note that success is\r
+* identified as IB_WCS_SUCCESS, which is always zero.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_status_t\r
+{\r
+ IB_WCS_SUCCESS,\r
+ IB_WCS_LOCAL_LEN_ERR,\r
+ IB_WCS_LOCAL_OP_ERR,\r
+ IB_WCS_LOCAL_PROTECTION_ERR,\r
+ IB_WCS_WR_FLUSHED_ERR,\r
+ IB_WCS_MEM_WINDOW_BIND_ERR,\r
+ IB_WCS_REM_ACCESS_ERR,\r
+ IB_WCS_REM_OP_ERR,\r
+ IB_WCS_RNR_RETRY_ERR,\r
+ IB_WCS_TIMEOUT_RETRY_ERR,\r
+ IB_WCS_REM_INVALID_REQ_ERR,\r
+ IB_WCS_BAD_RESP_ERR,\r
+ IB_WCS_LOCAL_ACCESS_ERR,\r
+ IB_WCS_GENERAL_ERR,\r
+ IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */\r
+ IB_WCS_CANCELED, /* InfiniBand Access Layer */\r
+ IB_WCS_REM_ABORT_ERR,\r
+ IB_WCS_UNKNOWN /* Must be last. */\r
+\r
+} ib_wc_status_t;\r
+/*\r
+* VALUES\r
+* IB_WCS_SUCCESS\r
+* Work request completed successfully.\r
+*\r
+* IB_WCS_MAD\r
+* The completed work request was associated with a managmenet datagram\r
+* that requires post processing. The MAD will be returned to the user\r
+* through a callback once all post processing has completed.\r
+*\r
+* IB_WCS_LOCAL_LEN_ERR\r
+* Generated for a work request posted to the send queue when the\r
+* total of the data segment lengths exceeds the message length of the\r
+* channel. Generated for a work request posted to the receive queue when\r
+* the total of the data segment lengths is too small for a\r
+* valid incoming message.\r
+*\r
+* IB_WCS_LOCAL_OP_ERR\r
+* An internal QP consistency error was generated while processing this\r
+* work request. This may indicate that the QP was in an incorrect state\r
+* for the requested operation.\r
+*\r
+* IB_WCS_LOCAL_EEC_OP_ERR\r
+* An internal EEC consistency error was generated while processing\r
+* this work request. This may indicate that the EEC was in an incorrect\r
+* state for the requested operation.\r
+*\r
+* IB_WCS_LOCAL_PROTECTION_ERR\r
+* The data segments of the locally posted work request did not refer to\r
+* a valid memory region. The memory may not have been properly\r
+* registered for the requested operation.\r
+*\r
+* IB_WCS_WR_FLUSHED_ERR\r
+* The work request was flushed from the QP before being completed.\r
+*\r
+* IB_WCS_MEM_WINDOW_BIND_ERR\r
+* A memory window bind operation failed due to insufficient access\r
+* rights.\r
+*\r
+* IB_WCS_REM_ACCESS_ERR,\r
+* A protection error was detected at the remote node for a RDMA or atomic\r
+* operation.\r
+*\r
+* IB_WCS_REM_OP_ERR,\r
+* The operation could not be successfully completed at the remote node.\r
+* This may indicate that the remote QP was in an invalid state or\r
+* contained an invalid work request.\r
+*\r
+* IB_WCS_RNR_RETRY_ERR,\r
+* The RNR retry count was exceeded while trying to send this message.\r
+*\r
+* IB_WCS_TIMEOUT_RETRY_ERR\r
+* The local transport timeout counter expired while trying to send this\r
+* message.\r
+*\r
+* IB_WCS_REM_INVALID_REQ_ERR,\r
+* The remote node detected an invalid message on the channel. This error\r
+* is usually a result of one of the following:\r
+* - The operation was not supported on receive queue.\r
+* - There was insufficient buffers to receive a new RDMA request.\r
+* - There was insufficient buffers to receive a new atomic operation.\r
+* - An RDMA request was larger than 2^31 bytes.\r
+*\r
+* IB_WCS_REM_INVALID_RD_REQ_ERR,\r
+* Responder detected an invalid RD message. This may be the result of an\r
+* invalid qkey or an RDD mismatch.\r
+*\r
+* IB_WCS_REM_ABORT_ERR,\r
+* The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+* the responder aborted the operation).\r
+*\r
+* IB_WCS_UNMATCHED_RESPONSE\r
+* A response MAD was received for which there was no matching send. The\r
+* send operation may have been canceled by the user or may have timed\r
+* out.\r
+*\r
+* IB_WCS_CANCELED\r
+* The completed work request was canceled by the user.\r
+*****/\r
+\r
+OSM_EXPORT const char* ib_wc_status_str[];\r
+\r
+/****f* IBA Base: Types/ib_get_wc_status_str\r
+* NAME\r
+* ib_get_wc_status_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified work completion status.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline const char* OSM_API\r
+ib_get_wc_status_str(\r
+ IN ib_wc_status_t wc_status )\r
+{\r
+ if( wc_status > IB_WCS_UNKNOWN )\r
+ wc_status = IB_WCS_UNKNOWN;\r
+ return( ib_wc_status_str[wc_status] );\r
+}\r
+/*\r
+* PARAMETERS\r
+* wc_status\r
+* [in] work completion status value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the work completion status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Access Layer/ib_wc_type_t\r
+* NAME\r
+* ib_wc_type_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_type_t\r
+{\r
+ IB_WC_SEND,\r
+ IB_WC_RDMA_WRITE,\r
+ IB_WC_RECV,\r
+ IB_WC_RDMA_READ,\r
+ IB_WC_MW_BIND,\r
+ IB_WC_FETCH_ADD,\r
+ IB_WC_COMPARE_SWAP,\r
+ IB_WC_RECV_RDMA_WRITE\r
+\r
+} ib_wc_type_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_recv_opt_t\r
+* NAME\r
+* ib_recv_opt_t\r
+*\r
+* DESCRIPTION\r
+* Indicates optional fields valid in a receive work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_recv_opt_t;\r
+#define IB_RECV_OPT_IMMEDIATE 0x00000001\r
+#define IB_RECV_OPT_FORWARD 0x00000002\r
+#define IB_RECV_OPT_GRH_VALID 0x00000004\r
+#define IB_RECV_OPT_VEND_MASK 0xFFFF0000\r
+/*\r
+* VALUES\r
+* IB_RECV_OPT_IMMEDIATE\r
+* Indicates that immediate data is valid for this work completion.\r
+*\r
+* IB_RECV_OPT_FORWARD\r
+* Indicates that the received trap should be forwarded to the SM.\r
+*\r
+* IB_RECV_OPT_GRH_VALID\r
+* Indicates presence of the global route header. When set, the first\r
+* 40 bytes received are the GRH.\r
+*\r
+* IB_RECV_OPT_VEND_MASK\r
+* This mask indicates bits reserved in the receive options that may be\r
+* used by the verbs provider to indicate vendor specific options. Bits\r
+* set in this area of the receive options are ignored by the Access Layer,\r
+* but may have specific meaning to the underlying VPD.\r
+*****/\r
+\r
+/****s* Access Layer/ib_wc_t\r
+* NAME\r
+* ib_wc_t\r
+*\r
+* DESCRIPTION\r
+* Work completion information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_wc\r
+{\r
+ struct _ib_wc *p_next;\r
+ uint64_t wr_id;\r
+ ib_wc_type_t wc_type;\r
+\r
+ uint32_t length;\r
+ ib_wc_status_t status;\r
+ uint64_t vendor_specific;\r
+\r
+ union _wc_recv\r
+ {\r
+ struct _wc_conn\r
+ {\r
+ ib_recv_opt_t recv_opt;\r
+ ib_net32_t immediate_data;\r
+\r
+ } conn;\r
+\r
+ struct _wc_ud\r
+ {\r
+ ib_recv_opt_t recv_opt;\r
+ ib_net32_t immediate_data;\r
+ ib_net32_t remote_qp;\r
+ uint16_t pkey_index;\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+\r
+ } ud;\r
+\r
+ struct _wc_rd\r
+ {\r
+ ib_net32_t remote_eecn;\r
+ ib_net32_t remote_qp;\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint32_t free_cnt;\r
+\r
+ } rd;\r
+\r
+ struct _wc_raw_ipv6\r
+ {\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+\r
+ } raw_ipv6;\r
+\r
+ struct _wc_raw_ether\r
+ {\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+ ib_net16_t ether_type;\r
+\r
+ } raw_ether;\r
+\r
+ } recv;\r
+\r
+} ib_wc_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work completions. This permits multiple\r
+* work completions to be retrieved from a completion queue through a\r
+* single function call. This value is set to NULL to mark the end of\r
+* the chain.\r
+*\r
+* wr_id\r
+* The 64-bit work request identifier that was specified when posting the\r
+* work request.\r
+*\r
+* wc_type\r
+* Indicates the type of work completion.\r
+*\r
+*\r
+* length\r
+* The total length of the data sent or received with the work request.\r
+*\r
+* status\r
+* The result of the work request.\r
+*\r
+* vendor_specific\r
+* HCA vendor specific information returned as part of the completion.\r
+*\r
+* recv.conn.recv_opt\r
+* Indicates optional fields valid as part of a work request that\r
+* completed on a connected (reliable or unreliable) queue pair.\r
+*\r
+* recv.conn.immediate_data\r
+* 32-bit field received as part of an inbound message on a connected\r
+* queue pair. This field is only valid if the recv_opt flag\r
+* IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+* recv.ud.recv_opt\r
+* Indicates optional fields valid as part of a work request that\r
+* completed on an unreliable datagram queue pair.\r
+*\r
+* recv.ud.immediate_data\r
+* 32-bit field received as part of an inbound message on a unreliable\r
+* datagram queue pair. This field is only valid if the recv_opt flag\r
+* IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+* recv.ud.remote_qp\r
+* Identifies the source queue pair of a received datagram.\r
+*\r
+* recv.ud.pkey_index\r
+* The pkey index for the source queue pair. This is valid only for\r
+* GSI type QP's.\r
+*\r
+* recv.ud.remote_lid\r
+* The source LID of the received datagram.\r
+*\r
+* recv.ud.remote_sl\r
+* The service level used by the source of the received datagram.\r
+*\r
+* recv.ud.path_bits\r
+* path bits...\r
+*\r
+* recv.rd.remote_eecn\r
+* The remote end-to-end context number that sent the received message.\r
+*\r
+* recv.rd.remote_qp\r
+* Identifies the source queue pair of a received message.\r
+*\r
+* recv.rd.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.rd.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.rd.free_cnt\r
+* The number of available entries in the completion queue. Reliable\r
+* datagrams may complete out of order, so this field may be used to\r
+* determine the number of additional completions that may occur.\r
+*\r
+* recv.raw_ipv6.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.raw_ipv6.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.raw_ipv6.path_bits\r
+* path bits...\r
+*\r
+* recv.raw_ether.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.raw_ether.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.raw_ether.path_bits\r
+* path bits...\r
+*\r
+* recv.raw_ether.ether_type\r
+* ether type...\r
+* NOTES\r
+* When the work request completes with error, the only values that the\r
+* consumer can depend on are the wr_id field, and the status of the\r
+* operation.\r
+*\r
+* If the consumer is using the same CQ for completions from more than\r
+* one type of QP (i.e Reliable Connected, Datagram etc), then the consumer\r
+* must have additional information to decide what fields of the union are\r
+* valid.\r
+* SEE ALSO\r
+* ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_mr_create_t\r
+* NAME\r
+* ib_mr_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_create\r
+{\r
+ void *vaddr;\r
+ uint64_t length;\r
+ ib_access_t access_ctrl;\r
+} ib_mr_create_t;\r
+/*\r
+* FIELDS\r
+* vaddr\r
+* Starting virtual address of the region being registered.\r
+*\r
+* length\r
+* Length of the buffer to register.\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_phys_create_t\r
+* NAME\r
+* ib_phys_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a physical memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_create\r
+{\r
+ uint64_t length;\r
+ uint32_t num_bufs;\r
+ uint64_t *buf_array;\r
+ uint32_t buf_offset;\r
+ uint32_t page_size;\r
+ ib_access_t access_ctrl;\r
+} ib_phys_create_t;\r
+/*\r
+* length\r
+* The length of the memory region in bytes.\r
+*\r
+* num_bufs\r
+* Number of buffers listed in the specified buffer array.\r
+*\r
+* buf_array\r
+* An array of physical buffers to be registered as a single memory\r
+* region.\r
+*\r
+* buf_offset\r
+* The offset into the first physical page of the specified memory\r
+* region to start the virtual address.\r
+*\r
+* page_size\r
+* The physical page size of the memory being registered.\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+/****s* Access Layer/ib_mr_attr_t\r
+* NAME\r
+* ib_mr_attr_t\r
+*\r
+* DESCRIPTION\r
+* Attributes of a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_attr\r
+{\r
+TO_LONG_PTR( struct _ib_pd* , h_pd) ; \r
+ void *local_lb;\r
+ void *local_ub;\r
+ void *remote_lb;\r
+ void *remote_ub;\r
+ ib_access_t access_ctrl;\r
+ uint32_t lkey;\r
+ uint32_t rkey;\r
+} ib_mr_attr_t;\r
+/*\r
+* DESCRIPTION\r
+* h_pd\r
+* Handle to the protection domain for this memory region.\r
+*\r
+* local_lb\r
+* The virtual address of the lower bound of protection for local\r
+* memory access.\r
+*\r
+* local_ub\r
+* The virtual address of the upper bound of protection for local\r
+* memory access.\r
+*\r
+* remote_lb\r
+* The virtual address of the lower bound of protection for remote\r
+* memory access.\r
+*\r
+* remote_ub\r
+* The virtual address of the upper bound of protection for remote\r
+* memory access.\r
+*\r
+* access_ctrl\r
+* Access rights for the specified memory region.\r
+*\r
+* lkey\r
+* The lkey associated with this memory region.\r
+*\r
+* rkey\r
+* The rkey associated with this memory region.\r
+*\r
+* NOTES\r
+* The remote_lb, remote_ub, and rkey are only valid if remote memory access\r
+* is enabled for this memory region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+/****d* Access Layer/ib_ca_mod_t\r
+* NAME\r
+* ib_ca_mod_t -- Modify port attributes and error counters\r
+*\r
+* DESCRIPTION\r
+* Specifies modifications to the port attributes of a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_ca_mod_t;\r
+#define IB_CA_MOD_IS_CM_SUPPORTED 0x00000001\r
+#define IB_CA_MOD_IS_SNMP_SUPPORTED 0x00000002\r
+#define IB_CA_MOD_IS_DEV_MGMT_SUPPORTED 0x00000004\r
+#define IB_CA_MOD_IS_VEND_SUPPORTED 0x00000008\r
+#define IB_CA_MOD_IS_SM 0x00000010\r
+#define IB_CA_MOD_IS_SM_DISABLED 0x00000020\r
+#define IB_CA_MOD_QKEY_CTR 0x00000040\r
+#define IB_CA_MOD_PKEY_CTR 0x00000080\r
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED 0x00000100\r
+#define IB_CA_MOD_IS_TRAP_SUPPORTED 0x00000200\r
+#define IB_CA_MOD_IS_APM_SUPPORTED 0x00000400\r
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED 0x00000800\r
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED 0x00001000\r
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED 0x00002000\r
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED 0x00004000\r
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED 0x00008000\r
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED 0x00010000\r
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED 0x00020000\r
+#define IB_CA_MOD_IS_REINIT_SUPORTED 0x00040000\r
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED 0x00080000\r
+#define IB_CA_MOD_SHUTDOWN_PORT 0x00100000\r
+#define IB_CA_MOD_INIT_TYPE_VALUE 0x00200000\r
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID 0x00400000\r
+/*\r
+* VALUES\r
+* IB_CA_MOD_IS_CM_SUPPORTED\r
+* Indicates if there is a communication manager accessible through\r
+* the port.\r
+*\r
+* IB_CA_MOD_IS_SNMP_SUPPORTED\r
+* Indicates if there is an SNMP agent accessible through the port.\r
+*\r
+* IB_CA_MOD_IS_DEV_MGMT_SUPPORTED\r
+* Indicates if there is a device management agent accessible\r
+* through the port.\r
+*\r
+* IB_CA_MOD_IS_VEND_SUPPORTED\r
+* Indicates if there is a vendor supported agent accessible\r
+* through the port.\r
+*\r
+* IB_CA_MOD_IS_SM\r
+* Indicates if there is a subnet manager accessible through\r
+* the port.\r
+*\r
+* IB_CA_MOD_IS_SM_DISABLED\r
+* Indicates if the port has been disabled for configuration by the\r
+* subnet manager.\r
+*\r
+* IB_CA_MOD_QKEY_CTR\r
+* Used to reset the qkey violation counter associated with the\r
+* port.\r
+*\r
+* IB_CA_MOD_PKEY_CTR\r
+* Used to reset the pkey violation counter associated with the\r
+* port.\r
+*\r
+* IB_CA_MOD_IS_NOTICE_SUPPORTED\r
+* Indicates that this CA supports ability to generate Notices for\r
+* Port State changes. (only applicable to switches)\r
+*\r
+* IB_CA_MOD_IS_TRAP_SUPPORTED\r
+* Indicates that this management port supports ability to generate\r
+* trap messages. (only applicable to switches)\r
+*\r
+* IB_CA_MOD_IS_APM_SUPPORTED\r
+* Indicates that this port is capable of performing Automatic\r
+* Path Migration.\r
+*\r
+* IB_CA_MOD_IS_SLMAP_SUPPORTED\r
+* Indicates this port supports SLMAP capability.\r
+*\r
+* IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED\r
+* Indicates that PKEY is supported in NVRAM\r
+*\r
+* IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED\r
+* Indicates that MKEY is supported in NVRAM\r
+*\r
+* IB_CA_MOD_IS_SYSGUID_SUPPORTED\r
+* Indicates System Image GUID support.\r
+*\r
+* IB_CA_MOD_IS_DR_NOTICE_SUPPORTED\r
+* Indicate support for generating Direct Routed Notices\r
+*\r
+* IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED\r
+* Indicates support for Boot Management\r
+*\r
+* IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED\r
+* Indicates capability to generate notices for changes to CAPMASK\r
+*\r
+* IB_CA_MOD_IS_REINIT_SUPORTED\r
+* Indicates type of node init supported. Refer to Chapter 14 for\r
+* Initialization actions.\r
+*\r
+* IB_CA_MOD_IS_LEDINFO_SUPPORTED\r
+* Indicates support for LED info.\r
+*\r
+* IB_CA_MOD_SHUTDOWN_PORT\r
+* Used to modify the port active indicator.\r
+*\r
+* IB_CA_MOD_INIT_TYPE_VALUE\r
+* Used to modify the init_type value for the port.\r
+*\r
+* IB_CA_MOD_SYSTEM_IMAGE_GUID\r
+* Used to modify the system image GUID for the port.\r
+*****/\r
+\r
+/****d* Access Layer/ib_mr_mod_t\r
+* NAME\r
+* ib_mr_mod_t\r
+*\r
+* DESCRIPTION\r
+* Mask used to specify which attributes of a registered memory region are\r
+* being modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_mr_mod_t;\r
+#define IB_MR_MOD_ADDR 0x00000001\r
+#define IB_MR_MOD_PD 0x00000002\r
+#define IB_MR_MOD_ACCESS 0x00000004\r
+/*\r
+* PARAMETERS\r
+* IB_MEM_MOD_ADDR\r
+* The address of the memory region is being modified.\r
+*\r
+* IB_MEM_MOD_PD\r
+* The protection domain associated with the memory region is being\r
+* modified.\r
+*\r
+* IB_MEM_MOD_ACCESS\r
+* The access rights the memory region are being modified.\r
+*****/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT\r
+* NAME\r
+* IB_SMINFO_STATE_INIT\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_INIT 4\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_HANDOVER\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_HANDOVER (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_DISABLE\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISABLE (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_STANDBY\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_STANDBY (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_DISCOVER\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISCOVER (CL_NTOH32(0x000005))\r
+/**********/\r
+\r
+/****s* Access Layer/ib_ci_op_t\r
+* NAME\r
+* ib_ci_op_t\r
+*\r
+* DESCRIPTION\r
+* A structure used for vendor specific CA interface communication.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ci_op\r
+{\r
+ IN uint32_t command;\r
+ IN OUT void* p_buf OPTIONAL;\r
+ IN uint32_t buf_size;\r
+ IN OUT uint32_t num_bytes_ret;\r
+ IN OUT int32_t status;\r
+\r
+} ib_ci_op_t;\r
+/*\r
+* FIELDS\r
+* command\r
+* A command code that is understood by the verbs provider.\r
+*\r
+* p_buf\r
+* A reference to a buffer containing vendor specific data. The verbs\r
+* provider must not access pointers in the p_buf between user-mode and\r
+* kernel-mode. Any pointers embedded in the p_buf are invalidated by\r
+* the user-mode/kernel-mode transition.\r
+*\r
+* buf_size\r
+* The size of the buffer in bytes.\r
+*\r
+* num_bytes_ret\r
+* The size in bytes of the vendor specific data returned in the buffer.\r
+* This field is set by the verbs provider. The verbs provider should\r
+* verify that the buffer size is sufficient to hold the data being\r
+* returned.\r
+*\r
+* status\r
+* The completion status from the verbs provider. This field should be\r
+* initialize to indicate an error to allow detection and cleanup in\r
+* case a communication error occurs between user-mode and kernel-mode.\r
+*\r
+* NOTES\r
+* This structure is provided to allow the exchange of vendor specific\r
+* data between the originator and the verbs provider. Users of this\r
+* structure are expected to know the format of data in the p_buf based\r
+* on the structure command field or the usage context.\r
+*****/\r
+\r
+END_C_DECLS\r
+\r
+#endif /* ndef WIN */\r
+#if defined( __WIN__ )\r
+ #include <iba/ib_types_extended.h>\r
+#endif\r
+\r
+#endif /* __IB_TYPES_H__ */\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright (c) 2004,2005 Voltaire, Inc. All rights reserved. \r
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. \r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ * \r
+ * This software is available to you under the OpenIB.org BSD license \r
+ * below: \r
+ * \r
+ * Redistribution and use in source and binary forms, with or \r
+ * without modification, are permitted provided that the following \r
+ * conditions are met: \r
+ * \r
+ * - Redistributions of source code must retain the above \r
+ * copyright notice, this list of conditions and the following \r
+ * disclaimer. \r
+ * \r
+ * - Redistributions in binary form must reproduce the above \r
+ * copyright notice, this list of conditions and the following \r
+ * disclaimer in the documentation and/or other materials \r
+ * provided with the distribution. \r
+ * \r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, \r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF \r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS \r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN \r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN \r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE \r
+ * SOFTWARE. \r
+ * \r
+ * $Id: ib_types_extended.h 2165 2009-05-12 13:05:24Z leonidk $\r
+ */\r
+\r
+\r
+#if !defined(__IB_TYPES_EXTENDED_H__)\r
+#define __IB_TYPES_EXTENDED_H__\r
+\r
+\r
+#if defined( WIN32 )\r
+ #if defined( EXPORT_AL_SYMBOLS )\r
+ #define AL_EXPORT __declspec(dllexport)\r
+ #else\r
+ #define AL_EXPORT __declspec(dllimport)\r
+ #endif\r
+\r
+ #ifdef CL_KERNEL\r
+ #define AL_API\r
+ #define AL_INLINE static inline\r
+ #else\r
+ #define AL_API __stdcall\r
+ #define AL_INLINE static inline\r
+ #endif /* CL_KERNEL */\r
+#else\r
+ #define AL_EXPORT extern\r
+ #define AL_INLINE static inline\r
+ #define AL_API\r
+ #define __ptr64\r
+#endif\r
+\r
+/*\r
+ * Defines the size of user available data in communication management MADs\r
+ */\r
+#define IB_REQ_PDATA_SIZE 92\r
+#define IB_MRA_PDATA_SIZE 222\r
+#define IB_REJ_PDATA_SIZE 148\r
+#define IB_REP_PDATA_SIZE 196\r
+#define IB_RTU_PDATA_SIZE 224\r
+#define IB_LAP_PDATA_SIZE 168\r
+#define IB_APR_PDATA_SIZE 148\r
+#define IB_DREQ_PDATA_SIZE 220\r
+#define IB_DREP_PDATA_SIZE 224\r
+#define IB_SIDR_REQ_PDATA_SIZE 216\r
+#define IB_SIDR_REP_PDATA_SIZE 136\r
+\r
+/* following v1 ver1.2 p901 */\r
+#define IB_PATH_RECORD_RATE_5_GBS 5\r
+#define IB_PATH_RECORD_RATE_20_GBS 6\r
+#define IB_PATH_RECORD_RATE_40_GBS 7\r
+#define IB_PATH_RECORD_RATE_60_GBS 8\r
+#define IB_PATH_RECORD_RATE_80_GBS 9\r
+#define IB_PATH_RECORD_RATE_120_GBS 10\r
+\r
+\r
+\r
+typedef struct _ib_srq* ib_srq_handle_t ; \r
+\r
+/*\r
+ * The following definitions are shared between the Access Layer and VPD\r
+ */\r
+\r
+\r
+\r
+/****d* Access Layer/ib_api_status_t\r
+* NAME\r
+* ib_api_status_t\r
+*\r
+* DESCRIPTION\r
+* Function return codes indicating the success or failure of an API call.\r
+* Note that success is indicated by the return value IB_SUCCESS, which\r
+* is always zero.\r
+*\r
+* NOTES\r
+* IB_VERBS_PROCESSING_DONE is used by UVP library to terminate a verbs call\r
+* in the pre-ioctl step itself.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_api_status_t\r
+{\r
+ IB_SUCCESS,\r
+ IB_INSUFFICIENT_RESOURCES,\r
+ IB_INSUFFICIENT_MEMORY,\r
+ IB_INVALID_PARAMETER,\r
+ IB_INVALID_SETTING,\r
+ IB_NOT_FOUND,\r
+ IB_TIMEOUT,\r
+ IB_CANCELED,\r
+ IB_INTERRUPTED,\r
+ IB_INVALID_PERMISSION,\r
+ IB_UNSUPPORTED,\r
+ IB_OVERFLOW,\r
+ IB_MAX_MCAST_QPS_REACHED,\r
+ IB_INVALID_QP_STATE,\r
+ IB_INVALID_APM_STATE,\r
+ IB_INVALID_PORT_STATE,\r
+ IB_INVALID_STATE,\r
+ IB_RESOURCE_BUSY,\r
+ IB_INVALID_PKEY,\r
+ IB_INVALID_LKEY,\r
+ IB_INVALID_RKEY,\r
+ IB_INVALID_MAX_WRS,\r
+ IB_INVALID_MAX_SGE,\r
+ IB_INVALID_CQ_SIZE,\r
+ IB_INVALID_SRQ_SIZE,\r
+ IB_INVALID_SERVICE_TYPE,\r
+ IB_INVALID_GID,\r
+ IB_INVALID_LID,\r
+ IB_INVALID_GUID,\r
+ IB_INVALID_GUID_MASK,\r
+ IB_INVALID_CA_HANDLE,\r
+ IB_INVALID_AV_HANDLE,\r
+ IB_INVALID_CQ_HANDLE,\r
+ IB_INVALID_QP_HANDLE,\r
+ IB_INVALID_SRQ_HANDLE,\r
+ IB_INVALID_PD_HANDLE,\r
+ IB_INVALID_MR_HANDLE,\r
+ IB_INVALID_FMR_HANDLE,\r
+ IB_INVALID_MW_HANDLE,\r
+ IB_INVALID_MCAST_HANDLE,\r
+ IB_INVALID_CALLBACK,\r
+ IB_INVALID_AL_HANDLE, /* InfiniBand Access Layer */\r
+ IB_INVALID_HANDLE, /* InfiniBand Access Layer */\r
+ IB_ERROR, /* InfiniBand Access Layer */\r
+ IB_REMOTE_ERROR, /* Infiniband Access Layer */\r
+ IB_VERBS_PROCESSING_DONE, /* See Notes above */\r
+ IB_INVALID_WR_TYPE,\r
+ IB_QP_IN_TIMEWAIT,\r
+ IB_EE_IN_TIMEWAIT,\r
+ IB_INVALID_PORT,\r
+ IB_NOT_DONE,\r
+ IB_INVALID_INDEX,\r
+ IB_NO_MATCH,\r
+ IB_PENDING,\r
+ IB_UNKNOWN_ERROR /* ALWAYS LAST ENUM VALUE! */\r
+\r
+} ib_api_status_t;\r
+/*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_err_str\r
+* NAME\r
+* ib_get_err_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified status value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_err_str(\r
+ IN ib_api_status_t status );\r
+/*\r
+* PARAMETERS\r
+* status\r
+* [in] status value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****d* Verbs/ib_async_event_t\r
+* NAME\r
+* ib_async_event_t -- Async event types\r
+*\r
+* DESCRIPTION\r
+* This type indicates the reason the async callback was called.\r
+* The context in the ib_event_rec_t indicates the resource context\r
+* that associated with the callback. For example, for IB_AE_CQ_ERROR\r
+* the context provided during the ib_create_cq is returned in the event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_async_event_t\r
+{\r
+ IB_AE_SQ_ERROR = 1,\r
+ IB_AE_SQ_DRAINED,\r
+ IB_AE_RQ_ERROR,\r
+ IB_AE_CQ_ERROR,\r
+ IB_AE_QP_FATAL,\r
+ IB_AE_QP_COMM,\r
+ IB_AE_QP_APM,\r
+ IB_AE_LOCAL_FATAL,\r
+ IB_AE_PKEY_TRAP,\r
+ IB_AE_QKEY_TRAP,\r
+ IB_AE_MKEY_TRAP,\r
+ IB_AE_PORT_TRAP,\r
+ IB_AE_SYSIMG_GUID_TRAP,\r
+ IB_AE_BUF_OVERRUN,\r
+ IB_AE_LINK_INTEGRITY,\r
+ IB_AE_FLOW_CTRL_ERROR,\r
+ IB_AE_BKEY_TRAP,\r
+ IB_AE_QP_APM_ERROR,\r
+ IB_AE_WQ_REQ_ERROR,\r
+ IB_AE_WQ_ACCESS_ERROR,\r
+ IB_AE_PORT_ACTIVE,\r
+ IB_AE_PORT_DOWN,\r
+ IB_AE_CLIENT_REREGISTER,\r
+ IB_AE_SRQ_LIMIT_REACHED,\r
+ IB_AE_SRQ_CATAS_ERROR,\r
+ IB_AE_SRQ_QP_LAST_WQE_REACHED,\r
+ IB_AE_RESET_DRIVER,\r
+ IB_AE_RESET_CLIENT,\r
+ IB_AE_RESET_END,\r
+ IB_AE_RESET_FAILED,\r
+ IB_AE_LID_CHANGE,\r
+ IB_AE_PKEY_CHANGE,\r
+ IB_AE_SM_CHANGE,\r
+ IB_AE_GID_CHANGE,\r
+ IB_AE_UNKNOWN /* ALWAYS LAST ENUM VALUE */\r
+\r
+} ib_async_event_t;\r
+/*\r
+* VALUES\r
+* IB_AE_SQ_ERROR\r
+* An error occurred when accessing the send queue of the QP.\r
+* This event is optional.\r
+*\r
+* IB_AE_SQ_DRAINED\r
+* The send queue of the specified QP has completed the outstanding\r
+* messages in progress when the state change was requested and, if\r
+* applicable, has received all acknowledgements for those messages.\r
+*\r
+* IB_AE_RQ_ERROR\r
+* An error occurred when accessing the receive queue of the QP.\r
+* This event is optional.\r
+*\r
+* IB_AE_CQ_ERROR\r
+* An error occurred when writing an entry to the CQ.\r
+*\r
+* IB_AE_QP_FATAL\r
+* A catastrophic error occurred while accessing or processing the\r
+* work queue that prevents reporting of completions.\r
+*\r
+* IB_AE_QP_COMM\r
+* The first packet has arrived for the receive work queue where the\r
+* QP is still in the RTR state.\r
+*\r
+* IB_AE_QP_APM\r
+* If alternate path migration is supported, this event indicates that\r
+* the QP connection has migrated to the alternate path.\r
+*\r
+* IB_AE_LOCAL_FATAL\r
+* A catastrophic HCA error occurred which cannot be attributed to any\r
+* resource; behavior is indeterminate.\r
+*\r
+* IB_AE_PKEY_TRAP\r
+* A PKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_QKEY_TRAP\r
+* A QKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_MKEY_TRAP\r
+* An MKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_PORT_TRAP\r
+* A port capability change was detected. This event is optional.\r
+*\r
+* IB_AE_SYSIMG_GUID_TRAP\r
+* If the system image GUID is supported, this event indicates that the\r
+* system image GUID of this HCA has been changed. This event is\r
+* optional.\r
+*\r
+* IB_AE_BUF_OVERRUN\r
+* The number of consecutive flow control update periods with at least\r
+* one overrun error in each period has exceeded the threshold specified\r
+* in the port info attributes. This event is optional.\r
+*\r
+* IB_AE_LINK_INTEGRITY\r
+* The detection of excessively frequent local physical errors has\r
+* exceeded the threshold specified in the port info attributes. This\r
+* event is optional.\r
+*\r
+* IB_AE_FLOW_CTRL_ERROR\r
+* An HCA watchdog timer monitoring the arrival of flow control updates\r
+* has expired without receiving an update. This event is optional.\r
+*\r
+* IB_AE_BKEY_TRAP\r
+* An BKEY violation was detected. This event is optional.\r
+*\r
+* IB_AE_QP_APM_ERROR\r
+* If alternate path migration is supported, this event indicates that\r
+* an incoming path migration request to this QP was not accepted.\r
+*\r
+* IB_AE_WQ_REQ_ERROR\r
+* An OpCode violation was detected at the responder.\r
+*\r
+* IB_AE_WQ_ACCESS_ERROR\r
+* An access violation was detected at the responder.\r
+*\r
+* IB_AE_PORT_ACTIVE\r
+* If the port active event is supported, this event is generated\r
+* when the link becomes active: IB_LINK_ACTIVE.\r
+*\r
+* IB_AE_PORT_DOWN\r
+* The link is declared unavailable: IB_LINK_INIT, IB_LINK_ARMED,\r
+* IB_LINK_DOWN.\r
+*\r
+* IB_AE_CLIENT_REREGISTER\r
+* The SM idicate to client to reregister its SA records.\r
+*\r
+* IB_AE_SRQ_LIMIT_REACHED\r
+* Reached SRQ low watermark\r
+*\r
+* IB_AE_SRQ_CATAS_ERROR\r
+* An error occurred while processing or accessing the SRQ that prevents\r
+* dequeuing a WQE from the SRQ and reporting of receive completions.\r
+*\r
+* IB_AE_SRQ_QP_LAST_WQE_REACHED\r
+* An event, issued for a QP, associated with a shared receive queue, when\r
+* a CQE is generated for the last WQE, or\r
+* the QP gets in the Error State and there are no more WQEs on the RQ.\r
+*\r
+* IB_AE_UNKNOWN\r
+* An unknown error occurred which cannot be attributed to any\r
+* resource; behavior is indeterminate.\r
+*\r
+*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_async_event_str\r
+* NAME\r
+* ib_get_async_event_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified asynchronous event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_async_event_str(\r
+ IN ib_async_event_t event );\r
+/*\r
+* PARAMETERS\r
+* event\r
+* [in] event value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the asynchronous event description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****s* Verbs/ib_event_rec_t\r
+* NAME\r
+* ib_event_rec_t -- Async event notification record\r
+*\r
+* DESCRIPTION\r
+* When an async event callback is made, this structure is passed to indicate\r
+* the type of event, the source of event that caused it, and the context\r
+* associated with this event.\r
+*\r
+* context -- Context of the resource that caused the event.\r
+* -- ca_context if this is a port/adapter event.\r
+* -- qp_context if the source is a QP event\r
+* -- cq_context if the source is a CQ event.\r
+* -- ee_context if the source is an EE event.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_event_rec\r
+{\r
+ TO_LONG_PTR(void*, context);\r
+ ib_async_event_t type;\r
+\r
+ /* HCA vendor specific event information. */\r
+ uint64_t vendor_specific;\r
+ uint8_t port_number;\r
+\r
+} ib_event_rec_t;\r
+/*******/\r
+\r
+\r
+/****d* Access Layer/ib_atomic_t\r
+* NAME\r
+* ib_atomic_t\r
+*\r
+* DESCRIPTION\r
+* Indicates atomicity levels supported by an adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_atomic_t\r
+{\r
+ IB_ATOMIC_NONE,\r
+ IB_ATOMIC_LOCAL,\r
+ IB_ATOMIC_GLOBAL\r
+\r
+} ib_atomic_t;\r
+/*\r
+* VALUES\r
+* IB_ATOMIC_NONE\r
+* Atomic operations not supported.\r
+*\r
+* IB_ATOMIC_LOCAL\r
+* Atomic operations guaranteed between QPs of a single CA.\r
+*\r
+* IB_ATOMIC_GLOBAL\r
+* Atomic operations are guaranteed between CA and any other entity\r
+* in the system.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_cap_t\r
+* NAME\r
+* ib_port_cap_t\r
+*\r
+* DESCRIPTION\r
+* Indicates which management agents are currently available on the specified\r
+* port.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_cap\r
+{\r
+ boolean_t cm;\r
+ boolean_t snmp;\r
+ boolean_t dev_mgmt;\r
+ boolean_t vend;\r
+ boolean_t sm;\r
+ boolean_t sm_disable;\r
+ boolean_t qkey_ctr;\r
+ boolean_t pkey_ctr;\r
+ boolean_t notice;\r
+ boolean_t trap;\r
+ boolean_t apm;\r
+ boolean_t slmap;\r
+ boolean_t pkey_nvram;\r
+ boolean_t mkey_nvram;\r
+ boolean_t sysguid;\r
+ boolean_t dr_notice;\r
+ boolean_t boot_mgmt;\r
+ boolean_t capm_notice;\r
+ boolean_t reinit;\r
+ boolean_t ledinfo;\r
+ boolean_t port_active;\r
+ boolean_t ipd;\r
+ boolean_t pkey_switch_ext_port;\r
+ boolean_t bm;\r
+ boolean_t link_rtl;\r
+ boolean_t client_reregister; \r
+\r
+} ib_port_cap_t;\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_init_type_t\r
+* NAME\r
+* ib_init_type_t\r
+*\r
+* DESCRIPTION\r
+* If supported by the HCA, the type of initialization requested by\r
+* this port before SM moves it to the active or armed state. If the\r
+* SM implements reinitialization, it shall set these bits to indicate\r
+* the type of initialization performed prior to activating the port.\r
+* Otherwise, these bits shall be set to 0.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint8_t ib_init_type_t;\r
+#define IB_INIT_TYPE_NO_LOAD 0x01\r
+#define IB_INIT_TYPE_PRESERVE_CONTENT 0x02\r
+#define IB_INIT_TYPE_PRESERVE_PRESENCE 0x04\r
+#define IB_INIT_TYPE_DO_NOT_RESUSCITATE 0x08\r
+/*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_attr_mod_t\r
+* NAME\r
+* ib_port_attr_mod_t\r
+*\r
+* DESCRIPTION\r
+* Port attributes that may be modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr_mod\r
+{\r
+ ib_port_cap_t cap;\r
+ uint16_t pkey_ctr;\r
+ uint16_t qkey_ctr;\r
+\r
+ ib_init_type_t init_type;\r
+ ib_net64_t system_image_guid;\r
+\r
+} ib_port_attr_mod_t;\r
+/*\r
+* SEE ALSO\r
+* ib_port_cap_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_port_attr_t\r
+* NAME\r
+* ib_port_attr_t\r
+*\r
+* DESCRIPTION\r
+* Information about a port on a given channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_port_attr\r
+{\r
+ ib_net64_t port_guid;\r
+ uint8_t port_num;\r
+ uint8_t mtu;\r
+ uint64_t max_msg_size;\r
+ ib_net16_t lid;\r
+ uint8_t lmc;\r
+\r
+ /*\r
+ * LinkWidthSupported as defined in PortInfo. Required to calculate\r
+ * inter-packet delay (a.k.a. static rate).\r
+ */\r
+ uint8_t link_width_supported;\r
+\r
+ uint16_t max_vls;\r
+\r
+ ib_net16_t sm_lid;\r
+ uint8_t sm_sl;\r
+ uint8_t link_state;\r
+\r
+ ib_init_type_t init_type_reply; /* Optional */\r
+\r
+ /*\r
+ * subnet_timeout:\r
+ * The maximum expected subnet propagation delay to reach any port on\r
+ * the subnet. This value also determines the rate at which traps can\r
+ * be generated from this node.\r
+ *\r
+ * timeout = 4.096 microseconds * 2^subnet_timeout\r
+ */\r
+ uint8_t subnet_timeout;\r
+ uint8_t active_speed;\r
+ uint8_t phys_state;\r
+\r
+ ib_port_cap_t cap;\r
+ uint16_t pkey_ctr;\r
+ uint16_t qkey_ctr;\r
+\r
+ uint16_t num_gids;\r
+ uint16_t num_pkeys;\r
+ /*\r
+ * Pointers at the end of the structure to allow doing a simple\r
+ * memory comparison of contents up to the first pointer.\r
+ */\r
+ TO_LONG_PTR(ib_gid_t*, p_gid_table);\r
+ TO_LONG_PTR(ib_net16_t*,p_pkey_table);\r
+\r
+} ib_port_attr_t;\r
+/*\r
+* SEE ALSO\r
+* uint8_t, ib_port_cap_t, ib_link_states_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_ca_attr_t\r
+* NAME\r
+* ib_ca_attr_t\r
+*\r
+* DESCRIPTION\r
+* Information about a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ca_attr\r
+{\r
+ ib_net64_t ca_guid;\r
+\r
+ uint32_t vend_id;\r
+ uint16_t dev_id;\r
+ uint16_t revision;\r
+ uint64_t fw_ver;\r
+\r
+ /*\r
+ * Total size of the ca attributes in bytes\r
+ */\r
+ uint32_t size;\r
+ uint32_t max_qps;\r
+ uint32_t max_wrs;\r
+\r
+ uint32_t max_sges;\r
+ uint32_t max_rd_sges;\r
+\r
+ uint32_t max_cqs;\r
+ uint32_t max_cqes;\r
+\r
+ uint32_t max_pds;\r
+\r
+ uint32_t init_regions;\r
+ uint64_t init_region_size;\r
+\r
+ uint32_t init_windows;\r
+ uint64_t max_addr_handles;\r
+\r
+ uint32_t max_partitions;\r
+\r
+ ib_atomic_t atomicity;\r
+\r
+ uint8_t max_qp_resp_res;\r
+ uint8_t max_resp_res;\r
+\r
+ uint8_t max_qp_init_depth;\r
+\r
+ uint32_t max_ipv6_qps;\r
+ uint32_t max_ether_qps;\r
+\r
+ uint32_t max_mcast_grps;\r
+ uint32_t max_mcast_qps;\r
+ uint32_t max_qps_per_mcast_grp;\r
+ uint32_t max_fmr;\r
+ uint32_t max_map_per_fmr;\r
+ uint32_t max_srq;\r
+ uint32_t max_srq_wrs;\r
+ uint32_t max_srq_sges;\r
+\r
+ /*\r
+ * local_ack_delay:\r
+ * Specifies the maximum time interval between the local CA receiving\r
+ * a message and the transmission of the associated ACK or NAK.\r
+ *\r
+ * timeout = 4.096 microseconds * 2^local_ack_delay\r
+ */\r
+ uint8_t local_ack_delay;\r
+\r
+ boolean_t bad_pkey_ctr_support;\r
+ boolean_t bad_qkey_ctr_support;\r
+ boolean_t raw_mcast_support;\r
+ boolean_t apm_support;\r
+ boolean_t av_port_check;\r
+ boolean_t change_primary_port;\r
+ boolean_t modify_wr_depth;\r
+ boolean_t modify_srq_depth;\r
+ boolean_t current_qp_state_support;\r
+ boolean_t shutdown_port_capability;\r
+ boolean_t init_type_support;\r
+ boolean_t port_active_event_support;\r
+ boolean_t system_image_guid_support;\r
+ boolean_t hw_agents;\r
+ boolean_t ipoib_csum;\r
+ \r
+ ib_net64_t system_image_guid;\r
+\r
+ uint32_t num_page_sizes;\r
+ uint8_t num_ports;\r
+\r
+ TO_LONG_PTR(uint32_t*, p_page_size);\r
+ TO_LONG_PTR(ib_port_attr_t*, p_port_attr);\r
+\r
+} ib_ca_attr_t;\r
+/*\r
+* FIELDS\r
+* ca_guid\r
+* GUID for this adapter.\r
+*\r
+* vend_id\r
+* IEEE vendor ID for this adapter\r
+*\r
+* dev_id\r
+* Device ID of this adapter. (typically from PCI device ID)\r
+*\r
+* revision\r
+* Revision ID of this adapter\r
+*\r
+* fw_ver\r
+* Device Firmware version.\r
+*\r
+* size\r
+* Total size in bytes for the HCA attributes. This size includes total\r
+* size required for all the variable members of the structure. If a\r
+* vendor requires to pass vendor specific fields beyond this structure,\r
+* the HCA vendor can choose to report a larger size. If a vendor is\r
+* reporting extended vendor specific features, they should also provide\r
+* appropriate access functions to aid with the required interpretation.\r
+*\r
+* max_qps\r
+* Maximum number of QP's supported by this HCA.\r
+*\r
+* max_wrs\r
+* Maximum number of work requests supported by this HCA.\r
+*\r
+* max_sges\r
+* Maximum number of scatter gather elements supported per work request.\r
+*\r
+* max_rd_sges\r
+* Maximum number of scatter gather elements supported for READ work\r
+* requests for a Reliable Datagram QP. This value must be zero if RD\r
+* service is not supported.\r
+*\r
+* max_cqs\r
+* Maximum number of Completion Queues supported.\r
+*\r
+* max_cqes\r
+* Maximum number of CQ elements supported per CQ.\r
+*\r
+* max_pds\r
+* Maximum number of protection domains supported.\r
+*\r
+* init_regions\r
+* Initial number of memory regions supported. These are only informative\r
+* values. HCA vendors can extended and grow these limits on demand.\r
+*\r
+* init_region_size\r
+* Initial limit on the size of the registered memory region.\r
+*\r
+* init_windows\r
+* Initial number of window entries supported.\r
+*\r
+* max_addr_handles\r
+* Maximum number of address handles supported.\r
+*\r
+* max_partitions\r
+* Maximum number of partitions supported.\r
+*\r
+* atomicity\r
+* Indicates level of atomic operations supported by this HCA.\r
+*\r
+* max_qp_resp_res\r
+* Maximum limit on number of responder resources for incomming RDMA\r
+* operations on QPs.\r
+*\r
+* max_fmr\r
+* Maximum number of Fast Memory Regions supported.\r
+*\r
+* max_map_per_fmr\r
+* Maximum number of mappings, supported by a Fast Memory Region.\r
+*\r
+* max_srq\r
+* Maximum number of Shared Receive Queues supported.\r
+*\r
+* max_srq_wrs\r
+* Maximum number of work requests supported by this SRQ.\r
+*\r
+* max_srq_sges\r
+* Maximum number of scatter gather elements supported per work request on SRQ.\r
+*\r
+* max_resp_res\r
+* Maximum number of responder resources per HCA, with this HCA used as\r
+* the target.\r
+*\r
+* max_qp_init_depth\r
+* Maximimum initiator depth per QP for initiating RDMA reads and\r
+* atomic operations.\r
+*\r
+* max_ipv6_qps\r
+* max_ether_qps\r
+* Maximum number of IPV6 and raw ether QP's supported by this HCA.\r
+*\r
+* max_mcast_grps\r
+* Maximum number of multicast groups supported.\r
+*\r
+* max_mcast_qps\r
+* Maximum number of QP's that can support multicast operations.\r
+*\r
+* max_qps_per_mcast_grp\r
+* Maximum number of multicast QP's per multicast group.\r
+*\r
+* local_ack_delay\r
+* Specifies the maximum time interval between the local CA receiving\r
+* a message and the transmission of the associated ACK or NAK.\r
+* timeout = 4.096 microseconds * 2^local_ack_delay\r
+*\r
+* bad_pkey_ctr_support\r
+* bad_qkey_ctr_support\r
+* Indicates support for the bad pkey and qkey counters.\r
+*\r
+* raw_mcast_support\r
+* Indicates support for raw packet multicast.\r
+*\r
+* apm_support\r
+* Indicates support for Automatic Path Migration.\r
+*\r
+* av_port_check\r
+* Indicates ability to check port number in address handles.\r
+*\r
+* change_primary_port\r
+* Indicates ability to change primary port for a QP during a\r
+* SQD->RTS transition.\r
+*\r
+* modify_wr_depth\r
+* Indicates ability to modify QP depth during a modify QP operation.\r
+* Check the verb specification for permitted states.\r
+*\r
+* modify_srq_depth\r
+* Indicates ability to modify SRQ depth during a modify SRQ operation.\r
+* Check the verb specification for permitted states.\r
+*\r
+* current_qp_state_support\r
+* Indicates ability of the HCA to support the current QP state modifier\r
+* during a modify QP operation.\r
+*\r
+* shutdown_port_capability\r
+* Shutdown port capability support indicator.\r
+*\r
+* init_type_support\r
+* Indicates init_type_reply and ability to set init_type is supported.\r
+*\r
+* port_active_event_support\r
+* Port active event support indicator.\r
+*\r
+* system_image_guid_support\r
+* System image GUID support indicator.\r
+*\r
+* hw_agents\r
+* Indicates SMA is implemented in HW.\r
+*\r
+* system_image_guid\r
+* Optional system image GUID. This field is valid only if the\r
+* system_image_guid_support flag is set.\r
+*\r
+* num_page_sizes\r
+* Indicates support for different page sizes supported by the HCA.\r
+* The variable size array can be obtained from p_page_size.\r
+*\r
+* num_ports\r
+* Number of physical ports supported on this HCA.\r
+*\r
+* p_page_size\r
+* Array holding different page size supported.\r
+*\r
+* p_port_attr\r
+* Array holding port attributes.\r
+*\r
+* NOTES\r
+* This structure contains the attributes of a channel adapter. Users must\r
+* call ib_copy_ca_attr to copy the contents of this structure to a new\r
+* memory region.\r
+*\r
+* SEE ALSO\r
+* ib_port_attr_t, ib_atomic_t, ib_copy_ca_attr\r
+*****/\r
+\r
+/****f* Access layer/ib_copy_ca_attr\r
+* NAME\r
+* ib_copy_ca_attr\r
+*\r
+* DESCRIPTION\r
+* Copies CA attributes.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT ib_ca_attr_t* AL_API\r
+ib_copy_ca_attr(\r
+ IN ib_ca_attr_t* const p_dest,\r
+ IN const ib_ca_attr_t* const p_src );\r
+/*\r
+* PARAMETERS\r
+* p_dest\r
+* Pointer to the buffer that is the destination of the copy.\r
+*\r
+* p_src\r
+* Pointer to the CA attributes to copy.\r
+*\r
+* RETURN VALUE\r
+* Pointer to the copied CA attributes.\r
+*\r
+* NOTES\r
+* The buffer pointed to by the p_dest parameter must be at least the size\r
+* specified in the size field of the buffer pointed to by p_src.\r
+*\r
+* SEE ALSO\r
+* ib_ca_attr_t, ib_dup_ca_attr, ib_free_ca_attr\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_pd_type_t\r
+* NAME\r
+* ib_pd_type_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of protection domain being allocated.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_pd_type\r
+{\r
+ IB_PDT_NORMAL,\r
+ IB_PDT_ALIAS,\r
+ IB_PDT_SQP,\r
+ IB_PDT_UD\r
+\r
+} ib_pd_type_t;\r
+/*\r
+* VALUES\r
+* IB_PDT_NORMAL\r
+* Protection domain for all non-aliased QPs.\r
+*\r
+* IB_PDT_ALIAS\r
+* Protection domain for IB_QPT_QP0_ALIAS and IB_QPT_QP1_ALIAS QPs.\r
+*\r
+* IB_PDT_SQP\r
+* Protection domain for special queue pair usage.\r
+*\r
+* IB_PDT_UD\r
+* Protection domain for UD queue pair usage.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_av_attr_t\r
+* NAME\r
+* ib_av_attr_t\r
+*\r
+* DESCRIPTION\r
+* IBA address vector.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_av_attr\r
+{\r
+ uint8_t port_num;\r
+\r
+ uint8_t sl;\r
+ ib_net16_t dlid;\r
+\r
+ boolean_t grh_valid;\r
+ ib_grh_t grh;\r
+ uint8_t static_rate;\r
+ uint8_t path_bits;\r
+\r
+ struct _av_conn\r
+ {\r
+ uint8_t path_mtu;\r
+ uint8_t local_ack_timeout;\r
+ uint8_t seq_err_retry_cnt;\r
+ uint8_t rnr_retry_cnt;\r
+\r
+ } conn;\r
+\r
+} ib_av_attr_t;\r
+/*\r
+* SEE ALSO\r
+* ib_gid_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_type_t\r
+* NAME\r
+* ib_qp_type_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of queue pair being created.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_qp_type\r
+{\r
+ IB_QPT_RELIABLE_CONN = 0, /* Matches CM REQ transport type */\r
+ IB_QPT_UNRELIABLE_CONN = 1, /* Matches CM REQ transport type */\r
+ IB_QPT_RELIABLE_DGRM = 2, /* Matches CM REQ transport type */\r
+ IB_QPT_UNRELIABLE_DGRM,\r
+ IB_QPT_QP0,\r
+ IB_QPT_QP1,\r
+ IB_QPT_RAW_IPV6,\r
+ IB_QPT_RAW_ETHER,\r
+ IB_QPT_MAD, /* InfiniBand Access Layer */\r
+ IB_QPT_QP0_ALIAS, /* InfiniBand Access Layer */\r
+ IB_QPT_QP1_ALIAS, /* InfiniBand Access Layer */\r
+ IB_QPT_UNKNOWN\r
+} ib_qp_type_t;\r
+/*\r
+* VALUES\r
+* IB_QPT_RELIABLE_CONN\r
+* Reliable, connected queue pair.\r
+*\r
+* IB_QPT_UNRELIABLE_CONN\r
+* Unreliable, connected queue pair.\r
+*\r
+* IB_QPT_RELIABLE_DGRM\r
+* Reliable, datagram queue pair.\r
+*\r
+* IB_QPT_UNRELIABLE_DGRM\r
+* Unreliable, datagram queue pair.\r
+*\r
+* IB_QPT_QP0\r
+* Queue pair 0.\r
+*\r
+* IB_QPT_QP1\r
+* Queue pair 1.\r
+*\r
+* IB_QPT_RAW_DGRM\r
+* Raw datagram queue pair.\r
+*\r
+* IB_QPT_RAW_IPV6\r
+* Raw IP version 6 queue pair.\r
+*\r
+* IB_QPT_RAW_ETHER\r
+* Raw Ethernet queue pair.\r
+*\r
+* IB_QPT_MAD\r
+* Unreliable, datagram queue pair that will send and receive management\r
+* datagrams with assistance from the access layer.\r
+*\r
+* IB_QPT_QP0_ALIAS\r
+* Alias to queue pair 0. Aliased QPs can only be created on an aliased\r
+* protection domain.\r
+*\r
+* IB_QPT_QP1_ALIAS\r
+* Alias to queue pair 1. Aliased QPs can only be created on an aliased\r
+* protection domain.\r
+*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_qp_type_str\r
+* NAME\r
+* ib_get_qp_type_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified QP type\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_qp_type_str(\r
+ IN uint8_t qp_type );\r
+\r
+/*\r
+* PARAMETERS\r
+* qp_type\r
+* [in] Encoded QP type as defined in the\r
+QP attribute.\r
+\r
+* RETURN VALUES\r
+* Pointer to the QP type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t\r
+*********/\r
+\r
+/****d* Access Layer/ib_access_t\r
+* NAME\r
+* ib_access_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of access is permitted on resources such as QPs,\r
+* memory regions and memory windows.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_access_t;\r
+#define IB_AC_RDMA_READ 0x00000001\r
+#define IB_AC_RDMA_WRITE 0x00000002\r
+#define IB_AC_ATOMIC 0x00000004\r
+#define IB_AC_LOCAL_WRITE 0x00000008\r
+#define IB_AC_MW_BIND 0x00000010\r
+/*\r
+* NOTES\r
+* Users may combine access rights using a bit-wise or operation to specify\r
+* additional access. For example: IB_AC_RDMA_READ | IB_AC_RDMA_WRITE grants\r
+* RDMA read and write access.\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_state_t\r
+* NAME\r
+* ib_qp_state_t\r
+*\r
+* DESCRIPTION\r
+* Indicates or sets the state of a queue pair. The current state of a queue\r
+* pair is returned through the ib_qp_query call and set via the\r
+* ib_qp_modify call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_qp_state_t;\r
+#define IB_QPS_RESET 0x00000001\r
+#define IB_QPS_INIT 0x00000002\r
+#define IB_QPS_RTR 0x00000004\r
+#define IB_QPS_RTS 0x00000008\r
+#define IB_QPS_SQD 0x00000010\r
+#define IB_QPS_SQD_DRAINING 0x00000030\r
+#define IB_QPS_SQD_DRAINED 0x00000050\r
+#define IB_QPS_SQERR 0x00000080\r
+#define IB_QPS_ERROR 0x00000100\r
+#define IB_QPS_TIME_WAIT 0xDEAD0000 /* InfiniBand Access Layer */\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_apm_state_t\r
+* NAME\r
+* ib_apm_state_t\r
+*\r
+* DESCRIPTION\r
+* The current automatic path migration state of a queue pair\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_apm_state\r
+{\r
+ IB_APM_MIGRATED = 1,\r
+ IB_APM_REARM,\r
+ IB_APM_ARMED\r
+\r
+} ib_apm_state_t;\r
+/*****/\r
+\r
+/****d* Access Layer/ib_srq_attr_mask_t\r
+* NAME\r
+* ib_srq_attr_mask_t\r
+*\r
+* DESCRIPTION\r
+* Indicates valid fields in ib_srq_attr_t structure\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_srq_attr_mask {\r
+ IB_SRQ_MAX_WR = 1 << 0,\r
+ IB_SRQ_LIMIT = 1 << 1,\r
+} ib_srq_attr_mask_t;\r
+/*****/\r
+\r
+\r
+/****s* Access Layer/ib_srq_attr_t\r
+* NAME\r
+* ib_srq_attr_t\r
+*\r
+* DESCRIPTION\r
+* Attributes used to initialize a shared queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_srq_attr {\r
+ uint32_t max_wr;\r
+ uint32_t max_sge;\r
+ uint32_t srq_limit;\r
+} ib_srq_attr_t;\r
+/*\r
+* FIELDS\r
+* max_wr\r
+* Specifies the max number of work request on SRQ.\r
+*\r
+* max_sge\r
+* Specifies the max number of scatter/gather elements in one work request.\r
+*\r
+* srq_limit\r
+* Specifies the low water mark for SRQ.\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t, ib_srq_attr_mask_t\r
+*****/\r
+\r
+\r
+\r
+/****s* Access Layer/ib_qp_create_t\r
+* NAME\r
+* ib_qp_create_t\r
+*\r
+* DESCRIPTION\r
+* Attributes used to initialize a queue pair at creation time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_create\r
+{\r
+ ib_qp_type_t qp_type;\r
+\r
+ uint32_t sq_max_inline;\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+ uint32_t sq_sge;\r
+ uint32_t rq_sge;\r
+\r
+ TO_LONG_PTR(ib_cq_handle_t, h_sq_cq);\r
+ TO_LONG_PTR(ib_cq_handle_t, h_rq_cq);\r
+ TO_LONG_PTR(ib_srq_handle_t, h_srq);\r
+\r
+ boolean_t sq_signaled;\r
+\r
+} ib_qp_create_t;\r
+/*\r
+* FIELDS\r
+* type\r
+* Specifies the type of queue pair to create.\r
+*\r
+* sq_max_inline\r
+* Maximum payload that can be inlined directly in a WQE, eliminating\r
+* protection checks and additional DMA operations.\r
+*\r
+* sq_depth\r
+* Indicates the requested maximum number of work requests that may be\r
+* outstanding on the queue pair's send queue. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* rq_depth\r
+* Indicates the requested maximum number of work requests that may be\r
+* outstanding on the queue pair's receive queue. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* sq_sge\r
+* Indicates the maximum number scatter-gather elements that may be\r
+* given in a send work request. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* rq_sge\r
+* Indicates the maximum number scatter-gather elements that may be\r
+* given in a receive work request. This value must be less\r
+* than or equal to the maximum reported by the channel adapter associated\r
+* with the queue pair.\r
+*\r
+* h_sq_cq\r
+* A handle to the completion queue that will be used to report send work\r
+* request completions. This handle must be NULL if the type is\r
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+* h_rq_cq\r
+* A handle to the completion queue that will be used to report receive\r
+* work request completions. This handle must be NULL if the type is\r
+* IB_QPT_MAD, IB_QPT_QP0_ALIAS, or IB_QPT_QP1_ALIAS.\r
+*\r
+* h_srq\r
+* A handle to an SRQ to get receive completions via. Must be coded NULL \r
+* when QP is not associated with SRQ\r
+*\r
+* sq_signaled\r
+* A flag that is used to indicate whether the queue pair will signal\r
+* an event upon completion of a send work request. If set to\r
+* TRUE, send work requests will always generate a completion\r
+* event. If set to FALSE, a completion event will only be\r
+* generated if the send_opt field of the send work request has the\r
+* IB_SEND_OPT_SIGNALED flag set.\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t, ib_qp_attr_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_qp_attr_t\r
+* NAME\r
+* ib_qp_attr_t\r
+*\r
+* DESCRIPTION\r
+* Queue pair attributes returned through ib_query_qp.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_attr\r
+{\r
+ TO_LONG_PTR(ib_pd_handle_t, h_pd);\r
+ ib_qp_type_t qp_type;\r
+ ib_access_t access_ctrl;\r
+ uint16_t pkey_index;\r
+\r
+ uint32_t sq_max_inline;\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+ uint32_t sq_sge;\r
+ uint32_t rq_sge;\r
+ uint8_t init_depth;\r
+ uint8_t resp_res;\r
+\r
+ TO_LONG_PTR(ib_cq_handle_t, h_sq_cq);\r
+ TO_LONG_PTR(ib_cq_handle_t, h_rq_cq);\r
+ TO_LONG_PTR(ib_srq_handle_t,h_srq);\r
+\r
+ boolean_t sq_signaled;\r
+\r
+ ib_qp_state_t state;\r
+ ib_net32_t num;\r
+ ib_net32_t dest_num;\r
+ ib_net32_t qkey;\r
+\r
+ ib_net32_t sq_psn;\r
+ ib_net32_t rq_psn;\r
+\r
+ uint8_t primary_port;\r
+ uint8_t alternate_port;\r
+ ib_av_attr_t primary_av;\r
+ ib_av_attr_t alternate_av;\r
+ ib_apm_state_t apm_state;\r
+\r
+} ib_qp_attr_t;\r
+/*\r
+* FIELDS\r
+* h_pd\r
+* This is a handle to a protection domain associated with the QP.\r
+*\r
+* sq_max_inline\r
+* Maximum payload that can be inlined directly in a WQE, eliminating\r
+* protection checks and additional DMA operations.\r
+*\r
+* NOTES\r
+* Other fields are defined by the Infiniband specification.\r
+*\r
+* SEE ALSO\r
+* ib_qp_type_t, ib_access_t, ib_qp_state_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_qp_opts_t\r
+* NAME\r
+* ib_qp_opts_t\r
+*\r
+* DESCRIPTION\r
+* Optional fields supplied in the modify QP operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_qp_opts_t;\r
+#define IB_MOD_QP_ALTERNATE_AV 0x00000001\r
+#define IB_MOD_QP_PKEY 0x00000002\r
+#define IB_MOD_QP_APM_STATE 0x00000004\r
+#define IB_MOD_QP_PRIMARY_AV 0x00000008\r
+#define IB_MOD_QP_RNR_NAK_TIMEOUT 0x00000010\r
+#define IB_MOD_QP_RESP_RES 0x00000020\r
+#define IB_MOD_QP_INIT_DEPTH 0x00000040\r
+#define IB_MOD_QP_PRIMARY_PORT 0x00000080\r
+#define IB_MOD_QP_ACCESS_CTRL 0x00000100\r
+#define IB_MOD_QP_QKEY 0x00000200\r
+#define IB_MOD_QP_SQ_DEPTH 0x00000400\r
+#define IB_MOD_QP_RQ_DEPTH 0x00000800\r
+#define IB_MOD_QP_CURRENT_STATE 0x00001000\r
+#define IB_MOD_QP_RETRY_CNT 0x00002000\r
+#define IB_MOD_QP_LOCAL_ACK_TIMEOUT 0x00004000\r
+#define IB_MOD_QP_RNR_RETRY_CNT 0x00008000\r
+\r
+/*\r
+* SEE ALSO\r
+* ib_qp_mod_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_qp_mod_t\r
+* NAME\r
+* ib_qp_mod_t\r
+*\r
+* DESCRIPTION\r
+* Information needed to change the state of a queue pair through the\r
+* ib_modify_qp call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_qp_mod\r
+{\r
+ ib_qp_state_t req_state;\r
+\r
+ union _qp_state\r
+ {\r
+ struct _qp_init\r
+ {\r
+ uint8_t primary_port;\r
+ ib_net32_t qkey;\r
+ uint16_t pkey_index;\r
+ ib_access_t access_ctrl;\r
+\r
+ } init;\r
+\r
+ struct _qp_rtr\r
+ {\r
+ ib_net32_t rq_psn;\r
+ ib_net32_t dest_qp;\r
+ ib_av_attr_t primary_av;\r
+ uint8_t resp_res;\r
+ uint8_t rnr_nak_timeout;\r
+\r
+ ib_qp_opts_t opts;\r
+ ib_av_attr_t alternate_av;\r
+ ib_net32_t qkey;\r
+ uint16_t pkey_index;\r
+ ib_access_t access_ctrl;\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+\r
+ } rtr;\r
+\r
+ struct _qp_rts\r
+ {\r
+ ib_net32_t sq_psn;\r
+ uint8_t retry_cnt;\r
+ uint8_t rnr_retry_cnt;\r
+ uint8_t local_ack_timeout;\r
+ uint8_t init_depth;\r
+\r
+ ib_qp_opts_t opts;\r
+ uint8_t rnr_nak_timeout;\r
+ ib_qp_state_t current_state;\r
+ ib_net32_t qkey;\r
+ ib_access_t access_ctrl;\r
+ uint8_t resp_res;\r
+\r
+ ib_av_attr_t primary_av;\r
+ ib_av_attr_t alternate_av;\r
+\r
+ uint32_t sq_depth;\r
+ uint32_t rq_depth;\r
+\r
+ ib_apm_state_t apm_state;\r
+ uint8_t primary_port;\r
+ uint16_t pkey_index;\r
+\r
+ } rts;\r
+\r
+ struct _qp_sqd\r
+ {\r
+ boolean_t sqd_event;\r
+\r
+ } sqd;\r
+\r
+ } state;\r
+\r
+} ib_qp_mod_t;\r
+/*\r
+* SEE ALSO\r
+* ib_qp_state_t, ib_access_t, ib_av_attr_t, ib_apm_state_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_wr_type_t\r
+* NAME\r
+* ib_wr_type_t\r
+*\r
+* DESCRIPTION\r
+* Identifies the type of work request posted to a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wr_type_t\r
+{\r
+ WR_SEND,\r
+ WR_RDMA_WRITE,\r
+ WR_RDMA_READ,\r
+ WR_COMPARE_SWAP,\r
+ WR_FETCH_ADD,\r
+ WR_LSO,\r
+ WR_UNKNOWN\r
+\r
+} ib_wr_type_t;\r
+/*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wr_type_str\r
+* NAME\r
+* ib_get_wr_type_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified work request type\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wr_type_str(\r
+ IN uint8_t wr_type );\r
+\r
+/*\r
+* PARAMETERS\r
+* wr_type\r
+* [in] Encoded work request type as defined in the\r
+work request attribute.\r
+\r
+* RETURN VALUES\r
+* Pointer to the work request type string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+* ib_wr_type_t\r
+*********/\r
+\r
+\r
+/****s* Access Layer/ib_local_ds_t\r
+* NAME\r
+* ib_local_ds_t\r
+*\r
+* DESCRIPTION\r
+* Local data segment information referenced by send and receive work\r
+* requests. This is used to specify local data buffers used as part of a\r
+* work request.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_local_ds\r
+{\r
+ uint64_t vaddr;\r
+ uint32_t length;\r
+ uint32_t lkey;\r
+\r
+} ib_local_ds_t;\r
+/*****/\r
+\r
+\r
+/****d* Access Layer/ib_send_opt_t\r
+* NAME\r
+* ib_send_opt_t\r
+*\r
+* DESCRIPTION\r
+* Optional flags used when posting send work requests. These flags\r
+* indicate specific processing for the send operation.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_send_opt_t;\r
+#define IB_SEND_OPT_IMMEDIATE 0x00000001\r
+#define IB_SEND_OPT_FENCE 0x00000002\r
+#define IB_SEND_OPT_SIGNALED 0x00000004\r
+#define IB_SEND_OPT_SOLICITED 0x00000008\r
+#define IB_SEND_OPT_INLINE 0x00000010\r
+#define IB_SEND_OPT_LOCAL 0x00000020\r
+#define IB_SEND_OPT_TX_IP_CSUM 0x00000040\r
+#define IB_SEND_OPT_TX_TCP_UDP_CSUM 0x00000080\r
+\r
+#define IB_SEND_OPT_VEND_MASK 0xFFFF0000\r
+/*\r
+* VALUES\r
+* The following flags determine the behavior of a work request when\r
+* posted to the send side.\r
+*\r
+* IB_SEND_OPT_IMMEDIATE\r
+* Send immediate data with the given request.\r
+*\r
+* IB_SEND_OPT_FENCE\r
+* The operation is fenced. Complete all pending send operations\r
+* before processing this request.\r
+*\r
+* IB_SEND_OPT_SIGNALED\r
+* If the queue pair is configured for signaled completion, then\r
+* generate a completion queue entry when this request completes.\r
+*\r
+* IB_SEND_OPT_SOLICITED\r
+* Set the solicited bit on the last packet of this request.\r
+*\r
+* IB_SEND_OPT_INLINE\r
+* Indicates that the requested send data should be copied into a VPD\r
+* owned data buffer. This flag permits the user to issue send operations\r
+* without first needing to register the buffer(s) associated with the\r
+* send operation. Verb providers that support this operation may place\r
+* vendor specific restrictions on the size of send operation that may\r
+* be performed as inline.\r
+*\r
+*\r
+* IB_SEND_OPT_LOCAL\r
+* Indicates that a sent MAD request should be given to the local VPD for\r
+* processing. MADs sent using this option are not placed on the wire.\r
+* This send option is only valid for MAD send operations.\r
+*\r
+*\r
+* IB_SEND_OPT_VEND_MASK\r
+* This mask indicates bits reserved in the send options that may be used\r
+* by the verbs provider to indicate vendor specific options. Bits set\r
+* in this area of the send options are ignored by the Access Layer, but\r
+* may have specific meaning to the underlying VPD.\r
+*\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_send_wr_t\r
+* NAME\r
+* ib_send_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a work request to the send queue of a queue\r
+* pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_send_wr\r
+{\r
+ uint64_t wr_id;\r
+ struct _ib_send_wr* p_next;\r
+ ib_local_ds_t* ds_array;\r
+ uint32_t num_ds;\r
+ ib_wr_type_t wr_type;\r
+ ib_send_opt_t send_opt;\r
+ ib_net32_t immediate_data;\r
+\r
+ union\r
+ {\r
+ union _send_dgrm\r
+ {\r
+ struct _send_ud\r
+ {\r
+ ib_av_handle_t h_av; \r
+ ib_net32_t remote_qp;\r
+ ib_net32_t remote_qkey;\r
+ void* rsvd;\r
+ uint16_t pkey_index;\r
+ void* header;\r
+ int hlen;\r
+ int mss;\r
+ } ud;\r
+\r
+ struct _send_rd\r
+ {\r
+ ib_net32_t remote_qp;\r
+ ib_net32_t remote_qkey;\r
+ ib_net32_t eecn;\r
+\r
+ } rd;\r
+\r
+ struct _send_raw_ether\r
+ {\r
+ ib_net16_t dest_lid;\r
+ uint8_t path_bits;\r
+ uint8_t sl;\r
+ uint8_t max_static_rate;\r
+ ib_net16_t ether_type;\r
+ \r
+ } raw_ether;\r
+\r
+ struct _send_raw_ipv6\r
+ {\r
+ ib_net16_t dest_lid;\r
+ uint8_t path_bits;\r
+ uint8_t sl;\r
+ uint8_t max_static_rate;\r
+ \r
+ } raw_ipv6;\r
+ \r
+ } dgrm;\r
+\r
+ struct _send_remote_ops\r
+ {\r
+ uint64_t vaddr;\r
+ net32_t rkey;\r
+\r
+ ib_net64_t atomic1;\r
+ ib_net64_t atomic2;\r
+ \r
+ } remote_ops;\r
+ };\r
+} ib_send_wr_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work requests together. This permits multiple\r
+* work requests to be posted to a queue pair through a single function\r
+* call. This value is set to NULL to mark the end of the chain.\r
+*\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* wr_type\r
+* The type of work request being submitted to the send queue.\r
+*\r
+* send_opt\r
+* Optional send control parameters.\r
+*\r
+* num_ds\r
+* Number of local data segments specified by this work request.\r
+*\r
+* ds_array\r
+* A reference to an array of local data segments used by the send\r
+* operation.\r
+*\r
+* immediate_data\r
+* 32-bit field sent as part of a message send or RDMA write operation.\r
+* This field is only valid if the send_opt flag IB_SEND_OPT_IMMEDIATE\r
+* has been set.\r
+*\r
+* dgrm.ud.remote_qp\r
+* Identifies the destination queue pair of an unreliable datagram send\r
+* operation.\r
+*\r
+* dgrm.ud.remote_qkey\r
+* The qkey for the destination queue pair.\r
+*\r
+* dgrm.ud.h_av\r
+* An address vector that specifies the path information used to route\r
+* the outbound datagram to the destination queue pair.\r
+*\r
+* dgrm.ud.pkey_index\r
+* The pkey index for this send work request. This is valid only\r
+* for IB_QPT_QP1 and IB_QPT_QP1_ALIAS QP types. The work request\r
+* is posted to using this pkey index build the GMP's BTH instead\r
+* of the QP's pkey.\r
+*\r
+* dgrm.ud.rsvd\r
+* Reserved for use by the Access Layer.\r
+*\r
+* dgrm.raw_ether.dest_lid\r
+* The destination LID that will receive this raw ether send.\r
+*\r
+* dgrm.raw_ether.path_bits\r
+* path bits...\r
+*\r
+* dgrm.raw_ether.sl\r
+* service level...\r
+*\r
+* dgrm.raw_ether.max_static_rate\r
+* static rate...\r
+*\r
+* dgrm.raw_ether.ether_type\r
+* ether type...\r
+*\r
+* dgrm.raw_ipv6.dest_lid\r
+* The destination LID that will receive this raw ether send.\r
+*\r
+* dgrm.raw_ipv6.path_bits\r
+* path bits...\r
+*\r
+* dgrm.raw_ipv6.sl\r
+* service level...\r
+*\r
+* dgrm.raw_ipv6.max_static_rate\r
+* static rate...\r
+*\r
+* remote_ops.vaddr\r
+* The registered virtual memory address of the remote memory to access\r
+* with an RDMA or atomic operation.\r
+*\r
+* remote_ops.rkey\r
+* The rkey associated with the specified remote vaddr. This data must\r
+* be presented exactly as obtained from the remote node. No swapping\r
+* of data must be performed.\r
+*\r
+* atomic1\r
+* The first operand for an atomic operation.\r
+*\r
+* atomic2\r
+* The second operand for an atomic operation.\r
+*\r
+* NOTES\r
+* The format of data sent over the fabric is user-defined and is considered\r
+* opaque to the access layer. The sole exception to this are MADs posted\r
+* to a MAD QP service. MADs are expected to match the format defined by\r
+* the Infiniband specification and must be in network-byte order when posted\r
+* to the MAD QP service.\r
+*\r
+* SEE ALSO\r
+* ib_wr_type_t, ib_local_ds_t, ib_send_opt_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_recv_wr_t\r
+* NAME\r
+* ib_recv_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a work request to the receive queue of a queue\r
+* pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_recv_wr\r
+{\r
+ TO_LONG_PTR(struct _ib_recv_wr*, p_next);\r
+ uint64_t wr_id;\r
+ uint32_t num_ds;\r
+ TO_LONG_PTR(ib_local_ds_t*, ds_array);\r
+\r
+} ib_recv_wr_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work requests together. This permits multiple\r
+* work requests to be posted to a queue pair through a single function\r
+* call. This value is set to NULL to mark the end of the chain.\r
+*\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* num_ds\r
+* Number of local data segments specified by this work request.\r
+*\r
+* ds_array\r
+* A reference to an array of local data segments used by the send\r
+* operation.\r
+*\r
+* SEE ALSO\r
+* ib_local_ds_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_bind_wr_t\r
+* NAME\r
+* ib_bind_wr_t\r
+*\r
+* DESCRIPTION\r
+* Information used to submit a memory window bind work request to the send\r
+* queue of a queue pair.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_bind_wr\r
+{\r
+ uint64_t wr_id;\r
+ ib_send_opt_t send_opt;\r
+\r
+ TO_LONG_PTR(ib_mr_handle_t, h_mr);\r
+ ib_access_t access_ctrl;\r
+ net32_t current_rkey;\r
+\r
+ ib_local_ds_t local_ds;\r
+\r
+} ib_bind_wr_t;\r
+/*\r
+* FIELDS\r
+* wr_id\r
+* A 64-bit work request identifier that is returned to the consumer\r
+* as part of the work completion.\r
+*\r
+* send_opt\r
+* Optional send control parameters.\r
+*\r
+* h_mr\r
+* Handle to the memory region to which this window is being bound.\r
+*\r
+* access_ctrl\r
+* Access rights for this memory window.\r
+*\r
+* current_rkey\r
+* The current rkey assigned to this window for remote access.\r
+*\r
+* local_ds\r
+* A reference to a local data segment used by the bind operation.\r
+*\r
+* SEE ALSO\r
+* ib_send_opt_t, ib_access_t, ib_local_ds_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_wc_status_t\r
+* NAME\r
+* ib_wc_status_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the status of a completed work request. These VALUES are\r
+* returned to the user when retrieving completions. Note that success is\r
+* identified as IB_WCS_SUCCESS, which is always zero.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_status_t\r
+{\r
+ IB_WCS_SUCCESS,\r
+ IB_WCS_LOCAL_LEN_ERR,\r
+ IB_WCS_LOCAL_OP_ERR,\r
+ IB_WCS_LOCAL_PROTECTION_ERR,\r
+ IB_WCS_WR_FLUSHED_ERR,\r
+ IB_WCS_MEM_WINDOW_BIND_ERR,\r
+ IB_WCS_REM_ACCESS_ERR,\r
+ IB_WCS_REM_OP_ERR,\r
+ IB_WCS_RNR_RETRY_ERR,\r
+ IB_WCS_TIMEOUT_RETRY_ERR,\r
+ IB_WCS_REM_INVALID_REQ_ERR,\r
+ IB_WCS_BAD_RESP_ERR,\r
+ IB_WCS_LOCAL_ACCESS_ERR,\r
+ IB_WCS_GENERAL_ERR,\r
+ IB_WCS_UNMATCHED_RESPONSE, /* InfiniBand Access Layer */\r
+ IB_WCS_CANCELED, /* InfiniBand Access Layer */\r
+ IB_WCS_REM_ABORT_ERR,\r
+ IB_WCS_UNKNOWN /* Must be last. */\r
+\r
+} ib_wc_status_t;\r
+\r
+/*\r
+* VALUES\r
+* IB_WCS_SUCCESS\r
+* Work request completed successfully.\r
+*\r
+* IB_WCS_MAD\r
+* The completed work request was associated with a managmenet datagram\r
+* that requires post processing. The MAD will be returned to the user\r
+* through a callback once all post processing has completed.\r
+*\r
+* IB_WCS_LOCAL_LEN_ERR\r
+* Generated for a work request posted to the send queue when the\r
+* total of the data segment lengths exceeds the message length of the\r
+* channel. Generated for a work request posted to the receive queue when\r
+* the total of the data segment lengths is too small for a\r
+* valid incoming message.\r
+*\r
+* IB_WCS_LOCAL_OP_ERR\r
+* An internal QP consistency error was generated while processing this\r
+* work request. This may indicate that the QP was in an incorrect state\r
+* for the requested operation.\r
+*\r
+* IB_WCS_LOCAL_PROTECTION_ERR\r
+* The data segments of the locally posted work request did not refer to\r
+* a valid memory region. The memory may not have been properly\r
+* registered for the requested operation.\r
+*\r
+* IB_WCS_WR_FLUSHED_ERR\r
+* The work request was flushed from the QP before being completed.\r
+*\r
+* IB_WCS_MEM_WINDOW_BIND_ERR\r
+* A memory window bind operation failed due to insufficient access\r
+* rights.\r
+*\r
+* IB_WCS_REM_ACCESS_ERR,\r
+* A protection error was detected at the remote node for a RDMA or atomic\r
+* operation.\r
+*\r
+* IB_WCS_REM_OP_ERR,\r
+* The operation could not be successfully completed at the remote node.\r
+* This may indicate that the remote QP was in an invalid state or\r
+* contained an invalid work request.\r
+*\r
+* IB_WCS_RNR_RETRY_ERR,\r
+* The RNR retry count was exceeded while trying to send this message.\r
+*\r
+* IB_WCS_TIMEOUT_RETRY_ERR\r
+* The local transport timeout counter expired while trying to send this\r
+* message.\r
+*\r
+* IB_WCS_REM_INVALID_REQ_ERR,\r
+* The remote node detected an invalid message on the channel. This error\r
+* is usually a result of one of the following:\r
+* - The operation was not supported on receive queue.\r
+* - There was insufficient buffers to receive a new RDMA request.\r
+* - There was insufficient buffers to receive a new atomic operation.\r
+* - An RDMA request was larger than 2^31 bytes.\r
+*\r
+* IB_WCS_BAD_RESP_ERR,\r
+* An unexpected transport layer opcode was returned\r
+* by the responder.\r
+*\r
+* IB_WCS_LOCAL_ACCESS_ERR,\r
+* A protection error occurred on a local data buffer\r
+* during the processing of a RDMA Write with Immediate Data \r
+* operation sent from the remote node.\r
+*\r
+* IB_WCS_REM_ABORT_ERR,\r
+* The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+* the responder aborted the operation).\r
+*\r
+* IB_WCS_REM_ABORT_ERR,\r
+* The operation was aborted (e.g., For UD QPs associated with an SRQ, \r
+* the responder aborted the operation).\r
+*\r
+* IB_WCS_UNMATCHED_RESPONSE\r
+* A response MAD was received for which there was no matching send. The\r
+* send operation may have been canceled by the user or may have timed\r
+* out.\r
+*\r
+* IB_WCS_CANCELED\r
+* The completed work request was canceled by the user.\r
+ *\r
+ * IB_WCS_GENERAL_ERR,\r
+ * Any other error\r
+ *\r
+*****/\r
+\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wc_status_str\r
+* NAME\r
+* ib_get_wc_status_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified work completion status.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wc_status_str(\r
+ IN ib_wc_status_t wc_status );\r
+/*\r
+* PARAMETERS\r
+* wc_status\r
+* [in] work completion status value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the work completion status description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****d* Access Layer/ib_wc_type_t\r
+* NAME\r
+* ib_wc_type_t\r
+*\r
+* DESCRIPTION\r
+* Indicates the type of work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _ib_wc_type_t\r
+{\r
+ IB_WC_SEND,\r
+ IB_WC_RDMA_WRITE,\r
+ IB_WC_RDMA_READ,\r
+ IB_WC_COMPARE_SWAP,\r
+ IB_WC_FETCH_ADD,\r
+ IB_WC_MW_BIND,\r
+ IB_WC_UNKNOWN1,\r
+ IB_WC_RECV = (1 << 7),\r
+ IB_WC_RECV_RDMA_WRITE,\r
+ IB_WR_LSO,\r
+ IB_WC_UNKNOWN2\r
+\r
+} ib_wc_type_t;\r
+/*****/\r
+\r
+\r
+/****f* IBA Base: Types/ib_get_wc_type_str\r
+* NAME\r
+* ib_get_wc_type_str\r
+*\r
+* DESCRIPTION\r
+* Returns a string for the specified work completion type.\r
+*\r
+* SYNOPSIS\r
+*/\r
+AL_EXPORT const char* AL_API\r
+ib_get_wc_type_str(\r
+ IN ib_wc_type_t wc_type );\r
+/*\r
+* PARAMETERS\r
+* wc_type\r
+* [in] work completion type value\r
+*\r
+* RETURN VALUES\r
+* Pointer to the work completion type description string.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+/****d* Access Layer/ib_recv_opt_t\r
+* NAME\r
+* ib_recv_opt_t\r
+*\r
+* DESCRIPTION\r
+* Indicates optional fields valid in a receive work completion.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_recv_opt_t;\r
+#define IB_RECV_OPT_IMMEDIATE 0x00000001\r
+#define IB_RECV_OPT_FORWARD 0x00000002\r
+#define IB_RECV_OPT_GRH_VALID 0x00000004\r
+#define IB_RECV_OPT_VEND_MASK 0xFFFF0000\r
+/*\r
+* VALUES\r
+* IB_RECV_OPT_IMMEDIATE\r
+* Indicates that immediate data is valid for this work completion.\r
+*\r
+* IB_RECV_OPT_FORWARD\r
+* Indicates that the received trap should be forwarded to the SM.\r
+*\r
+* IB_RECV_OPT_GRH_VALID\r
+* Indicates presence of the global route header. When set, the first\r
+* 40 bytes received are the GRH.\r
+*\r
+* IB_RECV_OPT_VEND_MASK\r
+* This mask indicates bits reserved in the receive options that may be\r
+* used by the verbs provider to indicate vendor specific options. Bits\r
+* set in this area of the receive options are ignored by the Access Layer,\r
+* but may have specific meaning to the underlying VPD.\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_wc_t\r
+* NAME\r
+* ib_wc_t\r
+*\r
+* DESCRIPTION\r
+* Work completion information.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_wc\r
+{\r
+ TO_LONG_PTR(struct _ib_wc*, p_next);\r
+ uint64_t wr_id;\r
+ ib_wc_type_t wc_type;\r
+\r
+ uint32_t length;\r
+ uint64_t vendor_specific;\r
+ ib_wc_status_t status;\r
+\r
+ union _wc_recv\r
+ {\r
+ struct _wc_conn\r
+ {\r
+ ib_recv_opt_t recv_opt;\r
+ ib_net32_t immediate_data;\r
+\r
+ } conn;\r
+\r
+ struct _wc_ud\r
+ {\r
+ ib_recv_opt_t recv_opt;\r
+ ib_net32_t immediate_data;\r
+ ib_net32_t remote_qp;\r
+ uint16_t pkey_index;\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+ uint8_t csum_ok;\r
+\r
+ } ud;\r
+\r
+ struct _wc_rd\r
+ {\r
+ ib_net32_t remote_eecn;\r
+ ib_net32_t remote_qp;\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint32_t free_cnt;\r
+\r
+ } rd;\r
+\r
+ struct _wc_raw_ipv6\r
+ {\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+\r
+ } raw_ipv6;\r
+\r
+ struct _wc_raw_ether\r
+ {\r
+ ib_net16_t remote_lid;\r
+ uint8_t remote_sl;\r
+ uint8_t path_bits;\r
+ ib_net16_t ether_type;\r
+\r
+ } raw_ether;\r
+\r
+ } recv;\r
+\r
+} ib_wc_t;\r
+/*\r
+* FIELDS\r
+* p_next\r
+* A pointer used to chain work completions. This permits multiple\r
+* work completions to be retrieved from a completion queue through a\r
+* single function call. This value is set to NULL to mark the end of\r
+* the chain.\r
+*\r
+* wr_id\r
+* The 64-bit work request identifier that was specified when posting the\r
+* work request.\r
+*\r
+* wc_type\r
+* Indicates the type of work completion.\r
+*\r
+*\r
+* length\r
+* The total length of the data sent or received with the work request.\r
+*\r
+* status\r
+* The result of the work request.\r
+*\r
+* vendor_specific\r
+* HCA vendor specific information returned as part of the completion.\r
+*\r
+* recv.conn.recv_opt\r
+* Indicates optional fields valid as part of a work request that\r
+* completed on a connected (reliable or unreliable) queue pair.\r
+*\r
+* recv.conn.immediate_data\r
+* 32-bit field received as part of an inbound message on a connected\r
+* queue pair. This field is only valid if the recv_opt flag\r
+* IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+* recv.ud.recv_opt\r
+* Indicates optional fields valid as part of a work request that\r
+* completed on an unreliable datagram queue pair.\r
+*\r
+* recv.ud.immediate_data\r
+* 32-bit field received as part of an inbound message on a unreliable\r
+* datagram queue pair. This field is only valid if the recv_opt flag\r
+* IB_RECV_OPT_IMMEDIATE has been set.\r
+*\r
+* recv.ud.remote_qp\r
+* Identifies the source queue pair of a received datagram.\r
+*\r
+* recv.ud.pkey_index\r
+* The pkey index for the source queue pair. This is valid only for\r
+* GSI type QP's.\r
+*\r
+* recv.ud.remote_lid\r
+* The source LID of the received datagram.\r
+*\r
+* recv.ud.remote_sl\r
+* The service level used by the source of the received datagram.\r
+*\r
+* recv.ud.path_bits\r
+* path bits...\r
+*\r
+* recv.rd.remote_eecn\r
+* The remote end-to-end context number that sent the received message.\r
+*\r
+* recv.rd.remote_qp\r
+* Identifies the source queue pair of a received message.\r
+*\r
+* recv.rd.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.rd.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.rd.free_cnt\r
+* The number of available entries in the completion queue. Reliable\r
+* datagrams may complete out of order, so this field may be used to\r
+* determine the number of additional completions that may occur.\r
+*\r
+* recv.raw_ipv6.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.raw_ipv6.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.raw_ipv6.path_bits\r
+* path bits...\r
+*\r
+* recv.raw_ether.remote_lid\r
+* The source LID of the received message.\r
+*\r
+* recv.raw_ether.remote_sl\r
+* The service level used by the source of the received message.\r
+*\r
+* recv.raw_ether.path_bits\r
+* path bits...\r
+*\r
+* recv.raw_ether.ether_type\r
+* ether type...\r
+* NOTES\r
+* When the work request completes with error, the only values that the\r
+* consumer can depend on are the wr_id field, and the status of the\r
+* operation.\r
+*\r
+* If the consumer is using the same CQ for completions from more than\r
+* one type of QP (i.e Reliable Connected, Datagram etc), then the consumer\r
+* must have additional information to decide what fields of the union are\r
+* valid.\r
+* SEE ALSO\r
+* ib_wc_type_t, ib_qp_type_t, ib_wc_status_t, ib_recv_opt_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_mr_create_t\r
+* NAME\r
+* ib_mr_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_create\r
+{\r
+ TO_LONG_PTR(void*, vaddr);\r
+ uint64_t length;\r
+ ib_access_t access_ctrl;\r
+\r
+} ib_mr_create_t;\r
+/*\r
+* FIELDS\r
+* vaddr\r
+* Starting virtual address of the region being registered.\r
+*\r
+* length\r
+* Length of the buffer to register.\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+#ifdef CL_KERNEL\r
+\r
+/****s* Access Layer/mlnx_fmr_create_t\r
+* NAME\r
+* mlnx_fmr_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a Mellanox fast memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _mlnx_fmr_create\r
+{\r
+ int max_pages;\r
+ int max_maps;\r
+ uint8_t page_size;\r
+ ib_access_t access_ctrl;\r
+\r
+} mlnx_fmr_create_t;\r
+/*\r
+* FIELDS\r
+* max_pages\r
+* max pages in the region.\r
+*\r
+* max_maps\r
+* max times, the region can be mapped before remapping.\r
+*\r
+* page_size\r
+* log2 of the page size (e.g. 12 for 4KB).\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* NOTES\r
+* This is a Mellanox specific extension to verbs.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/mlnx_fmr_pool_create_t\r
+* NAME\r
+* mlnx_fmr_pool_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a Mellanox fast memory region pool.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _mlnx_fmr_pool_create\r
+{\r
+ int max_pages_per_fmr;\r
+ uint8_t page_size; /* really - page_shift, log2 of page_size */\r
+ enum ib_access_flags access_ctrl;\r
+ int pool_size;\r
+ int dirty_watermark;\r
+ void (*flush_function)(mlnx_fmr_pool_handle_t h_pool, void *arg);\r
+ void *flush_arg;\r
+ boolean_t cache;\r
+} mlnx_fmr_pool_create_t;\r
+/*\r
+* FIELDS\r
+* max_pages\r
+* max pages in the region.\r
+*\r
+* max_maps\r
+* max times, the region can be mapped before remapping.\r
+*\r
+* page_size\r
+* log2 of the page size (e.g. 12 for 4KB).\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* NOTES\r
+* This is a Mellanox specific extension to verbs.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+#endif\r
+\r
+/****s* Access Layer/ib_phys_range_t\r
+* NAME\r
+* ib_phys_range_t\r
+*\r
+* DESCRIPTION\r
+* Information describing a physical memory range.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_range\r
+{\r
+ uint64_t base_addr;\r
+ uint64_t size;\r
+\r
+} ib_phys_range_t;\r
+/*\r
+* FIELDS\r
+* base_addr\r
+* Physical address of the base of the memory range.\r
+*\r
+* size\r
+* size, in bytes, of the memory range.\r
+*\r
+* NOTES\r
+* The base address must be start and end on an HCA-supported page boundary.\r
+*\r
+* SEE ALSO\r
+* ib_phys_create_t\r
+*********/\r
+\r
+\r
+/****s* Access Layer/ib_phys_create_t\r
+* NAME\r
+* ib_phys_create_t\r
+*\r
+* DESCRIPTION\r
+* Information required to create a physical memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_phys_create\r
+{\r
+ uint64_t length;\r
+ uint32_t num_ranges;\r
+ ib_phys_range_t* range_array;\r
+ uint32_t buf_offset;\r
+ uint32_t hca_page_size;\r
+ ib_access_t access_ctrl;\r
+\r
+} ib_phys_create_t;\r
+/*\r
+* FIELDS\r
+* length\r
+* The length of the memory region in bytes.\r
+*\r
+* num_ranges\r
+* Number of ib_phys_range structures listed in the specified range array.\r
+*\r
+* range_array\r
+* An array of ib_phys_range structures to be registered as a single memory\r
+* region.\r
+*\r
+* buf_offset\r
+* The offset into the first physical memory range of the specified memory\r
+* region on which to start the virtual address.\r
+*\r
+* hca_page_size\r
+* The HCA page size to use to register the memory.\r
+*\r
+* access_ctrl\r
+* Access rights of the registered region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+\r
+/****s* Access Layer/ib_mr_attr_t\r
+* NAME\r
+* ib_mr_attr_t\r
+*\r
+* DESCRIPTION\r
+* Attributes of a registered memory region.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_mr_attr\r
+{\r
+ TO_LONG_PTR(ib_pd_handle_t, h_pd);\r
+ uint64_t local_lb;\r
+ uint64_t local_ub;\r
+ uint64_t remote_lb;\r
+ uint64_t remote_ub;\r
+ ib_access_t access_ctrl;\r
+ net32_t lkey;\r
+ net32_t rkey;\r
+\r
+} ib_mr_attr_t;\r
+/*\r
+* DESCRIPTION\r
+* h_pd\r
+* Handle to the protection domain for this memory region.\r
+*\r
+* local_lb\r
+* The virtual address of the lower bound of protection for local\r
+* memory access. This is always a 64-bit quantity to support registering\r
+* more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+* local_ub\r
+* The virtual address of the upper bound of protection for local\r
+* memory access. This is always a 64-bit quantity to support registering\r
+* more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+* remote_lb\r
+* The virtual address of the lower bound of protection for remote\r
+* memory access. This is always a 64-bit quantity to support registering\r
+* more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+* remote_ub\r
+* The virtual address of the upper bound of protection for remote\r
+* memory access. This is always a 64-bit quantity to support registering\r
+* more than 4GB of memory on 32-bit systems with PAE.\r
+*\r
+* access_ctrl\r
+* Access rights for the specified memory region.\r
+*\r
+* lkey\r
+* The lkey associated with this memory region.\r
+*\r
+* rkey\r
+* The rkey associated with this memory region.\r
+*\r
+* NOTES\r
+* The remote_lb, remote_ub, and rkey are only valid if remote memory access\r
+* is enabled for this memory region.\r
+*\r
+* SEE ALSO\r
+* ib_access_t\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_ca_mod_t\r
+* NAME\r
+* ib_ca_mod_t -- Modify port attributes and error counters\r
+*\r
+* DESCRIPTION\r
+* Specifies modifications to the port attributes of a channel adapter.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_ca_mod_t;\r
+#define IB_CA_MOD_IS_CM_SUPPORTED 0x00000001\r
+#define IB_CA_MOD_IS_SNMP_SUPPORTED 0x00000002\r
+#define IB_CA_MOD_IS_DEV_MGMT_SUPPORTED 0x00000004\r
+#define IB_CA_MOD_IS_VEND_SUPPORTED 0x00000008\r
+#define IB_CA_MOD_IS_SM 0x00000010\r
+#define IB_CA_MOD_IS_SM_DISABLED 0x00000020\r
+#define IB_CA_MOD_QKEY_CTR 0x00000040\r
+#define IB_CA_MOD_PKEY_CTR 0x00000080\r
+#define IB_CA_MOD_IS_NOTICE_SUPPORTED 0x00000100\r
+#define IB_CA_MOD_IS_TRAP_SUPPORTED 0x00000200\r
+#define IB_CA_MOD_IS_APM_SUPPORTED 0x00000400\r
+#define IB_CA_MOD_IS_SLMAP_SUPPORTED 0x00000800\r
+#define IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED 0x00001000\r
+#define IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED 0x00002000\r
+#define IB_CA_MOD_IS_SYSGUID_SUPPORTED 0x00004000\r
+#define IB_CA_MOD_IS_DR_NOTICE_SUPPORTED 0x00008000\r
+#define IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED 0x00010000\r
+#define IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED 0x00020000\r
+#define IB_CA_MOD_IS_REINIT_SUPORTED 0x00040000\r
+#define IB_CA_MOD_IS_LEDINFO_SUPPORTED 0x00080000\r
+#define IB_CA_MOD_SHUTDOWN_PORT 0x00100000\r
+#define IB_CA_MOD_INIT_TYPE_VALUE 0x00200000\r
+#define IB_CA_MOD_SYSTEM_IMAGE_GUID 0x00400000\r
+#define IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED 0x00800000\r
+#define IB_CA_MOD_RESERVED_MASK 0xFF000000\r
+/*\r
+* VALUES\r
+* IB_CA_MOD_IS_CM_SUPPORTED\r
+* Indicates if there is a communication manager accessible through\r
+* the port.\r
+*\r
+* IB_CA_MOD_IS_SNMP_SUPPORTED\r
+* Indicates if there is an SNMP agent accessible through the port.\r
+*\r
+* IB_CA_MOD_IS_DEV_MGMT_SUPPORTED\r
+* Indicates if there is a device management agent accessible\r
+* through the port.\r
+*\r
+* IB_CA_MOD_IS_VEND_SUPPORTED\r
+* Indicates if there is a vendor supported agent accessible\r
+* through the port.\r
+*\r
+* IB_CA_MOD_IS_SM\r
+* Indicates if there is a subnet manager accessible through\r
+* the port.\r
+*\r
+* IB_CA_MOD_IS_SM_DISABLED\r
+* Indicates if the port has been disabled for configuration by the\r
+* subnet manager.\r
+*\r
+* IB_CA_MOD_QKEY_CTR\r
+* Used to reset the qkey violation counter associated with the\r
+* port.\r
+*\r
+* IB_CA_MOD_PKEY_CTR\r
+* Used to reset the pkey violation counter associated with the\r
+* port.\r
+*\r
+* IB_CA_MOD_IS_NOTICE_SUPPORTED\r
+* Indicates that this CA supports ability to generate Notices for\r
+* Port State changes. (only applicable to switches)\r
+*\r
+* IB_CA_MOD_IS_TRAP_SUPPORTED\r
+* Indicates that this management port supports ability to generate\r
+* trap messages. (only applicable to switches)\r
+*\r
+* IB_CA_MOD_IS_APM_SUPPORTED\r
+* Indicates that this port is capable of performing Automatic\r
+* Path Migration.\r
+*\r
+* IB_CA_MOD_IS_SLMAP_SUPPORTED\r
+* Indicates this port supports SLMAP capability.\r
+*\r
+* IB_CA_MOD_IS_PKEY_NVRAM_SUPPORTED\r
+* Indicates that PKEY is supported in NVRAM\r
+*\r
+* IB_CA_MOD_IS_MKEY_NVRAM_SUPPORTED\r
+* Indicates that MKEY is supported in NVRAM\r
+*\r
+* IB_CA_MOD_IS_SYSGUID_SUPPORTED\r
+* Indicates System Image GUID support.\r
+*\r
+* IB_CA_MOD_IS_DR_NOTICE_SUPPORTED\r
+* Indicate support for generating Direct Routed Notices\r
+*\r
+* IB_CA_MOD_IS_BOOT_MGMT_SUPPORTED\r
+* Indicates support for Boot Management\r
+*\r
+* IB_CA_MOD_IS_CAPM_NOTICE_SUPPORTED\r
+* Indicates capability to generate notices for changes to CAPMASK\r
+*\r
+* IB_CA_MOD_IS_REINIT_SUPORTED\r
+* Indicates type of node init supported. Refer to Chapter 14 for\r
+* Initialization actions.\r
+*\r
+* IB_CA_MOD_IS_LEDINFO_SUPPORTED\r
+* Indicates support for LED info.\r
+*\r
+* IB_CA_MOD_SHUTDOWN_PORT\r
+* Used to modify the port active indicator.\r
+*\r
+* IB_CA_MOD_INIT_TYPE_VALUE\r
+* Used to modify the init_type value for the port.\r
+*\r
+* IB_CA_MOD_SYSTEM_IMAGE_GUID\r
+* Used to modify the system image GUID for the port.\r
+*\r
+* IB_CA_MOD_IS_CLIENT_REREGISTER_SUPPORTED\r
+* Used to modify the system image GUID for the port.\r
+*\r
+* IB_CA_MOD_RESERVED_MASK\r
+* Mask of all the reserved bits. If any of these bits are set\r
+* ib_modify_ca will return IB_INVALID_PARAMETER.\r
+*****/\r
+\r
+\r
+/****d* Access Layer/ib_mr_mod_t\r
+* NAME\r
+* ib_mr_mod_t\r
+*\r
+* DESCRIPTION\r
+* Mask used to specify which attributes of a registered memory region are\r
+* being modified.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef uint32_t ib_mr_mod_t;\r
+#define IB_MR_MOD_ADDR 0x00000001\r
+#define IB_MR_MOD_PD 0x00000002\r
+#define IB_MR_MOD_ACCESS 0x00000004\r
+/*\r
+* PARAMETERS\r
+* IB_MEM_MOD_ADDR\r
+* The address of the memory region is being modified.\r
+*\r
+* IB_MEM_MOD_PD\r
+* The protection domain associated with the memory region is being\r
+* modified.\r
+*\r
+* IB_MEM_MOD_ACCESS\r
+* The access rights the memory region are being modified.\r
+*****/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_STATE_INIT\r
+* NAME\r
+* IB_SMINFO_STATE_INIT\r
+*\r
+* DESCRIPTION\r
+* Encoded state value used in the SMInfo attribute.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_STATE_INIT 4\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_HANDOVER\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_HANDOVER\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_HANDOVER (CL_NTOH32(0x000001))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_ACKNOWLEDGE\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_ACKNOWLEDGE (CL_NTOH32(0x000002))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISABLE\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_DISABLE\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISABLE (CL_NTOH32(0x000003))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_STANDBY\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_STANDBY\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_STANDBY (CL_NTOH32(0x000004))\r
+/**********/\r
+\r
+/****d* IBA Base: Constants/IB_SMINFO_ATTR_MOD_DISCOVER\r
+* NAME\r
+* IB_SMINFO_ATTR_MOD_DISCOVER\r
+*\r
+* DESCRIPTION\r
+* Encoded attribute modifier value used on SubnSet(SMInfo) SMPs.\r
+*\r
+* SOURCE\r
+*/\r
+#define IB_SMINFO_ATTR_MOD_DISCOVER (CL_NTOH32(0x000005))\r
+/**********/\r
+\r
+/****s* Access Layer/ib_ci_op_t\r
+* NAME\r
+* ib_ci_op_t\r
+*\r
+* DESCRIPTION\r
+* A structure used for vendor specific CA interface communication.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _ib_ci_op\r
+{\r
+ IN uint32_t command;\r
+ IN uint32_t buf_size;\r
+ IN uint32_t buf_info;\r
+ IN OUT int32_t status;\r
+ IN OUT TO_LONG_PTR(void*, p_buf) OPTIONAL; // Do not put it last in the structure, because of memory alignment\r
+ OUT uint32_t num_bytes_ret;\r
+ \r
+\r
+} ib_ci_op_t;\r
+/*\r
+* FIELDS\r
+* command\r
+* A command code that is understood by the verbs provider.\r
+*\r
+* status\r
+* The completion status from the verbs provider. This field should be\r
+* initialize to indicate an error to allow detection and cleanup in\r
+* case a communication error occurs between user-mode and kernel-mode.\r
+*\r
+* buf_size\r
+* The size of the buffer in bytes.\r
+*\r
+* buf_info\r
+* Additional buffer information\r
+*\r
+* p_buf\r
+* A reference to a buffer containing vendor specific data. The verbs\r
+* provider must not access pointers in the p_buf between user-mode and\r
+* kernel-mode. Any pointers embedded in the p_buf are invalidated by\r
+* the user-mode/kernel-mode transition.\r
+*\r
+* num_bytes_ret\r
+* The size in bytes of the vendor specific data returned in the buffer.\r
+* This field is set by the verbs provider. The verbs provider should\r
+* verify that the buffer size is sufficient to hold the data being\r
+* returned.\r
+*\r
+* NOTES\r
+* This structure is provided to allow the exchange of vendor specific\r
+* data between the originator and the verbs provider. Users of this\r
+* structure are expected to know the format of data in the p_buf based\r
+* on the structure command field or the usage context.\r
+*****/\r
+\r
+\r
+#endif // __IB_TYPES_EXTENDED_H__\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: cl_dispatcher.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of dispatcher abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_DISPATCHER_H_
+#define _CL_DISPATCHER_H_
+
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_threadpool.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qpool.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_ptr_vector.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* 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_) */
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: cl_event_wheel.h 474 2006-08-31 08:57:19Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of event wheel abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _CL_EVENT_WHEEL_H_
+#define _CL_EVENT_WHEEL_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.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* 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;
+ osm_log_t *p_log;
+} 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.
+*
+* p_log
+* Pointer to opensm log object.
+*
+* 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,
+ IN osm_log_t *p_log);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* 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 osm_log_t *p_log,
+ IN cl_spinlock_t *p_external_lock);
+
+/*
+* PARAMETERS
+* p_event_wheel
+* [in] Pointer to a Event_Wheel.
+*
+* p_log
+* [in] Pointer to opensm log object to be used for logging
+*
+* 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_) */
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_attrib_req.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_ATTRIB_REQ_H_
+#define _OSM_ATTRIB_REQ_H_
+
+#include <opensm/osm_path.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
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****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_ */
+
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_base.h 1927 2009-02-04 15:20:41Z tzachid $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Basic OpenSM definitions and structures.\r
+ * This object represents an OpenSM "base class".\r
+ * This object is part of the OpenSM family of objects.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.15 $\r
+ */\r
+\r
+#ifndef _OSM_BASE_H_\r
+#define _OSM_BASE_H_\r
+\r
+#ifdef __WIN__\r
+#include <vendor/winosm_common.h>\r
+#define OSM_CDECL __cdecl\r
+#else\r
+#define OSM_CDECL\r
+#endif\r
+\r
+#include <complib/cl_types.h>\r
+\r
+#ifdef __cplusplus\r
+# define BEGIN_C_DECLS extern "C" {\r
+# define END_C_DECLS }\r
+#else /* !__cplusplus */\r
+# define BEGIN_C_DECLS\r
+# define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+/****h* OpenSM/Constants\r
+* NAME\r
+* Constants\r
+*\r
+* DESCRIPTION\r
+* The following constants are used throughout the OpenSM.\r
+*\r
+* AUTHOR\r
+* Steve King, Intel\r
+*\r
+*********/\r
+\r
+/****h* OpenSM/Base\r
+* NAME\r
+* Base\r
+*\r
+* DESCRIPTION\r
+* The Base object encapsulates basic information needed by the\r
+* OpenSM to manage objects. Each OpenSM object includes the\r
+* Base object as the first member.\r
+*\r
+* This object should be treated as opaque and should be\r
+* manipulated only through the provided functions.\r
+*\r
+* AUTHOR\r
+* Steve King, Intel\r
+*\r
+*********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_M_KEY\r
+* NAME\r
+* OSM_DEFAULT_M_KEY\r
+*\r
+* DESCRIPTION\r
+* Managment key value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_M_KEY 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SM_KEY\r
+* NAME\r
+* OSM_DEFAULT_SM_KEY\r
+*\r
+* DESCRIPTION\r
+* Subnet Manager key value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SM_KEY 1\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SA_KEY\r
+* NAME\r
+* OSM_DEFAULT_SA_KEY\r
+*\r
+* DESCRIPTION\r
+* Subnet Adminstration key value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SA_KEY OSM_DEFAULT_SM_KEY\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_LMC\r
+* NAME\r
+* OSM_DEFAULT_LMC\r
+*\r
+* DESCRIPTION\r
+* Default LMC value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LMC 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_MAX_OP_VLS\r
+* NAME\r
+* OSM_DEFAULT_MAX_OP_VLS\r
+*\r
+* DESCRIPTION\r
+* Default Maximal Operational VLs to be initialized on \r
+* the link ports PortInfo by the OpenSM.\r
+* Default value provides backward compatibility.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_MAX_OP_VLS 5\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SL\r
+* NAME\r
+* OSM_DEFAULT_SL\r
+*\r
+* DESCRIPTION\r
+* Default SL value used by the OpenSM.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SL 0\r
+/********/\r
+\r
+/****s* OpenSM: Base/OSM_DEFAULT_SM_PRIORITY\r
+* NAME\r
+* OSM_DEFAULT_SM_PRIORITY\r
+*\r
+* DESCRIPTION\r
+* Default SM priority value used by the OpenSM,\r
+* as defined in the SMInfo attribute. 0 is the lowest priority.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SM_PRIORITY 1\r
+/********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TMP_DIR\r
+* NAME\r
+* OSM_DEFAULT_TMP_DIR\r
+*\r
+* DESCRIPTION\r
+* Specifies the default temporary directory for the log file,\r
+* osm-subnet.lst, and other log files.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_TMP_DIR GetOsmTempPath()\r
+#else\r
+#define OSM_DEFAULT_TMP_DIR "/var/log/"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_CACHE_DIR\r
+* NAME\r
+* OSM_DEFAULT_CACHE_DIR\r
+*\r
+* DESCRIPTION\r
+* Specifies the default cache directory for the db files.\r
+* Note that the directory must appear with "/" ("\\" for windows) at the end.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_CACHE_DIR GetOsmCachePath()\r
+#else\r
+#define OSM_DEFAULT_CACHE_DIR "/var/cache/osm/"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LOG_FILE\r
+* NAME\r
+* OSM_DEFAULT_LOG_FILE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default log file name\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_LOG_FILE strcat(GetOsmTempPath(), "osm.log")\r
+#else\r
+#define OSM_DEFAULT_LOG_FILE "/var/log/osm.log"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE\r
+* NAME\r
+* OSM_DEFAULT_PARTITION_CONFIG_FILE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default partition config file name\r
+*\r
+* SYNOPSIS\r
+*/\r
+#ifdef __WIN__\r
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE strcat(GetOsmCachePath(), "osm-partitions.conf")\r
+#else\r
+#define OSM_DEFAULT_PARTITION_CONFIG_FILE "/etc/osm-partitions.conf"\r
+#endif\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SWEEP_INTERVAL_SECS\r
+* NAME\r
+* OSM_DEFAULT_SWEEP_INTERVAL_SECS\r
+*\r
+* DESCRIPTION\r
+* Specifies the default number of seconds between subnet sweeps.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SWEEP_INTERVAL_SECS 10\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC\r
+* NAME\r
+* OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC\r
+*\r
+* DESCRIPTION\r
+* Specifies the default transaction timeout in milliseconds.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC 200\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SUBNET_TIMEOUT\r
+* NAME\r
+* OSM_DEFAULT_SUBNET_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+* Specifies the default transaction timeout.\r
+* timeout time = 4us * 2^timeout.\r
+* We use here ~1sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SUBNET_TIMEOUT 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SWITCH_PACKET_LIFE\r
+* NAME\r
+* OSM_DEFAULT_SWITCH_PACKET_LIFE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default max life time for a pcket on the switch.\r
+* timeout time = 4us * 2^timeout.\r
+* We use here the value of ~1sec\r
+* A Value > 19dec disables this mechanism.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SWITCH_PACKET_LIFE 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_HEAD_OF_QUEUE_LIFE\r
+* NAME\r
+* OSM_DEFAULT_HEAD_OF_QUEUE_LIFE\r
+*\r
+* DESCRIPTION\r
+* Sets the time a packet can live in the head of the VL Queue\r
+* We use here the value of ~1sec\r
+* A Value > 19dec disables this mechanism.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_HEAD_OF_QUEUE_LIFE 0x12\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE\r
+* NAME\r
+* OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE\r
+*\r
+* DESCRIPTION\r
+* Sets the time a packet can live in the head of the VL Queue\r
+* of a port that drives a CA port.\r
+* We use here the value of ~130usec\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE 0xC\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_VL_STALL_COUNT\r
+* NAME\r
+* OSM_DEFAULT_LEAF_VL_COUNT\r
+*\r
+* DESCRIPTION\r
+* Sets the number of consecutive head of queue life time drops that \r
+* puts the VL into stalled state. In stalled state, the port is supposed\r
+* to drop everything for 8*(head of queue lifetime) \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_VL_STALL_COUNT 0x7\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_LEAF_VL_STALL_COUNT\r
+* NAME\r
+* OSM_DEFAULT_LEAF_VL_STALL_COUNT\r
+*\r
+* DESCRIPTION\r
+* Sets the number of consecutive head of queue life time drops that \r
+* puts the VL into stalled state. In stalled state, the port is supposed\r
+* to drop everything for 8*(head of queue lifetime). This value is for\r
+* switch ports driving a CA port.\r
+* We use the value of 1 here - so any drop due to HOQ means stalling the VL\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_LEAF_VL_STALL_COUNT 0x1\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT\r
+* NAME\r
+* OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+* Specifies the default timeout for ignoring same trap.\r
+* timeout time = 5000000us\r
+* We use here ~5sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT 5000000\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_UNHEALTHY_TIMEOUT\r
+* NAME\r
+* OSM_DEFAULT_UNHEALTHY_TIMEOUT\r
+*\r
+* DESCRIPTION\r
+* Specifies the default timeout for setting port as unhealthy.\r
+* timeout time = 60000000us\r
+* We use here ~60sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_UNHEALTHY_TIMEOUT 60000000\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_ERROR_THRESHOLD\r
+* NAME\r
+* OSM_DEFAULT_ERROR_THRESHOLD\r
+*\r
+* DESCRIPTION\r
+* Specifies default link error threshold to be set by SubnMgt(Set.PortInfo).\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_ERROR_THRESHOLD 0x08\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_DEFAULT_SMP_MAX_ON_WIRE\r
+* NAME\r
+* OSM_DEFAULT_SMP_MAX_ON_WIRE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default number of VL15 SMP MADs allowed on \r
+* the wire at any one time.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_DEFAULT_SMP_MAX_ON_WIRE 4\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_RCV_SIZE\r
+* NAME\r
+* OSM_SM_DEFAULT_QP0_RCV_SIZE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default size (in MADs) of the QP0 receive queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP0_RCV_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP0_SEND_SIZE\r
+* NAME\r
+* OSM_SM_DEFAULT_QP0_SEND_SIZE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default size (in MADs) of the QP0 send queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP0_SEND_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_RCV_SIZE\r
+* NAME\r
+* OSM_SM_DEFAULT_QP1_RCV_SIZE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default size (in MADs) of the QP1 receive queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP1_RCV_SIZE 256\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_QP1_SEND_SIZE\r
+* NAME\r
+* OSM_SM_DEFAULT_QP1_SEND_SIZE\r
+*\r
+* DESCRIPTION\r
+* Specifies the default size (in MADs) of the QP1 send queue\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_QP1_SEND_SIZE 256\r
+\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS\r
+* NAME\r
+* OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS\r
+*\r
+* DESCRIPTION\r
+* Specifies the polling timeout (in miliseconds) - the timeout\r
+* between one poll to another.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS 10000\r
+/**********/\r
+\r
+/****d* OpenSM: Base/OSM_SM_DEFAULT_POLLING_RETRY_NUMBER\r
+* NAME\r
+* OSM_SM_DEFAULT_POLLING_RETRY_NUMBER\r
+*\r
+* DESCRIPTION\r
+* Specifies the number of polling retries before the SM goes back\r
+* to DISCOVERY stage. So the default total time for handoff is 40 sec.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SM_DEFAULT_POLLING_RETRY_NUMBER 4\r
+/**********/\r
+\r
+/****d* OpenSM: Base/OSM_NO_PATH\r
+* NAME\r
+* OSM_NO_PATH\r
+*\r
+* DESCRIPTION\r
+* Value indicating there is no path to the given LID.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_NO_PATH 0xFF\r
+/**********/\r
+\r
+/****d* OpenSM: Base/osm_thread_state_t\r
+* NAME\r
+* osm_thread_state_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible states of worker threads, such\r
+* as the subnet sweeper.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_thread_state\r
+{\r
+ OSM_THREAD_STATE_NONE = 0,\r
+ OSM_THREAD_STATE_INIT,\r
+ OSM_THREAD_STATE_RUN,\r
+ OSM_THREAD_STATE_EXIT\r
+\r
+} osm_thread_state_t;\r
+/***********/\r
+\r
+/*\r
+ * OSM_CAP are from Table 117 and C15-0.1.7 Table 186\r
+ */\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_TRAP_SUP\r
+* Name\r
+* OSM_CAP_IS_SUBN_TRAP_SUP\r
+*\r
+* DESCRIPTION\r
+* Management class generates Trap() MADs\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_TRAP_SUP (1 << 0)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_GET_SET_NOTICE_SUP\r
+* Name\r
+* OSM_CAP_IS_GET_SET_NOTICE_SUP\r
+*\r
+* DESCRIPTION\r
+* Management class supports Get/Set(Notice)\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP (1 << 1)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_SUBN_OPT_RECS_SUP\r
+* Name\r
+* OSM_CAP_IS_SUBN_OPT_RECS_SUP\r
+*\r
+* DESCRIPTION\r
+* Support all optional attributes except:\r
+* MCMemberRecord, TraceRecord, MultiPathRecord\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_SUBN_OPT_RECS_SUP (1 << 8)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_UD_MCAST_SUP\r
+* Name\r
+* OSM_CAP_IS_UD_MCAST_SUP\r
+*\r
+* DESCRIPTION\r
+* Multicast is supported \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_UD_MCAST_SUP (1 << 9)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_MULTIPATH_SUP\r
+* Name\r
+* OSM_CAP_IS_MULTIPATH_SUP\r
+*\r
+* DESCRIPTION\r
+* MultiPathRecord and TraceRecord are supported\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_MULTIPATH_SUP (1 << 10)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_REINIT_SUP\r
+* Name\r
+* OSM_CAP_IS_REINIT_SUP\r
+*\r
+* DESCRIPTION\r
+* SM/SA supports re-initialization supported\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_REINIT_SUP (1 << 11)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED\r
+* Name\r
+* OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED\r
+*\r
+* DESCRIPTION\r
+* SM/SA supports enhanced SA PortInfoRecord searches per 1.2 Errata:\r
+* ClassPortInfo:CapabilityMask.IsPortInfoCapMaskMatchSupported is 1, \r
+* then the AttributeModifier of the SubnAdmGet() and SubnAdmGetTable() \r
+* methods affects the matching behavior on the PortInfo:CapabilityMask \r
+* component. If the high-order bit (bit 31) of the AttributeModifier \r
+* is set to 1, matching on the CapabilityMask component will not be an \r
+* exact bitwise match as described in <ref to 15.4.4>. Instead, \r
+* matching will only be performed on those bits which are set to 1 in \r
+* the PortInfo:CapabilityMask embedded in the query. \r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED (1 << 13)\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_sm_state_t\r
+* NAME\r
+* osm_sm_state_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible states of the SM object.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_sm_state\r
+{\r
+ OSM_SM_STATE_NO_STATE = 0,\r
+ OSM_SM_STATE_INIT,\r
+ OSM_SM_STATE_IDLE,\r
+ OSM_SM_STATE_SWEEP_LIGHT,\r
+ OSM_SM_STATE_SWEEP_LIGHT_WAIT,\r
+ OSM_SM_STATE_SWEEP_HEAVY_SELF,\r
+ OSM_SM_STATE_SWEEP_HEAVY_SUBNET,\r
+ OSM_SM_STATE_SET_SM_UCAST_LID,\r
+ OSM_SM_STATE_SET_SM_UCAST_LID_WAIT,\r
+ OSM_SM_STATE_SET_SM_UCAST_LID_DONE,\r
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS,\r
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT,\r
+ OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE,\r
+ OSM_SM_STATE_SET_UCAST_TABLES,\r
+ OSM_SM_STATE_SET_UCAST_TABLES_WAIT,\r
+ OSM_SM_STATE_SET_UCAST_TABLES_DONE,\r
+ OSM_SM_STATE_SET_MCAST_TABLES,\r
+ OSM_SM_STATE_SET_MCAST_TABLES_WAIT,\r
+ OSM_SM_STATE_SET_MCAST_TABLES_DONE,\r
+ OSM_SM_STATE_SET_LINK_PORTS,\r
+ OSM_SM_STATE_SET_LINK_PORTS_WAIT,\r
+ OSM_SM_STATE_SET_LINK_PORTS_DONE,\r
+ OSM_SM_STATE_SET_ARMED,\r
+ OSM_SM_STATE_SET_ARMED_WAIT,\r
+ OSM_SM_STATE_SET_ARMED_DONE,\r
+ OSM_SM_STATE_SET_ACTIVE,\r
+ OSM_SM_STATE_SET_ACTIVE_WAIT,\r
+ OSM_SM_STATE_LOST_NEGOTIATION,\r
+ OSM_SM_STATE_STANDBY,\r
+ OSM_SM_STATE_SUBNET_UP,\r
+ OSM_SM_STATE_PROCESS_REQUEST,\r
+ OSM_SM_STATE_PROCESS_REQUEST_WAIT,\r
+ OSM_SM_STATE_PROCESS_REQUEST_DONE,\r
+ OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED,\r
+ OSM_SM_STATE_SET_PKEY,\r
+ OSM_SM_STATE_SET_PKEY_WAIT,\r
+ OSM_SM_STATE_SET_PKEY_DONE,\r
+ OSM_SM_STATE_MAX\r
+} osm_sm_state_t;\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_signal_t\r
+* NAME\r
+* osm_signal_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible signal codes used by the OSM managers\r
+* This cannot be an enum type, since conversion to and from\r
+* integral types is necessary when passing signals through\r
+* the dispatcher.\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_SIGNAL_NONE 0\r
+#define OSM_SIGNAL_SWEEP 1\r
+#define OSM_SIGNAL_CHANGE_DETECTED 2\r
+#define OSM_SIGNAL_NO_PENDING_TRANSACTIONS 3\r
+#define OSM_SIGNAL_DONE 4\r
+#define OSM_SIGNAL_DONE_PENDING 5\r
+#define OSM_SIGNAL_LOST_SM_NEGOTIATION 6\r
+#define OSM_SIGNAL_LIGHT_SWEEP_FAIL 7\r
+#define OSM_SIGNAL_IDLE_TIME_PROCESS 8\r
+#define OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST 9\r
+#define OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED 10\r
+#define OSM_SIGNAL_EXIT_STBY 11\r
+#define OSM_SIGNAL_MAX 12\r
+\r
+typedef uintn_t osm_signal_t;\r
+/***********/\r
+\r
+/****d* OpenSM: Base/osm_state_mgr_mode_t\r
+* NAME\r
+* osm_state_mgr_mode_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible state progressing codes used by the OSM \r
+* state manager.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_state_mgr_mode\r
+{\r
+ OSM_STATE_STEP_CONTINUOUS = 0,\r
+ OSM_STATE_STEP_TAKE_ONE,\r
+ OSM_STATE_STEP_BREAK\r
+} osm_state_mgr_mode_t;\r
+/*\r
+* OSM_STATE_STEP_CONTINUOUS \r
+* normal automatic progress mode\r
+*\r
+* OSM_STATE_STEP_TAKE_ONE \r
+* Do one step \r
+*\r
+* OSM_STATE_STEP_BREAK\r
+* Stop before taking next step (the while loop in the state \r
+* manager automatically change to this state).\r
+*\r
+**********/\r
+\r
+/****d* OpenSM: Base/osm_sm_signal_t\r
+* NAME\r
+* osm_sm_signal_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible signals used by the OSM_SM_MGR\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_sm_signal\r
+{\r
+ OSM_SM_SIGNAL_INIT = 0,\r
+ OSM_SM_SIGNAL_DISCOVERY_COMPLETED,\r
+ OSM_SM_SIGNAL_POLLING_TIMEOUT,\r
+ OSM_SM_SIGNAL_DISCOVER,\r
+ OSM_SM_SIGNAL_DISABLE,\r
+ OSM_SM_SIGNAL_HANDOVER,\r
+ OSM_SM_SIGNAL_HANDOVER_SENT,\r
+ OSM_SM_SIGNAL_ACKNOWLEDGE,\r
+ OSM_SM_SIGNAL_STANDBY,\r
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED,\r
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE,\r
+ OSM_SM_SIGNAL_WAIT_FOR_HANDOVER,\r
+ OSM_SM_SIGNAL_MAX\r
+\r
+} osm_sm_signal_t;\r
+/***********/\r
+\r
+/****d* OpenSM/osm_mcast_req_type_t\r
+* NAME\r
+* osm_mcast_req_type_t\r
+*\r
+* DESCRIPTION\r
+* Enumerates the possible signals used by the OSM_MCAST_REQUEST\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef enum _osm_mcast_req_type\r
+{\r
+ OSM_MCAST_REQ_TYPE_CREATE,\r
+ OSM_MCAST_REQ_TYPE_JOIN,\r
+ OSM_MCAST_REQ_TYPE_LEAVE,\r
+ OSM_MCAST_REQ_TYPE_SUBNET_CHANGE\r
+\r
+} osm_mcast_req_type_t;\r
+/***********/\r
+\r
+/****s* OpenSM: Base/MAX_UPDN_GUID_FILE_LINE_LENGTH\r
+* NAME\r
+* MAX_UPDN_GUID_FILE_LINE_LENGTH\r
+*\r
+* DESCRIPTION\r
+* The maximum line number when reading updn guid file\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define MAX_UPDN_GUID_FILE_LINE_LENGTH 120\r
+/**********/\r
+\r
+/****s* OpenSM: Base/VendorOUIs\r
+* NAME\r
+* VendorOUIs\r
+*\r
+* DESCRIPTION\r
+* Known device vendor ID and GUID OUIs\r
+*\r
+* SYNOPSIS\r
+*/\r
+#define OSM_VENDOR_ID_INTEL 0x00D0B7\r
+#define OSM_VENDOR_ID_MELLANOX 0x0002C9\r
+#define OSM_VENDOR_ID_REDSWITCH 0x000617\r
+#define OSM_VENDOR_ID_SILVERSTORM 0x00066A\r
+#define OSM_VENDOR_ID_TOPSPIN 0x0005AD\r
+#define OSM_VENDOR_ID_FUJITSU 0x00E000\r
+#define OSM_VENDOR_ID_FUJITSU2 0x000B5D\r
+#define OSM_VENDOR_ID_VOLTAIRE 0x0008F1\r
+#define OSM_VENDOR_ID_YOTTAYOTTA 0x000453\r
+#define OSM_VENDOR_ID_PATHSCALE 0x001175\r
+#define OSM_VENDOR_ID_IBM 0x000255\r
+#define OSM_VENDOR_ID_DIVERGENET 0x00084E\r
+#define OSM_VENDOR_ID_FLEXTRONICS 0x000B8C\r
+#define OSM_VENDOR_ID_AGILENT 0x0030D3\r
+#define OSM_VENDOR_ID_OBSIDIAN 0x001777\r
+#define OSM_VENDOR_ID_BAYMICRO 0x000BC1\r
+#define OSM_VENDOR_ID_LSILOGIC 0x00A0B8\r
+#define OSM_VENDOR_ID_DDN 0x0001FF\r
+#define OSM_VENDOR_ID_PANTA 0x001393\r
+#define OSM_VENDOR_ID_HP 0x001708\r
+#define OSM_VENDOR_ID_RIOWORKS 0x005045\r
+\r
+/**********/\r
+\r
+END_C_DECLS\r
+\r
+#endif /* _OSM_BASE_H_ */\r
+\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_console.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_CONSOLE_H_
+#define _OSM_CONSOLE_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.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
+
+void osm_console(osm_opensm_t *p_osm);
+void osm_console_prompt(void);
+
+END_C_DECLS
+
+#endif /* _OSM_CONSOLE_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_db.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_DB_H_
+#define _OSM_DB_H_
+
+/*
+ * Abstract:
+ * Declaration of the DB interface.
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <complib/cl_list.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_log.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/Database
+* NAME
+* Database
+*
+* DESCRIPTION
+* The OpenSM database interface provide the means to restore persistat
+* data, query, modify, delete and evemtually commit it back to the
+* persistent media.
+*
+* The interface is defined such that it can is not "data dependant":
+* 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;
+ osm_log_t *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* const p_db );
+/*
+* PARAMETERS
+* p_db
+* [in] Pointer to the database object to custruct
+*
+* 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* const 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* const p_db,
+ IN osm_log_t *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* const p_db,
+ IN 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);
+/*
+* 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_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 *const 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 *const p_key,
+ IN char *const 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 *const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_db_pack.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/****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 <opensm/osm_db.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
+
+/****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* const 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* const 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* const 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* const 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* const 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DB_PACK_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_drop_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_DROP_MGR_H_
+#define _OSM_DROP_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.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/Drop Manager
+* NAME
+* Drop Manager
+*
+* DESCRIPTION
+* The Drop Manager object encapsulates the information
+* needed to receive the SwitchInfo attribute from a node.
+*
+* The Drop 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
+*
+*********/
+
+/****s* OpenSM: Drop Manager/osm_drop_mgr_t
+* NAME
+* osm_drop_mgr_t
+*
+* DESCRIPTION
+* Drop Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_drop_mgr
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_req_t *p_req;
+ cl_plock_t *p_lock;
+
+} osm_drop_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_req
+* Pointer to the Request object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Drop Manager object
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_construct
+* NAME
+* osm_drop_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Drop Manager object.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_construct(
+ IN osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Drop Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_drop_mgr_init, osm_drop_mgr_destroy
+*
+* Calling osm_drop_mgr_construct is a prerequisite to calling any other
+* method except osm_drop_mgr_init.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_init,
+* osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_destroy
+* NAME
+* osm_drop_mgr_destroy
+*
+* DESCRIPTION
+* The osm_drop_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_destroy(
+ IN osm_drop_mgr_t* const 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
+* Drop Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_drop_mgr_construct or osm_drop_mgr_init.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_construct,
+* osm_drop_mgr_init
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_init
+* NAME
+* osm_drop_mgr_init
+*
+* DESCRIPTION
+* The osm_drop_mgr_init function initializes a
+* Drop Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_drop_mgr_init(
+ IN osm_drop_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_drop_mgr_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Drop Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Drop Manager methods.
+*
+* SEE ALSO
+* Drop Manager object, osm_drop_mgr_construct,
+* osm_drop_mgr_destroy
+*********/
+
+/****f* OpenSM: Drop Manager/osm_drop_mgr_process
+* NAME
+* osm_drop_mgr_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_drop_mgr_process(
+ IN const osm_drop_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_drop_mgr_t object.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* Drop Manager, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_DROP_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_errors.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of error code ranges for the various OpenSM modules.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_fwd_tbl_t.
+ * This object represents a unicast forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_FWD_TBL_H_
+#define _OSM_FWD_TBL_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_rand_fwd_tbl.h>
+#include <opensm/osm_lin_fwd_tbl.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/Forwarding Table
+* NAME
+* Forwarding Table
+*
+* DESCRIPTION
+* The Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage forwarding tables. The OpenSM
+* allocates one Forwarding Table object per switch in the
+* IBA subnet.
+*
+* The Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_fwd_tbl_t
+* NAME
+* osm_fwd_tbl_t
+*
+* DESCRIPTION
+* Forwarding Table structure. This object hides the type
+* of fowarding table (linear or random) actually used by
+* the switch.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_fwd_tbl_t
+{
+ osm_rand_fwd_tbl_t *p_rnd_tbl;
+ osm_lin_fwd_tbl_t *p_lin_tbl;
+
+} osm_fwd_tbl_t;
+/*
+* FIELDS
+* p_rnd_tbl
+* Pointer to the switch's Random Forwarding Table object.
+* If the switch does not use a Random Forwarding Table,
+* then this pointer is NULL.
+*
+* p_lin_tbl
+* Pointer to the switch's Linear Forwarding Table object.
+* If the switch does not use a Linear Forwarding Table,
+* then this pointer is NULL.
+*
+* SEE ALSO
+* Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_init
+* NAME
+* osm_fwd_tbl_init
+*
+* DESCRIPTION
+* Initializes a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_fwd_tbl_init(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const ib_switch_info_t* const p_si );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* p_si
+* [in] Pointer to the SwitchInfo attribute of the associated
+* switch.
+*
+* RETURN VALUE
+* IB_SUCCESS if the operation is successful.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_destroy
+* NAME
+* osm_fwd_tbl_destroy
+*
+* DESCRIPTION
+* Destroys a Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_fwd_tbl_destroy(
+ IN osm_fwd_tbl_t* const p_tbl );
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get
+* NAME
+* osm_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_fwd_tbl_get(
+ IN const osm_fwd_tbl_t* const p_tbl,
+ IN uint16_t const lid_ho )
+{
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get( p_tbl->p_lin_tbl, lid_ho ) );
+ else
+ return( osm_rand_fwd_tbl_get( p_tbl->p_rnd_tbl, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* lid_ho
+* [in] LID (host order) for which to find the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+* IB_INVALID_PORT_NUM if the table does not have a route for this LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set
+* NAME
+* osm_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_fwd_tbl_set(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ osm_lin_fwd_tbl_set( p_tbl->p_lin_tbl, lid_ho, port );
+ else
+ osm_rand_fwd_tbl_set( p_tbl->p_rnd_tbl, lid_ho, port );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_set_block
+* NAME
+* osm_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_fwd_tbl_set_block(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_set_block( p_tbl->p_lin_tbl,
+ p_block, block_num ) );
+ else
+ return( osm_rand_fwd_tbl_set_block( p_tbl->p_rnd_tbl,
+ p_block, block_num ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_size
+* NAME
+* osm_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_size(
+ IN const osm_fwd_tbl_t* const p_tbl )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_size( p_tbl->p_lin_tbl ) );
+ else
+ return( osm_rand_fwd_tbl_get_size( p_tbl->p_rnd_tbl ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_lids_per_block
+* NAME
+* osm_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_lids_per_block(
+ IN const osm_fwd_tbl_t* const p_tbl )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_lids_per_block( p_tbl->p_lin_tbl ) );
+ else
+ return( osm_rand_fwd_tbl_get_lids_per_block( p_tbl->p_rnd_tbl ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ CL_ASSERT( p_tbl );
+ if( p_tbl->p_lin_tbl )
+ return( osm_lin_fwd_tbl_get_max_block_id_in_use(
+ p_tbl->p_lin_tbl, lid_top_ho ) );
+ else
+ return( osm_rand_fwd_tbl_get_max_block_id_in_use(
+ p_tbl->p_rnd_tbl, lid_top_ho ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_FWD_TBL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_helper.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_HELPER_H_
+#define _OSM_HELPER_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_path.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
+
+/*
+ * Abstract:
+ * Declaration of helpful functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+/****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/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* const p_log,
+ IN const ib_net64_t node_guid,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const ib_port_info_t* const p_pi,
+ IN const 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
+*********/
+
+void
+osm_dump_path_record(
+ IN osm_log_t* const p_log,
+ IN const ib_path_rec_t* const p_pr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_multipath_record(
+ IN osm_log_t* const p_log,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_node_record(
+ IN osm_log_t* const p_log,
+ IN const ib_node_record_t* const p_nr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_mc_record(
+ IN osm_log_t* const p_log,
+ IN const ib_member_rec_t* const p_mcmr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_link_record(
+ IN osm_log_t* const p_log,
+ IN const ib_link_record_t* const p_lr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_service_record(
+ IN osm_log_t* const p_log,
+ IN const ib_service_record_t* const p_sr,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_portinfo_record(
+ IN osm_log_t* const p_log,
+ IN const ib_portinfo_record_t* const p_pir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_guidinfo_record(
+ IN osm_log_t* const p_log,
+ IN const ib_guidinfo_record_t* const p_gir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_inform_info(
+ IN osm_log_t* const p_log,
+ IN const ib_inform_info_t* const p_ii,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_inform_info_record(
+ IN osm_log_t* const p_log,
+ IN const ib_inform_info_record_t* const p_iir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_switch_info_record(
+ IN osm_log_t* const p_log,
+ IN const ib_switch_info_record_t* const p_sir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_sm_info_record(
+ IN osm_log_t* const p_log,
+ IN const ib_sminfo_record_t* const p_smir,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_pkey_block(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint16_t block_num,
+ IN uint8_t port_num,
+ IN const ib_pkey_table_t* const p_pkey_tbl,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_slvl_map_table(
+ IN osm_log_t* const 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* const p_slvl_tbl,
+ IN const osm_log_level_t log_level );
+
+void
+osm_dump_vl_arb_table(
+ IN osm_log_t* const p_log,
+ IN uint64_t port_guid,
+ IN uint8_t block_num,
+ IN uint8_t port_num,
+ IN const ib_vl_arb_table_t* const p_vla_tbl,
+ IN const 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* const p_log,
+ IN const ib_node_info_t* const p_ni,
+ IN const 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* const p_log,
+ IN const ib_sm_info_t* const p_smi,
+ IN const 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* const p_log,
+ IN const ib_switch_info_t* const p_si,
+ IN const 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* const p_log,
+ IN const ib_mad_notice_attr_t *p_ntci,
+ IN const 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 discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+void osm_dump_dr_path(
+ IN osm_log_t* const p_log,
+ IN const osm_dr_path_t* const p_path,
+ IN const osm_log_level_t level );
+
+void osm_dump_smp_dr_path(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t level );
+
+void osm_dump_dr_smp(
+ IN osm_log_t* const p_log,
+ IN const ib_smp_t* const p_smp,
+ IN const osm_log_level_t level );
+
+void osm_dump_sa_mad(
+ IN osm_log_t* const p_log,
+ IN const ib_sa_mad_t* const p_smp,
+ IN const osm_log_level_t level );
+
+/****f* IBA Base: Types/osm_get_sm_state_str
+* NAME
+* osm_get_sm_state_str
+*
+* DESCRIPTION
+* Returns a string for the specified SM state.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_sm_state_str(
+ IN osm_sm_state_t state );
+/*
+* PARAMETERS
+* state
+* [in] SM State value
+*
+* RETURN VALUES
+* Pointer to the state discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****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 discription 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 uint32_t node_type );
+
+const char*
+osm_get_manufacturer_str(
+ IN uint64_t const guid_ho );
+
+const char*
+osm_get_mtu_str(
+ IN uint8_t const mtu );
+
+const char*
+osm_get_lwa_str(
+ IN uint8_t const lwa );
+
+const char*
+osm_get_mtu_str(
+ IN uint8_t const mtu );
+
+const char*
+osm_get_lwa_str(
+ IN uint8_t const lwa );
+
+const char*
+osm_get_lsa_str(
+ IN uint8_t const lsa );
+
+
+/****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 discription 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 discription string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_HELPER_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_inform.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_inform_rec_t.
+ * This object represents an IBA Inform Record.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * Author:
+ * Eitan Zahavi, Mellanox
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_INFR_H_
+#define _OSM_INFR_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_trap_rcv.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/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_t
+{
+ cl_list_item_t list_item;
+ osm_bind_handle_t h_bind;
+ osm_infr_rcv_t* p_infr_rcv;
+ 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
+*
+* p_infr_rcv
+* The receiver of inform_info's
+*
+* 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 service record methods.
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_init
+* NAME
+* osm_infr_new
+*
+* DESCRIPTION
+* Initializes the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_init(
+ IN osm_infr_t* const p_infr,
+ IN const osm_infr_t *p_infr_rec );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+* p_inf_rec
+* [in] Pointer to the ib_inform_info_record_t
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_construct
+* NAME
+* osm_infr_construct
+*
+* DESCRIPTION
+* Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_construct(
+ IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****f* OpenSM: Inform Record/osm_infr_destroy
+* NAME
+* osm_infr_destroy
+*
+* DESCRIPTION
+* Constructs the osm_infr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_destroy(
+ IN osm_infr_t* const p_infr );
+/*
+* PARAMETERS
+* p_infr
+* [in] Pointer to osm_infr_t structure
+*
+* SEE ALSO
+* Inform Record, osm_infr_construct, osm_infr_destroy
+*********/
+
+/****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* const 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_construct, osm_infr_destroy
+*********/
+
+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_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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lid_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lid_mgr_t.
+ * This object represents the LID Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LID_MGR_H_
+#define _OSM_LID_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_log.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 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
+*
+*********/
+
+/****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
+{
+ osm_subn_t *p_subn;
+ osm_db_t *p_db;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ boolean_t send_set_reqs;
+ osm_db_domain_t *p_g2l;
+ cl_ptr_vector_t used_lids;
+ cl_qlist_t free_ranges;
+} osm_lid_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_db
+* Pointer to the database (persistency) object
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* 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.
+*
+* used_lids
+* A vector the maps from the lid to its guid. keeps track of
+* existing and non existing mapping of guid->lid
+*
+* 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
+*
+* 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* const 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* const 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* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_db
+* [in] Pointer to the database object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* 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
+*/
+osm_signal_t
+osm_lid_mgr_process_sm(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* 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
+*/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+ IN osm_lid_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_lid_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+* LID Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LID_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lft_rcv_t.
+ * This object represents the LFT Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFT_RCV_H_
+#define _OSM_LFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/LFT Receiver
+* NAME
+* LFT Receiver
+*
+* DESCRIPTION
+* The LFT Receiver object encapsulates the information
+* needed to receive the LFT attribute from a node.
+*
+* The LFT Receiver 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: LFT Receiver/osm_lft_rcv_t
+* NAME
+* osm_lft_rcv_t
+*
+* DESCRIPTION
+* LFT Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_lft_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* LFT Receiver object
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_construct
+* NAME
+* osm_lft_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a LFT Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_construct(
+ IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a LFT Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lft_rcv_init, osm_lft_rcv_destroy
+*
+* Calling osm_lft_rcv_construct is a prerequisite to calling any other
+* method except osm_lft_rcv_init.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_init,
+* osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_destroy
+* NAME
+* osm_lft_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lft_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_destroy(
+ IN osm_lft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* LFT Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lft_rcv_construct or osm_lft_rcv_init.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_construct,
+* osm_lft_rcv_init
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_init
+* NAME
+* osm_lft_rcv_init
+*
+* DESCRIPTION
+* The osm_lft_rcv_init function initializes a
+* LFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lft_rcv_init(
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other LFT Receiver methods.
+*
+* SEE ALSO
+* LFT Receiver object, osm_lft_rcv_construct,
+* osm_lft_rcv_destroy
+*********/
+
+/****f* OpenSM: LFT Receiver/osm_lft_rcv_process
+* NAME
+* osm_lft_rcv_process
+*
+* DESCRIPTION
+* Process the LFT attribute.
+*
+* SYNOPSIS
+*/
+void osm_lft_rcv_process(
+ IN const osm_lft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's LFT attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT processing was successful.
+*
+* NOTES
+* This function processes a LFT attribute.
+*
+* SEE ALSO
+* LFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFT_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lft_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * LFT attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFT_RCV_CTRL_H_
+#define _OSM_LFT_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_log.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/LFT Receive Controller
+* NAME
+* LFT Receive Controller
+*
+* DESCRIPTION
+* The LFT Receive Controller object
+* encapsulates the information
+* needed to receive the NodeDescription attribute from a node.
+*
+* The LFT Receive 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: LFT Receive Controller/osm_lft_rcv_ctrl_t
+* NAME
+* osm_lft_rcv_ctrl_t
+*
+* DESCRIPTION
+* LFT Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft_rcv_ctrl
+{
+ osm_lft_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lft_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the LFT Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* LFT Receive Controller object
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_construct
+* NAME
+* osm_lft_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a LFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_construct(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a LFT Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lft_rcv_ctrl_init, osm_lft_rcv_ctrl_destroy
+*
+* Calling osm_lft_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_init,
+* osm_lft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_destroy
+* NAME
+* osm_lft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lft_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lft_rcv_ctrl_destroy(
+ IN osm_lft_rcv_ctrl_t* const 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
+* LFT Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lft_rcv_ctrl_construct or osm_lft_rcv_ctrl_init.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+* osm_lft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: LFT Receive Controller/osm_lft_rcv_ctrl_init
+* NAME
+* osm_lft_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lft_rcv_ctrl_init function initializes a
+* LFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl,
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lft_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lft_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LFT Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other LFT Receive Controller methods.
+*
+* SEE ALSO
+* LFT Receive Controller object, osm_lft_rcv_ctrl_construct,
+* osm_lft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_LFT_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lin_fwd_tbl_t.
+ * This object represents a linear forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LIN_FWD_TBL_H_
+#define _OSM_LIN_FWD_TBL_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.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/Linear Forwarding Table
+* NAME
+* Linear Forwarding Table
+*
+* DESCRIPTION
+* The Linear Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage linear forwarding tables. The OpenSM
+* allocates one Linear Forwarding Table object per switch in the
+* IBA subnet, if that switch uses a linear table.
+*
+* The Linear Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_lin_fwd_tbl_t
+* NAME
+* osm_lin_fwd_tbl_t
+*
+* DESCRIPTION
+* Linear Forwarding Table structure.
+*
+* Callers may directly access this object.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lin_fwd_tbl
+{
+ uint16_t size;
+ uint8_t port_tbl[1];
+
+} osm_lin_fwd_tbl_t;
+/*
+* FIELDS
+* Size
+* Number of entries in the linear forwarding table. This value
+* is taken from the SwitchInfo attribute.
+*
+* port_tbl
+* The array that specifies the port number which routes the
+* corresponding LID. Index is by LID.
+*
+* SEE ALSO
+* Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_new
+* NAME
+* osm_lin_tbl_new
+*
+* DESCRIPTION
+* This function creates and initializes a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+ IN uint16_t const size );
+/*
+* PARAMETERS
+* size
+* [in] Number of entries in the Linear Forwarding Table.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_tbl_delete
+* NAME
+* osm_lin_tbl_delete
+*
+* DESCRIPTION
+* This destroys and deallocates a Linear Forwarding Table object.
+*
+* SYNOPSIS
+*/
+void
+osm_lin_tbl_delete(
+ IN osm_lin_fwd_tbl_t** const pp_tbl );
+/*
+* PARAMETERS
+* pp_tbl
+* [in] Pointer a Pointer to the Linear Forwarding Table object.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set
+* NAME
+* osm_lin_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lin_fwd_tbl_set(
+ IN osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ CL_ASSERT( lid_ho < p_tbl->size );
+ if( lid_ho < p_tbl->size )
+ p_tbl->port_tbl[lid_ho] = port;
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get
+* NAME
+* osm_lin_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lin_fwd_tbl_get(
+ IN const osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho )
+{
+ if( lid_ho < p_tbl->size )
+ return( p_tbl->port_tbl[lid_ho] );
+ else
+ return( 0xFF );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_size
+* NAME
+* osm_lin_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_size(
+ IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+ return( p_tbl->size );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_lids_per_block
+* NAME
+* osm_lin_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_lids_per_block(
+ IN const osm_lin_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ return( 64 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_lin_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lin_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ return( (uint16_t)(lid_top_ho /
+ osm_lin_fwd_tbl_get_lids_per_block( p_tbl ) ) );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_lin_fwd_tbl_set_block
+* NAME
+* osm_lin_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Linear Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_lin_fwd_tbl_set_block(
+ IN osm_lin_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ uint16_t lid_start;
+ uint16_t num_lids;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( p_block );
+
+ num_lids = osm_lin_fwd_tbl_get_lids_per_block( p_tbl );
+ lid_start = (uint16_t)(block_num * num_lids);
+
+ if( lid_start + num_lids > p_tbl->size )
+ return( IB_INVALID_PARAMETER );
+
+ memcpy( &p_tbl->port_tbl[lid_start], p_block, num_lids );
+ return( IB_SUCCESS );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LIN_FWD_TBL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_link_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_link_mgr_t.
+ * This object represents the Link Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LINK_MGR_H_
+#define _OSM_LINK_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/Link Manager
+* NAME
+* Link Manager
+*
+* DESCRIPTION
+* The Link Manager object encapsulates the information
+* needed to control unicast LID forwarding on the subnet.
+*
+* The Link 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
+*
+*********/
+
+/****s* OpenSM: Link Manager/osm_link_mgr_t
+* NAME
+* osm_link_mgr_t
+*
+* DESCRIPTION
+* Link Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_link_mgr
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ boolean_t send_set_reqs;
+
+} osm_link_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Link Manager object
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_construct
+* NAME
+* osm_link_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Link Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_construct(
+ IN osm_link_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Link Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_link_mgr_destroy
+*
+* Calling osm_link_mgr_construct is a prerequisite to calling any other
+* method except osm_link_mgr_init.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_init,
+* osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_destroy
+* NAME
+* osm_link_mgr_destroy
+*
+* DESCRIPTION
+* The osm_link_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_link_mgr_destroy(
+ IN osm_link_mgr_t* const 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
+* Link Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_link_mgr_construct or osm_link_mgr_init.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_construct,
+* osm_link_mgr_init
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_init
+* NAME
+* osm_link_mgr_init
+*
+* DESCRIPTION
+* The osm_link_mgr_init function initializes a
+* Link Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_link_mgr_init(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_link_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Link Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Manager methods.
+*
+* SEE ALSO
+* Link Manager object, osm_link_mgr_construct,
+* osm_link_mgr_destroy
+*********/
+
+/****f* OpenSM: Link Manager/osm_link_mgr_process
+* NAME
+* osm_link_mgr_process
+*
+* DESCRIPTION
+* Processes all ports in the subnet per the link manager command.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_link_mgr_process(
+ IN osm_link_mgr_t* const p_mgr,
+ IN const uint8_t link_state );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_link_mgr_t object.
+*
+* link_state
+* [in] state to which to the set the port.
+*
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+*
+* SEE ALSO
+* Link Manager, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LINK_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_log.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_LOG_H_
+#define _OSM_LOG_H_
+
+#ifndef __WIN__
+#include <syslog.h>
+#endif
+#include <complib/cl_log.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <iba/ib_types.h>
+#include <stdio.h>
+
+#ifdef __GNUC__
+#define STRICT_OSM_LOG_FORMAT __attribute__((format(printf, 3, 4)))
+#else
+#define STRICT_OSM_LOG_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__
+
+#define OSM_LOG_ENTER( OSM_LOG_PTR, NAME ) \
+ 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__);
+
+/****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_SYS 0x80
+
+/*
+ DEFAULT - turn on ERROR and INFO only
+*/
+#define OSM_LOG_DEFAULT_LEVEL OSM_LOG_ERROR | OSM_LOG_INFO
+
+/****s* OpenSM: MAD Wrapper/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;
+} osm_log_t;
+/*********/
+
+/****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* const 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* const 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* const p_log,
+ IN const boolean_t flush,
+ IN const uint8_t log_flags,
+ IN const char *log_file,
+ IN const unsigned long max_size,
+ IN const 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_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* const p_log,
+ IN const boolean_t flush,
+ IN const uint8_t log_flags,
+ IN const char *log_file,
+ IN const boolean_t accum_log_file );
+/*
+ * Same as osm_log_init_v2() but without max_size parameter
+ */
+
+/****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* const 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* const p_log,
+ IN const osm_log_level_t level )
+{
+ p_log->level = level;
+}
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to the log object.
+*
+* level
+* [in] New level to set.
+*
+* RETURN VALUES
+* Returns the current log level.
+*
+* 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* const p_log,
+ IN const 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
+*********/
+
+extern int osm_log_printf(osm_log_t *p_log, osm_log_level_t level,
+ const char *fmt, ...);
+
+void
+osm_log(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_str, ... ) STRICT_OSM_LOG_FORMAT;
+
+void
+osm_log_raw(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_buf );
+
+#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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mad_pool.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MAD_POOL_H_
+#define _OSM_MAD_POOL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_atomic.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.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/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
+{
+ osm_log_t *p_log;
+ cl_qlock_pool_t madw_pool;
+ atomic32_t mads_out;
+} osm_mad_pool_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* lock
+* Spinlock guarding the pool.
+*
+* 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* const 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* const 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* const p_pool,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_pool
+* [in] Pointer to an osm_mad_pool_t object to initialize.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+*
+* 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* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const osm_mad_addr_t* const 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* const p_pool,
+ IN osm_madw_t* const 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* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const ib_mad_t* const p_mad,
+ IN const osm_mad_addr_t* const 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* const 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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_madw.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MADW_H_
+#define _OSM_MADW_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.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: 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;
+} osm_bind_info_t;
+/*
+* FIELDS
+* portguid
+* PortGuid of local port
+*
+* 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_processo
+* True if GSI Report msgs are handled
+*
+* send_q_size
+* SendQueueSize
+*
+* recv_q_size
+* Receive Queue Size
+*
+* 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;
+} 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 update_master_sm_base_lid;
+ boolean_t ignore_errors;
+ boolean_t active_transition;
+} osm_pi_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;
+} 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;
+} 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;
+/*********/
+
+#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_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;
+#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;
+ ib_net16_t pkey;
+ 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_pool_item_t pool_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
+* pool_item
+* List linkage for pools and 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_construct
+* NAME
+* osm_madw_construct
+*
+* DESCRIPTION
+* This function constructs a MAD Wrapper object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_madw_construct(
+ IN osm_madw_t* const p_madw )
+{
+ /*
+ Don't touch the pool_item since that is an opaque object.
+ Clear all other objects in the mad wrapper.
+ */
+ memset( ((uint8_t *)p_madw) + sizeof( cl_pool_item_t ), 0,
+ sizeof(*p_madw) - sizeof( cl_pool_item_t ) );
+}
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to a MAD Wrapper object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_madw_init, osm_madw_destroy
+*
+* Calling osm_madw_construct is a prerequisite to calling any other
+* method except osm_madw_init.
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_init, osm_madw_destroy
+*********/
+
+/****f* OpenSM: MAD Wrapper/osm_madw_destroy
+* NAME
+* osm_madw_destroy
+*
+* DESCRIPTION
+* The osm_madw_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_madw_destroy(
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_madw
+* [in] Pointer to a MAD Wrapper object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified MAD Wrapper object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_madw_construct or
+* osm_madw_init.
+*
+* SEE ALSO
+* MAD Wrapper object, osm_madw_construct, osm_madw_init
+*********/
+
+/****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* const p_madw,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t mad_size,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_construct( 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* const 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, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****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* const p_madw )
+{
+ return( (ib_sa_mad_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, osm_madw_construct, osm_madw_destroy
+*********/
+
+/****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* const 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* const 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_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* const 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* const 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* const 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* const 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* const 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* const 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* const 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* const 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* const 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_vend_ptr
+* NAME
+* osm_madw_get_vend_ptr
+*
+* 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* const 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* const 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* const 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* const 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* const p_madw,
+ IN const ib_mad_t* const 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* const p_dest,
+ IN const osm_madw_t* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_matrix.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lid_matrix_t.
+ * This object represents a two dimensional array of port numbers
+ * and LID values.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+
+#ifndef _OSM_MATRIX_H_
+#define _OSM_MATRIX_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_vector.h>
+#include <opensm/osm_base.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/LID Matrix
+* NAME
+* LID Matrix
+*
+* DESCRIPTION
+* The LID Matrix object encapsulates the information needed by the
+* OpenSM to manage fabric routes. It is a two dimensional array
+* index by LID value and Port Number. Each element contains the
+* number of hops from that Port Number to the LID.
+* Every Switch object contains a LID Matrix.
+*
+* The LID Matrix 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: LID Matrix/osm_lid_matrix_t
+* NAME
+* osm_lid_matrix_t
+*
+* DESCRIPTION
+*
+* The LID Matrix object encapsulates the information needed by the
+* OpenSM to manage fabric routes. It is a two dimensional array
+* index by LID value and Port Number. Each element contains the
+* number of hops from that Port Number to the LID.
+* Every Switch object contains a LID Matrix.
+*
+* The LID Matrix is not thread safe, thus callers must provide
+* serialization.
+*
+* The num_ports index into the matrix serves a special purpose, in that it
+* contains the shortest hop path for that LID through any port.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lid_matrix_t
+{
+ cl_vector_t lid_vec;
+ uint8_t num_ports;
+
+} osm_lid_matrix_t;
+/*
+* FIELDS
+* lid_vec
+* Vector (indexed by LID) of port arrays (indexed by port number)
+*
+* num_ports
+* Number of ports at each entry in the LID vector.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_construct
+* NAME
+* osm_lid_matrix_construct
+*
+* DESCRIPTION
+* This function constructs a LID Matrix object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_lid_matrix_construct(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ p_lmx->num_ports = 0;
+ cl_vector_construct( &p_lmx->lid_vec );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to a LID Matrix object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lid_matrix_init, osm_lid_matrix_destroy
+*
+* Calling osm_lid_matrix_construct is a prerequisite to calling any other
+* method except osm_lid_matrix_init.
+*
+* SEE ALSO
+* LID Matrix object, osm_lid_matrix_init, osm_lid_matrix_destroy
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_destroy
+* NAME
+* osm_lid_matrix_destroy
+*
+* DESCRIPTION
+* The osm_lid_matrix_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lid_matrix_destroy(
+ IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to a LID Matrix object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified LID Matrix object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_lid_matrix_construct or
+* osm_lid_matrix_init.
+*
+* SEE ALSO
+* LID Matrix object, osm_lid_matrix_construct, osm_lid_matrix_init
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_init
+* NAME
+* osm_lid_matrix_init
+*
+* DESCRIPTION
+* Initializes a LID Matrix object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lid_matrix_init(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint8_t num_ports );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object to initialize.
+*
+* num_ports
+* [in] Number of ports at each LID index. This value is fixed
+* at initialization time.
+*
+* RETURN VALUES
+* IB_SUCCESS on success
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get
+* NAME
+* osm_lid_matrix_get
+*
+* DESCRIPTION
+* Returns the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get(
+ IN const osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num )
+{
+ CL_ASSERT( port_num < p_lmx->num_ports );
+ CL_ASSERT( lid_ho <cl_vector_get_size(&p_lmx->lid_vec) );
+ return( ((uint8_t *)cl_vector_get_ptr(
+ &p_lmx->lid_vec, lid_ho ))[port_num] );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t 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: LID Matrix/osm_lid_matrix_get_max_lid_ho
+* NAME
+* osm_lid_matrix_get_max_lid_ho
+*
+* DESCRIPTION
+* Returns the maximum LID (host order) value contained
+* in the matrix.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_lid_matrix_get_max_lid_ho(
+ IN const osm_lid_matrix_t* const p_lmx )
+{
+ return( (uint16_t)(cl_vector_get_size( &p_lmx->lid_vec ) - 1 ) );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+* Returns the maximum LID (host order) value contained
+* in the matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_num_ports
+* NAME
+* osm_lid_matrix_get_num_ports
+*
+* DESCRIPTION
+* Returns the number of ports in this lid matrix.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_num_ports(
+ IN const osm_lid_matrix_t* const p_lmx )
+{
+ return( p_lmx->num_ports );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* RETURN VALUES
+* Returns the number of ports in this lid matrix.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_get_least_hops
+* NAME
+* osm_lid_matrix_get_least_hops
+*
+* DESCRIPTION
+* Returns the least number of hops for specified lid
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_lid_matrix_get_least_hops(
+ IN const osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho )
+{
+ if( lid_ho > osm_lid_matrix_get_max_lid_ho( p_lmx ) )
+ return( OSM_NO_PATH );
+
+ return( ((uint8_t *)cl_vector_get_ptr(
+ &p_lmx->lid_vec, lid_ho ))[p_lmx->num_ports] );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] LID (host order) for which to retrieve the shortest hop count.
+*
+* RETURN VALUES
+* Returns the least number of hops for specified lid
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set
+* NAME
+* osm_lid_matrix_set
+*
+* DESCRIPTION
+* Sets the hop count at the specified LID/Port intersection.
+*
+* SYNOPSIS
+*/
+cl_status_t
+osm_lid_matrix_set(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t val );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] LID value (host order) to index into the vector.
+*
+* port_num
+* [in] port number index into the vector entry.
+*
+* val
+* [in] value (number of hops) to assign to this entry.
+*
+* RETURN VALUES
+* Returns the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_set_min_lid_size
+* NAME
+* osm_lid_matrix_set_min_lid_size
+*
+* DESCRIPTION
+* Sets the size of the matrix to at least accomodate the
+* specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_lid_matrix_set_min_lid_size(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho )
+{
+ return( cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 ) );
+}
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object.
+*
+* lid_ho
+* [in] Minimum LID value (host order) to accomodate.
+*
+* RETURN VALUES
+* Sets the size of the matrix to at least accomodate the
+* specified LID value (host ordered)
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: LID Matrix/osm_lid_matrix_clear
+* NAME
+* osm_lid_matrix_clear
+*
+* DESCRIPTION
+* Clears a LID Matrix object in anticipation of a rebuild.
+*
+* SYNOPSIS
+*/
+void
+osm_lid_matrix_clear(
+ IN osm_lid_matrix_t* const p_lmx );
+/*
+* PARAMETERS
+* p_lmx
+* [in] Pointer to an osm_lid_matrix_t object to clear.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MATRIX_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_fwd_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mft_rcv_t.
+ * This object represents the Multicast Forwarding Table Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MFT_RCV_H_
+#define _OSM_MFT_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/MFT Receiver
+* NAME
+* MFT Receiver
+*
+* DESCRIPTION
+* The MFT Receiver object encapsulates the information
+* needed to receive the MFT attribute from a node.
+*
+* The MFT Receiver 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: MFT Receiver/osm_mft_rcv_t
+* NAME
+* osm_mft_rcv_t
+*
+* DESCRIPTION
+* MFT Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_mft_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* MFT Receiver object
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_construct
+* NAME
+* osm_mft_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a MFT Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_construct(
+ IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a MFT Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mft_rcv_init, osm_mft_rcv_destroy
+*
+* Calling osm_mft_rcv_construct is a prerequisite to calling any other
+* method except osm_mft_rcv_init.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_init,
+* osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_destroy
+* NAME
+* osm_mft_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mft_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_destroy(
+ IN osm_mft_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* MFT Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mft_rcv_construct or osm_mft_rcv_init.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_construct,
+* osm_mft_rcv_init
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_init
+* NAME
+* osm_mft_rcv_init
+*
+* DESCRIPTION
+* The osm_mft_rcv_init function initializes a
+* MFT Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_init(
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MFT Receiver methods.
+*
+* SEE ALSO
+* MFT Receiver object, osm_mft_rcv_construct,
+* osm_mft_rcv_destroy
+*********/
+
+/****f* OpenSM: MFT Receiver/osm_mft_rcv_process
+* NAME
+* osm_mft_rcv_process
+*
+* DESCRIPTION
+* Process the MFT attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_process(
+ IN const osm_mft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's MFT attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT processing was successful.
+*
+* NOTES
+* This function processes a MFT attribute.
+*
+* SEE ALSO
+* MFT Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFT_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_fwd_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mft_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * Multicast Forwarding Table attribute from a node (specifically, a
+ * switch).
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MFT_RCV_CTRL_H_
+#define _OSM_MFT_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_log.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/MFT Receive Controller
+* NAME
+* MFT Receive Controller
+*
+* DESCRIPTION
+* The MFT Receive Controller object
+* encapsulates the information
+* needed to receive the Multicast Forwarding Table
+* attribute from a node.
+*
+* The MFT Receive 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: MFT Receive Controller/osm_mft_rcv_ctrl_t
+* NAME
+* osm_mft_rcv_ctrl_t
+*
+* DESCRIPTION
+* MFT Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft_rcv_ctrl
+{
+ osm_mft_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_mft_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the MFT Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* MFT Receive Controller object
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_construct
+* NAME
+* osm_mft_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a MFT Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_construct(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a MFT Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mft_rcv_ctrl_init, osm_mft_rcv_ctrl_destroy
+*
+* Calling osm_mft_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_init,
+* osm_mft_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_destroy
+* NAME
+* osm_mft_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mft_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mft_rcv_ctrl_destroy(
+ IN osm_mft_rcv_ctrl_t* const 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
+* MFT Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mft_rcv_ctrl_construct or osm_mft_rcv_ctrl_init.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+* osm_mft_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MFT Receive Controller/osm_mft_rcv_ctrl_init
+* NAME
+* osm_mft_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mft_rcv_ctrl_init function initializes a
+* MFT Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl,
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mft_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mft_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MFT Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MFT Receive Controller methods.
+*
+* SEE ALSO
+* MFT Receive Controller object, osm_mft_rcv_ctrl_construct,
+* osm_mft_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_MFT_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcast_mgr_t.
+ * This object represents the Multicast Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCAST_MGR_H_
+#define _OSM_MCAST_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_multicast.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 OSM_MCAST_MGR_LIST_SIZE_MIN 256
+
+/****h* OpenSM/Multicast Manager
+* NAME
+* Multicast Manager
+*
+* DESCRIPTION
+* The Multicast Manager object encapsulates the information
+* needed to control multicast LID forwarding on the subnet.
+*
+* The Multicast 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
+*
+*********/
+
+/****s* OpenSM: Multicast Manager/osm_mcast_mgr_t
+* NAME
+* osm_mcast_mgr_t
+*
+* DESCRIPTION
+* Multicast Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcast_mgr
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_mcast_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Multicast Manager object
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_construct
+* NAME
+* osm_mcast_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_construct(
+ IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a Multicast Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_mcast_mgr_destroy
+*
+* Calling osm_mcast_mgr_construct is a prerequisite to calling any other
+* method except osm_mcast_mgr_init.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_init,
+* osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_destroy
+* NAME
+* osm_mcast_mgr_destroy
+*
+* DESCRIPTION
+* The osm_mcast_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcast_mgr_destroy(
+ IN osm_mcast_mgr_t* const 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
+* Multicast Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcast_mgr_construct or osm_mcast_mgr_init.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_construct,
+* osm_mcast_mgr_init
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_init
+* NAME
+* osm_mcast_mgr_init
+*
+* DESCRIPTION
+* The osm_mcast_mgr_init function initializes a
+* Multicast Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_init(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Multicast Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Multicast Manager methods.
+*
+* SEE ALSO
+* Multicast Manager object, osm_mcast_mgr_construct,
+* osm_mcast_mgr_destroy
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+* osm_mcast_mgr_process
+*
+* DESCRIPTION
+* Process and configure the subnet's multicast forwarding tables.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process(
+ IN osm_mcast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+* This function processes the subnet, configuring switch
+* multicast forwarding tables.
+*
+* SEE ALSO
+* Multicast Manager, Node Info Response Controller
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process_mgrp_cb
+* NAME
+* osm_mcast_mgr_process_mgrp_cb
+*
+* DESCRIPTION
+* Callback entry point for the osm_mcast_mgr_process_mgrp function.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+ IN void* const Context1,
+ IN void* const Context2 );
+/*
+* PARAMETERS
+* (Context1) p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* (Context2) p_mgrp
+* [in] Pointer to the multicast group to process.
+*
+* RETURN VALUES
+* IB_SUCCESS
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Manager/osm_mcast_mgr_process
+* NAME
+* osm_mcast_mgr_process_single
+*
+* DESCRIPTION
+* Attempts to add a single port to an existing multicast spanning tree.
+* This function can only succeed if the port to be added is connected
+* to a switch that is already routing traffic for this multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mcast_mgr_process_single(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t join_state );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_mcast_mgr_t object.
+*
+* mlid
+* [in] Multicast LID of relevent multicast group.
+*
+* port_guid
+* [in] GUID of port to attempt to add to the group.
+*
+* join_state
+* [in] Specifies the join state for this port per the spec.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_NOT_DONE
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCAST_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcast_tbl_t.
+ * This object represents a multicast forwarding table.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_MCAST_TBL_H_
+#define _OSM_MCAST_TBL_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.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: 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_fwd_tbl
+{
+ 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 (*p_mask_tbl)[][IB_MCAST_POSITION_MAX];
+} 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 value (host order).
+*
+* pp_mask_tbl
+* Pointer to a two dimensional array of port_masks for this switch.
+* The first dimension is MLID, the 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
+*/
+ib_api_status_t
+osm_mcast_tbl_init(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN uint8_t const num_ports,
+ IN uint16_t const 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
+* IB_SUCCESS on success.
+*
+* 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** const 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_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* const 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* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const 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* const p_tbl,
+ IN const 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* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const 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* const p_tbl,
+ IN const 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* const p_tbl,
+ IN const ib_net16_t* const p_block,
+ IN const int16_t block_num,
+ IN const 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* const p_tbl,
+ IN const int16_t block_num,
+ IN const uint8_t position,
+ OUT ib_net16_t* const 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* const 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* const 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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcm_info.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_INFO_H_
+#define _OSM_MCM_INFO_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.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: Multicast Member Info/osm_mcm_info_t
+* NAME
+* osm_mcm_info_t
+*
+* DESCRIPTION
+* Multicast Membership Info object.
+* This object contains information about a nodes membership
+* in a particular multicast group.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcm_info
+{
+ cl_list_item_t list_item;
+ ib_net16_t mlid;
+
+} osm_mcm_info_t;
+/*
+* FIELDS
+* list_item
+* Linkage structure for cl_qlist. MUST BE FIRST MEMBER!
+*
+* mlid
+* MLID of this multicast group.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_construct
+* NAME
+* osm_mcm_info_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Member Info object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mcm_info_construct(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ memset( p_mcm, 0, sizeof(*p_mcm) );
+}
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a Multicast Member Info object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_destroy
+* NAME
+* osm_mcm_info_destroy
+*
+* DESCRIPTION
+* The osm_mcm_info_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_destroy(
+ IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a Multicast Member Info object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Member Info object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mtree_construct or
+* osm_mtree_init.
+*
+* SEE ALSO
+* Multicast Member Info object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_init
+* NAME
+* osm_mcm_info_init
+*
+* DESCRIPTION
+* Initializes a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_init(
+ IN osm_mcm_info_t* const p_mcm,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to an osm_mcm_info_t object to initialize.
+*
+* mlid
+* [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_new
+* NAME
+* osm_mcm_info_new
+*
+* DESCRIPTION
+* Returns an initialized a Multicast Member Info object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_info_t*
+osm_mcm_info_new(
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* mlid
+* [in] MLID value for this multicast group.
+*
+* RETURN VALUES
+* Pointer to an initialized tree node.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Member Info/osm_mcm_info_delete
+* NAME
+* osm_mcm_info_delete
+*
+* DESCRIPTION
+* Destroys and deallocates the specified object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_info_delete(
+ IN osm_mcm_info_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* Pointer to the object to destroy.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCM_INFO_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcm_port.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MCM_PORT_H_
+#define _OSM_MCM_PORT_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.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: 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;
+ ib_gid_t port_gid;
+ uint8_t scope_state;
+ boolean_t proxy_join;
+} osm_mcm_port_t;
+/*
+* FIELDS
+* map_item
+* Map Item for qmap linkage. Must be first element!!
+*
+* 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 Object
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_construct
+* NAME
+* osm_mcm_port_construct
+*
+* DESCRIPTION
+* This function constructs a MCM Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_construct(
+ IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a MCM Port Object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcm_port_init, osm_mcm_port_destroy.
+*
+* Calling osm_mcm_port_construct is a prerequisite to calling any other
+* method except osm_mcm_port_init.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_init, osm_mcm_port_destroy
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+* osm_mcm_port_destroy
+*
+* DESCRIPTION
+* The osm_mcm_port_destroy function destroys a MCM Port Object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_destroy(
+ IN osm_mcm_port_t* const p_mcm );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to a MCM Port Object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified MCM Port Object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcm_port_construct or osm_mcm_port_init.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_init
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+* osm_mcm_port_init
+*
+* DESCRIPTION
+* The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_init(
+ IN osm_mcm_port_t* const p_mcm,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+* p_mcm
+* [in] Pointer to an osm_mcm_port_t object to initialize.
+*
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* scope_state
+* [in] scope state of the join request
+*
+* proxy_join
+* [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Allows calling other MCM Port Object methods.
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_init
+* NAME
+* osm_mcm_port_init
+*
+* DESCRIPTION
+* The osm_mcm_port_init function initializes a MCM Port Object for use.
+*
+* SYNOPSIS
+*/
+osm_mcm_port_t*
+osm_mcm_port_new(
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join );
+/*
+* PARAMETERS
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* scope_state
+* [in] scope state of the join request
+*
+* proxy_join
+* [in] proxy_join state analyzed from the request
+*
+* RETURN VALUES
+* Pointer to the allocated and initialized MCM Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* MCM Port Object, osm_mcm_port_construct, osm_mcm_port_destroy,
+*********/
+
+/****f* OpenSM: MCM Port Object/osm_mcm_port_destroy
+* NAME
+* osm_mcm_port_destroy
+*
+* DESCRIPTION
+* The osm_mcm_port_destroy function destroys and dellallocates an
+* MCM Port Object, releasing all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mcm_port_delete(
+ IN osm_mcm_port_t* const 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_construct, osm_mcm_port_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCM_PORT_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_msgdef.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of Dispatcher message values.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#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_REQ
+* NAME
+* OSM_MSG_REQ
+*
+* DESCRIPTION
+* Initiates a QP0 attribute request.
+*
+* NOTES
+* Sent by: osm_sm_t
+* Received by: osm_req_ctrl_t
+* Delivery notice: yes
+*
+***********/
+
+/****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
+***********/
+
+/****d* OpenSM: Dispatcher Messages/OSM_MSG_NO_SMPS_OUTSTANDING
+* NAME
+* OSM_MSG_NO_SMPS_OUTSTANDING
+*
+* DESCRIPTION
+* Message indicating that there are no outstanding SMPs on the subnet.
+*
+* NOTES
+* Sent by: osm_mad_ctrl_t
+* Received by: osm_state_mgr_ctrl_t
+* Delivery notice: no
+*
+* SOURCE
+***********/
+enum
+{
+ OSM_MSG_REQ = 0,
+ OSM_MSG_MAD_NODE_INFO,
+ OSM_MSG_MAD_PORT_INFO,
+ OSM_MSG_MAD_SWITCH_INFO,
+ OSM_MSG_MAD_NODE_DESC,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ 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_MAX
+};
+
+END_C_DECLS
+
+#endif /* _OSM_MSGDEF_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mtl_bind.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_BIND_H_
+#define _OSM_BIND_H_
+
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_mtl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.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/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_
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mtree.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mtree_t.
+ * This object represents multicast spanning tree.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MTREE_H_
+#define _OSM_MTREE_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_switch.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 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;
+ 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_construct
+* NAME
+* osm_mtree_node_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Tree Node object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_mtree_node_construct(
+ IN osm_mtree_node_t* const p_mtn )
+{
+ memset( p_mtn, 0, sizeof(*p_mtn) );
+}
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to a Multicast Tree Node object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_destroy
+* NAME
+* osm_mtree_node_destroy
+*
+* DESCRIPTION
+* The osm_mtree_node_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_destroy(
+ IN osm_mtree_node_t* const p_mtn );
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to a Multicast Tree Node object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Tree object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mtree_construct or
+* osm_mtree_init.
+*
+* SEE ALSO
+* Multicast Tree object, osm_mtree_construct, osm_mtree_init
+*********/
+
+/****f* OpenSM: Multicast Tree/osm_mtree_node_init
+* NAME
+* osm_mtree_node_init
+*
+* DESCRIPTION
+* Initializes a Multicast Tree Node object for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mtree_node_init(
+ IN osm_mtree_node_t* const p_mtn,
+ IN const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_mtn
+* [in] Pointer to an osm_mtree_node_t object to initialize.
+*
+* p_sw
+* [in] Pointer to the switch represented by this node.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* 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* const 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* const 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* const p_mtn,
+ IN const 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 osm_switch_t*
+osm_mtree_node_get_switch_ptr(
+ IN const osm_mtree_node_t* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_multicast.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mgrp_t.
+ * This object represents an IBA Multicast Group.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_MULTICAST_H_
+#define _OSM_MULTICAST_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/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
+*
+*********/
+
+/****f* IBA Base: OpneSM: Multicast Group/osm_get_mcast_req_type_str
+* NAME
+* osm_get_mcast_req_type_str
+*
+* DESCRIPTION
+* Returns a string for the specified osm_mcast_req_type_t value.
+*
+* SYNOPSIS
+*/
+const char*
+osm_get_mcast_req_type_str(
+ IN osm_mcast_req_type_t req_type );
+/*
+* PARAMETERS
+* req_type
+* [in] osm_mcast_req_type value
+*
+* RETURN VALUES
+* Pointer to the request type description string.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****s* OpenSM: Multicast Group/osm_mcast_mgr_ctxt_t
+* NAME
+* osm_mcast_mgr_ctxt_t
+*
+* DESCRIPTION
+* Struct for passing context arguments to the multicast manager.
+*
+* The osm_mcast_mgr_ctxt_t object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct osm_mcast_mgr_ctxt
+{
+ ib_net16_t mlid;
+ osm_mcast_req_type_t req_type;
+ ib_net64_t port_guid;
+} osm_mcast_mgr_ctxt_t;
+/*
+* FIELDS
+*
+* mlid
+* The network ordered LID of this Multicast Group (must be >= 0xC000).
+*
+* req_type
+* The type of the request that caused this call
+* (multicast create/join/leave).
+*
+* port_guid
+* The port guid of the port that is being added/removed from
+* the multicast group due to this call.
+*
+* SEE ALSO
+*********/
+
+/****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_map_item_t map_item;
+ ib_net16_t mlid;
+ osm_mtree_node_t *p_root;
+ cl_qmap_t mcm_port_tbl;
+ ib_member_rec_t mcmember_rec;
+ boolean_t well_known;
+ boolean_t to_be_deleted;
+ uint32_t last_change_id;
+ uint32_t last_tree_id;
+} osm_mgrp_t;
+/*
+* FIELDS
+* map_item
+* Map Item for qmap linkage. Must be first element!!
+*
+* mlid
+* The network 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.
+*
+* mcm_port_tbl
+* Table (sorted by port GUID) of osm_mcm_port_t objects
+* representing the member ports of this multicast group.
+*
+* mcmember_rec
+* Hold the parameters of the Multicast Group.
+*
+* well_known
+* Indicates that this is the wellknow multicast group which
+* is created during the initialization of SM/SA and will be
+* present even if there are no ports for this group
+*
+* to_be_deleted
+* Since groups are deleted only after re-route we need to
+* track the fact the group is about to be deleted so we can
+* track the fact a new join is actually a create request.
+*
+* last_change_id
+* a counter for the number of changes applied to the group.
+* This counter shuold be incremented on any modification
+* to the group: joining or leaving of ports.
+*
+* last_tree_id
+* the last change id used for building the current tree.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Vendor API/osm_mgrp_func_t
+* NAME
+* osm_mgrp_func_t
+*
+* DESCRIPTION
+* Callback for the osm_mgrp_apply_func function.
+* The callback function must not modify the tree linkage.
+*
+* SYNOPSIS
+*/
+typedef void (*osm_mgrp_func_t)(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const osm_mtree_node_t* const p_mtn,
+ IN void* context );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to the multicast group object.
+*
+* p_mtn
+* [in] Pointer to the multicast tree node.
+*
+* context
+* [in] User context.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_construct
+* NAME
+* osm_mgrp_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_construct(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to a Multicast Group to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mgrp_init, osm_mgrp_destroy.
+*
+* Calling osm_mgrp_construct is a prerequisite to calling any other
+* method except osm_mgrp_init.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_init, osm_mgrp_destroy
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_destroy
+* NAME
+* osm_mgrp_destroy
+*
+* DESCRIPTION
+* The osm_mgrp_destroy function destroys a Multicast Group, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_destroy(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to a Muticast Group to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Multicast Group.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_mgrp_construct or
+* osm_mgrp_init.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_init
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_init
+* NAME
+* osm_mgrp_init
+*
+* DESCRIPTION
+* The osm_mgrp_init function initializes a Multicast Group for use.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_init(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object to initialize.
+*
+* mlid
+* [in] Multicast LID for this multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* Allows calling other Multicast Group methods.
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****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 const ib_net16_t mlid );
+/*
+* PARAMETERS
+* mlid
+* [in] Multicast LID 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_construct, osm_mgrp_destroy,
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_delete
+* NAME
+* osm_mgrp_delete
+*
+* DESCRIPTION
+* Destroys and de-allocates a Multicast Group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_delete(
+ IN osm_mgrp_t* const p_mgrp );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group, osm_mgrp_construct, osm_mgrp_destroy,
+*********/
+
+/****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* const p_mgrp,
+ IN const 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* const 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* const 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(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t join_state,
+ IN boolean_t proxy_join);
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object to initialize.
+*
+* p_port_gid
+* [in] Pointer to the GID of the port to add to the multicast group.
+*
+* join_state
+* [in] The join state for this port in the group.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_is_port_present
+* NAME
+* osm_mgrp_is_port_present
+*
+* DESCRIPTION
+* checks a port from the multicast group.
+*
+* SYNOPSIS
+*/
+
+boolean_t
+osm_mgrp_is_port_present(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid,
+ OUT osm_mcm_port_t ** const pp_mcm_port);
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* port_guid
+* [in] Port guid of the departing port.
+*
+* pp_mcm_port
+* [out] Pointer to a pointer to osm_mcm_port_t
+* Updated to the member on success or NULLed
+*
+* RETURN VALUES
+* TRUE if port present
+* FALSE if port is not present.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_remove_port
+* NAME
+* osm_mgrp_remove_port
+*
+* DESCRIPTION
+* Removes a port from the multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_remove_port(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+*
+* p_subn
+* [in] Pointer to the subnet object
+*
+* p_log
+* [in] The log object pointer
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* port_guid
+* [in] Port guid of the departing port.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_get_root_switch
+* NAME
+* osm_mgrp_get_root_switch
+*
+* DESCRIPTION
+* Returns the "root" switch of this multicast group. The root switch
+* is at the trunk of the multicast single spanning tree.
+*
+* SYNOPSIS
+*/
+static inline osm_switch_t*
+osm_mgrp_get_root_switch(
+ IN const osm_mgrp_t* const p_mgrp )
+{
+ if( p_mgrp->p_root )
+ return( p_mgrp->p_root->p_sw );
+ else
+ return( NULL );
+}
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* Returns the "root" switch of this multicast group. The root switch
+* is at the trunk of the multicast single spanning tree.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_compute_avg_hops
+* NAME
+* osm_mgrp_compute_avg_hops
+*
+* DESCRIPTION
+* Returns the average number of hops from the given to switch
+* to all member of a multicast group.
+*
+* SYNOPSIS
+*/
+float
+osm_mgrp_compute_avg_hops(
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* p_sw
+* [in] Pointer to the switch from which to measure.
+*
+* RETURN VALUES
+* Returns the average number of hops from the given to switch
+* to all member of a multicast group.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_apply_func
+* NAME
+* osm_mgrp_apply_func
+*
+* DESCRIPTION
+* Calls the specified function for each element in the tree.
+* Elements are passed to the callback function in no particular order.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_apply_func(
+ const osm_mgrp_t* const p_mgrp,
+ osm_mgrp_func_t p_func,
+ void* context );
+/*
+* PARAMETERS
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* p_func
+* [in] Pointer to the users callback function.
+*
+* context
+* [in] User context passed to the callback function.
+*
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_delete_notice
+* NAME
+* osm_mgrp_send_delete_notice
+*
+* DESCRIPTION
+* Sends a notice that the given multicast group is now deleted.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_delete_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+/****f* OpenSM: Multicast Group/osm_mgrp_send_create_notice
+* NAME
+* osm_mgrp_send_create_notice
+*
+* DESCRIPTION
+* Sends a notice that the given multicast group is now created.
+*
+* SYNOPSIS
+*/
+void
+osm_mgrp_send_create_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp );
+/*
+* PARAMETERS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_mgrp
+* [in] Pointer to an osm_mgrp_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Multicast Group
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MULTICAST_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_node_t.
+ * This object represents an IBA node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NODE_H_
+#define _OSM_NODE_H_
+
+#include <complib/cl_qmap.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_madw.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
+
+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;
+ 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.
+*
+* phsyp_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 bizzare reason.
+*
+* phsyp_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_destroy
+* NAME
+* osm_node_destroy
+*
+* DESCRIPTION
+* The osm_node_destroy function destroys a node, releasing
+* all resources.
+*
+* SYNOPSIS
+*/void
+osm_node_destroy(
+ IN osm_node_t *p_node );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer a Node object to destroy.
+*
+* 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_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** const 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* const 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_is_lid
+* NAME
+* osm_node_is_lid
+*
+* DESCRIPTION
+* Indicates if the specified LID belongs to this node.
+*
+* SYNOPSIS
+*/
+boolean_t osm_node_is_lid(
+ IN const osm_node_t* const p_node,
+ IN const uint16_t lid );
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* lid
+* [in] LID value.
+*
+* RETURN VALUES
+* TRUE if the specified LID belongs to the node,
+* FALSE 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 const osm_node_t* const p_node,
+ IN const uint32_t port_num )
+{
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+ return( (osm_physp_t*)&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_any_physp_ptr
+* NAME
+* osm_node_get_any_physp_ptr
+*
+* DESCRIPTION
+* Returns a pointer to any valid physical port object associated
+* with this node. This operation is mostly meaningful for switches,
+* in which case all the Physical Ports share the same GUID.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_node_get_any_physp_ptr(
+ IN const osm_node_t* const p_node )
+{
+ CL_ASSERT( p_node );
+ return( (osm_physp_t*)&p_node->physp_table[
+ ib_node_info_get_local_port_num( &p_node->node_info )] );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns a pointer to any valid physical port object associated
+* with this node. This operation is mostly meaningful for switches,
+* in which case all the Physical Ports share the same GUID.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_get_any_path
+* NAME
+* osm_node_get_any_path
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline osm_dr_path_t*
+osm_node_get_any_dr_path_ptr(
+ IN const osm_node_t* const p_node )
+{
+ CL_ASSERT( p_node );
+ return( osm_physp_get_dr_path_ptr( &p_node->physp_table[
+ ib_node_info_get_local_port_num( &p_node->node_info )] ) );
+}
+/*
+* 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* const 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 type of this node.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_num_physp(
+ IN const osm_node_t* const 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 const osm_node_t* const p_node,
+ IN const 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* const p_node,
+ IN const 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 const osm_node_t* const p_node,
+ IN const 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_remote_type
+* NAME
+* osm_node_get_remote_type
+*
+* DESCRIPTION
+* Returns the type of the node on the other side
+* of the wire from the specified port on this node.
+* The remote node must exist.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_node_get_remote_type(
+ IN const osm_node_t* const p_node,
+ IN const uint8_t port_num )
+{
+ osm_node_t *p_remote_node;
+
+ p_remote_node = osm_node_get_remote_node( p_node, port_num, NULL );
+ CL_ASSERT( p_remote_node );
+ return( osm_node_get_type( p_remote_node ) );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* port_num
+* [in] Local port number.
+*
+* RETURN VALUES
+* Returns the type of the node on the other side
+* of the wire from the specified port on this node.
+*
+* 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* const p_node,
+ IN const 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* const p_node,
+ IN const osm_madw_t* const 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_discovery_count_get
+* NAME
+* osm_node_discovery_count_get
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_node_discovery_count_get(
+ IN const osm_node_t* const p_node )
+{
+ return( p_node->discovery_count );
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_reset
+* NAME
+* osm_node_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this node to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_reset(
+ IN osm_node_t* const p_node )
+{
+ p_node->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_node_discovery_count_inc
+* NAME
+* osm_node_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_node_discovery_count_inc(
+ IN osm_node_t* const p_node )
+{
+ p_node->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_node
+* [in] Pointer to an osm_node_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node 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* const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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* const p_node,
+ IN const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_desc_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nd_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ND_RCV_H_
+#define _OSM_ND_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/Node Description Receiver
+* NAME
+* Node Description Receiver
+*
+* DESCRIPTION
+* The Node Description Receiver object encapsulates the information
+* needed to receive the NodeInfo attribute from a node.
+*
+* The Node Description Receiver 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: Node Description Receiver/osm_nd_rcv_t
+* NAME
+* osm_nd_rcv_t
+*
+* DESCRIPTION
+* Node Description Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_nd_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Node Description Receiver object
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_construct
+* NAME
+* osm_nd_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Description Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_construct(
+ IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Node Description Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nd_rcv_init, osm_nd_rcv_destroy
+*
+* Calling osm_nd_rcv_construct is a prerequisite to calling any other
+* method except osm_nd_rcv_init.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_init,
+* osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_destroy
+* NAME
+* osm_nd_rcv_destroy
+*
+* DESCRIPTION
+* The osm_nd_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_destroy(
+ IN osm_nd_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Description Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nd_rcv_construct or osm_nd_rcv_init.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_construct,
+* osm_nd_rcv_init
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_init
+* NAME
+* osm_nd_rcv_init
+*
+* DESCRIPTION
+* The osm_nd_rcv_init function initializes a
+* Node Description Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nd_rcv_init(
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Description Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Description Receiver methods.
+*
+* SEE ALSO
+* Node Description Receiver object, osm_nd_rcv_construct,
+* osm_nd_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Description Receiver/osm_nd_rcv_process
+* NAME
+* osm_nd_rcv_process
+*
+* DESCRIPTION
+* Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_nd_rcv_process(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+* This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+* Node Description Receiver, Node Description Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_ND_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_desc_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nd_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeDescription
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_ND_RCV_CTRL_H_
+#define _OSM_ND_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_log.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/Node Description Receive Controller
+* NAME
+* Node Description Receive Controller
+*
+* DESCRIPTION
+* The Node Description Receive Controller object encapsulates the information
+* needed to receive the NodeDescription attribute from a node.
+*
+* The Node Description Receive 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: Node Description Receive Controller/osm_nd_rcv_ctrl_t
+* NAME
+* osm_nd_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Description Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nd_rcv_ctrl
+{
+ osm_nd_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_nd_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Description Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Description Receive Controller object
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_construct
+* NAME
+* osm_nd_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Description Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_construct(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Description Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nd_rcv_ctrl_init, osm_nd_rcv_ctrl_destroy
+*
+* Calling osm_nd_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_init,
+* osm_nd_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_destroy
+* NAME
+* osm_nd_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_nd_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_nd_rcv_ctrl_destroy(
+ IN osm_nd_rcv_ctrl_t* const 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
+* Node Description Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nd_rcv_ctrl_construct or osm_nd_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+* osm_nd_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Description Receive Controller/osm_nd_rcv_ctrl_init
+* NAME
+* osm_nd_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_nd_rcv_ctrl_init function initializes a
+* Node Description Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl,
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_nd_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_nd_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Description Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Description Receive Controller methods.
+*
+* SEE ALSO
+* Node Description Receive Controller object, osm_nd_rcv_ctrl_construct,
+* osm_nd_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_ND_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NI_RCV_H_
+#define _OSM_NI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_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
+
+/****h* OpenSM/Node Info Receiver
+* NAME
+* Node Info Receiver
+*
+* DESCRIPTION
+* The Node Info Receiver object encapsulates the information
+* needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receiver 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: Node Info Receiver/osm_ni_rcv_t
+* NAME
+* osm_ni_rcv_t
+*
+* DESCRIPTION
+* Node Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_gen_req;
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_ni_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_construct
+* NAME
+* osm_ni_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_construct(
+ IN osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_ni_rcv_init, osm_ni_rcv_destroy,
+* and osm_ni_rcv_is_inited.
+*
+* Calling osm_ni_rcv_construct is a prerequisite to calling any other
+* method except osm_ni_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_init,
+* osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_destroy
+* NAME
+* osm_ni_rcv_destroy
+*
+* DESCRIPTION
+* The osm_ni_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_destroy(
+ IN osm_ni_rcv_t* const 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
+* Node Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ni_rcv_construct or osm_ni_rcv_init.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_init
+* NAME
+* osm_ni_rcv_init
+*
+* DESCRIPTION
+* The osm_ni_rcv_init function initializes a
+* Node Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_init(
+ IN osm_ni_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receiver methods.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_destroy, osm_ni_rcv_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_is_inited
+* NAME
+* osm_ni_rcv_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_ni_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_is_inited(
+ IN const osm_ni_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_ni_rcv_construct or osm_ni_rcv_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receiver object, osm_ni_rcv_construct,
+* osm_ni_rcv_init
+*********/
+
+/****f* OpenSM: Node Info Receiver/osm_ni_rcv_process
+* NAME
+* osm_ni_rcv_process
+*
+* DESCRIPTION
+* Process the NodeInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_process(
+ IN const osm_ni_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the NodeInfo processing was successful.
+*
+* NOTES
+* This function processes a NodeInfo attribute.
+*
+* SEE ALSO
+* Node Info Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ni_rcv_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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NI_RCV_CTRL_H_
+#define _OSM_NI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node_info_rcv.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/Node Info Receive Controller
+* NAME
+* Node Info Receive Controller
+*
+* DESCRIPTION
+* The Node Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Info Receive 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: Node Info Receive Controller/osm_ni_rcv_ctrl_t
+* NAME
+* osm_ni_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_ni_rcv_ctrl
+{
+ osm_ni_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_ni_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Info Receive Controller object
+* Node Info Receiver object
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_construct
+* NAME
+* osm_ni_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_construct(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_ni_rcv_ctrl_init, osm_ni_rcv_ctrl_destroy,
+* and osm_ni_rcv_ctrl_is_inited.
+*
+* Calling osm_ni_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_init,
+* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_destroy
+* NAME
+* osm_ni_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_ni_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_ni_rcv_ctrl_destroy(
+ IN osm_ni_rcv_ctrl_t* const 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
+* Node Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_init
+* NAME
+* osm_ni_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_ni_rcv_ctrl_init function initializes a
+* Node Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_ni_rcv_ctrl_init(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl,
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_ni_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Info Receive Controller methods.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_destroy, osm_ni_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Node Info Receive Controller/osm_ni_rcv_ctrl_is_inited
+* NAME
+* osm_ni_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_ni_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_ni_rcv_ctrl_is_inited(
+ IN const osm_ni_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_ni_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_ni_rcv_ctrl_construct or osm_ni_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Node Info Receive Controller object, osm_ni_rcv_ctrl_construct,
+* osm_ni_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NI_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_opensm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_opensm_t.
+ * This object represents the OpenSM super object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_OPENSM_H_
+#define _OSM_OPENSM_H_
+
+#include <signal.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_atomic.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_db.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.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/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
+*
+*********/
+
+/****s* OpenSM: OpenSM/osm_routing_engine
+* NAME
+* struct osm_routing_engine
+*
+* DESCRIPTION
+* OpenSM routing engine module definition.
+* NOTES
+* routing engine structure - yet limited by ucast_fdb_assign and
+* ucast_build_fwd_tables (multicast callbacks may be added later)
+*/
+struct osm_routing_engine {
+ 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 (*delete)(void *context);
+};
+/*
+* 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.
+*
+* delete
+* The delete method, may be used for routing engine
+* internals cleanup.
+*/
+
+/****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_t
+{
+ osm_subn_t subn;
+ osm_sm_t sm;
+ osm_sa_t sa;
+ osm_db_t db;
+ osm_mad_pool_t mad_pool;
+ osm_vendor_t *p_vendor;
+ osm_vl15_t vl15;
+ osm_log_t log;
+ cl_dispatcher_t disp;
+ cl_plock_t lock;
+ struct osm_routing_engine routing_engine;
+ osm_stats_t stats;
+} osm_opensm_t;
+/*
+* FIELDS
+* 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.
+*
+* lock
+* Shared lock guarding most OpenSM structures.
+*
+* routing_engine
+* Routing engine; will be initialized then 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* const 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_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* const 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_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* const p_osm,
+ IN const osm_subn_opt_t* const 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_sweep
+* NAME
+* osm_opensm_sweep
+*
+* DESCRIPTION
+* Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_opensm_sweep(
+ IN osm_opensm_t* const 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* const p_osm,
+ IN const 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* const p_osm,
+ IN const 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* const p_osm,
+ IN uint32_t const wait_us,
+ IN boolean_t const 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
+*********/
+
+/****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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_partition.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_prtn_t.
+ * This object represents an IBA Partition.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PARTITION_H_
+#define _OSM_PARTITION_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.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/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;
+ uint16_t pkey;
+ uint8_t sl;
+ cl_map_t full_guid_tbl;
+ cl_map_t part_guid_tbl;
+ char name[32];
+} 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.
+*
+* 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 OUT osm_prtn_t** const 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 const 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* const p_prtn,
+ IN const 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 * const p_log,
+ IN osm_subn_t * const 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PARTITION_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_path.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PATH_H_
+#define _OSM_PATH_H_
+
+#include <string.h>
+#include <opensm/osm_base.h>
+#include <vendor/osm_vendor.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
+
+/*
+ * Abstract:
+ * Declaration of path related objects.
+ * These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+/****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
+{
+ osm_bind_handle_t h_bind;
+ 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* const p_path )
+{
+ /* The first location in the path array is reserved. */
+ memset( p_path, 0, sizeof(*p_path) );
+ p_path->h_bind = OSM_BIND_INVALID_HANDLE;
+}
+
+/*
+* 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* const p_path,
+ IN const osm_bind_handle_t h_bind,
+ IN const 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->h_bind = h_bind;
+ p_path->hop_count = hop_count;
+ memcpy( p_path->path, path, IB_SUBNET_PATH_HOPS_MAX );
+}
+
+/*
+* 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 void
+osm_dr_path_extend(
+ IN osm_dr_path_t* const p_path,
+ IN const uint8_t port_num )
+{
+ p_path->hop_count++;
+ CL_ASSERT( p_path->hop_count < IB_SUBNET_PATH_HOPS_MAX );
+ /*
+ Location 0 in the path array is reserved per IB spec.
+ */
+ p_path->path[p_path->hop_count] = port_num;
+}
+
+/*
+* 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 VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: DR Path/osm_dr_path_get_bind_handle
+* NAME
+* osm_dr_path_get_bind_handle
+*
+* DESCRIPTION
+* Gets the bind handle from a path.
+*
+* SYNOPSIS
+*/
+static inline osm_bind_handle_t
+osm_dr_path_get_bind_handle(
+ IN const osm_dr_path_t* const p_path )
+{
+ return( p_path->h_bind );
+}
+
+/*
+* 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 VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PATH_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_H_
+#define _OSM_PKEY_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_req.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
+
+/*
+ Forward references.
+*/
+struct _osm_physp;
+struct _osm_port;
+struct _osm_subn;
+struct _osm_node;
+struct _osm_physp;
+
+/*
+ * Abstract:
+ * Declaration of pkey manipulation functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+/****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_pkey_tbl
+{
+ cl_ptr_vector_t blocks;
+ cl_ptr_vector_t new_blocks;
+ cl_map_t keys;
+ cl_qlist_t pending;
+ uint16_t used_blocks;
+ uint16_t max_blocks;
+} osm_pkey_tbl_t;
+/*
+* FIELDS
+* 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
+*
+* 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_get_num_blocks
+* NAME
+* osm_pkey_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)) ?
+ cl_ptr_vector_get(&p_pkey_tbl->blocks, block) : NULL );
+};
+/*
+* p_pkey_tbl
+* [in] Pointer to osm_pkey_tbl_t object.
+*
+* block
+* [in] The lock 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)) ?
+ cl_ptr_vector_get(&p_pkey_tbl->new_blocks, block) : NULL;
+};
+
+/****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);
+/*
+* 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
+*
+* 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 * const p_physp1,
+ IN const struct _osm_physp * const p_physp2,
+ IN const ib_net16_t pkey);
+/*
+* 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.
+*
+* 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 * const p_physp1,
+ IN const struct _osm_physp * const p_physp2 );
+/*
+* PARAMETERS
+*
+* p_physp1
+* [in] Pointer to an osm_physp_t object.
+*
+* p_physp2
+* [in] Pointer to an osm_physp_t object.
+*
+* 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* const p_physp_1,
+ IN const struct _osm_physp* const p_physp_2 );
+
+/*
+* 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.
+*
+* 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* const p_port_1,
+ IN const struct _osm_port* const p_port_2 );
+
+/*
+* 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_lid_share_pkey
+* NAME
+* osm_lid_share_pkey
+*
+* DESCRIPTION
+* Checks if the given lids and port_numbers 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_lid_share_pkey(
+ IN osm_log_t* p_log,
+ IN const struct _osm_subn* const p_subn,
+ IN const ib_net16_t lid1,
+ IN const uint8_t port_num1,
+ IN const ib_net16_t lid2,
+ IN const uint8_t port_num2 );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_subn
+* [in] Pointer to the subnet object for accessing of the options.
+*
+* lid1
+* [in] lid number of first port.
+*
+* port_num1
+* [in] port number of first port.
+*
+* lid2
+* [in] lid number of second port.
+*
+* port_num2
+* [in] port number of second port.
+*
+* RETURN VALUES
+* Returns TRUE if the 2 physical ports that belong to these lids/port_numbers
+* are matching. FALSE otherwise.
+*
+* NOTES
+*
+*********/
+
+/****f* OpenSM: osm_physp_has_pkey
+* NAME
+* osm_physp_has_pkey
+*
+* DESCRIPTION
+* Checks if the given lids and port_numbers 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_has_pkey(
+ IN osm_log_t* p_log,
+ IN const ib_net16_t pkey,
+ IN const struct _osm_physp* const 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_get_tables
+* NAME
+* osm_pkey_get_tables
+*
+* DESCRIPTION
+* Sends a request for getting the pkey tables of the given physp.
+*
+* SYNOPSIS
+*/
+void osm_pkey_get_tables(
+ IN osm_log_t *p_log,
+ IN osm_req_t *p_req,
+ IN osm_subn_t* const p_subn,
+ IN struct _osm_node* const p_node,
+ IN struct _osm_physp* const p_physp );
+
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to osm_log object.
+*
+* p_req
+* [in] Pointer to osm_req object.
+*
+* p_subn
+* [in] Pointer to osm_subn object.
+*
+* p_node
+* [in] Pointer to osm_node object.
+*
+* p_physp
+* [in] Pointer to osm_physp_t object.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Prototype for osm_pkey_mgr_process() function
+ * This is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PKEY_MGR_H_
+#define _OSM_PKEY_MGR_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_opensm.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
+
+/****f* OpenSM: P_Key Manager/osm_pkey_mgr_process
+* NAME
+* osm_pkey_mgr_process
+*
+* DESCRIPTION
+* This function enforces the pkey rules on the SM DB.
+*
+* SYNOPSIS
+*/
+osm_signal_t
+osm_pkey_mgr_process(
+ IN osm_opensm_t *p_osm );
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_RCV_H_
+#define _OSM_PKEY_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.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/P_Key Receiver
+* NAME
+* P_Key Receiver
+*
+* DESCRIPTION
+* The P_Key Receiver object encapsulates the information
+* needed to set or get the vl arbitration attribute from a port.
+*
+* The P_Key Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Receiver/osm_pkey_rcv_t
+* NAME
+* osm_pkey_rcv_t
+*
+* DESCRIPTION
+* P_Key Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_pkey_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_construct
+* NAME
+* osm_pkey_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_construct(
+ IN osm_pkey_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rcv_destroy
+*
+* Calling osm_pkey_rcv_construct is a prerequisite to calling any other
+* method except osm_pkey_rcv_init.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_init,
+* osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_destroy
+* NAME
+* osm_pkey_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_destroy(
+ IN osm_pkey_rcv_t* const 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
+* P_Key Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rcv_construct or osm_pkey_rcv_init.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_construct,
+* osm_pkey_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_init
+* NAME
+* osm_pkey_rcv_init
+*
+* DESCRIPTION
+* The osm_pkey_rcv_init function initializes a
+* P_Key Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_init(
+ IN osm_pkey_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Receiver methods.
+*
+* SEE ALSO
+* P_Key Receiver object, osm_pkey_rcv_construct,
+* osm_pkey_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Receiver/osm_pkey_rcv_process
+* NAME
+* osm_pkey_rcv_process
+*
+* DESCRIPTION
+* Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_process(
+ IN const osm_pkey_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* P_Key Receiver, P_Key Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_RCV_CTRL_H_
+#define _OSM_PKEY_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_pkey_rcv.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/P_Key Table Receive Controller
+* NAME
+* P_Key Receive Controller
+*
+* DESCRIPTION
+* The P_Key Receive Controller object encapsulates
+* the information needed to get or set P_Key table of a port.
+*
+* The P_Key Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_t
+* NAME
+* osm_pkey_rcv_ctrl_t
+*
+* DESCRIPTION
+* P_Key Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rcv_ctrl
+{
+ osm_pkey_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pkey_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the P_Key Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* P_Key Receive Controller object
+* P_Key Receiver object
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_construct
+* NAME
+* osm_pkey_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_construct(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rcv_ctrl_init, osm_pkey_rcv_ctrl_destroy,
+* and osm_pkey_rcv_ctrl_is_inited.
+*
+* Calling osm_pkey_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_init,
+* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_destroy
+* NAME
+* osm_pkey_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rcv_ctrl_destroy(
+ IN osm_pkey_rcv_ctrl_t* const 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
+* P_Key Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_init
+* NAME
+* osm_pkey_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pkey_rcv_ctrl_init function initializes a
+* P_Key Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rcv_ctrl_init(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pkey_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Receive Controller methods.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_destroy, osm_pkey_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: P_Key Receive Controller/osm_pkey_rcv_ctrl_is_inited
+* NAME
+* osm_pkey_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pkey_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pkey_rcv_ctrl_is_inited(
+ IN const osm_pkey_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pkey_rcv_ctrl_construct or osm_pkey_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* P_Key Receive Controller object, osm_pkey_rcv_ctrl_construct,
+* osm_pkey_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of port related objects.
+ * These objects comprise an IBA port.
+ * These objects are part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#ifndef _OSM_PORT_H_
+#define _OSM_PORT_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_pkey.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
+
+/*
+ Forward references.
+*/
+struct _osm_port;
+struct _osm_node;
+
+/****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_net64_t port_guid;
+ uint8_t port_num;
+ struct _osm_node *p_node;
+ struct _osm_physp *p_remote_physp;
+ boolean_t healthy;
+ 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;
+ boolean_t got_set_resp;
+} osm_physp_t;
+/*
+* FIELDS
+* port_info
+* The IBA defined PortInfo data for this port.
+*
+* port_guid
+* Port GUID value of this port. For switches,
+* all ports share the same GUID value.
+*
+* 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.
+*
+* 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).
+* On switches have an entry for every other input port (inc SMA=0).
+* On CAs only one per port.
+*
+* got_set_resp
+* Marks whether or not we got a PortInfoSetResp from this port or not.
+* This is used for minimizing the number of PortInfoSet requests sent.
+* If we already got a set response from this port, then we will
+* send a PortInfoSet only if the values we are updating are
+* different than the ones on the port. If the haven't gotten a set
+* response - then we want to send the request anyways - since
+* every we need at least one PortInfoSet request for every port
+* (by a new SM).
+*
+* 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* const 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* const p_physp,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const struct _osm_node* const p_node,
+ IN const osm_bind_handle_t h_bind,
+ IN const uint8_t hop_count,
+ IN const uint8_t* const 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_INVALID_BIND_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* const 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, osm_port_init, osm_port_destroy
+*********/
+
+/****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* const 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* const 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* const 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* const 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
+*/
+static inline void
+osm_physp_set_port_info(
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ 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;
+ }
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* p_pi
+* [in] Pointer to the IBA defined PortInfo at this port number.
+*
+* RETURN VALUES
+* This function does not return a value.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****f* OpenSM: Physical Port/osm_physp_trim_base_lid_to_valid_range
+* NAME
+* osm_physp_trim_base_lid_to_valid_range
+*
+* DESCRIPTION
+* Validates the base LID in the Physical Port object
+* and resets it if the base LID is invalid.
+*
+* SYNOPSIS
+*/
+static inline ib_net16_t
+osm_physp_trim_base_lid_to_valid_range(
+ IN osm_physp_t* const p_physp )
+{
+ ib_net16_t orig_lid = 0;
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ if ( ( cl_ntoh16( p_physp->port_info.base_lid ) > IB_LID_UCAST_END_HO ) ||
+ ( cl_ntoh16( p_physp->port_info.base_lid ) < IB_LID_UCAST_START_HO ) )
+ {
+ orig_lid = p_physp->port_info.base_lid;
+ p_physp->port_info.base_lid = 0;
+ }
+ return orig_lid;
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns 0 if the base LID in the Physical port object is valid.
+* Returns original invalid LID otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Port, Physical Port
+*********/
+
+/****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* const p_physp,
+ IN ib_pkey_table_t *p_pkey_tbl,
+ IN uint16_t block_num );
+/*
+* 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* const 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_get_mod_pkey_tbl
+* NAME
+* osm_physp_get_mod_pkey_tbl
+*
+* DESCRIPTION
+* Returns a NON CONST pointer to the P_Key table object of the Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline osm_pkey_tbl_t *
+osm_physp_get_mod_pkey_tbl( IN osm_physp_t* const 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* const 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 = 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* const p_physp,
+ IN uint8_t in_port_num )
+{
+ ib_slvl_table_t *p_tbl;
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ p_tbl = 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* const 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* const 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* const 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* const 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* const 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* const p_physp,
+ IN const osm_physp_t* const 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* const p_physp,
+ IN osm_physp_t* const 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* const p_physp,
+ IN osm_physp_t* const 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* const 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* const 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_port_info_ptr
+* NAME
+* osm_physp_get_port_info_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the PortInfo attribute for this port.
+*
+* SYNOPSIS
+*/
+static inline ib_port_info_t*
+osm_physp_get_port_info_ptr(
+ IN const osm_physp_t* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( (ib_port_info_t*)&p_physp->port_info );
+}
+/*
+* PARAMETERS
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the PortInfo attribute for this 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* const p_physp )
+{
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( (struct _osm_node*)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* const 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* const 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* const 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* const 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
+*
+*********/
+
+/****d* OpenSM: Port/osm_port_lid_category_t
+* NAME
+* osm_port_lid_category_t
+*
+* DESCRIPTION
+* Enumerated values for LID disposition.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_port_lid_category
+{
+ OSM_PORT_LID_ASSIGNED = 0,
+ OSM_PORT_LID_UNASSIGNED,
+ OSM_PORT_LID_CONFLICT,
+ OSM_PORT_LID_FOREIGN,
+
+} osm_port_lid_category_t;
+/*
+* FIELDS
+* OSM_PORT_LID_ASSIGNED
+* Indicates the Port has a known LID value.
+*
+* OSM_PORT_LID_UNASSIGNED
+* Indicates the Port does not have a LID value.
+*
+* OSM_PORT_LID_CONFLICT
+* Indicates the Port's LID conflicts with an assigned LID.
+*
+* OSM_PORT_LID_FOREIGN
+* Indicates the Port has a LID value not currently known in
+* in the OpenSM LID database.
+*
+* SEE ALSO
+* Port
+*********/
+
+/****s* OpenSM: Port/osm_port_t
+* NAME
+* osm_port_t
+*
+* DESCRIPTION
+* This object represents a logical port on a switch, router or end-point.
+*
+* 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;
+ struct _osm_node *p_node;
+ ib_net64_t guid;
+ uint32_t discovery_count;
+ uint8_t default_port_num;
+ uint8_t physp_tbl_size;
+ cl_qlist_t mcm_list;
+ osm_physp_t *tbl[1];
+} osm_port_t;
+/*
+* FIELDS
+* map_item
+* Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
+*
+* 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.
+*
+* default_port_num
+* Index of the physical port used when physical characteristics
+* contained in the Physical Port are needed.
+*
+* physp_tbl_size
+* Number of physical ports associated with this logical port.
+*
+* mcm_list
+* Multicast member list
+*
+* tbl
+* Array of pointers to Physical Port objects contained by this node.
+* MUST BE LAST ELEMENT SINCE IT CAN GROW !!!
+*
+* SEE ALSO
+* Port, Physical Port, Physical Port Table
+*********/
+
+/****f* OpenSM: Port/osm_port_construct
+* NAME
+* osm_port_construct
+*
+* DESCRIPTION
+* This function constructs a Port object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_construct(
+ IN osm_port_t* const p_port )
+{
+ memset( p_port, 0, sizeof(*p_port) );
+ cl_qlist_init( &p_port->mcm_list );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_port_init, and osm_port_destroy.
+*
+* Calling osm_port_construct is a prerequisite to calling any other
+* method except osm_port_init.
+*
+* SEE ALSO
+* Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_destroy
+* NAME
+* osm_port_destroy
+*
+* DESCRIPTION
+* This function destroys a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_destroy(
+ IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified Port object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_port_construct
+* or osm_port_init.
+*
+* SEE ALSO
+* Port, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_delete
+* NAME
+* osm_port_delete
+*
+* DESCRIPTION
+* This function destroys and deallocates a Port object.
+*
+* SYNOPSIS
+*/
+inline static void
+osm_port_delete(
+ IN OUT osm_port_t** const pp_port )
+{
+ osm_port_destroy( *pp_port );
+ free( *pp_port );
+ *pp_port = NULL;
+}
+/*
+* 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, osm_port_init, osm_port_destroy
+*********/
+
+/****f* OpenSM: Port/osm_port_init
+* NAME
+* osm_port_init
+*
+* DESCRIPTION
+* This function initializes a Port object.
+*
+* SYNOPSIS
+*/
+void
+osm_port_init(
+ IN osm_port_t* const p_port,
+ IN const ib_node_info_t* p_ni,
+ IN const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object to initialize.
+*
+* p_ni
+* [in] Pointer to the NodeInfo attribute relavent for this port.
+*
+* p_parent_node
+* [in] Pointer to the initialized parent osm_node_t object
+* that owns this port.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+* Allows calling other port methods.
+*
+* 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 const struct _osm_node* const p_parent_node );
+/*
+* PARAMETERS
+* p_ni
+* [in] Pointer to the NodeInfo attribute relavent 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* const p_port )
+{
+ const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( osm_physp_get_base_lid( 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* const p_port )
+{
+ const osm_physp_t* const p_physp = p_port->tbl[p_port->default_port_num];
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ return( osm_physp_get_lmc( 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* const 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_num_physp
+* NAME
+* osm_port_get_num_physp
+*
+* DESCRIPTION
+* Returns the number of Physical Port objects associated with this port.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_port_get_num_physp(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->physp_tbl_size );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object.
+*
+* RETURN VALUE
+* Returns the number of Physical Port objects associated with this port.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_phys_ptr
+* NAME
+* osm_port_get_phys_ptr
+*
+* DESCRIPTION
+* Gets the pointer to the specified Physical Port object.
+*
+* SYNOPSIS
+*/
+static inline osm_physp_t*
+osm_port_get_phys_ptr(
+ IN const osm_port_t* const p_port,
+ IN const uint8_t port_num )
+{
+ CL_ASSERT( port_num < p_port->physp_tbl_size );
+ return( p_port->tbl[port_num] );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object.
+*
+* port_num
+* [in] Number of physical port for which to return the
+* osm_physp_t object. If this port is on an HCA, then
+* this value is ignored.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_default_phys_ptr
+* NAME
+* osm_port_get_default_phys_ptr
+*
+* DESCRIPTION
+* Gets the pointer to the default Physical Port object.
+* This call should only be used for non-switch ports in which there
+* is a one-for-one mapping of port to physp.
+*
+* SYNOPSIS
+*/
+static inline
+osm_physp_t*
+osm_port_get_default_phys_ptr(
+ IN const osm_port_t* const p_port )
+{
+ CL_ASSERT( p_port->tbl[p_port->default_port_num] );
+ CL_ASSERT( osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) );
+ return( p_port->tbl[p_port->default_port_num] );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_get_parent_node
+* NAME
+* osm_port_get_parent_node
+*
+* DESCRIPTION
+* Gets the pointer to the this port's Node object.
+*
+* SYNOPSIS
+*/
+static inline struct _osm_node*
+osm_port_get_parent_node(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->p_node );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object.
+*
+* port_num
+* [in] Number of physical port for which to return the
+* osm_physp_t object.
+*
+* RETURN VALUE
+* Pointer to the Physical Port object.
+*
+* 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* const p_port,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const 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: Port/osm_get_port_by_base_lid
+* NAME
+* osm_get_port_by_base_lid
+*
+* DESCRIPTION
+* Returns a status on whether a Port was able to be
+* determined based on the LID supplied and if so, return the Port.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_get_port_by_base_lid(
+ IN const osm_subn_t* const p_subn,
+ IN const ib_net16_t lid,
+ IN OUT const osm_port_t** const pp_port );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the subnet data structure.
+*
+* lid
+* [in] LID requested.
+*
+* pp_port
+* [in][out] Pointer to pointer to Port object.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_NOT_FOUND
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_add_new_physp
+* NAME
+* osm_port_add_new_physp
+*
+* DESCRIPTION
+* Adds a new physical port to the logical collection owned by the Port.
+* Physical Ports added here must share the same GUID as the Port.
+*
+* SYNOPSIS
+*/
+void
+osm_port_add_new_physp(
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to a Port object.
+*
+* port_num
+* [in] Port number to add.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_reset
+* NAME
+* osm_port_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this Port to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_reset(
+ IN osm_port_t* const p_port )
+{
+ p_port->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_get
+* NAME
+* osm_port_discovery_count_get
+*
+* DESCRIPTION
+* Returns the number of times this port has been discovered
+* since the last time the discovery count was reset.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_port_discovery_count_get(
+ IN const osm_port_t* const p_port )
+{
+ return( p_port->discovery_count );
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* Returns the number of times this port has been discovered
+* since the last time the discovery count was reset.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_discovery_count_inc
+* NAME
+* osm_port_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this Port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_discovery_count_inc(
+ IN osm_port_t* const p_port )
+{
+ p_port->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_add_mgrp
+* NAME
+* osm_port_add_mgrp
+*
+* DESCRIPTION
+* Logically connects a port to a multicast group.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_port_add_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* mlid
+* [in] MLID of the multicast group.
+*
+* RETURN VALUES
+* IB_SUCCESS
+* IB_INSUFFICIENT_MEMORY
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_mgrp
+* NAME
+* osm_port_remove_mgrp
+*
+* DESCRIPTION
+* Logically disconnects a port from a multicast group.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* mlid
+* [in] MLID of the multicast group.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****f* OpenSM: Port/osm_port_remove_all_mgrp
+* NAME
+* osm_port_remove_all_mgrp
+*
+* DESCRIPTION
+* Logically disconnects a port from all its multicast groups.
+*
+* SYNOPSIS
+*/
+void
+osm_port_remove_all_mgrp(
+ IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+* p_port
+* [in] Pointer to an osm_port_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Port object
+*********/
+
+/****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 );
+/*
+* PARAMETERS
+* p_log
+* [in] Pointer to a log object.
+*
+* p_physp
+* [in] Pointer to an osm_physp_t object.
+*
+* 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 );
+/*
+* 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.
+*
+* 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PORT_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_RCV_H_
+#define _OSM_PI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_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
+
+/****h* OpenSM/Port Info Receiver
+* NAME
+* Port Info Receiver
+*
+* DESCRIPTION
+* The Port Info Receiver object encapsulates the information
+* needed to receive the PortInfo attribute from a node.
+*
+* The Port Info Receiver 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: Port Info Receiver/osm_pi_rcv_t
+* NAME
+* osm_pi_rcv_t
+*
+* DESCRIPTION
+* Port Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+} osm_pi_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_construct
+* NAME
+* osm_pi_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Port Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_construct(
+ IN osm_pi_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Port Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pi_rcv_destroy
+*
+* Calling osm_pi_rcv_construct is a prerequisite to calling any other
+* method except osm_pi_rcv_init.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_init,
+* osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_destroy
+* NAME
+* osm_pi_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pi_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_destroy(
+ IN osm_pi_rcv_t* const 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
+* Port Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pi_rcv_construct or osm_pi_rcv_init.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_construct,
+* osm_pi_rcv_init
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_init
+* NAME
+* osm_pi_rcv_init
+*
+* DESCRIPTION
+* The osm_pi_rcv_init function initializes a
+* Port Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_init(
+ IN osm_pi_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the state manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Port Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Port Info Receiver methods.
+*
+* SEE ALSO
+* Port Info Receiver object, osm_pi_rcv_construct,
+* osm_pi_rcv_destroy
+*********/
+
+/****f* OpenSM: Port Info Receiver/osm_pi_rcv_process
+* NAME
+* osm_pi_rcv_process
+*
+* DESCRIPTION
+* Process the PortInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_process(
+ IN const osm_pi_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's PortInfo attribute.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* This function processes a PortInfo attribute.
+*
+* SEE ALSO
+* Port Info Receiver, Port Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PI_RCV_CTRL_H_
+#define _OSM_PI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port_info_rcv.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/Port Info Receive Controller
+* NAME
+* Port Info Receive Controller
+*
+* DESCRIPTION
+* The Port Info Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Port Info Receive 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: Port Info Receive Controller/osm_pi_rcv_ctrl_t
+* NAME
+* osm_pi_rcv_ctrl_t
+*
+* DESCRIPTION
+* Port Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pi_rcv_ctrl
+{
+ osm_pi_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pi_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Port Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Port Info Receive Controller object
+* Port Info Receiver object
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_construct
+* NAME
+* osm_pi_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_construct(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Port Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pi_rcv_ctrl_init, osm_pi_rcv_ctrl_destroy,
+* and osm_pi_rcv_ctrl_is_inited.
+*
+* Calling osm_pi_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_init,
+* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_destroy
+* NAME
+* osm_pi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pi_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pi_rcv_ctrl_destroy(
+ IN osm_pi_rcv_ctrl_t* const 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
+* Port Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_init
+* NAME
+* osm_pi_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pi_rcv_ctrl_init function initializes a
+* Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pi_rcv_ctrl_init(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl,
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pi_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Port Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Port Info Receive Controller methods.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_destroy, osm_pi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Port Info Receive Controller/osm_pi_rcv_ctrl_is_inited
+* NAME
+* osm_pi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pi_rcv_ctrl_is_inited(
+ IN const osm_pi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pi_rcv_ctrl_construct or osm_pi_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Port Info Receive Controller object, osm_pi_rcv_ctrl_construct,
+* osm_pi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PI_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port_profile.h 1091 2008-04-30 07:01:35Z tzachid $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#ifndef _OSM_PORT_PROFILE_H_
+#define _OSM_PORT_PROFILE_H_
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.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/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
+*********/
+
+/****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* const 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* const p_prof )
+{
+ CL_ASSERT( p_prof );
+ p_prof->num_paths++;
+}
+/*
+* PARAMETERS
+* p_pro
+* [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* const p_prof )
+{
+ return( p_prof->num_paths );
+}
+/*
+* PARAMETERS
+* p_pro
+* [in] Pointer to the Port Profile object.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile Opt/osm_port_prof_is_ignored_port
+* NAME
+* osm_port_prof_is_ignored_port
+*
+* DESCRIPTION
+* Check to see if this port is to be ignored in path counting.
+* This is done by examining the optional list of port_prof_ignore_guids.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_port_prof_is_ignored_port(
+ IN const osm_subn_t *p_subn,
+ IN uint64_t port_guid,
+ IN uint8_t port_num )
+{
+ const cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids);
+ const void *p_obj = cl_map_get(p_map, port_guid);
+ size_t res;
+
+ // HACK: we currently support ignoring ports 0 - 31
+ if (p_obj != NULL) {
+ res = (size_t)p_obj & (size_t)(1 << port_num);
+ return (res != 0);
+ }
+ return FALSE;
+}
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the OSM Subnet object.
+*
+* port_guid
+* [in] The port guid
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Port Profile Opt/osm_port_prof_set_ignored_port
+* NAME
+* osm_port_prof_set_ignored_port
+*
+* DESCRIPTION
+* Set the ignored property of the port.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_port_prof_set_ignored_port(
+ IN osm_subn_t *p_subn,
+ IN uint64_t port_guid,
+ IN uint8_t port_num )
+{
+ cl_map_t *p_map = &(p_subn->opt.port_prof_ignore_guids);
+ const void *p_obj = cl_map_get(p_map, port_guid);
+ size_t value = 0;
+
+ // HACK: we currently support ignoring ports 0 - 31
+ CL_ASSERT(port_num < 32);
+
+ if (p_obj != NULL) {
+ value = (size_t)p_obj;
+ }
+
+ value = value | ((size_t)1 << port_num); //size_t will be 64 bit length in Win2003_64
+ cl_map_insert(&(p_subn->opt.port_prof_ignore_guids),
+ port_guid,
+ (void *)value);
+}
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to the OSM Subnet object.
+*
+* port_guid
+* [in] The port guid
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PORT_PROFILE_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_rand_fwd_tbl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_switch_t.
+ * This object represents an IBA switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_RAND_FWD_TBL_H_
+#define _OSM_RAND_FWD_TBL_H_
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_base.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/Random Forwarding Table
+* NAME
+* Random Forwarding Table
+*
+* DESCRIPTION
+* The Random Forwarding Table objects encapsulate the information
+* needed by the OpenSM to manage random forwarding tables. The OpenSM
+* allocates one Random Forwarding Table object per switch in the
+* IBA subnet, if that switch uses a random forwarding table.
+*
+* The Random Forwarding Table objects are not thread safe, thus
+* callers must provide serialization.
+*
+* ** RANDOM FORWARDING TABLES ARE NOT SUPPORTED IN THE CURRENT VERSION **
+*
+* AUTHOR
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Forwarding Table/osm_rand_fwd_tbl_t
+* NAME
+* osm_rand_fwd_tbl_t
+*
+* DESCRIPTION
+* Random Forwarding Table structure.
+*
+* THIS OBJECT IS PLACE HOLDER. SUPPORT FOR SWITCHES WITH
+* RANDOM FORWARDING TABLES HAS NOT BEEN IMPLEMENTED YET.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_rand_fwd_tbl
+{
+ /* PLACE HOLDER STRUCTURE ONLY!! */
+ uint32_t size;
+} osm_rand_fwd_tbl_t;
+/*
+* FIELDS
+* RANDOM FORWARDING TABLES ARE NOT SUPPORTED YET!!
+*
+* SEE ALSO
+* Forwarding Table object, Random Forwarding Table object.
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_tbl_delete
+* NAME
+* osm_rand_tbl_delete
+*
+* DESCRIPTION
+* This destroys and deallocates a Random Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_tbl_delete(
+ IN osm_rand_fwd_tbl_t** const pp_tbl )
+{
+ /*
+ TO DO - This is a place holder function only!
+ */
+ free( *pp_tbl );
+ *pp_tbl = NULL;
+}
+/*
+* PARAMETERS
+* pp_tbl
+* [in] Pointer a Pointer to the Random Forwarding Table object.
+*
+* RETURN VALUE
+* On success, returns a pointer to a new Linear Forwarding Table object
+* of the specified size.
+* NULL otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set
+* NAME
+* osm_rand_fwd_tbl_set
+*
+* DESCRIPTION
+* Sets the port to route the specified LID.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_rand_fwd_tbl_set(
+ IN osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port )
+{
+ /* Random forwarding tables not supported yet. */
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_ho );
+ UNUSED_PARAM( port );
+ CL_ASSERT( FALSE );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Random Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the route.
+*
+* port
+* [in] Port to route the specified LID value.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_set_block
+* NAME
+* osm_rand_fwd_tbl_set_block
+*
+* DESCRIPTION
+* Copies the specified block into the Random Forwarding Table.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_rand_fwd_tbl_set_block(
+ IN osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ /* Random forwarding tables not supported yet. */
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( p_block );
+ UNUSED_PARAM( block_num );
+ CL_ASSERT( FALSE );
+ return( IB_ERROR );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Random 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_rand_fwd_tbl_get
+* NAME
+* osm_rand_fwd_tbl_get
+*
+* DESCRIPTION
+* Returns the port that routes the specified LID.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_rand_fwd_tbl_get(
+ IN const osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_ho )
+{
+ CL_ASSERT( FALSE );
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_ho );
+
+ return( OSM_NO_PATH );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Linear Forwarding Table object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get the route.
+*
+* RETURN VALUE
+* Returns the port that routes the specified LID.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_lids_per_block
+* NAME
+* osm_rand_fwd_tbl_get_lids_per_block
+*
+* DESCRIPTION
+* Returns the number of LIDs per LID block.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_lids_per_block(
+ IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ return( 16 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of LIDs per LID block.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_max_block_id_in_use
+* NAME
+* osm_rand_fwd_tbl_get_max_block_id_in_use
+*
+* DESCRIPTION
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_max_block_id_in_use(
+ IN const osm_rand_fwd_tbl_t* const p_tbl,
+ IN const uint16_t lid_top_ho )
+{
+ UNUSED_PARAM( p_tbl );
+ UNUSED_PARAM( lid_top_ho );
+ CL_ASSERT( FALSE );
+ return( 0 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the maximum block ID in actual use by the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Forwarding Table/osm_rand_fwd_tbl_get_size
+* NAME
+* osm_rand_fwd_tbl_get_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_rand_fwd_tbl_get_size(
+ IN const osm_rand_fwd_tbl_t* const p_tbl )
+{
+ UNUSED_PARAM( p_tbl );
+ CL_ASSERT( FALSE );
+ return( 0 );
+}
+/*
+* PARAMETERS
+* p_tbl
+* [in] Pointer to the Forwarding Table object.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RAND_FWD_TBL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_remote_sm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REMOTE_SM_H_
+#define _OSM_REMOTE_SM_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_port.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/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;
+ const osm_port_t *p_port;
+ 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* const 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* const 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* const p_sm,
+ IN const osm_port_t* const p_port,
+ IN const ib_sm_info_t* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_req.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_req_t.
+ * This object represents an object that genericly requests
+ * attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REQ_H_
+#define _OSM_REQ_H_
+
+#include <complib/cl_atomic.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.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/Generic Requester
+* NAME
+* Generic Requester
+*
+* DESCRIPTION
+* The Generic Requester object encapsulates the information
+* needed to request an attribute from a node.
+*
+* The Generic Requester 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: Generic Requester/osm_req_t
+* NAME
+* osm_req_t
+*
+* DESCRIPTION
+* Generic Requester structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req
+{
+ osm_mad_pool_t *p_pool;
+ osm_vl15_t *p_vl15;
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+ atomic32_t *p_sm_trans_id;
+
+} osm_req_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* p_vl15
+* Pointer to the VL15 interface.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_subn
+* Pointer to the subnet object.
+*
+* SEE ALSO
+* Generic Requester object
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_construct
+* NAME
+* osm_req_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Requester object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_construct(
+ IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to a Generic Requester object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_req_init, and osm_req_destroy.
+*
+* Calling osm_req_construct is a prerequisite to calling any other
+* method except osm_req_init.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_init,
+* osm_req_destroy
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_destroy
+* NAME
+* osm_req_destroy
+*
+* DESCRIPTION
+* The osm_req_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_destroy(
+ IN osm_req_t* const p_req );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Generic Requester object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_req_construct or osm_req_init.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_construct,
+* osm_req_init
+*********/
+
+/****f* OpenSM: Generic Requester/osm_req_init
+* NAME
+* osm_req_init
+*
+* DESCRIPTION
+* The osm_req_init function initializes a
+* Generic Requester object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_init(
+ IN osm_req_t* const p_req,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN atomic32_t* const p_sm_trans_id );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_subn
+* [in] Pointer to the subnet object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_sm_trans_id
+* [in] Pointer to the atomic SM transaction ID.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Generic Requester object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Requester methods.
+*
+* SEE ALSO
+* Generic Requester object, osm_req_construct,
+* osm_req_destroy
+*********/
+
+/****f* OpenSM: Generic Requester/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 const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_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.
+*
+* 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.
+*
+* SEE ALSO
+* Generic Requester
+*********/
+/****f* OpenSM: Generic Requester/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 const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint8_t* const p_payload,
+ IN const size_t payload_size,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context );
+/*
+* PARAMETERS
+* p_req
+* [in] Pointer to an osm_req_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.
+*
+* 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.
+*
+* SEE ALSO
+* Generic Requester
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_req_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_req_ctrl_t.
+ * This object represents a controller that calls the
+ * generic requester object to retrieve attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_REQ_CTRL_H_
+#define _OSM_REQ_CTRL_H_
+
+#include <opensm/osm_base.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req.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/Generic Request Controller
+* NAME
+* Generic Request Controller
+*
+* DESCRIPTION
+* The Generic Request Controller object encapsulates the information
+* needed to request an attribute from a node.
+*
+* The Generic Request 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: Generic Request Controller/osm_req_ctrl_t
+* NAME
+* osm_req_ctrl_t
+*
+* DESCRIPTION
+* Generic Request Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_req_ctrl
+{
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_req_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Generic Request Controller object
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_construct
+* NAME
+* osm_req_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Request Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_construct(
+ IN osm_req_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Generic Request Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_req_ctrl_init, and osm_req_ctrl_destroy.
+*
+* Calling osm_req_ctrl_construct is a prerequisite to calling any other
+* method except osm_req_ctrl_init.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_init,
+* osm_req_ctrl_destroy
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_destroy
+* NAME
+* osm_req_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_req_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_req_ctrl_destroy(
+ IN osm_req_ctrl_t* const 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
+* Generic Request Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_req_ctrl_construct or osm_req_ctrl_init.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_construct,
+* osm_req_ctrl_init
+*********/
+
+/****f* OpenSM: Generic Request Controller/osm_req_ctrl_init
+* NAME
+* osm_req_ctrl_init
+*
+* DESCRIPTION
+* The osm_req_ctrl_init function initializes a
+* Generic Request Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_req_ctrl_init(
+ IN osm_req_ctrl_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_req_ctrl_t object to initialize.
+*
+* p_req
+* [in] Pointer to a Generic Requester object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Generic Request Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Request Controller methods.
+*
+* SEE ALSO
+* Generic Request Controller object, osm_req_ctrl_construct,
+* Generic Requester object, osm_req_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_REQ_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_resp.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_resp_t.
+ * This object represents an object that genericly requests
+ * attributes from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_RESP_H_
+#define _OSM_RESP_H_
+
+#include <complib/cl_atomic.h>
+#include <opensm/osm_base.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_path.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.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/Generic Responder
+* NAME
+* Generic Responder
+*
+* DESCRIPTION
+* The Generic Responder object encapsulates the information
+* needed to respond to an attribute from a node.
+*
+* The Generic Responder 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: Generic Responder/osm_resp_t
+* NAME
+* osm_resp_t
+*
+* DESCRIPTION
+* Generic Responder structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_resp
+{
+ osm_mad_pool_t *p_pool;
+ osm_vl15_t *p_vl15;
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+
+} osm_resp_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* p_vl15
+* Pointer to the VL15 interface.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_subn
+* Pointer to the subnet object.
+*
+* SEE ALSO
+* Generic Responder object
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_construct
+* NAME
+* osm_resp_construct
+*
+* DESCRIPTION
+* This function constructs a Generic Responder object.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_construct(
+ IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to a Generic Responder object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_resp_init, osm_resp_destroy
+*
+* Calling osm_resp_construct is a prerequisite to calling any other
+* method except osm_resp_init.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_init,
+* osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_destroy
+* NAME
+* osm_resp_destroy
+*
+* DESCRIPTION
+* The osm_resp_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_resp_destroy(
+ IN osm_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Generic Responder object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_resp_construct or osm_resp_init.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_construct,
+* osm_resp_init
+*********/
+
+/****f* OpenSM: Generic Responder/osm_resp_init
+* NAME
+* osm_resp_init
+*
+* DESCRIPTION
+* The osm_resp_init function initializes a
+* Generic Responder object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_resp_init(
+ IN osm_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_resp_t object to initialize.
+*
+* p_mad_pool
+* [in] Pointer to the MAD pool.
+*
+* p_vl15
+* [in] Pointer to the VL15 interface.
+*
+* p_subn
+* [in] Pointer to the subnet object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Generic Responder object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Generic Responder methods.
+*
+* SEE ALSO
+* Generic Responder object, osm_resp_construct,
+* osm_resp_destroy
+*********/
+
+/****f* OpenSM: Generic Responder/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 const osm_resp_t* const p_resp,
+ IN const osm_madw_t* const p_req_madw,
+ IN const ib_net16_t status,
+ IN const uint8_t* const 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.
+*
+* NOTES
+*
+* SEE ALSO
+* Generic Responder
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_RESP_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_router_t.
+ * This object represents an IBA router.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_ROUTER_H_
+#define _OSM_ROUTER_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+#include <opensm/osm_port_profile.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/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_construct
+* NAME
+* osm_router_construct
+*
+* DESCRIPTION
+* This function constructs a Router object.
+*
+* SYNOPSIS
+*/
+void
+osm_router_construct(
+ IN osm_router_t* const p_rtr );
+/*
+* PARAMETERS
+* p_rtr
+* [in] Pointer to a Router object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_router_init, and osm_router_destroy.
+*
+* Calling osm_router_construct is a prerequisite to calling any other
+* method except osm_router_init.
+*
+* SEE ALSO
+* Router object, osm_router_init, osm_router_destroy
+*********/
+
+/****f* OpenSM: Router/osm_router_destroy
+* NAME
+* osm_router_destroy
+*
+* DESCRIPTION
+* The osm_router_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_router_destroy(
+ IN osm_router_t* const p_rtr );
+/*
+* PARAMETERS
+* p_rtr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+* Performs any necessary cleanup of the specified object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_router_construct
+* or osm_router_init.
+*
+* SEE ALSO
+* Router object, osm_router_construct, osm_router_init
+*********/
+
+/****f* OpenSM: Router/osm_router_destroy
+* NAME
+* osm_router_destroy
+*
+* DESCRIPTION
+* Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void
+osm_router_delete(
+ IN OUT osm_router_t** const pp_rtr );
+/*
+* PARAMETERS
+* p_rtr
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Router object, osm_router_construct, osm_router_init
+*********/
+
+/****f* OpenSM: Router/osm_router_init
+* NAME
+* osm_router_init
+*
+* DESCRIPTION
+* The osm_router_init function initializes a Router object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_router_init(
+ IN osm_router_t* const p_rtr,
+ IN osm_port_t* const p_port );
+/*
+* PARAMETERS
+* p_rtr
+* [in] Pointer to an osm_router_t object to initialize.
+*
+* p_port
+* [in] Pointer to the port object of this router
+*
+* RETURN VALUES
+* IB_SUCCESS if the Router object was initialized successfully.
+*
+* NOTES
+* Allows calling other node methods.
+*
+* SEE ALSO
+* Router object, osm_router_construct, osm_router_destroy
+*********/
+
+/****f* OpenSM: Router/osm_router_new
+* NAME
+* osm_router_new
+*
+* DESCRIPTION
+* The osm_router_init function initializes a Router object for use.
+*
+* SYNOPSIS
+*/
+osm_router_t*
+osm_router_new(
+ IN osm_port_t* const 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_construct, osm_router_destroy,
+*********/
+
+/****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* const 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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SA_H_
+#define _OSM_SA_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_sa_guidinfo_record_ctrl.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_sa_multipath_record_ctrl.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+#include <opensm/osm_sa_sw_info_record_ctrl.h>
+#include <opensm/osm_sa_mft_record_ctrl.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/SA
+* NAME
+* SA
+*
+* DESCRIPTION
+* The SA object encapsulates the information needed by the
+* OpenSM to instantiate a subnet administrator. 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;
+/***********/
+
+/****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_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_plock_t *p_lock;
+ atomic32_t sa_trans_id;
+ osm_sa_mad_ctrl_t mad_ctrl;
+ osm_sa_resp_t resp;
+ osm_cpi_rcv_t cpi_rcv;
+ osm_cpi_rcv_ctrl_t cpi_rcv_ctrl;
+ osm_nr_rcv_t nr_rcv;
+ osm_nr_rcv_ctrl_t nr_rcv_ctrl;
+ osm_pir_rcv_t pir_rcv;
+ osm_pir_rcv_ctrl_t pir_rcv_ctrl;
+ osm_gir_rcv_t gir_rcv;
+ osm_gir_rcv_ctrl_t gir_rcv_ctrl;
+ osm_lr_rcv_t lr_rcv;
+ osm_lr_rcv_ctrl_t lr_rcv_ctrl;
+ osm_pr_rcv_t pr_rcv;
+ osm_pr_rcv_ctrl_t pr_rcv_ctrl;
+ osm_smir_rcv_t smir_rcv;
+ osm_smir_ctrl_t smir_ctrl;
+ osm_mcmr_recv_t mcmr_rcv;
+ osm_mcmr_rcv_ctrl_t mcmr_rcv_ctlr;
+ osm_sr_rcv_t sr_rcv;
+ osm_sr_rcv_ctrl_t sr_rcv_ctrl;
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+ osm_mpr_rcv_t mpr_rcv;
+ osm_mpr_rcv_ctrl_t mpr_rcv_ctrl;
+#endif
+
+ /* InformInfo Receiver */
+ osm_infr_rcv_t infr_rcv;
+ osm_infr_rcv_ctrl_t infr_rcv_ctrl;
+
+ /* VL Arbitrartion Query */
+ osm_vlarb_rec_rcv_t vlarb_rec_rcv;
+ osm_vlarb_rec_rcv_ctrl_t vlarb_rec_rcv_ctrl;
+
+ /* SLtoVL Map Query */
+ osm_slvl_rec_rcv_t slvl_rec_rcv;
+ osm_slvl_rec_rcv_ctrl_t slvl_rec_rcv_ctrl;
+
+ /* P_Key table Query */
+ osm_pkey_rec_rcv_t pkey_rec_rcv;
+ osm_pkey_rec_rcv_ctrl_t pkey_rec_rcv_ctrl;
+
+ /* LinearForwardingTable Query */
+ osm_lftr_rcv_t lftr_rcv;
+ osm_lftr_rcv_ctrl_t lftr_rcv_ctrl;
+
+ /* SwitchInfo Query */
+ osm_sir_rcv_t sir_rcv;
+ osm_sir_rcv_ctrl_t sir_rcv_ctrl;
+
+ /* MulticastForwardingTable Query */
+ osm_mftr_rcv_t mftr_rcv;
+ osm_mftr_rcv_ctrl_t mftr_rcv_ctrl;
+} osm_sa_t;
+/*
+* FIELDS
+* state
+* State of this SA 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_lock
+* Pointer to Lock for serialization
+*
+* sa_trans_id
+* Transaction ID
+*
+* mad_ctrl
+* Mad Controller
+*
+* resp
+* Response object
+*
+* nr
+*
+* nr_ctrl
+*
+* pir_rcv
+*
+* pir_rcv_ctrl
+*
+* lr
+*
+* lr_ctrl
+*
+* pr
+*
+* pr_ctrl
+*
+* smir
+*
+* smir_ctrl
+*
+* 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* const 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_init, osm_sa_destroy, and osm_sa_is_inited.
+*
+* 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, osm_sa_is_inited
+*********/
+
+/****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* const 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* const 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* const p_sm,
+ IN osm_sa_t* const p_sa,
+ IN osm_subn_t* const p_subn,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const 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_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,
+* osm_sa_is_inited
+*********/
+
+/****f* OpenSM: SA/osm_sa_is_inited
+* NAME
+* osm_sa_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_sa_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sa_is_inited(
+ IN const osm_sa_t* const p_sa );
+/*
+* PARAMETERS
+* p_sa
+* [in] Pointer to an osm_sa_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_sa_construct or osm_sa_init must be called before using
+* this function.
+*
+* SEE ALSO
+* SA object, osm_sa_construct, osm_sa_init
+*********/
+
+/****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* const p_sa,
+ IN const 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
+*********/
+
+struct _osm_opensm_t;
+/****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_t *p_osm);
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+* None
+*
+*********/
+
+/****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_t *p_osm);
+/*
+* PARAMETERS
+* p_osm
+* [in] Pointer to an osm_opensm_t object.
+*
+* RETURN VALUES
+* 0 on success, other value on failure.
+*
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_class_port_info.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_CPI_H_
+#define _OSM_CPI_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/ClassPort Info Receiver
+* NAME
+* ClassPort Info Receiver
+*
+* DESCRIPTION
+* The ClassPort Info Receiver object encapsulates the information
+* needed to receive the ClassPortInfo request from a node.
+*
+* The ClassPort Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_t
+* NAME
+* osm_cpi_rcv_t
+*
+* DESCRIPTION
+* ClassPort Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_cpi_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* ClassPort Info Receiver object
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_construct
+* NAME
+* osm_cpi_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a ClassPort Info Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_construct(
+ IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a ClassPort Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*
+* Calling osm_cpi_rcv_construct is a prerequisite to calling any other
+* method except osm_cpi_rcv_init.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_init, osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_destroy
+* NAME
+* osm_cpi_rcv_destroy
+*
+* DESCRIPTION
+* The osm_cpi_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_destroy(
+ IN osm_cpi_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* ClassPort Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_cpi_rcv_construct or osm_cpi_rcv_init.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_construct,
+* osm_cpi_rcv_init
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_init
+* NAME
+* osm_cpi_rcv_init
+*
+* DESCRIPTION
+* The osm_cpi_rcv_init function initializes a
+* ClassPort Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_cpi_rcv_init(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the ClassPort Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other ClassPort Info Receiver methods.
+*
+* SEE ALSO
+* ClassPort Info Receiver object, osm_cpi_rcv_construct,
+* osm_cpi_rcv_destroy
+*********/
+
+/****f* OpenSM: ClassPort Info Receiver/osm_cpi_rcv_process
+* NAME
+* osm_cpi_rcv_process
+*
+* DESCRIPTION
+* Process the ClassPortInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_cpi_rcv_process(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the ClassPortInfo attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the ClassPortInfo processing was successful.
+*
+* NOTES
+* This function processes a ClassPortInfo attribute.
+*
+* SEE ALSO
+* ClassPort Info Receiver, ClassPort Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPI_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_class_port_info_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_cpi_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA ClassPortInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_CPICTRL_H_
+#define _OSM_CPICTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_class_port_info.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/Class Port Info Receive Controller
+* NAME
+* Class Port Info Receive Controller
+*
+* DESCRIPTION
+* The Class Port Info Receive Controller object encapsulates
+* the information requested by the ClassPortInfo attribute.
+*
+* The ClassPortInfo Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: ClassPort Info Receive Controller/osm_cpi_rcv_ctrl_t
+* NAME
+* osm_cpi_rcv_ctrl_t
+*
+* DESCRIPTION
+* ClassPort Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_cpi_rcv_ctrl
+{
+ osm_cpi_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_cpi_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the ClassPort Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object
+* Class Port Info Receiver object
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_construct
+* NAME
+* osm_cpi_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Class Port Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_construct(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Class Port Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_cpi_rcv_ctrl_init, osm_cpi_rcv_ctrl_destroy,
+* and osm_cpi_rcv_ctrl_is_inited.
+*
+* Calling osm_cpi_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_init,
+* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_destroy
+* NAME
+* osm_cpi_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_cpi_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_cpi_rcv_ctrl_destroy(
+ IN osm_cpi_rcv_ctrl_t* const 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
+* Class Port Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_init
+* NAME
+* osm_cpi_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_cpi_rcv_ctrl_init function initializes a
+* Class Port Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_cpi_rcv_ctrl_init(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_cpi_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_cpi_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Class Port Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Class Port Info Receive Controller methods.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_destroy, osm_cpi_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Class Port Info Receive Controller/osm_cpi_rcv_ctrl_is_inited
+* NAME
+* osm_cpi_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_cpi_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_cpi_rcv_ctrl_is_inited(
+ IN const osm_cpi_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_cpi_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_cpi_rcv_ctrl_construct or osm_cpi_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Class Port Info Receive Controller object, osm_cpi_rcv_ctrl_construct,
+* osm_cpi_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_CPICTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_guidinfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_gir_rcv_t.
+ * This object represents the GUIDInfo Record Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_GIR_RCV_H_
+#define _OSM_GIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/GUIDInfo Record Receiver
+* NAME
+* GUIDInfo Record Receiver
+*
+* DESCRIPTION
+* The GUIDInfo Record Receiver object encapsulates the information
+* needed to receive the GUIDInfoRecord attribute from a node.
+*
+* The GUIDInfo Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_t
+* NAME
+* osm_gir_rcv_t
+*
+* DESCRIPTION
+* GUIDInfo Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_gir_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_gir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable GUIDInfo Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_construct
+* NAME
+* osm_gir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a GUIDInfo Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_construct(
+ IN osm_gir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a GUIDInfo Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_gir_rcv_init, osm_gir_rcv_destroy
+*
+* Calling osm_gir_rcv_construct is a prerequisite to calling any other
+* method except osm_gir_rcv_init.
+*
+* SEE ALSO
+* GUIDInfo Record Receiver object, osm_gir_rcv_init,
+* osm_gir_rcv_destroy
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_destroy
+* NAME
+* osm_gir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_gir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_destroy(
+ IN osm_gir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* GUIDInfo Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_gir_rcv_construct or osm_gir_rcv_init.
+*
+* SEE ALSO
+* GUIDInfo Record Receiver object, osm_gir_rcv_construct,
+* osm_gir_rcv_init
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_init
+* NAME
+* osm_gir_rcv_init
+*
+* DESCRIPTION
+* The osm_gir_rcv_init function initializes a
+* GUIDInfo Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_gir_rcv_init(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_gir_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the GUIDInfo Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other GUIDInfo Record Receiver methods.
+*
+* SEE ALSO
+* GUIDInfo Record Receiver object, osm_gir_rcv_construct,
+* osm_gir_rcv_destroy
+*********/
+
+/****f* OpenSM: GUIDInfo Record Receiver/osm_gir_rcv_process
+* NAME
+* osm_gir_rcv_process
+*
+* DESCRIPTION
+* Process the GUIDInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_gir_rcv_process(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_gir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's GUIDInfoRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the GUIDInfoRecord processing was successful.
+*
+* NOTES
+* This function processes a GUIDInfoRecord attribute.
+*
+* SEE ALSO
+* GUIDInfo Record Receiver, GUIDInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_GIR_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_guidinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_gir_rec_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA GUID Info
+ * record query from SA client.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_GIR_CTRL_H_
+#define _OSM_GIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_guidinfo_record.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/GUID Info Record Receive Controller
+* NAME
+* GUID Info Record Receive Controller
+*
+* DESCRIPTION
+* The GUID Info Record Receive Controller object encapsulates
+* the information needed to handle GUID Info record query from SA client.
+*
+* The GUID Info Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_t
+* NAME
+* osm_gir_rcv_ctrl_t
+*
+* DESCRIPTION
+* GUID Info Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_gir_rcv_ctrl
+{
+ osm_gir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_gir_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the GUID Info Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* GUID Info Record Receive Controller object
+* GUID Info Record Receiver object
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rec_rcv_ctrl_construct
+* NAME
+* osm_gir_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a GUID Info Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_gir_rcv_ctrl_construct(
+ IN osm_gir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a GUID Info Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_gir_rcv_ctrl_init, osm_gir_rcv_ctrl_destroy
+*
+* Calling osm_gir_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_gir_rcv_ctrl_init.
+*
+* SEE ALSO
+* GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_init,
+* osm_gir_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_destroy
+* NAME
+* osm_gir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_gir_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_gir_rcv_ctrl_destroy(
+ IN osm_gir_rcv_ctrl_t* const 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
+* GUIDInfo Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_gir_rcv_ctrl_construct or osm_gir_rcv_ctrl_init.
+*
+* SEE ALSO
+* GUIDInfo Record Receive Controller object, osm_gir_rcv_ctrl_construct,
+* osm_gir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: GUID Info Record Receive Controller/osm_gir_rcv_ctrl_init
+* NAME
+* osm_gir_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_gir_rcv_ctrl_init function initializes a
+* GUID Info Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_gir_rcv_ctrl_init(
+ IN osm_gir_rcv_ctrl_t* const p_ctrl,
+ IN osm_gir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_gir_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_gir_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the GUID Info Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other GUID Info Record Receive Controller methods.
+*
+* SEE ALSO
+* GUID Info Record Receive Controller object, osm_gir_rcv_ctrl_construct,
+* osm_gir_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_GIR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_informinfo.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_infr_rcv_t.
+ * This object represents the InformInfoRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SA_INFR_H_
+#define _OSM_SA_INFR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/InformInfo Receiver
+* NAME
+* InformInfo Receiver
+*
+* DESCRIPTION
+* The InformInfo Receiver object encapsulates the information
+* needed to receive the InformInfo request from a node.
+*
+* The InformInfo Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: InformInfo Receiver/osm_infr_rcv_t
+* NAME
+* osm_infr_rcv_t
+*
+* DESCRIPTION
+* InformInfo Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+} osm_infr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the osm_sa_resp_t object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable InformInfo Record objects used to
+* generate the query response.
+*
+* SEE ALSO
+* InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_construct
+* NAME
+* osm_infr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a InformInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_construct(
+ IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a InformInfo Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_infr_rcv_init, osm_infr_rcv_destroy
+*
+* Calling osm_infr_rcv_construct is a prerequisite to calling any other
+* method except osm_infr_rcv_init.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_init, osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_destroy
+* NAME
+* osm_infr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_infr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_destroy(
+ IN osm_infr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* InformInfo Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_infr_rcv_construct or osm_infr_rcv_init.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_construct,
+* osm_infr_rcv_init
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_init
+* NAME
+* osm_infr_rcv_init
+*
+* DESCRIPTION
+* The osm_infr_rcv_init function initializes a
+* InformInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_infr_rcv_init(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the InformInfo Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other InformInfo Receiver methods.
+*
+* SEE ALSO
+* InformInfo Receiver object, osm_infr_rcv_construct,
+* osm_infr_rcv_destroy
+*********/
+
+/****f* OpenSM: InformInfo Receiver/osm_infr_rcv_process
+* NAME
+* osm_infr_rcv_process
+*
+* DESCRIPTION
+* Process the InformInfo request.
+*
+* SYNOPSIS
+*/
+void
+osm_infr_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's InformInfo attribute.
+* NOTES
+* This function processes a InformInfo attribute.
+*
+* SEE ALSO
+* InformInfo Receiver
+*********/
+
+/****f* OpenSM: InformInfo Record Receiver/osm_infir_rcv_process
+* NAME
+* osm_infir_rcv_process
+*
+* DESCRIPTION
+* Process the InformInfo Record request.
+*
+* SYNOPSIS
+*/
+void
+osm_infir_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's InformInfo Record attribute.
+* NOTES
+* This function processes a InformInfo Record attribute.
+*
+* SEE ALSO
+* InformInfo Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_INFR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_informinfo_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_infr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA InfromInfo
+ * Set method attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_INFR_RCV_CTRL_H_
+#define _OSM_INFR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_inform.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/InformInfo Receive Controller
+* NAME
+* InformInfo Receive Controller
+*
+* DESCRIPTION
+* The InformInfo Receive Controller object encapsulates
+* the information needed to receive the InformInfo attribute from a node.
+*
+* The InformInfo Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_t
+* NAME
+* osm_infr_rcv_ctrl_t
+*
+* DESCRIPTION
+* InformInfo Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_infr_rcv_ctrl
+{
+ osm_infr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+ cl_disp_reg_handle_t h_disp2;
+} osm_infr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the InformInfo Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* InformInfo Receive Controller object
+* InformInfo Receiver object
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_construct
+* NAME
+* osm_infr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a InformInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_construct(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a InformInfo Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_infr_rcv_ctrl_init, osm_infr_rcv_ctrl_destroy,
+* and osm_infr_rcv_ctrl_is_inited.
+*
+* Calling osm_infr_rcv_ctrl_construct is a prerequisite to calling any
+* other method except osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_init,
+* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_destroy
+* NAME
+* osm_infr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_infr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_infr_rcv_ctrl_destroy(
+ IN osm_infr_rcv_ctrl_t* const 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
+* InformInfo Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_init
+* NAME
+* osm_infr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_infr_rcv_ctrl_init function initializes a
+* InformInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_infr_rcv_ctrl_init(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl,
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_infr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_infr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the InformInfo Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other InformInfo Receive Controller methods.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_destroy, osm_infr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: InformInfo Receive Controller/osm_infr_rcv_ctrl_is_inited
+* NAME
+* osm_infr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_infr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_infr_rcv_ctrl_is_inited(
+ IN const osm_infr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_infr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_infr_rcv_ctrl_construct or osm_infr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* InformInfo Receive Controller object, osm_infr_rcv_ctrl_construct,
+* osm_infr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_INFR_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_lft_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lftr_rcv_t.
+ * This object represents the LinearForwardingTable Receiver object.
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFTR_H_
+#define _OSM_LFTR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.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/Linear Forwarding Table Receiver
+* NAME
+* Linear Forwarding Table Receiver
+*
+* DESCRIPTION
+* The Linear Forwarding Table Receiver object encapsulates the information
+* needed to receive the LinearForwardingTable attribute from a switch node.
+*
+* The Linear Forwarding Table Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_t
+* NAME
+* osm_lftr_rcv_t
+*
+* DESCRIPTION
+* Linear Forwarding Table Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lft
+{
+ osm_subn_t* p_subn;
+ osm_stats_t* p_stats;
+ osm_sa_resp_t* p_resp;
+ osm_mad_pool_t* p_mad_pool;
+ osm_log_t* p_log;
+ cl_plock_t* p_lock;
+ cl_qlock_pool_t pool;
+} osm_lftr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the statistics.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable Linear Forwarding Table Record objects used to
+* generate the query response.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_construct
+* NAME
+* osm_lftr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Linear Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_construct(
+ IN osm_lftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Linear Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lftr_rcv_init, osm_lftr_rcv_destroy
+*
+* Calling osm_lftr_rcv_construct is a prerequisite to calling any other
+* method except osm_lftr_rcv_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_init,
+* osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_destroy
+* NAME
+* osm_lftr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lftr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_destroy(
+ IN osm_lftr_rcv_t* const 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
+* Linear Forwarding Table Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lftr_rcv_construct or osm_lftr_rcv_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct,
+* osm_lftr_rcv_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_init
+* NAME
+* osm_lftr_rcv_init
+*
+* DESCRIPTION
+* The osm_lftr_rcv_init function initializes a
+* Linear Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_init(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lftr_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Linear Forwarding Table Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Linear Forwarding Table Receiver methods.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver object, osm_lftr_rcv_construct,
+* osm_lftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receiver/osm_lftr_rcv_process
+* NAME
+* osm_lftr_rcv_process
+*
+* DESCRIPTION
+* Process the LinearForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_process(
+ IN osm_lftr_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lftr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the switch node's LinearForwardingTable attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the LinearForwardingTable processing was successful.
+*
+* NOTES
+* This function processes a LinearForwardingTable attribute.
+*
+* SEE ALSO
+* Linear Forwarding Table Receiver, Linear Forwarding Table Response
+* Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_lft_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lftr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * LinearForwardingTable attribute from a switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LFTR_RCV_CTRL_H_
+#define _OSM_LFTR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_lft_record.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/Linear Forwarding Table Receive Controller
+* NAME
+* Linear Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+* The Linear Forwarding Table Receive Controller object encapsulates
+* the information needed to receive the LinearFowardingTable attribute
+* from a switch node.
+*
+* The Linear Forwarding Table Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox Technologies LTD
+*
+*********/
+
+/****s* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_t
+* NAME
+* osm_lftr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Linear Forwarding Table Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lftr_rcv_ctrl
+{
+ osm_lftr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lftr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Linear Forwarding Table Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object
+* Linear Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_construct
+* NAME
+* osm_lftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Linear Forwarding Table Receive
+* Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_construct(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Linear Forwarding Table Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lftr_rcv_ctrl_init, osm_lftr_rcv_ctrl_destroy
+*
+* Calling osm_lftr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_init,
+* osm_lftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_destroy
+* NAME
+* osm_lftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lftr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lftr_rcv_ctrl_destroy(
+ IN osm_lftr_rcv_ctrl_t* const 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
+* Linear Forwarding Table Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lftr_rcv_ctrl_construct or osm_lftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object, osm_lftr_rcv_ctrl_construct,
+* osm_lftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Linear Forwarding Table Receive Controller/osm_lftr_rcv_ctrl_init
+* NAME
+* osm_lftr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lftr_rcv_ctrl_init function initializes a
+* Linear Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_lftr_rcv_ctrl_init(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lftr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lftr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Linear Forwarding Table Receive Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other Linear Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+* Linear Forwarding Table Receive Controller object,
+* osm_lftr_rcv_ctrl_construct, osm_lftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LFTR_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_link_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lr_rcv_t.
+ * This object represents the Link Record Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LR_RCV_H_
+#define _OSM_LR_RCV_H_
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/Link Record Receiver
+* NAME
+* Link Record Receiver
+*
+* DESCRIPTION
+* The Link Record Receiver object encapsulates the information
+* needed to receive the Link Record attribute from a node.
+*
+* The Link Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: Link Record Receiver/osm_lr_rcv_t
+* NAME
+* osm_lr_rcv_t
+*
+* DESCRIPTION
+* Link Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t lr_pool;
+
+} osm_lr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* lr_pool
+* Pool of link record objects used to generate the query response.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_construct
+* NAME
+* osm_lr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Link Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_construct(
+ IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Link Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lr_rcv_init, osm_lr_rcv_destroy
+*
+* Calling osm_lr_rcv_construct is a prerequisite to calling any other
+* method except osm_lr_rcv_init.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_destroy
+* NAME
+* osm_lr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_lr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_lr_rcv_destroy(
+ IN osm_lr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Link Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lr_rcv_construct or osm_lr_rcv_init.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_construct,
+* osm_lr_rcv_init
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_init
+* NAME
+* osm_lr_rcv_init
+*
+* DESCRIPTION
+* The osm_lr_rcv_init function initializes a
+* Link Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_init(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lr_rcv_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the SA Responder object.
+*
+* p_mad_pool
+* [in] Pointer to the mad pool.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Link Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+* Link Record Receiver object, osm_lr_rcv_construct, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Link Record Receiver/osm_lr_rcv_process
+* NAME
+* osm_lr_rcv_process
+*
+* DESCRIPTION
+* Process the Link Record attribute.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_process(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_lr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's Link Record attribute.
+*
+* NOTES
+* This function processes a Link Record attribute.
+*
+* SEE ALSO
+* Link Record Receiver, Link Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_link_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_lr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Link Record
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_LR_CTRL_H_
+#define _OSM_LR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_link_record.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/Link Record Receive Controller
+* NAME
+* Link Record Receive Controller
+*
+* DESCRIPTION
+* The Link Record Receive Controller object encapsulates
+* the information needed to receive the LinkRecord attribute from a node.
+*
+* The Link Record Receive 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
+*
+*********/
+
+/****s* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_t
+* NAME
+* osm_lr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Link Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_lr_rcv_ctrl
+{
+ osm_lr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_lr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Link Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Link Record Receive Controller object
+* Link Record Receiver object
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_construct
+* NAME
+* osm_lr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Link Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_construct(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Link Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_lr_rcv_ctrl_init, osm_lr_rcv_ctrl_destroy,
+* and osm_lr_rcv_ctrl_is_inited.
+*
+* Calling osm_lr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Link Record Receive Controller object, osm_lr_rcv_ctrl_init,
+* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_destroy
+* NAME
+* osm_lr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_lr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_lr_rcv_ctrl_destroy(
+ IN osm_lr_rcv_ctrl_t* const 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
+* Link Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_init
+* NAME
+* osm_lr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_lr_rcv_ctrl_init function initializes a
+* Link Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_lr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Link Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Record Receive Controller methods.
+*
+* SEE ALSO
+* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_destroy, osm_lr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Link Record Receive Controller/osm_lr_rcv_ctrl_is_inited
+* NAME
+* osm_lr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_lr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_lr_rcv_ctrl_is_inited(
+ IN const osm_lr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_lr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_lr_rcv_ctrl_construct or osm_lr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Link Record Receive Controller object, osm_lr_rcv_ctrl_construct,
+* osm_lr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_LR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SA_MAD_CTRL_H_
+#define _OSM_SA_MAD_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_response.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/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
+*
+*********/
+
+/****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
+{
+ 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_disp_reg_handle_t h_disp;
+ osm_stats_t *p_stats;
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+} osm_sa_mad_ctrl_t;
+/*
+* FIELDS
+* 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.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_resp
+* Pointer to the SA response manager
+*
+* 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* const 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* const 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* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sa_mad_ctrl_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the response SA manager 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.
+*
+* 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* const p_ctrl,
+ IN const 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* const 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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mcmember_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcmr_recv_t.
+ * This object represents the MCMemberRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#ifndef _OSM_MCMR_H_
+#define _OSM_MCMR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_log.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/MCMember Receiver
+* NAME
+* MCMember Receiver
+*
+* DESCRIPTION
+* The MCMember Receiver object encapsulates the information
+* needed to receive the MCMemberRecord attribute from a node.
+*
+* The MCMember Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: MCMember Receiver/osm_mcmr_recv_t
+* NAME
+* osm_mcmr_recv_t
+*
+* DESCRIPTION
+* MCMember Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+
+
+typedef struct _osm_mcmr
+{
+ osm_subn_t *p_subn;
+ osm_sm_t *p_sm;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ uint16_t mlid_ho;
+ cl_qlock_pool_t pool;
+} osm_mcmr_recv_t;
+
+
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* MCMember Receiver object
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_construct
+* NAME
+* osm_mcmr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a MCMember Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_construct(
+ IN osm_mcmr_recv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a MCMember Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcmr_rcv_init, osm_mcmr_rcv_destroy
+*
+* Calling osm_mcmr_rcv_construct is a prerequisite to calling any other
+* method except osm_mcmr_init.
+*
+* SEE ALSO
+* MCMember Receiver object, osm_mcmr_init,
+* osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_destroy
+* NAME
+* osm_mcmr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_destroy(
+ IN osm_mcmr_recv_t* const 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
+* MCMember Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcmr_rcv_construct or osm_mcmr_init.
+*
+* SEE ALSO
+* MCMember Receiver object, osm_mcmr_rcv_construct,
+* osm_mcmr_init
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_init
+* NAME
+* osm_mcmr_init
+*
+* DESCRIPTION
+* The osm_mcmr_init function initializes a
+* MCMember Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_mcmr_recv_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_sm
+* [in] pointer to osm_sm_t object
+* p_ctrl
+* [in] Pointer to an osm_mcmr_recv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MCMember Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MCMember Receiver methods.
+*
+* SEE ALSO
+* MCMember Receiver object, osm_mcmr_rcv_construct,
+* osm_mcmr_rcv_destroy
+*********/
+
+/****f* OpenSM: MCMember Receiver/osm_mcmr_rcv_process
+* NAME
+* osm_mcmr_rcv_process
+*
+* DESCRIPTION
+* Process the MCMemberRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_process(
+ IN osm_mcmr_recv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_recv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's MCMemberRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MCMemberRecord processing was successful.
+*
+* NOTES
+* This function processes a MCMemberRecord attribute.
+*
+* SEE ALSO
+* MCMember Receiver, MCMember Response Controller
+*********/
+
+
+
+/****f* OpenSM: MC Member Record Receiver/osm_mcmr_rcv_create_new_mgrp
+* NAME
+* osm_mcmr_rcv_create_new_mgrp
+*
+* DESCRIPTION
+* Create new Multicast group
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN uint64_t comp_mask,
+ IN const ib_member_rec_t* const p_recvd_mcmember_rec,
+ IN const osm_physp_t* const p_req_physp,
+ OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+* p_mcmr
+* [in] Pointer to an osm_mcmr_recv_t object.
+* p_recvd_mcmember_rec
+* [in] Received Multicast member record
+*
+* p_req_physp
+* [in] The requesting osm_physp_t object.
+* NULL if the creation is without a requesting port (e.g - ipoib known mcgroups)
+*
+* pp_mgrp
+* [out] pointer the osm_mgrp_t object
+*
+* RETURN VALUES
+* IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*
+*********/
+
+/****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
+*/
+
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN uint64_t comp_mask,
+ IN ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp);
+/*
+* PARAMETERS
+* p_mcmr
+* [in] Pointer to an osm_mcmr_recv_t object.
+* p_recvd_mcmember_rec
+* [in] Received Multicast member record
+*
+* pp_mgrp
+* [out] pointer the osm_mgrp_t object
+*
+* RETURN VALUES
+* IB_SUCCESS, IB_ERROR
+*
+* NOTES
+*
+*
+* SEE ALSO
+*
+*********/
+
+#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)
+
+/****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
+/***********/
+
+/* Scope component definitions from IBA 1.2 (Table 3 p. 146) */
+#define MC_SCOPE_LINK_LOCAL 0x2
+#define MC_SCOPE_SITE_LOCAL 0x5
+#define MC_SCOPE_ORG_LOCAL 0x8
+#define MC_SCOPE_GLOBAL 0xE
+
+/****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 MC_SCOPE_LINK_LOCAL
+/***********/
+
+/* JoinState definitions from IBA 1.2 */
+#define MC_FULL_MEMBER 0x1
+#define MC_NON_MEMBER 0x2
+#define MC_SENDONLY_NON_MEMBER 0x4
+
+END_C_DECLS
+
+#endif /* _OSM_MCMR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mcmember_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcmr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA MCMemberRecord
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+
+#ifndef _OSM_MCMRCTRL_H
+#define _OSM_MCMRCTRL_H
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mcmember_record.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/MCMember Receive Controller
+* NAME
+* MCMember Receive Controller
+*
+* DESCRIPTION
+* The MCMember Receive Controller object encapsulates
+* the information needed to receive the MCMemberRecord attribute from a node.
+*
+* The MCMember Receive 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
+*
+*********/
+
+/****s* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_t
+* NAME
+* osm_mcmr_rcv_ctrl_t
+*
+* DESCRIPTION
+* MCMember Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mcmr_rcv_ctrl
+{
+ osm_mcmr_recv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_mcmr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the MCMember Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* MCMember Receive Controller object
+* MCMember Receiver object
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_construct
+* NAME
+* osm_mcmr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a MCMember Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_construct(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a MCMember Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mcmr_rcv_ctrl_init, osm_mcmr_rcv_ctrl_destroy,
+* and osm_mcmr_ctrl_is_inited.
+*
+* Calling osm_mcmr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_init,
+* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_destroy
+* NAME
+* osm_mcmr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mcmr_rcv_ctrl_destroy(
+ IN osm_mcmr_rcv_ctrl_t* const 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
+* MCMember Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init.
+*
+* SEE ALSO
+* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_rcv_ctrl_init
+* NAME
+* osm_mcmr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mcmr_rcv_ctrl_init function initializes a
+* MCMember Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mcmr_rcv_ctrl_init(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mcmr_recv_t* const p_mcmr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mcmr_recv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MCMember Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MCMember Receive Controller methods.
+*
+* SEE ALSO
+* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_destroy, osm_mcmr_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MCMember Receive Controller/osm_mcmr_ctrl_is_inited
+* NAME
+* osm_mcmr_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_mcmr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mcmr_ctrl_is_inited(
+ IN const osm_mcmr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mcmr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_mcmr_rcv_ctrl_construct or osm_mcmr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* MCMember Receive Controller object, osm_mcmr_rcv_ctrl_construct,
+* osm_mcmr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MCMRCTRL_H */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mftr_rcv_t.
+ * This object represents the MulticastForwardingTable Receiver object.
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_H_
+#define _OSM_MFTR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.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/Multicast Forwarding Table Receiver
+* NAME
+* Multicast Forwarding Table Receiver
+*
+* DESCRIPTION
+* The Multicast Forwarding Table Receiver object encapsulates the information
+* needed to receive the MulticastForwardingTable attribute from a switch node.
+*
+* The Multicast Forwarding Table Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_t
+* NAME
+* osm_mftr_rcv_t
+*
+* DESCRIPTION
+* Multicast Forwarding Table Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mft
+{
+ osm_subn_t* p_subn;
+ osm_stats_t* p_stats;
+ osm_sa_resp_t* p_resp;
+ osm_mad_pool_t* p_mad_pool;
+ osm_log_t* p_log;
+ cl_plock_t* p_lock;
+ cl_qlock_pool_t pool;
+} osm_mftr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the statistics.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable Multicast Forwarding Table Record objects used to
+* generate the query response.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_construct
+* NAME
+* osm_mftr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Forwarding Table Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_construct(
+ IN osm_mftr_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Multicast Forwarding Table Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mftr_rcv_init, osm_mftr_rcv_destroy
+*
+* Calling osm_mftr_rcv_construct is a prerequisite to calling any other
+* method except osm_mftr_rcv_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_init,
+* osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_destroy
+* NAME
+* osm_mftr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mftr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_destroy(
+ IN osm_mftr_rcv_t* const 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
+* Multicast Forwarding Table Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mftr_rcv_construct or osm_mftr_rcv_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct,
+* osm_mftr_rcv_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_init
+* NAME
+* osm_mftr_rcv_init
+*
+* DESCRIPTION
+* The osm_mftr_rcv_init function initializes a
+* Multicast Forwarding Table Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_init(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mftr_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Multicast Forwarding Table Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Multicast Forwarding Table Receiver methods.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver object, osm_mftr_rcv_construct,
+* osm_mftr_rcv_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receiver/osm_mftr_rcv_process
+* NAME
+* osm_mftr_rcv_process
+*
+* DESCRIPTION
+* Process the MulticastForwardingTable attribute.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_process(
+ IN osm_mftr_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mftr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the switch node's MulticastForwardingTable attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MulticastForwardingTable processing was successful.
+*
+* NOTES
+* This function processes a MulticastForwardingTable attribute.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receiver, Multicast Forwarding Table Response
+* Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mftr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * MulticastForwardingTable attribute from a switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MFTR_RCV_CTRL_H_
+#define _OSM_MFTR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_mft_record.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/Multicast Forwarding Table Receive Controller
+* NAME
+* Multicast Forwarding Table Record Receive Controller
+*
+* DESCRIPTION
+* The Multicast Forwarding Table Receive Controller object encapsulates
+* the information needed to receive the MulticastFowardingTable attribute
+* from a switch node.
+*
+* The Multicast Forwarding Table Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_t
+* NAME
+* osm_mftr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Multicast Forwarding Table Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mftr_rcv_ctrl
+{
+ osm_mftr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+} osm_mftr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Multicast Forwarding Table Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object
+* Multicast Forwarding Table Receiver object
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_construct
+* NAME
+* osm_mftr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Multicast Forwarding Table Receive
+* Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_construct(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Multicast Forwarding Table Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mftr_rcv_ctrl_init, osm_mftr_rcv_ctrl_destroy
+*
+* Calling osm_mftr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_init,
+* osm_mftr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_destroy
+* NAME
+* osm_mftr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mftr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mftr_rcv_ctrl_destroy(
+ IN osm_mftr_rcv_ctrl_t* const 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
+* Multicast Forwarding Table Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mftr_rcv_ctrl_construct or osm_mftr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object, osm_mftr_rcv_ctrl_construct,
+* osm_mftr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Multicast Forwarding Table Receive Controller/osm_mftr_rcv_ctrl_init
+* NAME
+* osm_mftr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mftr_rcv_ctrl_init function initializes a
+* Multicast Forwarding Table Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mftr_rcv_ctrl_init(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mftr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mftr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Multicast Forwarding Table Receive Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other Multicast Forwarding Table Receive Controller methods.
+*
+* SEE ALSO
+* Multicast Forwarding Table Receive Controller object,
+* osm_mftr_rcv_ctrl_construct, osm_mftr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MFTR_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mpr_rcv_t.
+ * This object represents the MultiPathRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MPR_RCV_H_
+#define _OSM_MPR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_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
+
+/****h* OpenSM/MultiPath Record Receiver
+* NAME
+* MultiPath Record Receiver
+*
+* DESCRIPTION
+* The MultiPath Record Receiver object encapsulates the information
+* needed to receive the PathRecord request from a node.
+*
+* The MultiPath Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_t
+* NAME
+* osm_mpr_rcv_t
+*
+* DESCRIPTION
+* MultiPath Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mpr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pr_pool;
+} osm_mpr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pr_pool
+* Pool of multipath record objects used to generate query responses.
+*
+* SEE ALSO
+* MultiPath Record Receiver object
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_construct
+* NAME
+* osm_mpr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a MultiPath Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_construct(
+ IN osm_mpr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a MultiPath Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mpr_rcv_init, osm_mpr_rcv_destroy
+*
+* Calling osm_mpr_rcv_construct is a prerequisite to calling any other
+* method except osm_mpr_rcv_init.
+*
+* SEE ALSO
+* MultiPath Record Receiver object, osm_mpr_rcv_init, osm_mpr_rcv_destroy
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_destroy
+* NAME
+* osm_mpr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_mpr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_destroy(
+ IN osm_mpr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* MultiPath Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mpr_rcv_construct or osm_mpr_rcv_init.
+*
+* SEE ALSO
+* MultiPath Record Receiver object, osm_mpr_rcv_construct,
+* osm_mpr_rcv_init
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_init
+* NAME
+* osm_mpr_rcv_init
+*
+* DESCRIPTION
+* The osm_mpr_rcv_init function initializes a
+* MultiPath Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_mpr_rcv_init(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mpr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the MultiPath Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other MultiPath Record Receiver methods.
+*
+* SEE ALSO
+* MultiPath Record Receiver object, osm_mpr_rcv_construct,
+* osm_mpr_rcv_destroy
+*********/
+
+/****f* OpenSM: MultiPath Record Receiver/osm_mpr_rcv_process
+* NAME
+* osm_mpr_rcv_process
+*
+* DESCRIPTION
+* Process the MultiPathRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_mpr_rcv_process(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_mpr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's MultiPathRecord attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the MultiPathRecord processing was successful.
+*
+* NOTES
+* This function processes a MultiPathRecord attribute.
+*
+* SEE ALSO
+* MultiPath Record Receiver, Node Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MPR_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mpr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA
+ * MultiPathRecord attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_MPRCTRL_H_
+#define _OSM_MPRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_multipath_record.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/MultiPath Record Receive Controller
+* NAME
+* MultiPath Record Receive Controller
+*
+* DESCRIPTION
+* The MultiPath Record Receive Controller object encapsulates
+* the information needed to receive the MultiPathRecord attribute from a node.
+*
+* The MultiPath record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_t
+* NAME
+* osm_mpr_rcv_ctrl_t
+*
+* DESCRIPTION
+* MultiPath Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_mpr_rcv_ctrl
+{
+ osm_mpr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_mpr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the MultiPath Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* MultiPath Record Receive Controller object
+* MultiPath Record Receiver object
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_pr_rcv_ctrl_construct
+* NAME
+* osm_mpr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a MultiPath Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_mpr_rcv_ctrl_construct(
+ IN osm_mpr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a MultiPath Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_mpr_rcv_ctrl_init, osm_mpr_rcv_ctrl_destroy,
+* and osm_mpr_rcv_ctrl_is_inited.
+*
+* Calling osm_mpr_rcv_ctrl_construct is a prerequisite to calling any
+* other method except osm_mpr_rcv_ctrl_init.
+*
+* SEE ALSO
+* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_init,
+* osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_destroy
+* NAME
+* osm_mpr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_mpr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_mpr_rcv_ctrl_destroy(
+ IN osm_mpr_rcv_ctrl_t* const 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
+* MultiPath Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init.
+*
+* SEE ALSO
+* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct,
+* osm_mpr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_init
+* NAME
+* osm_mpr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_mpr_rcv_ctrl_init function initializes a
+* MultiPath Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_mpr_rcv_ctrl_init(
+ IN osm_mpr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mpr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_mpr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the MultiPath Record Receive Controller object was
+* initialized successfully.
+*
+* NOTES
+* Allows calling other MultiPath Record Receive Controller methods.
+*
+* SEE ALSO
+* MultiPath Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_mpr_rcv_ctrl_destroy, osm_mpr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: MultiPath Record Receive Controller/osm_mpr_rcv_ctrl_is_inited
+* NAME
+* osm_mpr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_mpr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_mpr_rcv_ctrl_is_inited(
+ IN const osm_mpr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_mpr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_mpr_rcv_ctrl_construct or osm_mpr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* MultiPath Record Receive Controller object, osm_mpr_rcv_ctrl_construct,
+* osm_mpr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_MPRCTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_node_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nr_rcv_t.
+ * This object represents the NodeRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NR_H_
+#define _OSM_NR_H_
+
+#include <complib/cl_qlockpool.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/Node Record Receiver
+* NAME
+* Node Record Receiver
+*
+* DESCRIPTION
+* The Node Record Receiver object encapsulates the information
+* needed to receive the NodeRecord attribute from a node.
+*
+* The Node record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Node Record Receiver/osm_nr_rcv_t
+* NAME
+* osm_nr_rcv_t
+*
+* DESCRIPTION
+* Node Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_recv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_nr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable node record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_construct
+* NAME
+* osm_nr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Node Record Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_construct(
+ IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Node Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nr_rcv_init, osm_nr_rcv_destroy
+*
+* Calling osm_nr_rcv_construct is a prerequisite to calling any other
+* method except osm_nr_rcv_init.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_init, osm_lr_rcv_destroy
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_destroy
+* NAME
+* osm_nr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_nr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_destroy(
+ IN osm_nr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Node Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nr_rcv_construct or osm_nr_rcv_init.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_construct,
+* osm_nr_rcv_init
+*********/
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_init
+* NAME
+* osm_nr_rcv_init
+*
+* DESCRIPTION
+* The osm_nr_rcv_init function initializes a
+* Node Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_init(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the SA Responder object.
+*
+* p_mad_pool
+* [in] Pointer to the mad pool.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Node Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Link Record Receiver methods.
+*
+* SEE ALSO
+* Node Record Receiver object, osm_nr_rcv_construct, osm_nr_rcv_destroy
+*********/
+
+
+/****f* OpenSM: Node Record Receiver/osm_nr_rcv_process
+* NAME
+* osm_nr_rcv_process
+*
+* DESCRIPTION
+* Process the NodeRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_process(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's NodeRecord attribute.
+*
+* NOTES
+* This function processes a NodeRecord attribute.
+*
+* SEE ALSO
+* Node Record Receiver, Node Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_node_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_nr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA NodeInfo
+ * record from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_NR_CTRL_H_
+#define _OSM_NR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_node_record.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/Node Record Receive Controller
+* NAME
+* Node Record Receive Controller
+*
+* DESCRIPTION
+* The Node Record Receive Controller object encapsulates
+* the information needed to receive the NodeInfo attribute from a node.
+*
+* The Node Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy, Intel
+*
+*********/
+
+/****s* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_t
+* NAME
+* osm_nr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Node Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_nr_ctrl
+{
+ osm_nr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_nr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Node Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Node Record Receive Controller object
+* Node Record Receiver object
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_construct
+* NAME
+* osm_nr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Node Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_construct(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Node Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_nr_rcv_ctrl_init, osm_nr_rcv_ctrl_destroy,
+*
+* Calling osm_nr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_init,
+* osm_nr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_destroy
+* NAME
+* osm_nr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_nr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_nr_rcv_ctrl_destroy(
+ IN osm_nr_rcv_ctrl_t* const 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
+* Node Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_nr_rcv_ctrl_construct or osm_nr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+* osm_nr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Node Record Receive Controller/osm_nr_rcv_ctrl_init
+* NAME
+* osm_nr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_nr_rcv_ctrl_init function initializes a
+* Node Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_nr_rcv_ctrl_init(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl,
+ IN osm_nr_rcv_t* const p_nr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_nr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_nr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Node Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Node Record Receive Controller methods.
+*
+* SEE ALSO
+* Node Record Receive Controller object, osm_nr_rcv_ctrl_construct,
+* osm_nr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_NR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_path_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pr_rcv_t.
+ * This object represents the PathRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PR_H_
+#define _OSM_PR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/Path Record Receiver
+* NAME
+* Path Record Receiver
+*
+* DESCRIPTION
+* The Path Record Receiver object encapsulates the information
+* needed to receive the PathRecord request from a node.
+*
+* The Path Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: Path Record Receiver/osm_pr_rcv_t
+* NAME
+* osm_pr_rcv_t
+*
+* DESCRIPTION
+* Path Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pr_pool;
+} osm_pr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_gen_req_ctrl
+* Pointer to the generic request controller.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pr_pool
+* Pool of path record objects used to generate query responses.
+*
+* SEE ALSO
+* Path Record Receiver object
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_construct
+* NAME
+* osm_pr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Path Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_construct(
+ IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Path Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pr_rcv_init, osm_pr_rcv_destroy
+*
+* Calling osm_pr_rcv_construct is a prerequisite to calling any other
+* method except osm_pr_rcv_init.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_init, osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_destroy
+* NAME
+* osm_pr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_destroy(
+ IN osm_pr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Path Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pr_rcv_construct or osm_pr_rcv_init.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_construct,
+* osm_pr_rcv_init
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_init
+* NAME
+* osm_pr_rcv_init
+*
+* DESCRIPTION
+* The osm_pr_rcv_init function initializes a
+* Path Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pr_rcv_init(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Path Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Path Record Receiver methods.
+*
+* SEE ALSO
+* Path Record Receiver object, osm_pr_rcv_construct,
+* osm_pr_rcv_destroy
+*********/
+
+/****f* OpenSM: Path Record Receiver/osm_pr_rcv_process
+* NAME
+* osm_pr_rcv_process
+*
+* DESCRIPTION
+* Process the PathRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_pr_rcv_process(
+ IN osm_pr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's PathRecord attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the PathRecord processing was successful.
+*
+* NOTES
+* This function processes a PathRecord attribute.
+*
+* SEE ALSO
+* Path Record Receiver, Path Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_path_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA PathRecord
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PRCTRL_H_
+#define _OSM_PRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_path_record.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/Path Record Receive Controller
+* NAME
+* Path Record Receive Controller
+*
+* DESCRIPTION
+* The Path Record Receive Controller object encapsulates
+* the information needed to receive the PathRecord attribute from a node.
+*
+* The Path record Receive 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
+*
+*********/
+
+/****s* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_t
+* NAME
+* osm_pr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Path Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pr_rcv_ctrl
+{
+ osm_pr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Path Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Path Record Receive Controller object
+* Path Record Receiver object
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_construct
+* NAME
+* osm_pr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Path Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_construct(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Path Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pr_rcv_ctrl_init, osm_pr_rcv_ctrl_destroy,
+* and osm_pr_rcv_ctrl_is_inited.
+*
+* Calling osm_pr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Path Record Receive Controller object, osm_pr_rcv_ctrl_init,
+* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_destroy
+* NAME
+* osm_pr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pr_rcv_ctrl_destroy(
+ IN osm_pr_rcv_ctrl_t* const 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
+* Path Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_init
+* NAME
+* osm_pr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pr_rcv_ctrl_init function initializes a
+* Path Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pr_rcv_ctrl_init(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl,
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Path Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Path Record Receive Controller methods.
+*
+* SEE ALSO
+* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_destroy, osm_pr_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Path Record Receive Controller/osm_pr_rcv_ctrl_is_inited
+* NAME
+* osm_pr_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_pr_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_pr_rcv_ctrl_is_inited(
+ IN const osm_pr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pr_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_pr_rcv_ctrl_construct or osm_pr_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Path Record Receive Controller object, osm_pr_rcv_ctrl_construct,
+* osm_pr_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PRCTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_pkey_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_REC_RCV_H_
+#define _OSM_PKEY_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/P_Key Record Receiver
+* NAME
+* P_Key Record Receiver
+*
+* DESCRIPTION
+* The P_Key Record Receiver object encapsulates the information
+* needed to handle P_Key Record query from a SA.
+*
+* The P_Key Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_t
+* NAME
+* osm_pkey_rec_rcv_t
+*
+* DESCRIPTION
+* P_Key Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_pkey_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable P_Key Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+* osm_pkey_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_construct(
+ IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a P_Key Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rec_rcv_init, osm_pkey_rec_rcv_destroy
+*
+* Calling osm_pkey_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_init,
+* osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_destroy
+* NAME
+* osm_pkey_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_destroy(
+ IN osm_pkey_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* P_Key Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rec_rcv_construct or osm_pkey_rec_rcv_init.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+* osm_pkey_rec_rcv_init
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_init
+* NAME
+* osm_pkey_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_init function initializes a
+* P_Key Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Record Receiver methods.
+*
+* SEE ALSO
+* P_Key Record Receiver object, osm_pkey_rec_rcv_construct,
+* osm_pkey_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receiver/osm_pkey_rec_rcv_process
+* NAME
+* osm_pkey_rec_rcv_process
+*
+* DESCRIPTION
+* Process the P_Key Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_pkey_rec_rcv_process(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the P_Key Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA P_Key Record attribute.
+*
+* SEE ALSO
+* P_Key Record Receiver, P_Key Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_REC_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_pkey_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_PKEY_REC_CTRL_H_
+#define _OSM_PKEY_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_pkey_record.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/P_Key Record Receive Controller
+* NAME
+* P_Key Record Receive Controller
+*
+* DESCRIPTION
+* The P_Key Record Receive Controller object encapsulates
+* the information needed to handle P_Key record query from SA client.
+*
+* The P_Key Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_t
+* NAME
+* osm_pkey_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* P_Key Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pkey_rec_rcv_ctrl
+{
+ osm_pkey_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pkey_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the P_Key Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object
+* P_Key Record Receiver object
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_construct
+* NAME
+* osm_pkey_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a P_Key Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_construct(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a P_Key Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pkey_rec_rcv_ctrl_init, osm_pkey_rec_rcv_ctrl_destroy
+*
+* Calling osm_pkey_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_init,
+* osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_destroy
+* NAME
+* osm_pkey_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pkey_rec_rcv_ctrl_destroy(
+ IN osm_pkey_rec_rcv_ctrl_t* const 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
+* P_Key Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pkey_rec_rcv_ctrl_construct or osm_pkey_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+* osm_pkey_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: P_Key Record Receive Controller/osm_pkey_rec_rcv_ctrl_init
+* NAME
+* osm_pkey_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pkey_rec_rcv_ctrl_init function initializes a
+* P_Key Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pkey_rec_rcv_ctrl_init(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pkey_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pkey_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the P_Key Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other P_Key Record Receive Controller methods.
+*
+* SEE ALSO
+* P_Key Record Receive Controller object, osm_pkey_rec_rcv_ctrl_construct,
+* osm_pkey_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PKEY_REC_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_portinfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pir_rcv_t.
+ * This object represents the PortInfo Record Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PIR_RCV_H_
+#define _OSM_PIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/PortInfo Record Receiver
+* NAME
+* PortInfo Record Receiver
+*
+* DESCRIPTION
+* The PortInfo Record Receiver object encapsulates the information
+* needed to receive the PortInfoRecord attribute from a node.
+*
+* The PortInfo Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+
+/****s* OpenSM: PortInfo Record Receiver/osm_pir_rcv_t
+* NAME
+* osm_pir_rcv_t
+*
+* DESCRIPTION
+* PortInfo Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+} osm_pir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable PortInfo Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_construct
+* NAME
+* osm_pir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a PortInfo Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_construct(
+ IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a PortInfo Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pir_rcv_init, osm_pir_rcv_destroy
+*
+* Calling osm_pir_rcv_construct is a prerequisite to calling any other
+* method except osm_pir_rcv_init.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_init,
+* osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_destroy
+* NAME
+* osm_pir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_pir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_destroy(
+ IN osm_pir_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* PortInfo Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pir_rcv_construct or osm_pir_rcv_init.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_construct,
+* osm_pir_rcv_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_init
+* NAME
+* osm_pir_rcv_init
+*
+* DESCRIPTION
+* The osm_pir_rcv_init function initializes a
+* PortInfo Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_pir_rcv_init(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfo Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other PortInfo Record Receiver methods.
+*
+* SEE ALSO
+* PortInfo Record Receiver object, osm_pir_rcv_construct,
+* osm_pir_rcv_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receiver/osm_pir_rcv_process
+* NAME
+* osm_pir_rcv_process
+*
+* DESCRIPTION
+* Process the PortInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void
+osm_pir_rcv_process(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's PortInfoRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfoRecord processing was successful.
+*
+* NOTES
+* This function processes a PortInfoRecord attribute.
+*
+* SEE ALSO
+* PortInfo Record Receiver, PortInfo Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_portinfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pir_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA PortInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_PIR_CTRL_H_
+#define _OSM_PIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_portinfo_record.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/PortInfo Record Receive Controller
+* NAME
+* PortInfo Record Receive Controller
+*
+* DESCRIPTION
+* The PortInfo Record Receive Controller object encapsulates
+* the information needed to receive the PortInfo attribute from a node.
+*
+* The PortInfo Record Receive 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
+*
+*********/
+
+/****s* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_t
+* NAME
+* osm_pir_rcv_ctrl_t
+*
+* DESCRIPTION
+* PortInfo Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_pir_rcv_ctrl
+{
+ osm_pir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_pir_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the PortInfo Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object
+* PortInfo Record Receiver object
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_construct
+* NAME
+* osm_pir_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a PortInfo Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_construct(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a PortInfo Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_pir_rcv_ctrl_init, osm_pir_rcv_ctrl_destroy
+*
+* Calling osm_pir_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_init,
+* osm_pir_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_destroy
+* NAME
+* osm_pir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_pir_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_pir_rcv_ctrl_destroy(
+ IN osm_pir_rcv_ctrl_t* const 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
+* PortInfo Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_pir_rcv_ctrl_construct or osm_pir_rcv_ctrl_init.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+* osm_pir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: PortInfo Record Receive Controller/osm_pir_rcv_ctrl_init
+* NAME
+* osm_pir_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_pir_rcv_ctrl_init function initializes a
+* PortInfo Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_pir_rcv_ctrl_init(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl,
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_pir_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_pir_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the PortInfo Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other PortInfo Record Receive Controller methods.
+*
+* SEE ALSO
+* PortInfo Record Receive Controller object, osm_pir_rcv_ctrl_construct,
+* osm_pir_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_PIR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_response.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_resp_t.
+ * This object represents an object that responds to SA queries.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SA_RESP_H_
+#define _OSM_SA_RESP_H_
+
+#include <opensm/osm_base.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.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/SA Response
+* NAME
+* SA Response
+*
+* DESCRIPTION
+* The SA Response object encapsulates the information
+* needed to respond to an SA query.
+*
+* The SA Response object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+* Steve King, Intel
+*
+*********/
+
+/****s* OpenSM: SA Response/osm_sa_resp_t
+* NAME
+* osm_sa_resp_t
+*
+* DESCRIPTION
+* SA Response structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sa_resp
+{
+ osm_mad_pool_t *p_pool;
+ osm_log_t *p_log;
+} osm_sa_resp_t;
+/*
+* FIELDS
+* p_pool
+* Pointer to the MAD pool.
+*
+* SEE ALSO
+* SA Response object
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_construct
+* NAME
+* osm_sa_resp_construct
+*
+* DESCRIPTION
+* This function constructs a SA Response object.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_construct(
+ IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to a SA Response object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sa_resp_init, and osm_sa_resp_destroy.
+*
+* Calling osm_sa_resp_construct is a prerequisite to calling any other
+* method except osm_sa_resp_init.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_init,
+* osm_sa_resp_destroy
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_destroy
+* NAME
+* osm_sa_resp_destroy
+*
+* DESCRIPTION
+* The osm_sa_resp_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sa_resp_destroy(
+ IN osm_sa_resp_t* const p_resp );
+/*
+* PARAMETERS
+* p_resp
+* [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 Response object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sa_resp_construct or osm_sa_resp_init.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_init
+*********/
+
+/****f* OpenSM: SA Response/osm_sa_resp_init
+* NAME
+* osm_sa_resp_init
+*
+* DESCRIPTION
+* The osm_sa_resp_init function initializes a
+* SA Response object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sa_resp_init(
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_sa_resp_t object to initialize.
+*
+* 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.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SA Response object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SA Response methods.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_destroy
+*********/
+
+/****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_resp_t* const p_resp,
+ IN const osm_madw_t* const p_madw,
+ IN const ib_net16_t sa_status );
+/*
+* PARAMETERS
+* p_resp
+* [in] Pointer to an osm_sa_resp_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.
+*
+* NOTES
+* Allows calling other SA Response methods.
+*
+* SEE ALSO
+* SA Response object, osm_sa_resp_construct,
+* osm_sa_resp_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SA_RESP_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_service_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SR_H_
+#define _OSM_SR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_timer.h>
+#include <complib/cl_qlockpool.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/Service Record Receiver
+* NAME
+* Service Record Receiver
+*
+* DESCRIPTION
+* The Service Record Receiver object encapsulates the information
+* needed to receive the ServiceRecord request from a node.
+*
+* The Service Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Anil S Keshavamurthy
+*
+*********/
+
+/****s* OpenSM: Service Record Receiver/osm_sr_rcv_t
+* NAME
+* osm_sr_rcv_t
+*
+* DESCRIPTION
+* Service Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t sr_pool;
+ cl_timer_t sr_timer;
+
+} osm_sr_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the osm_sa_resp_t object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* sr_pool
+* Pool of Service Record objects used to generate query responses.
+*
+* SEE ALSO
+* Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_construct
+* NAME
+* osm_sr_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Service Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_construct(
+ IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Service Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sr_rcv_init, osm_sr_rcv_destroy
+*
+* Calling osm_sr_rcv_construct is a prerequisite to calling any other
+* method except osm_sr_rcv_init.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_init, osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_destroy
+* NAME
+* osm_sr_rcv_destroy
+*
+* DESCRIPTION
+* The osm_sr_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_destroy(
+ IN osm_sr_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Service Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sr_rcv_construct or osm_sr_rcv_init.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_construct,
+* osm_sr_rcv_init
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_init
+* NAME
+* osm_sr_rcv_init
+*
+* DESCRIPTION
+* The osm_sr_rcv_init function initializes a
+* Service Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sr_rcv_init(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Service Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Service Record Receiver methods.
+*
+* SEE ALSO
+* Service Record Receiver object, osm_sr_rcv_construct,
+* osm_sr_rcv_destroy
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_process
+* NAME
+* osm_sr_rcv_process
+*
+* DESCRIPTION
+* Process the ServiceRecord request.
+*
+* SYNOPSIS
+*/
+void
+osm_sr_rcv_process(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's ServiceRecord attribute.
+* NOTES
+* This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+* Service Record Receiver
+*********/
+
+/****f* OpenSM: Service Record Receiver/osm_sr_rcv_lease_cb
+* NAME
+* osm_sr_rcv_lease_cb
+*
+* DESCRIPTION
+* Timer Callback function which is executed to check the lease period
+* expiration
+*
+* SYNOPSIS
+*/
+
+void
+osm_sr_rcv_lease_cb(
+ IN void* context );
+/*
+* PARAMETERS
+* context
+* [in] Pointer to osm_sa_db_t object.
+*
+* NOTES
+* This function processes a ServiceRecord attribute.
+*
+* SEE ALSO
+* Service Record Receiver
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_service_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sr_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Service
+ * record attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SRCTRL_H_
+#define _OSM_SRCTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_service_record.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/Service Record Receive Controller
+* NAME
+* Service Record Receive Controller
+*
+* DESCRIPTION
+* The Service Record Receive Controller object encapsulates
+* the information needed to receive the Service Record attribute from a node.
+*
+* The Service Record Receive Controller object is thread safe.
+*
+* 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 Receive Controller/osm_sr_rcv_ctrl_t
+* NAME
+* osm_sr_rcv_ctrl_t
+*
+* DESCRIPTION
+* Service Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sr_rcv_ctrl
+{
+ osm_sr_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_sr_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Service Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Service Record Receiver object
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_construct
+* NAME
+* osm_sr_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Service Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_construct(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Service Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sr_rcv_ctrl_init, osm_sr_rcv_ctrl_destroy,
+*
+* Calling osm_sr_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_psr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_init,
+* osm_sr_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_destroy
+* NAME
+* osm_sr_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sr_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sr_rcv_ctrl_destroy(
+ IN osm_sr_rcv_ctrl_t* const 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
+* Service Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sr_rcv_ctrl_construct or osm_sr_rcv_ctrl_init.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+* osm_sr_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Service Record Receive Controller/osm_sr_rcv_ctrl_init
+* NAME
+* osm_sr_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_sr_rcv_ctrl_init function initializes a
+* Service Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sr_rcv_ctrl_init(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl,
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sr_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sr_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the osm_sr_rcv_t Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Service Record Receive Controller methods.
+*
+* SEE ALSO
+* Service Record Receive Controller object, osm_sr_rcv_ctrl_construct,
+* osm_sr_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SRCTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_slvl_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_slvl_rec_rcv_t.
+ * This object represents the SLtoVL Mapping Table Receiver object.
+ * attribute from a SA query.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_REC_RCV_H_
+#define _OSM_SLVL_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/SLtoVL Mapping Record Receiver
+* NAME
+* SLtoVL Mapping Record Receiver
+*
+* DESCRIPTION
+* The SLtoVL Mapping Record Receiver object encapsulates the information
+* needed to handle SLtoVL Mapping Record query from a SA.
+*
+* The SLtoVL Mapping Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_t
+* NAME
+* osm_slvl_rec_rcv_t
+*
+* DESCRIPTION
+* SLtoVL Mapping Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+
+} osm_slvl_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable SLtoVL Mapping Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_construct
+* NAME
+* osm_slvl_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a SLtoVL Mapping Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_construct(
+ IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a SLtoVL Mapping Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rec_rcv_init, osm_slvl_rec_rcv_destroy
+*
+* Calling osm_slvl_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_init,
+* osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_destroy
+* NAME
+* osm_slvl_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_destroy(
+ IN osm_slvl_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SLtoVL Mapping Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rec_rcv_construct or osm_slvl_rec_rcv_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+* osm_slvl_rec_rcv_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_init
+* NAME
+* osm_slvl_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_init function initializes a
+* SLtoVL Mapping Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL Mapping Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SLtoVL Mapping Record Receiver methods.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver object, osm_slvl_rec_rcv_construct,
+* osm_slvl_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receiver/osm_slvl_rec_rcv_process
+* NAME
+* osm_slvl_rec_rcv_process
+*
+* DESCRIPTION
+* Process the SLtoVL Map Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_slvl_rec_rcv_process(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the SLtoVL Map Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA SLtoVL Map Record attribute.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receiver, SLtoVL Mapping Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_slvl_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_slvl_rec_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA VL Arbitration
+ * record query from SA client.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_REC_CTRL_H_
+#define _OSM_SLVL_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_slvl_record.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/SLtoVL Record Receive Controller
+* NAME
+* SLtoVL Record Receive Controller
+*
+* DESCRIPTION
+* The SLtoVL Mapping Record Receive Controller object encapsulates
+* the information needed to handle SLtoVL Mapping record query from SA client.
+*
+* The SLtoVL Mapping Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_t
+* NAME
+* osm_slvl_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* SLtoVL Mapping Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rec_rcv_ctrl
+{
+ osm_slvl_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_slvl_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the SLtoVL Mapping Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object
+* SLtoVL Mapping Record Receiver object
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_construct
+* NAME
+* osm_slvl_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SLtoVL Mapping Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_construct(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SLtoVL Mapping Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rec_rcv_ctrl_init, osm_slvl_rec_rcv_ctrl_destroy
+*
+* Calling osm_slvl_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_init,
+* osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_destroy
+* NAME
+* osm_slvl_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rec_rcv_ctrl_destroy(
+ IN osm_slvl_rec_rcv_ctrl_t* const 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
+* SLtoVL Mapping Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rec_rcv_ctrl_construct or osm_slvl_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+* osm_slvl_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SLtoVL Mapping Record Receive Controller/osm_slvl_rec_rcv_ctrl_init
+* NAME
+* osm_slvl_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_slvl_rec_rcv_ctrl_init function initializes a
+* SLtoVL Mapping Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rec_rcv_ctrl_init(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_slvl_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL Mapping Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SLtoVL Mapping Record Receive Controller methods.
+*
+* SEE ALSO
+* SLtoVL Mapping Record Receive Controller object, osm_slvl_rec_rcv_ctrl_construct,
+* osm_slvl_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_REC_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_sminfo_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_smir_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMIR_H_
+#define _OSM_SMIR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.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/SM Info Receiver
+* NAME
+* SM Info Receiver
+*
+* DESCRIPTION
+* The SM Info Receiver object encapsulates the information
+* needed to receive the SMInfoRecord attribute from a node.
+*
+* The SM Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Ranjit Pandit, Intel
+*
+*********/
+/****s* OpenSM: SM Info Receiver/osm_smir_rcv_t
+* NAME
+* osm_smir_rcv_t
+*
+* DESCRIPTION
+* SM Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir
+{
+ osm_subn_t* p_subn;
+ osm_stats_t* p_stats;
+ osm_sa_resp_t* p_resp;
+ osm_mad_pool_t* p_mad_pool;
+ osm_log_t* p_log;
+ cl_plock_t* p_lock;
+ cl_qlock_pool_t pool;
+} osm_smir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* SEE ALSO
+* SM Info Receiver object
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_construct
+* NAME
+* osm_smir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a SM Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_construct(
+ IN osm_smir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SM Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_smir_rcv_init, osm_smir_rcv_destroy
+*
+* Calling osm_smir_rcv_construct is a prerequisite to calling any other
+* method except osm_smir_rcv_init.
+*
+* SEE ALSO
+* SM Info Receiver object, osm_smir_rcv_init, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_destroy
+* NAME
+* osm_smir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_smir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_destroy(
+ IN osm_smir_rcv_t* const 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 Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_smir_rcv_construct or osm_smir_rcv_init.
+*
+* SEE ALSO
+* SM Info Receiver object, osm_smir_rcv_construct,
+* osm_smir_rcv_init
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_init
+* NAME
+* osm_smir_rcv_init
+*
+* DESCRIPTION
+* The osm_smir_rcv_init function initializes a
+* SM Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_rcv_init(
+ IN osm_smir_rcv_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the Statistics object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SM Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM Info Receiver methods.
+*
+* SEE ALSO
+* SM Info Receiver object, osm_smir_rcv_construct, osm_smir_rcv_destroy
+*********/
+
+/****f* OpenSM: SM Info Receiver/osm_smir_rcv_process
+* NAME
+* osm_smir_rcv_process
+*
+* DESCRIPTION
+* Process the SMInfoRecord attribute.
+*
+* SYNOPSIS
+*/
+void osm_smir_rcv_process(
+ IN osm_smir_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SMInfoRecord attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SMInfoRecord processing was successful.
+*
+* NOTES
+* This function processes a SMInfoRecord attribute.
+*
+* SEE ALSO
+* SM Info Receiver, SM Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_sminfo_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_smir_ctrl_t.
+ * This object represents a controller that receives the IBA SMInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMIR_CTRL_H_
+#define _OSM_SMIR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_sminfo_record.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/SM Info Receive Controller
+* NAME
+* SM Info Receive Controller
+*
+* DESCRIPTION
+* The SM Info Receive Controller object encapsulates
+* the information needed to receive the SMInfo attribute from a node.
+*
+* The SM Info Receive 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
+*
+*********/
+
+/****s* OpenSM: SM Info Receive Controller/osm_smir_ctrl_t
+* NAME
+* osm_smir_ctrl_t
+*
+* DESCRIPTION
+* SM Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_smir_ctrl
+{
+ osm_smir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_smir_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the SM Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* SM Info Receive Controller object
+* SM Info Receiver object
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_construct
+* NAME
+* osm_smir_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SM Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_construct(
+ IN osm_smir_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SM Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_smir_ctrl_init, osm_smir_ctrl_destroy
+*
+* Calling osm_smir_ctrl_construct is a prerequisite to calling any other
+* method except osm_smir_ctrl_init.
+*
+* SEE ALSO
+* SM Info Receive Controller object, osm_smir_ctrl_init,
+* osm_smir_ctrl_destroy
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_destroy
+* NAME
+* osm_smir_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_smir_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_smir_ctrl_destroy(
+ IN osm_smir_ctrl_t* const 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 Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_smir_ctrl_construct or osm_smir_ctrl_init.
+*
+* SEE ALSO
+* SM Info Receive Controller object, osm_smir_ctrl_construct,
+* osm_smir_ctrl_init
+*********/
+
+/****f* OpenSM: SM Info Receive Controller/osm_smir_ctrl_init
+* NAME
+* osm_smir_ctrl_init
+*
+* DESCRIPTION
+* The osm_smir_ctrl_init function initializes a
+* SM Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_smir_ctrl_init(
+ IN osm_smir_ctrl_t* const p_ctrl,
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_smir_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_smir_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SM Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM Info Receive Controller methods.
+*
+* SEE ALSO
+* SM Info Receive Controller object, osm_smir_ctrl_construct,
+* osm_smir_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMIR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sir_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_SIR_RCV_H_
+#define _OSM_SIR_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/Switch Info Receiver
+* NAME
+* Switch Info Receiver
+*
+* DESCRIPTION
+* The Switch Info Receiver object encapsulates the information
+* needed to receive the SwitchInfo attribute from a switch node.
+*
+* The Switch Info Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Switch Info Receiver/osm_sir_rcv_t
+* NAME
+* osm_sir_rcv_t
+*
+* DESCRIPTION
+* Switch Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sir_rcv
+{
+ osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ osm_req_t *p_req;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+} osm_sir_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_req
+* Pointer to the Request object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_construct
+* NAME
+* osm_sir_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_construct(
+ IN osm_sir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sir_rcv_init, osm_sir_rcv_destroy,
+* and osm_sir_rcv_is_inited.
+*
+* Calling osm_sir_rcv_construct is a prerequisite to calling any other
+* method except osm_sir_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_sir_rcv_init,
+* osm_sir_rcv_destroy, osm_sir_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_destroy
+* NAME
+* osm_sir_rcv_destroy
+*
+* DESCRIPTION
+* The osm_sir_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_destroy(
+ IN osm_sir_rcv_t* const 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
+* Switch Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sir_rcv_construct or osm_sir_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_sir_rcv_construct,
+* osm_sir_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_init
+* NAME
+* osm_sir_rcv_init
+*
+* DESCRIPTION
+* The osm_sir_rcv_init function initializes a
+* Switch Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sir_rcv_init(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sir_rcv_t object to initialize.
+*
+* p_resp
+* [in] Pointer to the SA Responder object.
+*
+* p_mad_pool
+* [in] Pointer to the mad pool.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Switch Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receiver methods.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_sir_rcv_construct,
+* osm_sir_rcv_destroy, osm_sir_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_is_inited
+* NAME
+* osm_sir_rcv_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_sir_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sir_rcv_is_inited(
+ IN const osm_sir_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sir_rcv_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_sir_rcv_construct or osm_sir_rcv_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_sir_rcv_construct,
+* osm_sir_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_sir_rcv_process
+* NAME
+* osm_sir_rcv_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_process(
+ IN osm_sir_rcv_t* const p_ctrl,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sir_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* Switch Info Receiver, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SIR_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sir_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA SwitchInfo
+ * attribute from a switch node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#ifndef _OSM_SIR_RCV_CTRL_H_
+#define _OSM_SIR_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_sw_info_record.h>
+#include <opensm/osm_log.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/Switch Info Receive Controller
+* NAME
+* Switch Info Receive Controller
+*
+* DESCRIPTION
+* The Switch Info Receive Controller object encapsulates the information
+* needed to receive the SwitchInfo attribute from a switch node.
+*
+* The Switch Info Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Hal Rosenstock, Voltaire
+*
+*********/
+
+/****s* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_t
+* NAME
+* osm_sir_rcv_ctrl_t
+*
+* DESCRIPTION
+* Switch Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sir_rcv_ctrl
+{
+ osm_sir_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+} osm_sir_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Switch Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Switch Info Receive Controller object
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_construct
+* NAME
+* osm_sir_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_ctrl_construct(
+ IN osm_sir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sir_rcv_ctrl_init, osm_sir_rcv_ctrl_destroy,
+* and osm_sir_rcv_ctrl_is_inited.
+*
+* Calling osm_sir_rcv_ctrl_construct is a prerequisite to calling any
+* other method except osm_sir_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_sir_rcv_ctrl_init,
+* osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_destroy
+* NAME
+* osm_sir_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sir_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sir_rcv_ctrl_destroy(
+ IN osm_sir_rcv_ctrl_t* const 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
+* Switch Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+* osm_sir_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_init
+* NAME
+* osm_sir_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_sir_rcv_ctrl_init function initializes a
+* Switch Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sir_rcv_ctrl_init(
+ IN osm_sir_rcv_ctrl_t* const p_ctrl,
+ IN osm_sir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sir_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sir_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Switch Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receive Controller methods.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+* osm_sir_rcv_ctrl_destroy, osm_sir_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_sir_rcv_ctrl_is_inited
+* NAME
+* osm_sir_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_sir_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_sir_rcv_ctrl_is_inited(
+ IN const osm_sir_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sir_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_sir_rcv_ctrl_construct or osm_sir_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_sir_rcv_ctrl_construct,
+* osm_sir_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SIR_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_vlarb_record.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vlarb_rec_rcv_t.
+ * This object represents the VLArbitration Record Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLARB_REC_RCV_H_
+#define _OSM_VLARB_REC_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_log.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/VLArbitration Record Receiver
+* NAME
+* VLArbitration Record Receiver
+*
+* DESCRIPTION
+* The VLArbitration Record Receiver object encapsulates the information
+* needed to handle VL Arbitration Record query from a SA.
+*
+* The VLArbitration Record Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_t
+* NAME
+* osm_vlarb_rec_rcv_t
+*
+* DESCRIPTION
+* VLArbitration Record Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv
+{
+ const osm_subn_t *p_subn;
+ osm_sa_resp_t *p_resp;
+ osm_mad_pool_t *p_mad_pool;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ cl_qlock_pool_t pool;
+} osm_vlarb_rec_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_resp
+* Pointer to the SA responder.
+*
+* p_mad_pool
+* Pointer to the mad pool.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* pool
+* Pool of linkable VLArbitration Record objects used to generate
+* the query response.
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_construct
+* NAME
+* osm_vlarb_rec_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a VLArbitration Record Receiver object.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_construct(
+ IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a VLArbitration Record Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vlarb_rec_rcv_init, osm_vlarb_rec_rcv_destroy
+*
+* Calling osm_vlarb_rec_rcv_construct is a prerequisite to calling any other
+* method except osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_init,
+* osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_destroy
+* NAME
+* osm_vlarb_rec_rcv_destroy
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_destroy(
+ IN osm_vlarb_rec_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* VLArbitration Record Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vlarb_rec_rcv_construct or osm_vlarb_rec_rcv_init.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+* osm_vlarb_rec_rcv_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_init
+* NAME
+* osm_vlarb_rec_rcv_init
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_init function initializes a
+* VLArbitration Record Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VLArbitration Record Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VLArbitration Record Receiver methods.
+*
+* SEE ALSO
+* VLArbitration Record Receiver object, osm_vlarb_rec_rcv_construct,
+* osm_vlarb_rec_rcv_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receiver/osm_vlarb_rec_rcv_process
+* NAME
+* osm_vlarb_rec_rcv_process
+*
+* DESCRIPTION
+* Process the VL Arbitration Table Query .
+*
+* SYNOPSIS
+*/
+void
+osm_vlarb_rec_rcv_process(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the VL Arbitration Record Query attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Query processing was successful.
+*
+* NOTES
+* This function processes a SA VL Arbitration Record attribute.
+*
+* SEE ALSO
+* VLArbitration Record Receiver, VLArbitration Record Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_vlarb_record_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sa_vlarb_rec_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA VL Arbitration
+ * record query from SA client.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLARB_REC_CTRL_H_
+#define _OSM_VLARB_REC_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_sa_vlarb_record.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/VLArbitration Record Receive Controller
+* NAME
+* VLArbitration Record Receive Controller
+*
+* DESCRIPTION
+* The VLArbitration Record Receive Controller object encapsulates
+* the information needed to handle VLArbitration record query from SA client.
+*
+* The VLArbitration Record Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_t
+* NAME
+* osm_vlarb_rec_rcv_ctrl_t
+*
+* DESCRIPTION
+* VLArbitration Record Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vlarb_rec_rcv_ctrl
+{
+ osm_vlarb_rec_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_vlarb_rec_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the VLArbitration Record Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object
+* VLArbitration Record Receiver object
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_construct
+* NAME
+* osm_vlarb_rec_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a VLArbitration Record Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_construct(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a VLArbitration Record Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vlarb_rec_rcv_ctrl_init, osm_vlarb_rec_rcv_ctrl_destroy
+*
+* Calling osm_vlarb_rec_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_init,
+* osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_destroy
+* NAME
+* osm_vlarb_rec_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vlarb_rec_rcv_ctrl_destroy(
+ IN osm_vlarb_rec_rcv_ctrl_t* const 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
+* VLArbitration Record Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vlarb_rec_rcv_ctrl_construct or osm_vlarb_rec_rcv_ctrl_init.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+* osm_vlarb_rec_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VLArbitration Record Receive Controller/osm_vlarb_rec_rcv_ctrl_init
+* NAME
+* osm_vlarb_rec_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_vlarb_rec_rcv_ctrl_init function initializes a
+* VLArbitration Record Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vlarb_rec_rcv_ctrl_init(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vlarb_rec_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_vlarb_rec_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VLArbitration Record Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VLArbitration Record Receive Controller methods.
+*
+* SEE ALSO
+* VLArbitration Record Receive Controller object, osm_vlarb_rec_rcv_ctrl_construct,
+* osm_vlarb_rec_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLARB_REC_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_service.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_spinlock.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.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/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_t
+{
+ 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_construct, osm_svcr_destroy
+*********/
+
+
+/****f* OpenSM: Service Record/osm_svcr_init
+* NAME
+* osm_svcr_new
+*
+* DESCRIPTION
+* Initializes the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_init(
+ IN osm_svcr_t* const 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, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_construct
+* NAME
+* osm_svcr_construct
+*
+* DESCRIPTION
+* Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_construct(
+ IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+/****f* OpenSM: Service Record/osm_svcr_destroy
+* NAME
+* osm_svcr_destroy
+*
+* DESCRIPTION
+* Constructs the osm_svcr_t structure.
+*
+* SYNOPSIS
+*/
+void
+osm_svcr_destroy(
+ IN osm_svcr_t* const p_svcr );
+/*
+* PARAMETERS
+* p_svc_rec
+* [in] Pointer to osm_svcr_t structure
+*
+* SEE ALSO
+* Service Record, osm_svcr_construct, osm_svcr_destroy
+*********/
+
+
+
+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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_slvl_map_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Map Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_RCV_H_
+#define _OSM_SLVL_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.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/Slvl Map Receiver
+* NAME
+* Slvl Map Receiver
+*
+* DESCRIPTION
+* The Slvl Map Receiver object encapsulates the information
+* needed to set or get the SLtoVL map attribute from a port.
+*
+* The Slvl Map Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: Slvl Map Receiver/osm_slvl_rcv_t
+* NAME
+* osm_slvl_rcv_t
+*
+* DESCRIPTION
+* Slvl Map Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_slvl_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_construct
+* NAME
+* osm_slvl_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Slvl Map Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_construct(
+ IN osm_slvl_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Slvl Map Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rcv_destroy
+*
+* Calling osm_slvl_rcv_construct is a prerequisite to calling any other
+* method except osm_slvl_rcv_init.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_init,
+* osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_destroy
+* NAME
+* osm_slvl_rcv_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_destroy(
+ IN osm_slvl_rcv_t* const 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
+* Slvl Map Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rcv_construct or osm_slvl_rcv_init.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_construct,
+* osm_slvl_rcv_init
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_init
+* NAME
+* osm_slvl_rcv_init
+*
+* DESCRIPTION
+* The osm_slvl_rcv_init function initializes a
+* Slvl Map Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_init(
+ IN osm_slvl_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Slvl Map Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Slvl Map Receiver methods.
+*
+* SEE ALSO
+* Slvl Map Receiver object, osm_slvl_rcv_construct,
+* osm_slvl_rcv_destroy
+*********/
+
+/****f* OpenSM: Slvl Map Receiver/osm_slvl_rcv_process
+* NAME
+* osm_slvl_rcv_process
+*
+* DESCRIPTION
+* Process the SLtoVL map attribute.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_process(
+ IN const osm_slvl_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* Slvl Map Receiver, Slvl Map Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_slvl_map_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_pi_rcv_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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_SLVL_RCV_CTRL_H_
+#define _OSM_SLVL_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_slvl_map_rcv.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/SltoVL Map Table Receive Controller
+* NAME
+* Slvl Map Receive Controller
+*
+* DESCRIPTION
+* The Slvl Map Receive Controller object encapsulates
+* the information needed to get or set SLtoVL Map of a port.
+*
+* The Slvl Map Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_t
+* NAME
+* osm_slvl_rcv_ctrl_t
+*
+* DESCRIPTION
+* Slvl Map Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_slvl_rcv_ctrl
+{
+ osm_slvl_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_slvl_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Slvl Map Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object
+* Slvl Map Receiver object
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_construct
+* NAME
+* osm_slvl_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Slvl Map Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_construct(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Slvl Map Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_slvl_rcv_ctrl_init, osm_slvl_rcv_ctrl_destroy,
+* and osm_slvl_rcv_ctrl_is_inited.
+*
+* Calling osm_slvl_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_init,
+* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_destroy
+* NAME
+* osm_slvl_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_slvl_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_slvl_rcv_ctrl_destroy(
+ IN osm_slvl_rcv_ctrl_t* const 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
+* Slvl Map Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_init
+* NAME
+* osm_slvl_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_slvl_rcv_ctrl_init function initializes a
+* Slvl Map Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_slvl_rcv_ctrl_init(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_slvl_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Slvl Map Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Slvl Map Receive Controller methods.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_destroy, osm_slvl_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Slvl Map Receive Controller/osm_slvl_rcv_ctrl_is_inited
+* NAME
+* osm_slvl_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_slvl_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_slvl_rcv_ctrl_is_inited(
+ IN const osm_slvl_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_slvl_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_slvl_rcv_ctrl_construct or osm_slvl_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Slvl Map Receive Controller object, osm_slvl_rcv_ctrl_construct,
+* osm_slvl_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SLVL_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_t, osm_other_sm_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_SM_H_
+#define _OSM_SM_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <opensm/osm_stats.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_db.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/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;
+ cl_event_t signal;
+ cl_event_t subnet_up_event;
+ cl_thread_t sweeper;
+ 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;
+ osm_req_t req;
+ osm_req_ctrl_t req_ctrl;
+ osm_resp_t resp;
+ osm_ni_rcv_t ni_rcv;
+ osm_ni_rcv_ctrl_t ni_rcv_ctrl;
+ osm_pi_rcv_t pi_rcv;
+ osm_pi_rcv_ctrl_t pi_rcv_ctrl;
+ osm_nd_rcv_t nd_rcv;
+ osm_nd_rcv_ctrl_t nd_rcv_ctrl;
+ osm_sm_mad_ctrl_t mad_ctrl;
+ osm_si_rcv_t si_rcv;
+ osm_si_rcv_ctrl_t si_rcv_ctrl;
+ osm_state_mgr_ctrl_t state_mgr_ctrl;
+ osm_lid_mgr_t lid_mgr;
+ osm_ucast_mgr_t ucast_mgr;
+ osm_link_mgr_t link_mgr;
+ osm_state_mgr_t state_mgr;
+ osm_drop_mgr_t drop_mgr;
+ osm_lft_rcv_t lft_rcv;
+ osm_lft_rcv_ctrl_t lft_rcv_ctrl;
+ osm_mft_rcv_t mft_rcv;
+ osm_mft_rcv_ctrl_t mft_rcv_ctrl;
+ osm_sweep_fail_ctrl_t sweep_fail_ctrl;
+ osm_sminfo_rcv_t sm_info_rcv;
+ osm_sminfo_rcv_ctrl_t sm_info_rcv_ctrl;
+ osm_trap_rcv_t trap_rcv;
+ osm_trap_rcv_ctrl_t trap_rcv_ctrl;
+ osm_sm_state_mgr_t sm_state_mgr;
+ osm_mcast_mgr_t mcast_mgr;
+ osm_slvl_rcv_t slvl_rcv;
+ osm_slvl_rcv_ctrl_t slvl_rcv_ctrl;
+ osm_vla_rcv_t vla_rcv;
+ osm_vla_rcv_ctrl_t vla_rcv_ctrl;
+ osm_pkey_rcv_t pkey_rcv;
+ osm_pkey_rcv_ctrl_t pkey_rcv_ctrl;
+} 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.
+*
+* req
+* Generic MAD attribute requester.
+*
+* req_ctrl
+* Controller for the generic requester.
+*
+* resp
+* MAD attribute responder.
+*
+* nd_rcv_ctrl
+* Node Description Receive Controller.
+*
+* ni_rcv_ctrl
+* Node Info Receive Controller.
+*
+* pi_rcv_ctrl
+* Port Info Receive Controller.
+*
+* si_rcv_ctrl
+* Switch Info Receive Controller.
+*
+* nd_rcv_ctrl
+* Node Description Receive Controller.
+*
+* mad_ctrl
+* MAD Controller.
+*
+* smi_get_ctrl
+* SM Info Get 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* const 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* const 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* const 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* const p_sm,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const 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_sweep
+* NAME
+* osm_sm_sweep
+*
+* DESCRIPTION
+* Initiates a subnet sweep.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_sweep(
+ IN osm_sm_t* const 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* const p_sm,
+ IN const 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_sm_mcgrp_join
+* NAME
+* osm_sm_mcgrp_join
+*
+* DESCRIPTION
+* Adds a port to the multicast group. Creates the multicast group
+* if necessary.
+*
+* This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_join(
+ IN osm_sm_t* const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object.
+*
+* mlid
+* [in] Multicast LID
+*
+* port_guid
+* [in] Port GUID to add to the group.
+*
+* req_type
+* [in] Type of the MC request that caused this join
+* (MC create/join).
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: SM/osm_sm_mcgrp_leave
+* NAME
+* osm_sm_mcgrp_leave
+*
+* DESCRIPTION
+* Removes a port from the multicast group.
+*
+* This function is called by the SA.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+ IN osm_sm_t* const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid );
+/*
+* PARAMETERS
+* p_sm
+* [in] Pointer to an osm_sm_t object.
+*
+* mlid
+* [in] Multicast LID
+*
+* port_guid
+* [in] Port GUID to remove from the group.
+*
+* 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* const p_sm,
+ IN uint32_t const wait_us,
+ IN boolean_t const 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
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm_mad_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SM_MAD_CTRL_H_
+#define _OSM_SM_MAD_CTRL_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl15intf.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/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* const 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* const 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* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const 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* const p_ctrl,
+ IN const 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* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sm_state_mgr_t.
+ * This object represents the SM State Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_SM_STATE_MGR_H_
+#define _OSM_SM_STATE_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_remote_sm.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/SM State Manager
+* NAME
+* SM State Manager
+*
+* DESCRIPTION
+* The SM State Manager object encapsulates the information
+* needed to control the state of the SM.
+*
+* The SM State Manager object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: SM State Manager/osm_sm_state_mgr_t
+* NAME
+* osm_sm_state_mgr_t
+*
+* DESCRIPTION
+* SM State Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sm_state_mgr
+{
+ cl_spinlock_t state_lock;
+ cl_timer_t polling_timer;
+ uint32_t retry_number;
+ ib_net64_t master_guid;
+ osm_state_mgr_t* p_state_mgr;
+ osm_subn_t* p_subn;
+ osm_req_t* p_req;
+ osm_log_t* p_log;
+ osm_remote_sm_t* p_polling_sm;
+} osm_sm_state_mgr_t;
+
+/*
+* FIELDS
+* state_lock
+* Spinlock guarding the state and processes.
+*
+* retry_number
+* Used on Standby state - to count the number of retries
+* of queries to the master SM.
+*
+* polling_timer
+* Timer for polling
+*
+* p_state_mgr
+* Point to the state manager object
+*
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_polling_sm
+* Pointer to a osm_remote_sm_t object. When our SM needs
+* to poll on a remote sm, this will be the pointer of the
+* polled SM.
+*
+* SEE ALSO
+* SM State Manager object
+*********/
+
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_construct
+* NAME
+* osm_sm_state_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a SM State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_construct(
+ IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to a SM State Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_sm_state_mgr_destroy
+*
+* Calling osm_sm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_sm_state_mgr_init.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_init,
+* osm_sm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_destroy
+* NAME
+* osm_sm_state_mgr_destroy
+*
+* DESCRIPTION
+* The osm_sm_state_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sm_state_mgr_destroy(
+ IN osm_sm_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_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
+* SM State Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sm_state_mgr_construct or osm_sm_state_mgr_init.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_construct,
+* osm_sm_state_mgr_init
+*********/
+
+/****f* OpenSM: SM State Manager/osm_sm_state_mgr_init
+* NAME
+* osm_sm_state_mgr_init
+*
+* DESCRIPTION
+* The osm_sm_state_mgr_init function initializes a
+* SM State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sm_state_mgr_init(
+ IN osm_sm_state_mgr_t* const p_sm_mgr,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object to initialize.
+*
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SM State Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SM State Manager methods.
+*
+* SEE ALSO
+* SM State Manager object, osm_sm_state_mgr_construct,
+* osm_sm_state_mgr_destroy
+*********/
+
+/****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_state_mgr_t* const p_sm_mgr,
+ IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_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_state_mgr_t* const p_sm_mgr );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_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_state_mgr_t* const p_sm_mgr,
+ IN osm_sm_signal_t signal );
+/*
+* PARAMETERS
+* p_sm_mgr
+* [in] Pointer to an osm_sm_state_mgr_t object.
+*
+* signal
+* [in] Signal to the state SM engine.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SM_STATE_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sminfo_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMINFO_RCV_H_
+#define _OSM_SMINFO_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_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
+
+/****h* OpenSM/SMInfo Receiver
+* NAME
+* SMInfo Receiver
+*
+* DESCRIPTION
+* The SMInfo Receiver object encapsulates the information
+* needed to receive the SMInfo attribute from a node.
+*
+* The SMInfo Receiver 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: SMInfo Receiver/osm_sminfo_rcv_t
+* NAME
+* osm_sminfo_rcv_t
+*
+* DESCRIPTION
+* SMInfo Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv
+{
+ osm_subn_t *p_subn;
+ osm_stats_t *p_stats;
+ osm_log_t *p_log;
+ osm_resp_t *p_resp;
+ osm_state_mgr_t *p_state_mgr;
+ struct _osm_sm_state_mgr *p_sm_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_sminfo_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_resp
+* Pointer to the generic MAD responder object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_sm_state_mgr
+* Pointer to the SM State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* SMInfo Receiver object
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_construct
+* NAME
+* osm_sminfo_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a SMInfo Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_construct(
+ IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a SMInfo Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sminfo_rcv_init, osm_sminfo_rcv_destroy
+*
+* Calling osm_sminfo_rcv_construct is a prerequisite to calling any other
+* method except osm_sminfo_rcv_init.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_init,
+* osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_destroy
+* NAME
+* osm_sminfo_rcv_destroy
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_destroy(
+ IN osm_sminfo_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* SMInfo Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sminfo_rcv_construct or osm_sminfo_rcv_init.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_construct,
+* osm_sminfo_rcv_init
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_init
+* NAME
+* osm_sminfo_rcv_init
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_init function initializes a
+* SMInfo Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_sminfo_rcv_init(
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN struct _osm_sm_state_mgr* const p_sm_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_resp
+* [in] Pointer to the generic MAD Responder object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_sm_state_mgr
+* [in] Pointer to the SM State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SMInfo Receiver methods.
+*
+* SEE ALSO
+* SMInfo Receiver object, osm_sminfo_rcv_construct,
+* osm_sminfo_rcv_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receiver/osm_sminfo_rcv_process
+* NAME
+* osm_sminfo_rcv_process
+*
+* DESCRIPTION
+* Process the SMInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_sminfo_rcv_process(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SMInfo attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo processing was successful.
+*
+* NOTES
+* This function processes a SMInfo attribute.
+*
+* SEE ALSO
+* SMInfo Receiver, SMInfo Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SMINFO_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sminfo_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sminfo_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA SMInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SMINFO_RCV_CTRL_H_
+#define _OSM_SMINFO_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_log.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/SMInfo Receive Controller
+* NAME
+* SMInfo Receive Controller
+*
+* DESCRIPTION
+* The SMInfo Receive Controller object encapsulates the information
+* needed to receive the SMInfo attribute from a node.
+*
+* The SMInfo Receive 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: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_t
+* NAME
+* osm_sminfo_rcv_ctrl_t
+*
+* DESCRIPTION
+* SMInfo Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sminfo_rcv_ctrl
+{
+ osm_sminfo_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_sminfo_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the SMInfo Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* SMInfo Receive Controller object
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_construct
+* NAME
+* osm_sminfo_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a SMInfo Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_construct(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a SMInfo Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sminfo_rcv_ctrl_init, osm_sminfo_rcv_ctrl_destroy
+*
+* Calling osm_sminfo_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_init,
+* osm_sminfo_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_destroy
+* NAME
+* osm_sminfo_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sminfo_rcv_ctrl_destroy(
+ IN osm_sminfo_rcv_ctrl_t* const 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
+* SMInfo Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sminfo_rcv_ctrl_construct or osm_sminfo_rcv_ctrl_init.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+* osm_sminfo_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: SMInfo Receive Controller/osm_sminfo_rcv_ctrl_init
+* NAME
+* osm_sminfo_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_sminfo_rcv_ctrl_init function initializes a
+* SMInfo Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sminfo_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sminfo_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the SMInfo Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other SMInfo Receive Controller methods.
+*
+* SEE ALSO
+* SMInfo Receive Controller object, osm_sminfo_rcv_ctrl_construct,
+* osm_sminfo_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_SMINFO_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_state_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_state_mgr_t.
+ * This object represents the State Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_STATE_MGR_H_
+#define _OSM_STATE_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <opensm/osm_log.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/State Manager
+* NAME
+* State Manager
+*
+* DESCRIPTION
+* The State Manager object encapsulates the information
+* needed to control subnet sweeps and configuration.
+*
+* The State 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
+*
+*********/
+
+/****s* OpenSM: State Manager/osm_state_mgr_t
+* NAME
+* osm_state_mgr_t
+*
+* DESCRIPTION
+* State Manager structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_lid_mgr_t *p_lid_mgr;
+ osm_ucast_mgr_t *p_ucast_mgr;
+ osm_mcast_mgr_t *p_mcast_mgr;
+ osm_link_mgr_t *p_link_mgr;
+ osm_drop_mgr_t *p_drop_mgr;
+ osm_req_t *p_req;
+ osm_stats_t *p_stats;
+ struct _osm_sm_state_mgr *p_sm_state_mgr;
+ const osm_sm_mad_ctrl_t *p_mad_ctrl;
+ cl_spinlock_t state_lock;
+ cl_spinlock_t idle_lock;
+ cl_qlist_t idle_time_list;
+ cl_plock_t *p_lock;
+ cl_event_t *p_subnet_up_event;
+ osm_sm_state_t state;
+ osm_state_mgr_mode_t state_step_mode;
+ osm_signal_t next_stage_signal;
+} osm_state_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lid_mgr
+* Pointer to the LID Manager object.
+*
+* p_ucast_mgr
+* Pointer to the Unicast Manager object.
+*
+* p_mcast_mgr
+* Pointer to the Multicast Manager object.
+*
+* p_link_mgr
+* Pointer to the Link Manager object.
+*
+* p_drop_mgr
+* Pointer to the Drop Manager object.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_sm_state_mgr
+* Pointer to the SM state mgr object.
+*
+* p_mad_ctrl
+* Pointer to the SM's MAD Controller object.
+*
+* state_lock
+* Spinlock guarding the state and processes.
+*
+* p_lock
+* lock guarding the subnet object.
+*
+* p_subnet_up_event
+* Pointer to the event to set if/when the subnet comes up.
+*
+* state
+* State of the SM.
+*
+* state_step_mode
+* Controls the mode of progressing to next stage:
+* OSM_STATE_STEP_CONTINUOUS - normal automatic progress mode
+* OSM_STATE_STEP_TAKE_ONE - do one step and stop
+* OSM_STATE_STEP_BREAK - stop before taking next step
+*
+* next_stage_signal
+* Stores the signal to be provided when running the next stage.
+*
+* SEE ALSO
+* State Manager object
+*********/
+
+/****s* OpenSM: State Manager/_osm_idle_item
+* NAME
+* _osm_idle_item
+*
+* DESCRIPTION
+* Idle item.
+*
+* SYNOPSIS
+*/
+
+typedef osm_signal_t
+(*osm_pfn_start_t)(
+ IN void *context1,
+ IN void *context2 );
+
+typedef void
+(*osm_pfn_done_t)(
+ IN void *context1,
+ IN void *context2 );
+
+typedef struct _osm_idle_item
+{
+ cl_list_item_t list_item;
+ void* context1;
+ void* context2;
+ osm_pfn_start_t pfn_start;
+ osm_pfn_done_t pfn_done;
+}osm_idle_item_t;
+
+/*
+* FIELDS
+* list_item
+* list item.
+*
+* context1
+* Context pointer
+*
+* context2
+* Context pointer
+*
+* pfn_start
+* Pointer to the start function.
+*
+* pfn_done
+* Pointer to the dine function.
+* SEE ALSO
+* State Manager object
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_process_idle
+* NAME
+* osm_state_mgr_process_idle
+*
+* DESCRIPTION
+* Formulates the osm_idle_item and inserts it into the queue and
+* signals the state manager.
+*
+* SYNOPSIS
+*/
+
+ib_api_status_t
+osm_state_mgr_process_idle(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_pfn_start_t pfn_start,
+ IN osm_pfn_done_t pfn_done,
+ void* context1,
+ void* context2
+ );
+
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a State Manager object to construct.
+*
+* pfn_start
+* [in] Pointer the start function which will be called at
+* idle time.
+*
+* pfn_done
+* [in] pointer the done function which will be called
+* when outstanding smps is zero
+*
+* context1
+* [in] Pointer to void
+*
+* context2
+* [in] Pointer to void
+*
+* RETURN VALUE
+* IB_SUCCESS or IB_ERROR
+*
+* NOTES
+* Allows osm_state_mgr_destroy
+*
+* Calling osm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_init,
+* osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_construct
+* NAME
+* osm_state_mgr_construct
+*
+* DESCRIPTION
+* This function constructs a State Manager object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_construct(
+ IN osm_state_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to a State Manager object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows osm_state_mgr_destroy
+*
+* Calling osm_state_mgr_construct is a prerequisite to calling any other
+* method except osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_init,
+* osm_state_mgr_destroy
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_destroy
+* NAME
+* osm_state_mgr_destroy
+*
+* DESCRIPTION
+* The osm_state_mgr_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_destroy(
+ IN osm_state_mgr_t* const 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
+* State Manager object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_state_mgr_construct or osm_state_mgr_init.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_construct,
+* osm_state_mgr_init
+*********/
+
+/****f* OpenSM: State Manager/osm_state_mgr_init
+* NAME
+* osm_state_mgr_init
+*
+* DESCRIPTION
+* The osm_state_mgr_init function initializes a
+* State Manager object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_init(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_lid_mgr_t* const p_lid_mgr,
+ IN osm_ucast_mgr_t* const p_ucast_mgr,
+ IN osm_mcast_mgr_t* const p_mcast_mgr,
+ IN osm_link_mgr_t* const p_link_mgr,
+ IN osm_drop_mgr_t* const p_drop_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_stats_t* const p_stats,
+ IN struct _osm_sm_state_mgr* const p_sm_state_mgr,
+ IN const osm_sm_mad_ctrl_t* const p_mad_ctrl,
+ IN cl_plock_t* const p_lock,
+ IN cl_event_t* const p_subnet_up_event,
+ IN osm_log_t* const p_log );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_lid_mgr
+* [in] Pointer to the LID Manager object.
+*
+* p_ucast_mgr
+* [in] Pointer to the Unicast Manager object.
+*
+* p_mcast_mgr
+* [in] Pointer to the Multicast Manager object.
+*
+* p_link_mgr
+* [in] Pointer to the Link Manager object.
+*
+* p_drop_mgr
+* [in] Pointer to the Drop Manager object.
+*
+* p_req
+* [in] Pointer to the Request Controller object.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_sm_state_mgr
+* [in] Pointer to the SM state mgr object.
+*
+* p_mad_ctrl
+* [in] Pointer to the SM's mad controller.
+*
+* p_subnet_up_event
+* [in] Pointer to the event to set if/when the subnet comes up.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* RETURN VALUES
+* IB_SUCCESS if the State Manager object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other State Manager methods.
+*
+* SEE ALSO
+* State Manager object, osm_state_mgr_construct,
+* osm_state_mgr_destroy
+*********/
+
+/****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 const uint8_t l_priority,
+ IN const ib_net64_t l_guid,
+ IN const uint8_t r_priority,
+ IN const ib_net64_t r_guid )
+{
+ if( l_priority > r_priority )
+ {
+ return( TRUE );
+ }
+ else
+ {
+ if( l_priority == r_priority )
+ {
+ if( cl_ntoh64(l_guid) < cl_ntoh64(r_guid) )
+ {
+ return( TRUE );
+ }
+ }
+ }
+ return( FALSE );
+}
+/*
+* 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: State Manager/osm_state_mgr_process
+* NAME
+* osm_state_mgr_process
+*
+* DESCRIPTION
+* Processes and maintains the states of the SM.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_process(
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_signal_t signal );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object.
+*
+* signal
+* [in] Signal to the state engine.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* State Manager
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_STATE_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_state_mgr_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_state_mgr_ctrl_t.
+ * This object represents a controller that receives the
+ * State indication after a subnet sweep.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATE_MGR_CTRL_H_
+#define _OSM_STATE_MGR_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.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/State Manager Controller
+* NAME
+* State Manager Controller
+*
+* DESCRIPTION
+* The State Manager Controller object encapsulates the information
+* needed to pass the dispatcher message from the dispatcher
+* to the State Manager.
+*
+* The State Manager 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: State Manager Controller/osm_state_mgr_ctrl_t
+* NAME
+* osm_state_mgr_ctrl_t
+*
+* DESCRIPTION
+* State Manager Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_state_mgr_ctrl
+{
+ osm_state_mgr_t *p_mgr;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_state_mgr_ctrl_t;
+/*
+* FIELDS
+* p_mgr
+* Pointer to the State Manager object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* State Manager Controller object
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_construct
+* NAME
+* osm_state_mgr_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a State Manager Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_construct(
+ IN osm_state_mgr_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a State Manager Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_state_mgr_ctrl_init, and osm_state_mgr_ctrl_destroy.
+*
+* Calling osm_state_mgr_ctrl_construct is a prerequisite to calling any
+* other method except osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_init,
+* osm_state_mgr_ctrl_destroy
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_destroy
+* NAME
+* osm_state_mgr_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_state_mgr_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_state_mgr_ctrl_destroy(
+ IN osm_state_mgr_ctrl_t* const 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
+* State Manager Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_state_mgr_ctrl_construct or osm_state_mgr_ctrl_init.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_construct,
+* osm_state_mgr_ctrl_init
+*********/
+
+/****f* OpenSM: State Manager Controller/osm_state_mgr_ctrl_init
+* NAME
+* osm_state_mgr_ctrl_init
+*
+* DESCRIPTION
+* The osm_state_mgr_ctrl_init function initializes a
+* State Manager Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+ IN osm_state_mgr_ctrl_t* const p_ctrl,
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_state_mgr_ctrl_t object to initialize.
+*
+* p_mgr
+* [in] Pointer to an osm_state_mgr_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the State Manager Controller object
+* was initialized successfully.
+*
+* NOTES
+* Allows calling other State Manager Controller methods.
+*
+* SEE ALSO
+* State Manager Controller object, osm_state_mgr_ctrl_construct,
+* osm_state_mgr_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_STATE_MGR_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_stats.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_stats_t.
+ * This object represents the OpenSM statistics object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_STATS_H_
+#define _OSM_STATS_H_
+
+#include <opensm/osm_base.h>
+#include <complib/cl_atomic.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/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 qp1_mads_outstanding;
+ atomic32_t qp1_mads_rcvd;
+ atomic32_t qp1_mads_sent;
+
+} 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.
+*
+* SEE ALSO
+***************/
+
+END_C_DECLS
+
+#endif /* _OSM_STATS_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_subnet.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#ifndef _OSM_SUBNET_H_
+#define _OSM_SUBNET_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_map.h>
+#include <complib/cl_ptr_vector.h>
+#include <complib/cl_list.h>
+#include <opensm/osm_base.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 OSM_SUBNET_VECTOR_MIN_SIZE 0
+#define OSM_SUBNET_VECTOR_GROW_SIZE 1
+#define OSM_SUBNET_VECTOR_CAPACITY 256
+
+struct _osm_opensm_t;
+
+/****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
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_extension
+* NAME
+* osm_pfn_ui_extension
+*
+* DESCRIPTION
+* This typedef defines the prototype for UI extension functions
+* The might be registered in the subnet options to handle pre_lid_assign,
+* and ui_ucast_fwd_assign.
+*
+* SYNOPSIS
+*/
+typedef int
+(*osm_pfn_ui_extension_t)(
+ IN void* context );
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in the subnet opt
+* Same prefix as the UI function (suffixed by ctx)
+*
+* RETURN VALUE
+* This function returns an int (the semantic is different between
+* the different calls)
+*
+* SEE ALSO
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_pfn_ui_mcast_extension
+* NAME
+* osm_pfn_ui_mcast_extension
+*
+* DESCRIPTION
+* This typedef defines the prototype for UI extension functions
+* They might be registered in the subnet options to handle ui_mcast_fwd_assign
+*
+* SYNOPSIS
+*/
+typedef void
+(*osm_pfn_ui_mcast_extension_t)(
+ IN void *context,
+ IN ib_net16_t mlid,
+ IN osm_mcast_req_type_t request_type,
+ IN ib_net64_t port_guid );
+/*
+* PARAMETERS
+* context
+* [in] Client specific context specified in the subnet opt
+* Same prefix as the UI function (suffixed by ctx)
+*
+* mlid
+* [in] multicast lid of the group handled.
+*
+* request_type
+* [in] Type of MC request being handled (create/join/leave)
+*
+* port_guid
+* [in] port gui of the port that was added/removed from the
+* multicast group handled.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* SEE ALSO
+*
+*********/
+
+/****d* OpenSM: Subnet/osm_testability_modes_t
+* NAME
+* osm_testability_modes_t
+*
+* DESCRIPTION
+* Enumerates the possible testability modes.
+*
+* SYNOPSIS
+*/
+typedef enum _osm_testability_modes
+{
+ OSM_TEST_MODE_NONE = 0,
+ OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER,
+ OSM_TEST_MODE_MAX
+} osm_testability_modes_t;
+/***********/
+
+/****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_t {
+ unsigned max_vls;
+ unsigned 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
+*
+* high_limit
+* The limit of High Priority component of VL Arbitration
+* table (IBA 7.6.9)
+*
+* vlarb_high
+* High priority VL Arbitration table template.
+*
+* vlarb_low
+* Low priority VL Arbitration table template.
+*
+* sl2vl
+* SL2VL Mapping table (IBA 7.6.6) template.
+*
+*********/
+
+/****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
+{
+ ib_net64_t guid;
+ ib_net64_t m_key;
+ ib_net64_t sm_key;
+ ib_net64_t subnet_prefix;
+ ib_net16_t m_key_lease_period;
+ uint32_t sweep_interval;
+ uint32_t max_wire_smps;
+ uint32_t transaction_timeout;
+ uint8_t sm_priority;
+ uint8_t lmc;
+ boolean_t lmc_esp0;
+ uint8_t max_op_vls;
+ uint8_t force_link_speed;
+ boolean_t reassign_lids;
+ boolean_t reassign_lfts;
+ boolean_t ignore_other_sm;
+ boolean_t single_thread;
+ boolean_t no_multicast_option;
+ 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;
+ 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;
+ unsigned long log_max_size;
+ char * partition_config_file;
+ boolean_t no_partition_enforcement;
+ boolean_t no_qos;
+ boolean_t accum_log_file;
+ boolean_t console;
+ cl_map_t port_prof_ignore_guids;
+ boolean_t port_profile_switch_nodes;
+ osm_pfn_ui_extension_t pfn_ui_pre_lid_assign;
+ void * ui_pre_lid_assign_ctx;
+ osm_pfn_ui_mcast_extension_t pfn_ui_mcast_fdb_assign;
+ void * ui_mcast_fdb_assign_ctx;
+ boolean_t sweep_on_trap;
+ osm_testability_modes_t testability_mode;
+ char * routing_engine_name;
+ char * lid_matrix_dump_file;
+ char * ucast_dump_file;
+ char * updn_guid_file;
+ char * sa_db_file;
+ boolean_t exit_on_fatal;
+ boolean_t honor_guid2lid_file;
+ 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 enable_quirks;
+ boolean_t no_clients_rereg;
+} osm_subn_opt_t;
+/*
+* FIELDS
+*
+* guid
+* The port guid that the SM is binding to.
+*
+* m_key
+* M_Key value sent to all ports qualifing all Set(PortInfo).
+*
+* sm_key
+* SM_Key value of the SM 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.
+*
+* 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.
+*
+* reassign_lfts
+* If TRUE ignore existing LFT entries on first sweep (default).
+* Otherwise only non minimal hop cases are modified.
+* NOTE: A standby SM clears its first sweep flag - since the
+* master SM already sweeps...
+*
+* ignore_other_sm_option
+* This flag is TRUE if other SMs on the subnet should be ignored.
+*
+* no_multicast_option
+* 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 SubnMgt.Set(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 SubnMgt.Set(SwitchInfo.life_state)
+*
+* dump_files_dir
+* The directory to be used for subnet.lst osm.fdbs, osm.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.
+*
+* 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_guids
+* A map of 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.
+*
+* pfn_ui_pre_lid_assign
+* A UI function to be invoked prior to lid assigment. It should
+* return 1 if any change was made to any lid or 0 otherwise.
+*
+* ui_pre_lid_assign_ctx
+* A UI context (void *) to be provided to the pfn_ui_pre_lid_assign
+*
+* pfn_ui_mcast_fdb_assign
+* A UI function to be called inside the mcast manager instead of
+* the call for the build spanning tree. This will be called on
+* every multicast call for create, join and leave, and is
+* responsible for the mcast FDB configuration.
+*
+* ui_mcast_fdb_assign_ctx
+* A UI context (void *) to be provided to the pfn_ui_mcast_fdb_assign
+*
+* sweep_on_trap
+* Received traps will initiate a new sweep.
+*
+* testability_mode
+* Object that indicates if we are running in a special testability mode.
+*
+* routing_engine_name
+* Name of used routing engine
+* (other than default Min Hop Algorithm)
+*
+* lid_matrix_dump_file
+* Name of the lid matrix dump file from where switch
+* lid matrices (min hops tables) will be loaded
+*
+* ucast_dump_file
+* Name of the unicast routing dump file from where switch
+* forwarding tables will be loaded
+*
+* updn_guid_file
+* Pointer to name of the UPDN guid file given by User
+*
+* sa_db_file
+* Name of the SA database file.
+*
+* 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.
+*
+* 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
+*
+* enable_quirks
+* Enable high risk new features and not fully qualified
+* hardware specific work arounds
+*
+* no_clients_rereg
+* When TRUE disables clients reregistration request.
+*
+* 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_t *p_osm;
+ cl_qmap_t sw_guid_tbl;
+ cl_qmap_t node_guid_tbl;
+ cl_qmap_t port_guid_tbl;
+ cl_qmap_t rtr_guid_tbl;
+ cl_qmap_t prtn_pkey_tbl;
+ cl_qmap_t mgrp_mlid_tbl;
+ cl_qmap_t sm_guid_tbl;
+ cl_list_t light_sweep_physp_list;
+ cl_qlist_t sa_sr_list;
+ cl_qlist_t sa_infr_list;
+ cl_ptr_vector_t node_lid_tbl;
+ 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 sm_state;
+ osm_subn_opt_t opt;
+ uint16_t max_unicast_lid_ho;
+ uint16_t max_multicast_lid_ho;
+ uint8_t min_ca_mtu;
+ uint8_t min_ca_rate;
+ boolean_t ignore_existing_lfts;
+ boolean_t subnet_initialization_error;
+ boolean_t force_immediate_heavy_sweep;
+ boolean_t force_delayed_heavy_sweep;
+ cl_list_t new_ports_list;
+ boolean_t in_sweep_hop_0;
+ boolean_t moved_to_master_state;
+ boolean_t first_time_master_sweep;
+ boolean_t coming_out_of_standby;
+} osm_subn_t;
+/*
+* FIELDS
+* sw_guid_tbl
+* Container of pointers to all Switch objects in the subent.
+* Indexed by node GUID.
+*
+* node_guid_tbl
+* Container of pointers to all Node objects in the subent.
+* Indexed by node GUID.
+*
+* port_guid_tbl
+* Container of pointers to all Port objects in the subent.
+* Indexed by port GUID - network order!
+*
+* rtr_guid_tbl
+* Container of pointers to all Router objects in the subent.
+* Indexed by node GUID.
+*
+* prtn_pkey_tbl
+* Container of pointers to all Partition objects in the subnet.
+* Indexed by P_KEY.
+*
+* mgrp_mlid_tbl
+* Container of pointers to all Multicast Group objects in the subnet.
+* Indexed by MLID.
+*
+* sm_guid_tbl
+* Container of pointers to SM objects representing other SMs
+* on the subnet.
+*
+* light_sweep_physp_list
+* A list of all phys ports to scan for a change in remote
+* side state in next light sweep. These ports are not down
+* but for some reason the remote side did not answer.
+*
+* node_lid_tbl
+* Container of pointers to all Node objects in the subent.
+* Indexed by node LID.
+*
+* port_ptr_tbl
+* Container of pointers to all Port objects in the subent.
+* 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.
+*
+* 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.
+*
+* max_unicast_lid_ho
+* The minimal max unicast lid reported by all switches
+*
+* max_multicast_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 :
+* - During SM init set to the reassign_lfts flag value
+* - Coming out of STANDBY it will be cleared (other SM worked)
+* - Any change to the list of switches will set it to high
+* - Set to FALSE upon end of all lft assignments.
+*
+* subnet_initalization_error
+* Similar to the force_immediate_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_immediate_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_delayed_heavy_sweep
+* In some means - similar to the force_immediate_heavy_sweep flag, only
+* it'll cause a heavy sweep in the next sweep. Note that this means that
+* if we are running with -s 0 (no sweeps) - then this forced heavy sweep
+* will not occur.
+* If we had some trouble on the subnet, that caused a strange dropping
+* of ports - we will try to do another heavy sweep on our next sweep.
+*
+* new_ports_list
+* Container of pointers to port objects that were discovered for
+* the first time during a current sweep.
+*
+* 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.
+*
+* moved_to_master_state
+* Used for the writing of "SUBNET UP" into /var/log/messages.
+* Will be TRUE when the SM switches to Master state, and returned
+* to FALSE once the sunbet is up.
+*
+* 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.
+*
+* 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* const 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* const 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* const p_subn,
+ IN struct _osm_opensm_t * const p_osm,
+ IN const osm_subn_opt_t* const 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;
+
+/****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 const 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 uint64_t guid );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The node guid in host 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
+* The looks for the given node giud 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 uint64_t guid );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The node guid in host 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
+* The 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 uint64_t guid );
+/*
+* PARAMETERS
+* p_subn
+* [in] Pointer to an osm_subn_t object
+*
+* guid
+* [in] The port guid in host 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: 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: 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* const 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_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* const 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
+*/
+void
+osm_subn_parse_conf_file(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* 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
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_parse_conf_file
+* NAME
+* osm_subn_rescan_conf_file
+*
+* DESCRIPTION
+* The osm_subn_rescan_conf_file function parses the configuration
+* file and update selected subnet options
+*
+* SYNOPSIS
+*/
+void
+osm_subn_rescan_conf_file(
+ IN osm_subn_opt_t* const p_opts );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* NOTES
+* This uses the same file as osm_subn_parse_conf_file()
+*
+*********/
+
+/****f* OpenSM: Subnet/osm_subn_write_conf_file
+* NAME
+* osm_subn_write_conf_file
+*
+* DESCRIPTION
+* Write the configuration file into the cache
+*
+* SYNOPSIS
+*/
+void
+osm_subn_write_conf_file(
+ IN osm_subn_opt_t* const p_opt );
+/*
+* PARAMETERS
+*
+* p_opt
+* [in] Pointer to the subnet options structure.
+*
+* RETURN VALUES
+* None
+*
+* 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
+*
+* SEE ALSO
+* Subnet object, osm_subn_construct, osm_subn_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SUBNET_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sw_info_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SI_RCV_H_
+#define _OSM_SI_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.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/Switch Info Receiver
+* NAME
+* Switch Info Receiver
+*
+* DESCRIPTION
+* The Switch Info Receiver object encapsulates the information
+* needed to receive the SwitchInfo attribute from a node.
+*
+* The Switch Info Receiver 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: Switch Info Receiver/osm_si_rcv_t
+* NAME
+* osm_si_rcv_t
+*
+* DESCRIPTION
+* Switch Info Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv
+{
+ osm_subn_t *p_subn;
+ osm_log_t *p_log;
+ osm_req_t *p_req;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+
+} osm_si_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_req
+* Pointer to the Request object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_construct
+* NAME
+* osm_si_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_construct(
+ IN osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_si_rcv_init, osm_si_rcv_destroy,
+* and osm_si_rcv_is_inited.
+*
+* Calling osm_si_rcv_construct is a prerequisite to calling any other
+* method except osm_si_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_init,
+* osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_destroy
+* NAME
+* osm_si_rcv_destroy
+*
+* DESCRIPTION
+* The osm_si_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_destroy(
+ IN osm_si_rcv_t* const 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
+* Switch Info Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_si_rcv_construct or osm_si_rcv_init.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_init
+* NAME
+* osm_si_rcv_init
+*
+* DESCRIPTION
+* The osm_si_rcv_init function initializes a
+* Switch Info Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_init(
+ IN osm_si_rcv_t* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Switch Info Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receiver methods.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_destroy, osm_si_rcv_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_is_inited
+* NAME
+* osm_si_rcv_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_si_rcv_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_is_inited(
+ IN const osm_si_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_si_rcv_construct or osm_si_rcv_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receiver object, osm_si_rcv_construct,
+* osm_si_rcv_init
+*********/
+
+/****f* OpenSM: Switch Info Receiver/osm_si_rcv_process
+* NAME
+* osm_si_rcv_process
+*
+* DESCRIPTION
+* Process the SwitchInfo attribute.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_process(
+ IN const osm_si_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SwitchInfo attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SwitchInfo processing was successful.
+*
+* NOTES
+* This function processes a SwitchInfo attribute.
+*
+* SEE ALSO
+* Switch Info Receiver, Switch Info Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sw_info_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_si_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA SwitchInfo
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SI_RCV_CTRL_H_
+#define _OSM_SI_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.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/Switch Info Receive Controller
+* NAME
+* Switch Info Receive Controller
+*
+* DESCRIPTION
+* The Switch Info Receive Controller object encapsulates
+* the information needed to receive the SwitchInfo attribute from a node.
+*
+* The Switch Info Receive 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: Switch Info Receive Controller/osm_si_rcv_ctrl_t
+* NAME
+* osm_si_rcv_ctrl_t
+*
+* DESCRIPTION
+* Switch Info Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_si_rcv_ctrl
+{
+ osm_si_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_si_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Switch Info Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Switch Info Receive Controller object
+* Switch Info Receiver object
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_construct
+* NAME
+* osm_si_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Switch Info Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_construct(
+ IN osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Switch Info Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_si_rcv_ctrl_init, osm_si_rcv_ctrl_destroy,
+* and osm_si_rcv_ctrl_is_inited.
+*
+* Calling osm_si_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_init,
+* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_destroy
+* NAME
+* osm_si_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_si_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_si_rcv_ctrl_destroy(
+ IN osm_si_rcv_ctrl_t* const 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
+* Switch Info Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_init
+* NAME
+* osm_si_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_si_rcv_ctrl_init function initializes a
+* Switch Info Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_si_rcv_ctrl_init(
+ IN osm_si_rcv_ctrl_t* const p_ctrl,
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_si_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Switch Info Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Switch Info Receive Controller methods.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_destroy, osm_si_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: Switch Info Receive Controller/osm_si_rcv_ctrl_is_inited
+* NAME
+* osm_si_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_si_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_si_rcv_ctrl_is_inited(
+ IN const osm_si_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_si_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_si_rcv_ctrl_construct or osm_si_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* Switch Info Receive Controller object, osm_si_rcv_ctrl_construct,
+* osm_si_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SI_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sweep_fail_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_sweep_fail_ctrl_t.
+ * This object represents a controller that
+ * handles transport failures during sweeps.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_SWEEP_FAIL_CTRL_H_
+#define _OSM_SWEEP_FAIL_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_log.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/Sweep Fail Controller
+* NAME
+* Sweep Fail Controller
+*
+* DESCRIPTION
+* The Sweep Fail Controller object encapsulates
+* the information needed to handle transport failures during
+* sweeps.
+*
+* The Sweep Fail 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: Sweep Fail Controller/osm_sweep_fail_ctrl_t
+* NAME
+* osm_sweep_fail_ctrl_t
+*
+* DESCRIPTION
+* Sweep Fail Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_sweep_fail_ctrl
+{
+ osm_log_t *p_log;
+ osm_state_mgr_t *p_state_mgr;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+
+} osm_sweep_fail_ctrl_t;
+/*
+* FIELDS
+* p_log
+* Pointer to the log object.
+*
+* p_sate_mgr
+* Pointer to the state manager object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Sweep Fail Controller object
+* Sweep Failr object
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_construct
+* NAME
+* osm_sweep_fail_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Sweep Fail Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_construct(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Sweep Fail Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_sweep_fail_ctrl_init, osm_sweep_fail_ctrl_destroy
+*
+* Calling osm_sweep_fail_ctrl_construct is a prerequisite to calling any other
+* method except osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_init,
+* osm_sweep_fail_ctrl_destroy
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_destroy
+* NAME
+* osm_sweep_fail_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_sweep_fail_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_sweep_fail_ctrl_destroy(
+ IN osm_sweep_fail_ctrl_t* const 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
+* Sweep Fail Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_sweep_fail_ctrl_construct or osm_sweep_fail_ctrl_init.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+* osm_sweep_fail_ctrl_init
+*********/
+
+/****f* OpenSM: Sweep Fail Controller/osm_sweep_fail_ctrl_init
+* NAME
+* osm_sweep_fail_ctrl_init
+*
+* DESCRIPTION
+* The osm_sweep_fail_ctrl_init function initializes a
+* Sweep Fail Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_sweep_fail_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_sweep_fail_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the state manager object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the Sweep Fail Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Sweep Fail Controller methods.
+*
+* SEE ALSO
+* Sweep Fail Controller object, osm_sweep_fail_ctrl_construct,
+* osm_sweep_fail_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWEEP_FAIL_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_switch.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_switch_t.
+ * This object represents an IBA switch.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_SWITCH_H_
+#define _OSM_SWITCH_H_
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_matrix.h>
+#include <opensm/osm_fwd_tbl.h>
+#include <opensm/osm_mcast_tbl.h>
+#include <opensm/osm_port_profile.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/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;
+ osm_fwd_tbl_t fwd_tbl;
+ osm_lid_matrix_t lmx;
+ uint16_t max_lid_ho;
+ osm_port_profile_t *p_prof;
+ osm_mcast_tbl_t mcast_tbl;
+ uint32_t discovery_count;
+} 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.
+*
+* fwd_tbl
+* This switch's forwarding table.
+*
+* lmx
+* LID Matrix for this switch containing the hop count
+* to every LID from every port.
+*
+* max_lid_ho
+* Max LID that is accessible from this switch.
+*
+* p_pro
+* Pointer to array of Port Profile objects for this switch.
+*
+* mcast_tbl
+* Multicast forwarding table for this switch.
+*
+* discovery_count
+* The number of times this switch has been discovered
+* during the current fabric sweep. This number is reset
+* to zero at the start of a sweep.
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_construct
+* NAME
+* osm_switch_construct
+*
+* DESCRIPTION
+* This function constructs a Switch object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_construct(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_switch_init, and osm_switch_destroy.
+*
+* Calling osm_switch_construct is a prerequisite to calling any other
+* method except osm_switch_init.
+*
+* SEE ALSO
+* Switch object, osm_switch_init, osm_switch_destroy
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+* osm_switch_destroy
+*
+* DESCRIPTION
+* The osm_switch_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_destroy(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+* Performs any necessary cleanup of the specified object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to osm_switch_construct
+* or osm_switch_init.
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+/****f* OpenSM: Switch/osm_switch_destroy
+* NAME
+* osm_switch_destroy
+*
+* DESCRIPTION
+* Destroys and deallocates the object.
+*
+* SYNOPSIS
+*/
+void
+osm_switch_delete(
+ IN OUT osm_switch_t** const pp_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_init
+*********/
+
+/****f* OpenSM: Switch/osm_switch_init
+* NAME
+* osm_switch_init
+*
+* DESCRIPTION
+* The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_switch_init(
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object to initialize.
+*
+* 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
+* IB_SUCCESS if the Switch object was initialized successfully.
+*
+* NOTES
+* Allows calling other node methods.
+*
+* SEE ALSO
+* Switch object, osm_switch_construct, osm_switch_destroy
+*********/
+
+/****f* OpenSM: Switch/osm_switch_new
+* NAME
+* osm_switch_new
+*
+* DESCRIPTION
+* The osm_switch_init function initializes a Switch object for use.
+*
+* SYNOPSIS
+*/
+osm_switch_t*
+osm_switch_new(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const 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_construct, osm_switch_destroy,
+*********/
+
+/****f* OpenSM: Switch/osm_switch_is_leaf_lid
+* NAME
+* osm_switch_is_leaf_lid
+*
+* DESCRIPTION
+* Indicates if the specified LID is the switch's LID, or is a leaf
+* of the switch.
+*
+* SYNOPSIS
+*/
+static inline boolean_t
+osm_switch_is_leaf_lid(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_get_least_hops( &p_sw->lmx, lid_ho ) <= 1 );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* lid_ho
+* [in] LID (host order) to compare.
+*
+* RETURN VALUES
+* TRUE if the LID is the switch's LID or is a leaf of the switch,
+* FALSE otherwise.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****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* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num )
+{
+ return( osm_lid_matrix_get( &p_sw->lmx, 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_get_fwd_tbl_ptr
+* NAME
+* osm_switch_get_fwd_tbl_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the switch's forwarding table.
+*
+* SYNOPSIS
+*/
+static inline osm_fwd_tbl_t*
+osm_switch_get_fwd_tbl_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (osm_fwd_tbl_t*)&p_sw->fwd_tbl );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* RETURN VALUES
+* Returns a pointer to the switch's forwarding table.
+*
+* 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
+*/
+static inline cl_status_t
+osm_switch_set_hops(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t num_hops )
+{
+ return( osm_lid_matrix_set( &p_sw->lmx, lid_ho, port_num, 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 the hop count at the specified LID/Port intersection.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_set_min_lid_size
+* NAME
+* osm_switch_set_min_lid_size
+*
+* DESCRIPTION
+* Sets the size of the switch's routing table to at least accomodate the
+* specified LID value (host ordered)
+*
+* SYNOPSIS
+*/
+static inline cl_status_t
+osm_switch_set_min_lid_size(
+ IN osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_set_min_lid_size( &p_sw->lmx, lid_ho ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a Switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to set the count.
+*
+* RETURN VALUES
+* Sets the size of the switch's routing table to at least accomodate the
+* specified LID value (host ordered)
+*
+* 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* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_lid_matrix_get_least_hops( &p_sw->lmx, 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.
+*
+* 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_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* const p_sw,
+ IN const uint16_t lid_ho )
+{
+ return( osm_fwd_tbl_get( &p_sw->fwd_tbl, 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.
+*
+* RETURN VALUES
+* Returns the switch port on which the specified LID is routed.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_physp_ptr
+* NAME
+* osm_switch_get_physp_ptr
+*
+* DESCRIPTION
+* Gets the Physical Port Object at the specified port number.
+*
+* SYNOPSIS
+*/
+osm_physp_t*
+osm_switch_get_physp_ptr(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t port_num );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* port_num
+* [in] Port number for which to retrieve the Physical Port Object.
+*
+* RETURN VALUES
+* Returns a pointer to the Physical Port Object object at the specified
+* port number.
+* A return value of zero means the port number was out of range.
+*
+*
+* 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* const p_sw,
+ IN const ib_net16_t lid )
+{
+ uint8_t port_num;
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( lid );
+
+ port_num = osm_fwd_tbl_get( &p_sw->fwd_tbl, cl_ntoh16( lid ) );
+ /*
+ 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_get_si_ptr
+* NAME
+* osm_switch_get_si_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the SwitchInfo for this switch.
+*
+* SYNOPSIS
+*/
+static inline ib_switch_info_t*
+osm_switch_get_si_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (ib_switch_info_t*)&p_sw->switch_info );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the SwitchInfo for this switch.
+*
+* 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* const 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
+* NAME
+* osm_switch_get_max_block_id
+*
+* DESCRIPTION
+* Returns the maximum block ID (host order) of this switch.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_get_max_block_id(
+ IN const osm_switch_t* const p_sw )
+{
+ return( (uint32_t)(osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) /
+ osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl ) ) );
+}
+/*
+* 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_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* const p_sw )
+{
+ return( osm_fwd_tbl_get_max_block_id_in_use( &p_sw->fwd_tbl,
+ cl_ntoh16( p_sw->switch_info.lin_top ) ) );
+}
+/*
+* 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_node_ptr
+* NAME
+* osm_switch_get_node_ptr
+*
+* DESCRIPTION
+* Returns a pointer to the Node object for this switch.
+*
+* SYNOPSIS
+*/
+static inline osm_node_t*
+osm_switch_get_node_ptr(
+ IN const osm_switch_t* const p_sw )
+{
+ return( p_sw->p_node );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns a pointer to the Node object for this switch.
+*
+* NOTES
+*
+* SEE ALSO
+* Switch object
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_max_lid_ho
+* NAME
+* osm_switch_get_max_lid_ho
+*
+* DESCRIPTION
+* Returns the maximum LID (host order) value contained
+* in the switch routing tables.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_max_lid_ho(
+ IN const osm_switch_t* const p_sw )
+{
+ if (p_sw->max_lid_ho != 0)
+ return p_sw->max_lid_ho;
+ return( osm_lid_matrix_get_max_lid_ho( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to a switch object.
+*
+* RETURN VALUES
+* Returns the maximum LID (host order) value contained
+* in the switch routing tables.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_num_ports
+* NAME
+* osm_switch_get_num_ports
+*
+* DESCRIPTION
+* Returns the number of ports in this switch.
+*
+* SYNOPSIS
+*/
+static inline uint8_t
+osm_switch_get_num_ports(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_lid_matrix_get_num_ports( &p_sw->lmx ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the number of ports in this switch.
+*
+* NOTES
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM: Switch/osm_switch_get_fwd_tbl_block
+* NAME
+* osm_switch_get_fwd_tbl_block
+*
+* DESCRIPTION
+* Retrieve a forwarding table block.
+*
+* SYNOPSIS
+*/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t block_id,
+ OUT uint8_t* const 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 clock 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* const 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* const p_sw,
+ IN const ib_switch_info_t* const 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* const p_sw,
+ IN const 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_ft_block
+* NAME
+* osm_switch_set_ft_block
+*
+* DESCRIPTION
+* Copies in the specified block into the switch's Forwarding Table object.
+*
+* SYNOPSIS
+*/
+static inline ib_api_status_t
+osm_switch_set_ft_block(
+ IN osm_switch_t* const p_sw,
+ IN const uint8_t* const p_block,
+ IN const uint32_t block_num )
+{
+ CL_ASSERT( p_sw );
+ return( osm_fwd_tbl_set_block( &p_sw->fwd_tbl, p_block, block_num ) );
+}
+/*
+* 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* const p_sw,
+ IN const ib_net16_t* const p_block,
+ IN const uint16_t block_num,
+ IN const 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* const p_sw,
+ IN const uint16_t block_num,
+ IN const uint8_t position,
+ OUT ib_net16_t* const 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* const 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* const 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* const 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_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* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const boolean_t ignore_existing,
+ IN OUT uint64_t *remote_sys_guids,
+ IN OUT uint16_t *p_num_used_sys,
+ IN OUT uint64_t *remote_node_guids,
+ IN OUT uint16_t *p_num_used_nodes
+ );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* lid_ho
+* [in] LID value (host order) for which to get a path advisory.
+*
+* 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.
+*
+* remote_sys_guids
+* [in out] The array of remote system guids already used to
+* route the other lids of the same target port (if LMC > 0).
+*
+* p_num_used_sys
+* [in out] The number of remote systems used for routing to
+* the port.
+*
+* remote_node_guids
+* [in out] The array of remote node guids already used to route
+* the other lids of the same target port (if LMC > 0).
+*
+* p_num_used_nodes
+* [in out] The number of remote nodes used for routing to
+* the port.
+*
+* 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* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const uint16_t mlid_ho,
+ IN const boolean_t ignore_existing );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch object.
+*
+* lid_ho
+* [in] LID value (host order) for of the node for with 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_fwd_tbl_size
+* NAME
+* osm_switch_get_fwd_tbl_size
+*
+* DESCRIPTION
+* Returns the number of entries available in the forwarding table.
+*
+* SYNOPSIS
+*/
+static inline uint16_t
+osm_switch_get_fwd_tbl_size(
+ IN const osm_switch_t* const p_sw )
+{
+ return( osm_fwd_tbl_get_size( &p_sw->fwd_tbl ) );
+}
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the switch.
+*
+* RETURN VALUE
+* Returns the number of entries available in the forwarding table.
+*
+* 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* const 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* const p_sw,
+ IN const 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
+*/
+void
+osm_switch_prepare_path_rebuild(
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_sw
+* [in] Pointer to the Switch object.
+*
+* RETURN VALUE
+* None.
+*
+* 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* const 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* const p_sw,
+ IN const 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
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_get
+* NAME
+* osm_switch_discovery_count_get
+*
+* DESCRIPTION
+* Returns a pointer to the physical port object at the
+* specified local port number.
+*
+* SYNOPSIS
+*/
+static inline uint32_t
+osm_switch_discovery_count_get(
+ IN const osm_switch_t* const p_switch )
+{
+ return( p_switch->discovery_count );
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* Returns the discovery count for this node.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_reset
+* NAME
+* osm_switch_discovery_count_reset
+*
+* DESCRIPTION
+* Resets the discovery count for this node to zero.
+* This operation should be performed at the start of a sweep.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_reset(
+ IN osm_switch_t* const p_switch )
+{
+ p_switch->discovery_count = 0;
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+/****f* OpenSM: Node/osm_switch_discovery_count_inc
+* NAME
+* osm_switch_discovery_count_inc
+*
+* DESCRIPTION
+* Increments the discovery count for this node.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_switch_discovery_count_inc(
+ IN osm_switch_t* const p_switch )
+{
+ p_switch->discovery_count++;
+}
+/*
+* PARAMETERS
+* p_switch
+* [in] Pointer to an osm_switch_t object.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+*
+* SEE ALSO
+* Node object
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_SWITCH_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_trap_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_TRAP_RCV_H_
+#define _OSM_TRAP_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <complib/cl_event_wheel.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_state_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
+
+/****h* OpenSM/Trap Receiver
+* NAME
+* Trap Receiver
+*
+* DESCRIPTION
+* The Trap Receiver object encapsulates the information
+* needed to receive the Trap attribute from a node.
+*
+* The Trap Receiver 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: Trap Receiver/osm_trap_rcv_t
+* NAME
+* osm_trap_rcv_t
+*
+* DESCRIPTION
+* Trap Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_trap_rcv
+{
+ osm_subn_t *p_subn;
+ osm_stats_t *p_stats;
+ osm_log_t *p_log;
+ osm_resp_t *p_resp;
+ osm_state_mgr_t *p_state_mgr;
+ cl_plock_t *p_lock;
+ cl_event_wheel_t trap_aging_tracker;
+} osm_trap_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* Pointer to the OpenSM statistics block.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_resp
+* Pointer to the generic MAD responder object.
+*
+* p_state_mgr
+* Pointer to the State Manager object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* trap_aging_tracker
+* An event wheel tracking erceived traps and their aging.
+* Basically we can start a timer every time we receive a specific
+* trap and check to seee if not expired next time it is received.
+*
+* SEE ALSO
+* Trap Receiver object
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_construct
+* NAME
+* osm_trap_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a Trap Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_construct(
+ IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to a Trap Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_trap_rcv_init, osm_trap_rcv_destroy
+*
+* Calling osm_trap_rcv_construct is a prerequisite to calling any other
+* method except osm_trap_rcv_init.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_init,
+* osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_destroy
+* NAME
+* osm_trap_rcv_destroy
+*
+* DESCRIPTION
+* The osm_trap_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_destroy(
+ IN osm_trap_rcv_t* const p_rcv );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to the object to destroy.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Performs any necessary cleanup of the specified
+* Trap Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_trap_rcv_construct or osm_trap_rcv_init.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_construct,
+* osm_trap_rcv_init
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_init
+* NAME
+* osm_trap_rcv_init
+*
+* DESCRIPTION
+* The osm_trap_rcv_init function initializes a
+* Trap Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_trap_rcv_init(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object to initialize.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_stats
+* [in] Pointer to the OpenSM statistics block.
+*
+* p_resp
+* [in] Pointer to the generic MAD Responder object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_state_mgr
+* [in] Pointer to the State Manager object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Trap Receiver methods.
+*
+* SEE ALSO
+* Trap Receiver object, osm_trap_rcv_construct,
+* osm_trap_rcv_destroy
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_process
+* NAME
+* osm_trap_rcv_process
+*
+* DESCRIPTION
+* Process the Trap attribute.
+*
+* SYNOPSIS
+*/
+void osm_trap_rcv_process(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's Trap attribute.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap processing was successful.
+*
+* NOTES
+* This function processes a Trap attribute.
+*
+* SEE ALSO
+* Trap Receiver, Trap Response Controller
+*********/
+
+/****f* OpenSM: Trap Receiver/osm_trap_rcv_aging_tracker_callback
+* NAME
+* osm_trap_rcv_aging_tracker_callback
+*
+* DESCRIPTION
+* Callback function called by the aging tracker mechanism.
+*
+* SYNOPSIS
+*/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+ IN uint64_t key,
+ IN uint32_t num_regs,
+ IN void* context );
+
+/*
+* PARAMETERS
+* key
+* [in] The key by which the event was inserted.
+*
+* num_regs
+* [in] The number of times the same event (key) was registered.
+*
+* context
+* [in] Pointer to the context given in the registering of the event.
+*
+* RETURN VALUES
+* None.
+*
+* NOTES
+* This function is called by the cl_event_wheel when the aging tracker
+* event has ended.
+*
+* SEE ALSO
+* Trap Receiver, Trap Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_TRAP_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_trap_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_trap_rcv_ctrl_t.
+ * This object represents a controller that receives the IBA Trap
+ * attribute from a node.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSM_TRAP_RCV_CTRL_H_
+#define _OSM_TRAP_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_log.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
+
+/***** OpenSM/Trap Receive Controller
+* NAME
+* Trap Receive Controller
+*
+* DESCRIPTION
+* The Trap Receive Controller object encapsulates the information
+* needed to receive the Trap attribute from a node.
+*
+* The Trap Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Yael Kalka, Mellanox
+*
+*********/
+
+/****s* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_t
+* NAME
+* osm_trap_rcv_ctrl_t
+*
+* DESCRIPTION
+* Trap Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_trap_rcv_ctrl
+{
+ osm_trap_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_trap_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the Trap Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* Trap Receive Controller object
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_construct
+* NAME
+* osm_trap_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a Trap Receive Controller object.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_construct(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a Trap Receive Controller object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_trap_rcv_ctrl_init, osm_trap_rcv_ctrl_destroy
+*
+* Calling osm_trap_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_init,
+* osm_trap_rcv_ctrl_destroy
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_destroy
+* NAME
+* osm_trap_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_trap_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void
+osm_trap_rcv_ctrl_destroy(
+ IN osm_trap_rcv_ctrl_t* const 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
+* Trap Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_trap_rcv_ctrl_construct or osm_trap_rcv_ctrl_init.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+* osm_trap_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: Trap Receive Controller/osm_trap_rcv_ctrl_init
+* NAME
+* osm_trap_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_trap_rcv_ctrl_init function initializes a
+* Trap Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl,
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_trap_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_trap_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* IB_SUCCESS if the Trap Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other Trap Receive Controller methods.
+*
+* SEE ALSO
+* Trap Receive Controller object, osm_trap_rcv_ctrl_construct,
+* osm_trap_rcv_ctrl_destroy
+*********/
+
+END_C_DECLS
+
+#endif /* OSM_TRAP_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_ts_useraccess.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#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
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_ucast_mgr.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_ucast_mgr_t.
+ * This object represents the Unicast Manager object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_UCAST_MGR_H_
+#define _OSM_UCAST_MGR_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.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 OSM_UCAST_MGR_LIST_SIZE_MIN 256
+
+/****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
+*
+*********/
+
+/****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
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+ boolean_t any_change;
+ uint8_t *lft_buf;
+} osm_ucast_mgr_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the Requester object sending SMPs.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* any_change
+* Initialized to FALSE at the beginning of the algorithm,
+* set to TRUE by osm_ucast_mgr_set_fwd_table() if any mad
+* was sent.
+*
+* lft_buf
+* LFT buffer - used during LFT calculation/setup.
+*
+* 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* const 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* const 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* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object to initialize.
+*
+* p_req
+* [in] Pointer to the attribute Requester object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* 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_table
+* NAME
+* osm_ucast_mgr_set_fwd_table
+*
+* DESCRIPTION
+* Setup forwarding table for the switch (from prepared lft_buf).
+*
+* SYNOPSIS
+*/
+void
+osm_ucast_mgr_set_fwd_table(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object.
+*
+* p_mgr
+* [in] Pointer to an osm_switch_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
+*/
+void
+osm_ucast_mgr_build_lid_matrices(
+ IN osm_ucast_mgr_t* const 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
+*/
+osm_signal_t
+osm_ucast_mgr_process(
+ IN osm_ucast_mgr_t* const p_mgr );
+/*
+* PARAMETERS
+* p_mgr
+* [in] Pointer to an osm_ucast_mgr_t object.
+*
+* RETURN VALUES
+* Returns the appropriate signal to the caller:
+* OSM_SIGNAL_DONE - operation is complete
+* OSM_SIGNAL_DONE_PENDING - local operations are complete, but
+* transactions are still pending on the wire.
+*
+* NOTES
+* This function processes the subnet, configuring switch
+* unicast forwarding tables.
+*
+* SEE ALSO
+* Unicast Manager, Node Info Response Controller
+*********/
+END_C_DECLS
+
+#endif /* _OSM_UCAST_MGR_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_umadt.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_UMADT_h_
+#define _OSM_UMADT_h_
+
+#include "iba/ib_types.h"
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_version.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef _OSM_VERSION_H_
+#define _OSM_VERSION_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: Base/OSM_VERSION
+* NAME
+* OSM_VERSION
+*
+* DESCRIPTION
+* The version string for OpenSM
+*
+* SYNOPSIS
+*/
+#define OSM_VERSION "OpenSM Rev:openib-3.0.0"
+/********/
+
+END_C_DECLS
+
+#endif /* _OSM_VERSION_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl15intf.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vl15_t.
+ * This object represents an IBA subnet.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#ifndef _OSM_VL15INTF_H_
+#define _OSM_VL15INTF_H_
+
+#include <iba/ib_types.h>
+#include <complib/cl_spinlock.h>
+#include <complib/cl_event.h>
+#include <complib/cl_thread.h>
+#include <complib/cl_qlist.h>
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_stats.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <opensm/osm_subnet.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/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;
+ 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;
+ cl_disp_reg_handle_t h_disp;
+ cl_plock_t *p_lock;
+
+} 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.
+*
+* 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 Subnet object for this subnet.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* 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* const 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_init, osm_vl15_destroy, and osm_vl15_is_inited.
+*
+* 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, osm_vl15_is_inited
+*********/
+
+/****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* const 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* const p_vl15,
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN const int32_t max_wire_smps,
+ IN osm_subn_t* const p_subn,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock );
+/*
+* 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 stastics block.
+*
+* max_wire_smps
+* [in] Maximum number of MADs allowed on the wire at one time.
+*
+* p_subn
+* [in] Pointer to the subnet object.
+*
+* p_disp
+* [in] Pointer to the dispatcher object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* 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,
+* osm_vl15_is_inited
+*********/
+
+/****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* const p_vl15,
+ IN osm_madw_t* const 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* const 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* const p_vl,
+ IN osm_mad_pool_t* const 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl_arb_rcv.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vla_rcv_t.
+ * This object represents the VL Arbitration Receiver object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLA_RCV_H_
+#define _OSM_VLA_RCV_H_
+
+#include <complib/cl_passivelock.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_log.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/VL Arbitration Receiver
+* NAME
+* VL Arbitration Receiver
+*
+* DESCRIPTION
+* The VL Arbitration Receiver object encapsulates the information
+* needed to set or get the vl arbitration attribute from a port.
+*
+* The VL Arbitration Receiver object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VL Arbitration Receiver/osm_vla_rcv_t
+* NAME
+* osm_vla_rcv_t
+*
+* DESCRIPTION
+* VL Arbitration Receiver structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv
+{
+ osm_subn_t *p_subn;
+ osm_req_t *p_req;
+ osm_log_t *p_log;
+ cl_plock_t *p_lock;
+
+} osm_vla_rcv_t;
+/*
+* FIELDS
+* p_subn
+* Pointer to the Subnet object for this subnet.
+*
+* p_req
+* Pointer to the generic attribute request object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_lock
+* Pointer to the serializing lock.
+*
+* SEE ALSO
+* VL Arbitration Receiver object
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_construct
+* NAME
+* osm_vla_rcv_construct
+*
+* DESCRIPTION
+* This function constructs a VL Arbitration Receiver object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_construct(
+ IN osm_vla_rcv_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a VL Arbitration Receiver object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vla_rcv_destroy
+*
+* Calling osm_vla_rcv_construct is a prerequisite to calling any other
+* method except osm_vla_rcv_init.
+*
+* SEE ALSO
+* VL Arbitration Receiver object, osm_vla_rcv_init,
+* osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_destroy
+* NAME
+* osm_vla_rcv_destroy
+*
+* DESCRIPTION
+* The osm_vla_rcv_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_destroy(
+ IN osm_vla_rcv_t* const 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
+* VL Arbitration Receiver object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vla_rcv_construct or osm_vla_rcv_init.
+*
+* SEE ALSO
+* VL Arbitration Receiver object, osm_vla_rcv_construct,
+* osm_vla_rcv_init
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_init
+* NAME
+* osm_vla_rcv_init
+*
+* DESCRIPTION
+* The osm_vla_rcv_init function initializes a
+* VL Arbitration Receiver object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_init(
+ IN osm_vla_rcv_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_t object to initialize.
+*
+* p_req
+* [in] Pointer to an osm_req_t object.
+*
+* p_subn
+* [in] Pointer to the Subnet object for this subnet.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_lock
+* [in] Pointer to the OpenSM serializing lock.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VL Arbitration Receiver object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VL Arbitration Receiver methods.
+*
+* SEE ALSO
+* VL Arbitration Receiver object, osm_vla_rcv_construct,
+* osm_vla_rcv_destroy
+*********/
+
+/****f* OpenSM: VL Arbitration Receiver/osm_vla_rcv_process
+* NAME
+* osm_vla_rcv_process
+*
+* DESCRIPTION
+* Process the vl arbitration attribute.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_process(
+ IN const osm_vla_rcv_t* const p_ctrl,
+ IN osm_madw_t* const p_madw );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_t object.
+*
+* p_madw
+* [in] Pointer to the MAD Wrapper containing the MAD
+* that contains the node's SLtoVL attribute.
+*
+* RETURN VALUES
+* CL_SUCCESS if the SLtoVL processing was successful.
+*
+* NOTES
+* This function processes a SLtoVL attribute.
+*
+* SEE ALSO
+* VL Arbitration Receiver, VL Arbitration Response Controller
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl_arb_rcv_ctrl.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osm_vla_rcv_ctrl_t.
+ * This object represents a controller that set or get resp the
+ * IBA VL Arbitration Table attribute from a port.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#ifndef _OSM_VLA_RCV_CTRL_H_
+#define _OSM_VLA_RCV_CTRL_H_
+
+#include <complib/cl_dispatcher.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_vl_arb_rcv.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/VL Arbitration Table Receive Controller
+* NAME
+* VL Arbitration Receive Controller
+*
+* DESCRIPTION
+* The VL Arbitration Receive Controller object encapsulates
+* the information needed to get or set VL Arbitration of a port.
+*
+* The VL Arbitration Receive Controller object is thread safe.
+*
+* This object should be treated as opaque and should be
+* manipulated only through the provided functions.
+*
+* AUTHOR
+* Eitan Zahavi, Mellanox
+*
+*********/
+
+/****s* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_t
+* NAME
+* osm_vla_rcv_ctrl_t
+*
+* DESCRIPTION
+* VL Arbitration Receive Controller structure.
+*
+* This object should be treated as opaque and should
+* be manipulated only through the provided functions.
+*
+* SYNOPSIS
+*/
+typedef struct _osm_vla_rcv_ctrl
+{
+ osm_vla_rcv_t *p_rcv;
+ osm_log_t *p_log;
+ cl_dispatcher_t *p_disp;
+ cl_disp_reg_handle_t h_disp;
+
+} osm_vla_rcv_ctrl_t;
+/*
+* FIELDS
+* p_rcv
+* Pointer to the VL Arbitration Receiver object.
+*
+* p_log
+* Pointer to the log object.
+*
+* p_disp
+* Pointer to the Dispatcher.
+*
+* h_disp
+* Handle returned from dispatcher registration.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object
+* VL Arbitration Receiver object
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_construct
+* NAME
+* osm_vla_rcv_ctrl_construct
+*
+* DESCRIPTION
+* This function constructs a VL Arbitration Receive Controller object.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_construct(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to a VL Arbitration Receive Controller
+* object to construct.
+*
+* RETURN VALUE
+* This function does not return a value.
+*
+* NOTES
+* Allows calling osm_vla_rcv_ctrl_init, osm_vla_rcv_ctrl_destroy,
+* and osm_vla_rcv_ctrl_is_inited.
+*
+* Calling osm_vla_rcv_ctrl_construct is a prerequisite to calling any other
+* method except osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_init,
+* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_destroy
+* NAME
+* osm_vla_rcv_ctrl_destroy
+*
+* DESCRIPTION
+* The osm_vla_rcv_ctrl_destroy function destroys the object, releasing
+* all resources.
+*
+* SYNOPSIS
+*/
+void osm_vla_rcv_ctrl_destroy(
+ IN osm_vla_rcv_ctrl_t* const 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
+* VL Arbitration Receive Controller object.
+* Further operations should not be attempted on the destroyed object.
+* This function should only be called after a call to
+* osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_init
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_init
+* NAME
+* osm_vla_rcv_ctrl_init
+*
+* DESCRIPTION
+* The osm_vla_rcv_ctrl_init function initializes a
+* VL Arbitration Receive Controller object for use.
+*
+* SYNOPSIS
+*/
+ib_api_status_t osm_vla_rcv_ctrl_init(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl,
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_ctrl_t object to initialize.
+*
+* p_rcv
+* [in] Pointer to an osm_vla_rcv_t object.
+*
+* p_log
+* [in] Pointer to the log object.
+*
+* p_disp
+* [in] Pointer to the OpenSM central Dispatcher.
+*
+* RETURN VALUES
+* CL_SUCCESS if the VL Arbitration Receive Controller object was initialized
+* successfully.
+*
+* NOTES
+* Allows calling other VL Arbitration Receive Controller methods.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_destroy, osm_vla_rcv_ctrl_is_inited
+*********/
+
+/****f* OpenSM: VL Arbitration Receive Controller/osm_vla_rcv_ctrl_is_inited
+* NAME
+* osm_vla_rcv_ctrl_is_inited
+*
+* DESCRIPTION
+* Indicates if the object has been initialized with osm_vla_rcv_ctrl_init.
+*
+* SYNOPSIS
+*/
+boolean_t osm_vla_rcv_ctrl_is_inited(
+ IN const osm_vla_rcv_ctrl_t* const p_ctrl );
+/*
+* PARAMETERS
+* p_ctrl
+* [in] Pointer to an osm_vla_rcv_ctrl_t object.
+*
+* RETURN VALUES
+* TRUE if the object was initialized successfully,
+* FALSE otherwise.
+*
+* NOTES
+* The osm_vla_rcv_ctrl_construct or osm_vla_rcv_ctrl_init must be
+* called before using this function.
+*
+* SEE ALSO
+* VL Arbitration Receive Controller object, osm_vla_rcv_ctrl_construct,
+* osm_vla_rcv_ctrl_init
+*********/
+
+END_C_DECLS
+
+#endif /* _OSM_VLA_RCV_CTRL_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: st.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/* @(#) st.h 5.1 89/12/14 */
+
+#ifndef ST_INCLUDED
+#define ST_INCLUDED
+
+#include <stdlib.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 (__WORDSIZE == 64) || defined (_WIN64)
+#define st_ptr_t unsigned long long
+#else
+#define st_ptr_t unsigned long
+#endif
+
+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 */
+
--- /dev/null
+/*
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 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.
+ *
+ * $Id: osm_base.h 1689 2006-09-12 20:55:47Z eitan $
+ */
+
+
+
+/*
+ * Abstract:
+ * Work around for cmpatibility mode with Linux.
+ *
+ */
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor.h 1923 2009-01-30 22:20:39Z stansmith $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Include file used by OpenSM to pull in the correct vendor file.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.6 $\r
+ */\r
+\r
+/*\r
+ this is the generic include file which includes\r
+ the proper vendor specific file\r
+*/\r
+#include <vendor/osm_vendor_select.h>\r
+\r
+#if defined( OSM_VENDOR_INTF_TEST )\r
+#include <vendor/osm_vendor_test.h>\r
+#elif defined( OSM_VENDOR_INTF_UMADT )\r
+#include <vendor/osm_vendor_umadt.h>\r
+#elif defined( OSM_VENDOR_INTF_MTL )\r
+/* HACK - I do not know how to prevent complib from loading kernel H files */\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_TS )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_ANAFA )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_SIM )\r
+#undef __init\r
+#include <vendor/osm_vendor_mlx.h>\r
+#elif defined( OSM_VENDOR_INTF_OPENIB )\r
+#include <vendor/osm_vendor_ibumad.h>\r
+#elif defined( OSM_VENDOR_INTF_AL )\r
+#include <vendor/osm_vendor_al.h>\r
+#elif\r
+#error No MAD Interface selected!\r
+#error Choose an interface in osm_vendor_select.h\r
+#endif\r
+\r
+\r
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor_al.h 1375 2008-07-13 08:55:53Z leonidk $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Declaration of osm_mad_wrapper_t.\r
+ * This object represents the context wrapper for OpenSM MAD processing.\r
+ * This object is part of the OpenSM family of objects.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.4 $\r
+ */\r
+\r
+\r
+\r
+\r
+#ifndef _OSM_VENDOR_AL_H_\r
+#define _OSM_VENDOR_AL_H_\r
+\r
+#include <iba/ib_types.h>\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_thread.h>\r
+#include <opensm/osm_base.h>\r
+#include <opensm/osm_log.h>\r
+\r
+#ifdef __cplusplus\r
+# define BEGIN_C_DECLS extern "C" {\r
+# define END_C_DECLS }\r
+#else /* !__cplusplus */\r
+# define BEGIN_C_DECLS\r
+# define END_C_DECLS\r
+#endif /* __cplusplus */\r
+\r
+BEGIN_C_DECLS\r
+\r
+/****h* OpenSM/Vendor AL\r
+* NAME\r
+* Vendor AL\r
+*\r
+* DESCRIPTION\r
+*\r
+* The Vendor AL object is thread safe.\r
+*\r
+* This object should be treated as opaque and should be\r
+* manipulated only through the provided functions.\r
+*\r
+* Enable various hacks to compensate for bugs in external code...\r
+*\r
+*\r
+* AUTHOR\r
+* \r
+*\r
+*********/\r
+\r
+\r
+\r
+/****h* OpenSM/Vendor Access Layer (AL)\r
+* NAME\r
+* Vendor AL\r
+*\r
+* DESCRIPTION\r
+* This file is the vendor specific file for the AL Infiniband API.\r
+*\r
+* AUTHOR\r
+* Steve King, Intel\r
+*\r
+*********/\r
+\r
+#define OSM_AL_SQ_SGE 256\r
+#define OSM_AL_RQ_SGE 256\r
+#define OSM_DEFAULT_RETRY_COUNT 3\r
+\r
+/* AL supports RMPP */\r
+#define VENDOR_RMPP_SUPPORT 1\r
+\r
+/****s* OpenSM: Vendor AL/osm_ca_info_t\r
+* NAME\r
+* osm_ca_info_t\r
+*\r
+* DESCRIPTION\r
+* Structure containing information about local Channle Adapters.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _osm_ca_info\r
+{\r
+ ib_net64_t guid;\r
+ size_t attr_size;\r
+ ib_ca_attr_t *p_attr;\r
+\r
+} osm_ca_info_t;\r
+/*\r
+* FIELDS\r
+* guid\r
+* Node GUID of the local CA.\r
+*\r
+* attr_size\r
+* Size of the CA attributes for this CA.\r
+*\r
+* p_attr\r
+* Pointer to dynamicly allocated CA Attribute structure.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_num_ports\r
+* NAME\r
+* osm_ca_info_get_num_ports\r
+*\r
+* DESCRIPTION\r
+* Returns the number of ports owned by this CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t\r
+osm_ca_info_get_num_ports(\r
+ IN const osm_ca_info_t* const p_ca_info )\r
+{\r
+ return( p_ca_info->p_attr->num_ports );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ca_info\r
+* [in] Pointer to a CA Info object.\r
+*\r
+* RETURN VALUE\r
+* Returns the number of ports owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_port_guid\r
+* NAME\r
+* osm_ca_info_get_port_guid\r
+*\r
+* DESCRIPTION\r
+* Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t\r
+osm_ca_info_get_port_guid(\r
+ IN const osm_ca_info_t* const p_ca_info,\r
+ IN const uint8_t index )\r
+{\r
+ return( p_ca_info->p_attr->p_port_attr[index].port_guid );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ca_info\r
+* [in] Pointer to a CA Info object.\r
+*\r
+* index\r
+* [in] Port "index" for which to retrieve the port GUID.\r
+* The index is the offset into the ca's internal array\r
+* of port attributes.\r
+*\r
+* RETURN VALUE\r
+* Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_port_num\r
+* NAME\r
+* osm_ca_info_get_port_num\r
+*\r
+* DESCRIPTION\r
+* Returns the port number of the specified port owned by this CA.\r
+* Port numbers start with 1 for HCA's.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline uint8_t\r
+osm_ca_info_get_port_num(\r
+ IN const osm_ca_info_t* const p_ca_info,\r
+ IN const uint8_t index )\r
+{\r
+ return( p_ca_info->p_attr->p_port_attr[index].port_num );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ca_info\r
+* [in] Pointer to a CA Info object.\r
+*\r
+* index\r
+* [in] Port "index" for which to retrieve the port GUID.\r
+* The index is the offset into the ca's internal array\r
+* of port attributes.\r
+*\r
+* RETURN VALUE\r
+* Returns the port GUID of the specified port owned by this CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_ca_guid\r
+* NAME\r
+* osm_ca_info_get_ca_guid\r
+*\r
+* DESCRIPTION\r
+* Returns the GUID of the specified CA.\r
+*\r
+* SYNOPSIS\r
+*/\r
+static inline ib_net64_t\r
+osm_ca_info_get_ca_guid(\r
+ IN const osm_ca_info_t* const p_ca_info )\r
+{\r
+ return( p_ca_info->p_attr->ca_guid );\r
+}\r
+/*\r
+* PARAMETERS\r
+* p_ca_info\r
+* [in] Pointer to a CA Info object.\r
+*\r
+* RETURN VALUE\r
+* Returns the GUID of the specified CA.\r
+*\r
+* NOTES\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+/****s* OpenSM: Vendor AL/osm_bind_handle_t\r
+* NAME\r
+* osm_bind_handle_t\r
+*\r
+* DESCRIPTION\r
+* handle returned by the vendor transport bind call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef struct _osm_vendor\r
+{\r
+ ib_al_handle_t h_al;\r
+ osm_log_t *p_log;\r
+ uint32_t ca_count;\r
+ osm_ca_info_t *p_ca_info;\r
+ uint32_t timeout;\r
+ ib_ca_handle_t h_ca;\r
+ ib_pd_handle_t h_pd;\r
+\r
+} osm_vendor_t;\r
+/*\r
+* FIELDS\r
+* h_al\r
+* Handle returned by AL open call (ib_open_al). \r
+*\r
+* p_log\r
+* Pointer to the log object.\r
+*\r
+* ca_count\r
+* Number of CA's in the array pointed to by p_ca_info.\r
+*\r
+* p_ca_info\r
+* Pointer to dynamically allocated array of CA info objects.\r
+*\r
+* h_pool\r
+* MAD Pool handle returned by ib_create_mad_pool at init time.\r
+*\r
+* timeout\r
+* Transaction timeout time in milliseconds.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+#define OSM_BIND_INVALID_HANDLE 0\r
+\r
+\r
+/****s* OpenSM: Vendor AL/osm_bind_handle_t\r
+* NAME\r
+* osm_bind_handle_t\r
+*\r
+* DESCRIPTION\r
+* handle returned by the vendor transport bind call.\r
+*\r
+* SYNOPSIS\r
+*/\r
+typedef void* osm_bind_handle_t;\r
+/***********/\r
+\r
+/****s* OpenSM/osm_vend_wrap_t\r
+* NAME\r
+* AL Vendor MAD Wrapper\r
+*\r
+* DESCRIPTION\r
+* AL specific MAD wrapper. AL transport layer uses this for\r
+* housekeeping.\r
+*\r
+* SYNOPSIS\r
+*********/\r
+typedef struct _osm_vend_wrap_t\r
+{\r
+ uint32_t size;\r
+ osm_bind_handle_t h_bind;\r
+ ib_mad_element_t *p_elem;\r
+ ib_av_handle_t h_av;\r
+ void* p_resp_madw;\r
+\r
+}osm_vend_wrap_t;\r
+/*\r
+* FIELDS\r
+* size\r
+* Size of the allocated MAD\r
+*\r
+* h_bind\r
+* Bind handle used on this transaction\r
+*\r
+* p_elem\r
+* Pointer to the mad element structure associated with\r
+* this mad.\r
+*\r
+* h_av\r
+* Address vector handle used for this transaction.\r
+*\r
+* p_resp_madw\r
+* Pointer to the mad wrapper structure used to hold the pending\r
+* reponse to the mad, if any. If a response is expected, the\r
+* wrapper for the reponse is allocated during the send call.\r
+*\r
+* SEE ALSO\r
+*********/\r
+\r
+\r
+END_C_DECLS\r
+\r
+#endif /* _OSM_VENDOR_AL_H_ */\r
+\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vendor_api.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Specification of the OpenSM transport API. This API is OpenSM's view
+ * of the Infiniband transport.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_API_H_
+#define _OSM_VENDOR_API_H_
+
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.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 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_ports
+* NAME
+* osm_vendor_get_ports
+*
+* 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 immediatly after
+* being sent.
+*
+* SEE ALSO
+*********/
+
+/****f* OpenSM Vendor API/osm_vendor_put
+* NAME
+* osm_vendor_put
+*
+* DESCRIPTION
+* Return a mad vandor 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vendor_sa_api.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Specification of the OpenSM SA Client API. This API uses the basic osm
+ * vendor API to provide SA Client interface.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#ifndef _OSM_VENDOR_SA_API_H_
+#define _OSM_VENDOR_SA_API_H_
+
+#include <iba/ib_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
+
+/****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 *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 *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 *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 *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 *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 *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;
+} 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 M_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.
+*
+* 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vendor_select.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Include file that defines which vendor files to compile.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSM_VENDOR_SELECT_H_
+#define _OSM_VENDOR_SELECT_H_
+
+/////////////////////////////////////////////////////
+//
+// MAD INTERFACE SELECTION
+//
+/////////////////////////////////////////////////////
+
+/*
+ TEST and UMADT must be specified in the 'make' command line,
+ with VENDOR=test or VENDOR=umadt.
+*/
+#ifndef OSM_VENDOR_INTF_OPENIB
+#ifndef OSM_VENDOR_INTF_TEST
+#ifndef OSM_VENDOR_INTF_UMADT
+#ifndef OSM_VENDOR_INTF_MTL
+#ifndef OSM_VENDOR_INTF_TS
+#ifndef OSM_VENDOR_INTF_SIM
+#ifndef OSM_VENDOR_INTF_AL
+#define OSM_VENDOR_INTF_AL
+#endif /* AL */
+#endif /* TS */
+#endif /* SIM */
+#endif /* MTL */
+#endif /* UMADT */
+#endif /* TEST */
+#endif /* OPENIB */
+
+#endif /* _OSM_VENDOR_SELECT_H_ */
+
--- /dev/null
+#ifndef _OSM_COMMON_H_\r
+#define _OSM_COMMON_H_\r
+\r
+#include <winsock2.h>\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <stdarg.h>\r
+#include <ctype.h>\r
+\r
+#pragma warning(disable : 4996)\r
+#pragma warning(disable : 4100)\r
+\r
+struct timezone {\r
+ int tz_minuteswest; /* minutes west of Greenwich */\r
+ int tz_dsttime; /* type of dst correction */\r
+};\r
+\r
+\r
+\r
+#ifndef _GETOPT_H_ \r
+\r
+# define no_argument 0\r
+# define required_argument 1\r
+# define optional_argument 2\r
+\r
+/* Global variables for getopt_long */\r
+char *optarg;\r
+\r
+struct option\r
+{\r
+ const char *name;\r
+ int has_arg;\r
+ int *flag;\r
+ int val;\r
+};\r
+#endif\r
+\r
+\r
+/************************************************************************/\r
+static char* \r
+get_char_option(const char* optstring,\r
+ char*const* argv,int argc, \r
+ int iArg, int* opt_ind,char* opt_p); \r
+int \r
+getopt_long_only(int argc, char *const*argv,\r
+ const char *optstring,\r
+ const struct option *longopts, int *longindex);\r
+/**************************************************************************/\r
+static __inline\r
+void FileTimeToTimeval(LPFILETIME pft, struct timeval * ptv)\r
+{ /* Note that LONGLONG is a 64-bit value */\r
+LONGLONG ll;\r
+\r
+if(!pft || !ptv)\r
+goto Exit;\r
+\r
+ll = ((LONGLONG) pft->dwHighDateTime << 32);\r
+ll += (LONGLONG) pft->dwLowDateTime;\r
+#ifdef __GNUC__\r
+ll -= 116444736000000000ll;\r
+#else\r
+ll -= 116444736000000000;\r
+#endif\r
+\r
+ptv->tv_sec = (long) (ll / 10000000);\r
+ptv->tv_usec = (long) (ll - ((LONGLONG)(ptv->tv_sec) * 10000000)) / 10;\r
+\r
+Exit:;\r
+}/* FileTimeToTimeval */\r
+\r
+/********************************************************************************/\r
+static __inline\r
+int gettimeofday(struct timeval *ptv, struct timezone *tzp)\r
+{\r
+static int QueryCounter = 2;\r
+FILETIME CurrentTime;\r
+/* TODO : We need to add it , since in DDK - compiler does not like vars that are not in use */\r
+UNREFERENCED_PARAMETER(tzp); \r
+if(!ptv)\r
+goto Exit;\r
+\r
+if(QueryCounter)\r
+{\r
+static LARGE_INTEGER Frequency;\r
+static LARGE_INTEGER Offset; /* counter offset for right time*/\r
+static LARGE_INTEGER LastCounter;\r
+LARGE_INTEGER Time;\r
+LARGE_INTEGER Counter;\r
+/* HANDLE hThread = GetCurrentThread();\r
+int ThreadPrio = GetThreadPriority(hThread);\r
+\r
+SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); */\r
+GetSystemTimeAsFileTime(&CurrentTime);\r
+QueryPerformanceCounter(&Counter);\r
+/* SetThreadPriority(hThread, ThreadPrio); */\r
+\r
+if(QueryCounter == 2)\r
+{\r
+QueryCounter = 1;\r
+if(!QueryPerformanceFrequency(&Frequency))\r
+{\r
+QueryCounter = 0;\r
+Frequency.QuadPart = 10000000; /* prevent division by 0 */\r
+}\r
+\r
+/* get time as a large integer */\r
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */\r
+Offset.LowPart = CurrentTime.dwLowDateTime;\r
+Offset.HighPart = (LONG) CurrentTime.dwHighDateTime;\r
+Offset.QuadPart -= Counter.QuadPart * 10000000 / Frequency.QuadPart;\r
+}\r
+\r
+/* Convert counter to a 100 nanoseconds resolution timer value. */\r
+\r
+Counter.HighPart &= 0x7fl; /* Clear the highest bits to prevent overflows */\r
+Counter.QuadPart *= 10000000; /* Because we need time stamp in units of 100 ns */\r
+Counter.QuadPart /= Frequency.QuadPart; /* counter of 0.1 microseconds */\r
+\r
+if(LastCounter.QuadPart > Counter.QuadPart)\r
+{ /* Counter value wrapped */\r
+#ifdef __GNUC__\r
+Offset.QuadPart += (0x7f00000000ll * 10000000ll) / Frequency.QuadPart;\r
+#else\r
+Offset.QuadPart += (0x7f00000000 * 10000000) / Frequency.QuadPart;\r
+#endif\r
+}\r
+LastCounter = Counter;\r
+\r
+/* Add the in previous call calculated offset */\r
+Counter.QuadPart += Offset.QuadPart;\r
+\r
+/* get time as a large integer */\r
+Time.LowPart = CurrentTime.dwLowDateTime;\r
+Time.HighPart = (LONG) CurrentTime.dwHighDateTime;\r
+\r
+/* keep time difference within an interval of +- 0.1 seconds\r
+relative to the time function by adjusting the counters offset */\r
+\r
+if(((Time.QuadPart + 1000000) < Counter.QuadPart) ||\r
+((Time.QuadPart - 1000000) > Counter.QuadPart))\r
+{ /* Adjust the offset */\r
+Offset.QuadPart += Time.QuadPart - Counter.QuadPart;\r
+Counter.QuadPart = Time.QuadPart;\r
+}\r
+\r
+/* Now let's use the adjusted performance counter time for the time stamp */\r
+CurrentTime.dwLowDateTime = Counter.LowPart;\r
+CurrentTime.dwHighDateTime = Counter.HighPart;\r
+}\r
+else\r
+{\r
+GetSystemTimeAsFileTime(&CurrentTime);\r
+}\r
+\r
+FileTimeToTimeval(&CurrentTime,ptv);\r
+\r
+Exit:;\r
+return(0);\r
+}/* int gettimeofday(struct timeval *ptv, void *tzp) */\r
+/*****************************************************************************/\r
+\r
+\r
+#ifndef getpid\r
+#define getpid() GetCurrentProcessId()\r
+#endif\r
+\r
+#define sleep(sec) SleepEx((sec)*1000,TRUE)\r
+#define usleep(usec) SleepEx(usec/1000,TRUE)\r
+//#define MT_ALIGN8 __declspec(align(8))\r
+/* Verify the correct ETIMEDOUT value is defined in all compiled files */\r
+#ifndef ETIMEDOUT\r
+#define ETIMEDOUT (10060)\r
+#endif\r
+\r
+#ifndef strtoull \r
+#define strtoull _strtoui64\r
+#endif\r
+\r
+#define OSM_MAX_LOG_NAME_SIZE 2048\r
+#define unlink(str) _unlink(str)\r
+#define strnicmp _strnicmp\r
+\r
+/* The following defines replace syslog.h */\r
+#define openlog(a,b,c)\r
+\r
+#define closelog()\r
+\r
+static __inline void\r
+syslog(int priority, ...) {}\r
+\r
+#define LOG_INFO 0\r
+#define LOG_WARNING 1\r
+#define LOG_ERR 2\r
+/*****************************************/\r
+\r
+/****f* OpenSM: osm_common/GetOsmTempPath\r
+* NAME\r
+* GetOsmTempPath\r
+*\r
+* DESCRIPTION\r
+* The function retrieves the temp path defined in Windows using its API\r
+*\r
+* SYNOPSIS\r
+*/\r
+char*\r
+GetOsmTempPath(void);\r
+/*\r
+* PARAMETERS\r
+* NONE\r
+*\r
+* RETURN VALUE\r
+* This function returns string containing the default temp path in windows\r
+*\r
+* NOTES\r
+*/\r
+\r
+/****f* OpenSM: osm_common/GetOsmCachePath\r
+* NAME\r
+* GetOsmCachePath\r
+*\r
+* DESCRIPTION\r
+* The function retrieves the path the cache directory. This directory is \r
+* the etc dir under the installation directory of the mellanox stack. \r
+* The installation directory should be pointed out by the WinIB_HOME variable.\r
+* If WinIB_HOME variable is missing, or there is not /etc/ dir under it - then\r
+* the function will return the getOsmTempPath() value.\r
+*\r
+* SYNOPSIS\r
+*/\r
+char*\r
+GetOsmCachePath(void);\r
+/*\r
+* PARAMETERS\r
+* NONE\r
+*\r
+* RETURN VALUE\r
+* This function returns string containing the default cache path for osm use.\r
+*\r
+* NOTES\r
+*/\r
+\r
+/* Implementation of strtok_r for windows: since strtok in windows is safe,\r
+ just ignore the last variable, and call strtok. */\r
+static inline \r
+char *strtok_r(char *s1, const char *s2, char **lasts)\r
+{\r
+ return strtok(s1, s2);\r
+}\r
+#endif /* _OSM_COMMON_H_ */\r
--- /dev/null
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
--- /dev/null
+!if $(FREEBUILD)\r
+TARGETNAME=opensm_ibal\r
+!else\r
+TARGETNAME=opensm_ibald\r
+!endif\r
+TARGETTYPE=LIBRARY\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+USE_NTDLL=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+ osm_log.c \\r
+ osm_mad_pool.c \\r
+ osm_helper.c\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+ $(LIBPATH)\*\ibal.lib \\r
+ $(LIBPATH)\*\complib.lib \\r
+ $(TARGETPATH)\*\osmv_ibal_3_0_0.lib\r
+\r
+!else\r
+ $(LIBPATH)\*\ibald.lib \\r
+ $(LIBPATH)\*\complibd.lib \\r
+ $(TARGETPATH)\*\osmv_ibal_3_0_0d.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+ $(OSM_HOME)\include; \\r
+ $(OSM_HOME); \\r
+ $(WINIBHOME)\inc; \\r
+ $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_helper.c 1930 2009-02-04 15:26:22Z tzachid $\r
+ */\r
+\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Implementation of opensm helper functions.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.19 $\r
+ */\r
+\r
+#if HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <complib/cl_debug.h>\r
+#include <iba/ib_types.h>\r
+#include <opensm/osm_helper.h>\r
+#include <opensm/osm_log.h>\r
+\r
+#define LINE_LENGTH 256\r
+\r
+/* we use two tables - one for queries and one for responses */\r
+const char* const __ib_sa_method_str[] =\r
+{\r
+ "RESERVED", /* 0 */\r
+ "SubnAdmGet", /* 1 */\r
+ "SubnAdmSet", /* 2 */\r
+ "RESERVED", /* 3 */\r
+ "RESERVED", /* 4 */\r
+ "RESERVED", /* 5 */\r
+ "SubnAdmReport", /* 6 */\r
+ "RESERVED", /* 7 */\r
+ "RESERVED", /* 8 */\r
+ "RESERVED", /* 9 */\r
+ "RESERVED", /* A */\r
+ "RESERVED", /* B */\r
+ "RESERVED", /* C */\r
+ "RESERVED", /* D */\r
+ "RESERVED", /* E */\r
+ "RESERVED", /* F */\r
+ "RESERVED", /* 10 */\r
+ "RESERVED", /* 11 */\r
+ "SubnAdmGetTable", /* 12 */\r
+ "SubnAdmGetTraceTable", /* 13 */\r
+ "SubnAdmGetMulti", /* 14 */\r
+ "SubnAdmDelete", /* 15 */\r
+ "UNKNOWN" /* 16 */\r
+};\r
+\r
+const char* const __ib_sa_resp_method_str[] =\r
+{\r
+ "RESERVED", /* 80 */\r
+ "SubnAdmGetResp", /* 81 */\r
+ "RESERVED (SetResp?)", /* 82 */\r
+ "RESERVED", /* 83 */\r
+ "RESERVED", /* 84 */\r
+ "RESERVED", /* 85 */\r
+ "SubnAdmReportResp", /* 86 */\r
+ "RESERVED", /* 87 */\r
+ "RESERVED", /* 88 */\r
+ "RESERVED", /* 89 */\r
+ "RESERVED", /* 8A */\r
+ "RESERVED", /* 8B */\r
+ "RESERVED", /* 8C */\r
+ "RESERVED", /* 8D */\r
+ "RESERVED", /* 8E */\r
+ "RESERVED", /* 8F */\r
+ "RESERVED", /* 90 */\r
+ "RESERVED", /* 91 */\r
+ "SubnAdmGetTableResp", /* 92 */\r
+ "RESERVED", /* 93 */\r
+ "SubnAdmGetMultiResp", /* 94 */\r
+ "SubnAdmDeleteResp", /* 95 */\r
+ "UNKNOWN"\r
+};\r
+\r
+#define OSM_SA_METHOD_STR_UNKNOWN_VAL 0x16\r
+\r
+const char* const __ib_sm_method_str[] =\r
+{\r
+ "RESERVED0", /* 0 */\r
+ "SubnGet", /* 1 */\r
+ "SubnSet", /* 2 */\r
+ "RESERVED3", /* 3 */\r
+ "RESERVED4", /* 4 */\r
+ "SubnTrap", /* 5 */\r
+ "RESERVED6", /* 6 */\r
+ "SubnTrapRepress", /* 7 */\r
+ "RESERVED8", /* 8 */\r
+ "RESERVED9", /* 9 */\r
+ "RESERVEDA", /* A */\r
+ "RESERVEDB", /* B */\r
+ "RESERVEDC", /* C */\r
+ "RESERVEDD", /* D */\r
+ "RESERVEDE", /* E */\r
+ "RESERVEDF", /* F */\r
+ "RESERVED10", /* 10 */\r
+ "SubnGetResp", /* 11 */\r
+ "RESERVED12", /* 12 */\r
+ "RESERVED13", /* 13 */\r
+ "RESERVED14", /* 14 */\r
+ "RESERVED15", /* 15 */\r
+ "RESERVED16", /* 16 */\r
+ "RESERVED17", /* 17 */\r
+ "RESERVED18", /* 18 */\r
+ "RESERVED19", /* 19 */\r
+ "RESERVED1A", /* 1A */\r
+ "RESERVED1B", /* 1B */\r
+ "RESERVED1C", /* 1C */\r
+ "RESERVED1D", /* 1D */\r
+ "RESERVED1E", /* 1E */\r
+ "RESERVED1F", /* 1F */\r
+ "UNKNOWN" /* 20 */\r
+};\r
+\r
+#define OSM_SM_METHOD_STR_UNKNOWN_VAL 0x21\r
+\r
+const char* const __ib_sm_attr_str[] =\r
+{\r
+ "RESERVED", /* 0 */\r
+ "ClassPortInfo", /* 1 */\r
+ "Notice", /* 2 */\r
+ "InformInfo", /* 3 */\r
+ "RESERVED", /* 4 */\r
+ "RESERVED", /* 5 */\r
+ "RESERVED", /* 6 */\r
+ "RESERVED", /* 7 */\r
+ "RESERVED", /* 8 */\r
+ "RESERVED", /* 9 */\r
+ "RESERVED", /* A */\r
+ "RESERVED", /* B */\r
+ "RESERVED", /* C */\r
+ "RESERVED", /* D */\r
+ "RESERVED", /* E */\r
+ "RESERVED", /* F */\r
+ "NodeDescription", /* 10 */\r
+ "NodeInfo", /* 11 */\r
+ "SwitchInfo", /* 12 */\r
+ "UNKNOWN", /* 13 */\r
+ "GUIDInfo", /* 14 */\r
+ "PortInfo", /* 15 */\r
+ "P_KeyTable", /* 16 */\r
+ "SLtoVLMappingTable", /* 17 */\r
+ "VLArbitrationTable", /* 18 */\r
+ "LinearForwardingTable", /* 19 */\r
+ "RandomForwardingTable", /* 1A */\r
+ "MulticastForwardingTable", /* 1B */\r
+ "UNKNOWN", /* 1C */\r
+ "UNKNOWN", /* 1D */\r
+ "UNKNOWN", /* 1E */\r
+ "UNKNOWN", /* 1F */\r
+ "SMInfo", /* 20 */\r
+ "UNKNOWN" /* 21 - always highest value */\r
+};\r
+\r
+#define OSM_SM_ATTR_STR_UNKNOWN_VAL 0x21\r
+\r
+const char* const __ib_sa_attr_str[] =\r
+{\r
+ "RESERVED", /* 0 */\r
+ "ClassPortInfo", /* 1 */\r
+ "Notice", /* 2 */\r
+ "InformInfo", /* 3 */\r
+ "RESERVED", /* 4 */\r
+ "RESERVED", /* 5 */\r
+ "RESERVED", /* 6 */\r
+ "RESERVED", /* 7 */\r
+ "RESERVED", /* 8 */\r
+ "RESERVED", /* 9 */\r
+ "RESERVED", /* A */\r
+ "RESERVED", /* B */\r
+ "RESERVED", /* C */\r
+ "RESERVED", /* D */\r
+ "RESERVED", /* E */\r
+ "RESERVED", /* F */\r
+ "RESERVED", /* 10 */\r
+ "NodeRecord", /* 11 */\r
+ "PortInfoRecord", /* 12 */\r
+ "SLtoVLMappingTableRecord", /* 13 */\r
+ "SwitchInfoRecord", /* 14 */\r
+ "LinearForwardingTableRecord", /* 15 */\r
+ "RandomForwardingTableRecord", /* 16 */\r
+ "MulticastForwardingTableRecord", /* 17 */\r
+ "SMInfoRecord", /* 18 */\r
+ "RESERVED", /* 19 */\r
+ "RandomForwardingTable", /* 1A */\r
+ "MulticastForwardingTable", /* 1B */\r
+ "UNKNOWN", /* 1C */\r
+ "UNKNOWN", /* 1D */\r
+ "UNKNOWN", /* 1E */\r
+ "UNKNOWN", /* 1F */\r
+ "LinkRecord", /* 20 */\r
+ "UNKNOWN", /* 21 */\r
+ "UNKNOWN", /* 22 */\r
+ "UNKNOWN", /* 23 */\r
+ "UNKNOWN", /* 24 */\r
+ "UNKNOWN", /* 25 */\r
+ "UNKNOWN", /* 26 */\r
+ "UNKNOWN", /* 27 */\r
+ "UNKNOWN", /* 28 */\r
+ "UNKNOWN", /* 29 */\r
+ "UNKNOWN", /* 2A */\r
+ "UNKNOWN", /* 2B */\r
+ "UNKNOWN", /* 2C */\r
+ "UNKNOWN", /* 2D */\r
+ "UNKNOWN", /* 2E */\r
+ "UNKNOWN", /* 2F */\r
+ "GuidInfoRecord", /* 30 */\r
+ "ServiceRecord", /* 31 */\r
+ "UNKNOWN", /* 32 */\r
+ "P_KeyTableRecord", /* 33 */\r
+ "UNKNOWN", /* 34 */\r
+ "PathRecord", /* 35 */\r
+ "VLArbitrationTableRecord", /* 36 */\r
+ "UNKNOWN", /* 37 */\r
+ "MCMemberRecord", /* 38 */\r
+ "TraceRecord", /* 39 */\r
+ "MultiPathRecord", /* 3A */\r
+ "ServiceAssociationRecord", /* 3B */\r
+ "UNKNOWN", /* 3C */\r
+ "UNKNOWN", /* 3D */\r
+ "UNKNOWN", /* 3E */\r
+ "UNKNOWN", /* 3F */\r
+ "UNKNOWN", /* 40 */\r
+ "UNKNOWN", /* 41 */\r
+ "UNKNOWN", /* 42 */\r
+ "UNKNOWN", /* 43 */\r
+ "UNKNOWN", /* 44 */\r
+ "UNKNOWN", /* 45 */\r
+ "UNKNOWN", /* 46 */\r
+ "UNKNOWN", /* 47 */\r
+ "UNKNOWN", /* 48 */\r
+ "UNKNOWN", /* 49 */\r
+ "UNKNOWN", /* 4A */\r
+ "UNKNOWN", /* 4B */\r
+ "UNKNOWN", /* 4C */\r
+ "UNKNOWN", /* 4D */\r
+ "UNKNOWN", /* 4E */\r
+ "UNKNOWN", /* 4F */\r
+ "UNKNOWN", /* 50 */\r
+ "UNKNOWN", /* 51 */\r
+ "UNKNOWN", /* 52 */\r
+ "UNKNOWN", /* 53 */\r
+ "UNKNOWN", /* 54 */\r
+ "UNKNOWN", /* 55 */\r
+ "UNKNOWN", /* 56 */\r
+ "UNKNOWN", /* 57 */\r
+ "UNKNOWN", /* 58 */\r
+ "UNKNOWN", /* 59 */\r
+ "UNKNOWN", /* 5A */\r
+ "UNKNOWN", /* 5B */\r
+ "UNKNOWN", /* 5C */\r
+ "UNKNOWN", /* 5D */\r
+ "UNKNOWN", /* 5E */\r
+ "UNKNOWN", /* 5F */\r
+ "UNKNOWN", /* 60 */\r
+ "UNKNOWN", /* 61 */\r
+ "UNKNOWN", /* 62 */\r
+ "UNKNOWN", /* 63 */\r
+ "UNKNOWN", /* 64 */\r
+ "UNKNOWN", /* 65 */\r
+ "UNKNOWN", /* 66 */\r
+ "UNKNOWN", /* 67 */\r
+ "UNKNOWN", /* 68 */\r
+ "UNKNOWN", /* 69 */\r
+ "UNKNOWN", /* 6A */\r
+ "UNKNOWN", /* 6B */\r
+ "UNKNOWN", /* 6C */\r
+ "UNKNOWN", /* 6D */\r
+ "UNKNOWN", /* 6E */\r
+ "UNKNOWN", /* 6F */\r
+ "UNKNOWN", /* 70 */\r
+ "UNKNOWN", /* 71 */\r
+ "UNKNOWN", /* 72 */\r
+ "UNKNOWN", /* 73 */\r
+ "UNKNOWN", /* 74 */\r
+ "UNKNOWN", /* 75 */\r
+ "UNKNOWN", /* 76 */\r
+ "UNKNOWN", /* 77 */\r
+ "UNKNOWN", /* 78 */\r
+ "UNKNOWN", /* 79 */\r
+ "UNKNOWN", /* 7A */\r
+ "UNKNOWN", /* 7B */\r
+ "UNKNOWN", /* 7C */\r
+ "UNKNOWN", /* 7D */\r
+ "UNKNOWN", /* 7E */\r
+ "UNKNOWN", /* 7F */\r
+ "UNKNOWN", /* 80 */\r
+ "UNKNOWN", /* 81 */\r
+ "UNKNOWN", /* 82 */\r
+ "UNKNOWN", /* 83 */\r
+ "UNKNOWN", /* 84 */\r
+ "UNKNOWN", /* 85 */\r
+ "UNKNOWN", /* 86 */\r
+ "UNKNOWN", /* 87 */\r
+ "UNKNOWN", /* 88 */\r
+ "UNKNOWN", /* 89 */\r
+ "UNKNOWN", /* 8A */\r
+ "UNKNOWN", /* 8B */\r
+ "UNKNOWN", /* 8C */\r
+ "UNKNOWN", /* 8D */\r
+ "UNKNOWN", /* 8E */\r
+ "UNKNOWN", /* 8F */\r
+ "UNKNOWN", /* 90 */\r
+ "UNKNOWN", /* 91 */\r
+ "UNKNOWN", /* 92 */\r
+ "UNKNOWN", /* 93 */\r
+ "UNKNOWN", /* 94 */\r
+ "UNKNOWN", /* 95 */\r
+ "UNKNOWN", /* 96 */\r
+ "UNKNOWN", /* 97 */\r
+ "UNKNOWN", /* 98 */\r
+ "UNKNOWN", /* 99 */\r
+ "UNKNOWN", /* 9A */\r
+ "UNKNOWN", /* 9B */\r
+ "UNKNOWN", /* 9C */\r
+ "UNKNOWN", /* 9D */\r
+ "UNKNOWN", /* 9E */\r
+ "UNKNOWN", /* 9F */\r
+ "UNKNOWN", /* A0 */\r
+ "UNKNOWN", /* A1 */\r
+ "UNKNOWN", /* A2 */\r
+ "UNKNOWN", /* A3 */\r
+ "UNKNOWN", /* A4 */\r
+ "UNKNOWN", /* A5 */\r
+ "UNKNOWN", /* A6 */\r
+ "UNKNOWN", /* A7 */\r
+ "UNKNOWN", /* A8 */\r
+ "UNKNOWN", /* A9 */\r
+ "UNKNOWN", /* AA */\r
+ "UNKNOWN", /* AB */\r
+ "UNKNOWN", /* AC */\r
+ "UNKNOWN", /* AD */\r
+ "UNKNOWN", /* AE */\r
+ "UNKNOWN", /* AF */\r
+ "UNKNOWN", /* B0 */\r
+ "UNKNOWN", /* B1 */\r
+ "UNKNOWN", /* B2 */\r
+ "UNKNOWN", /* B3 */\r
+ "UNKNOWN", /* B4 */\r
+ "UNKNOWN", /* B5 */\r
+ "UNKNOWN", /* B6 */\r
+ "UNKNOWN", /* B7 */\r
+ "UNKNOWN", /* B8 */\r
+ "UNKNOWN", /* B9 */\r
+ "UNKNOWN", /* BA */\r
+ "UNKNOWN", /* BB */\r
+ "UNKNOWN", /* BC */\r
+ "UNKNOWN", /* BD */\r
+ "UNKNOWN", /* BE */\r
+ "UNKNOWN", /* BF */\r
+ "UNKNOWN", /* C0 */\r
+ "UNKNOWN", /* C1 */\r
+ "UNKNOWN", /* C2 */\r
+ "UNKNOWN", /* C3 */\r
+ "UNKNOWN", /* C4 */\r
+ "UNKNOWN", /* C5 */\r
+ "UNKNOWN", /* C6 */\r
+ "UNKNOWN", /* C7 */\r
+ "UNKNOWN", /* C8 */\r
+ "UNKNOWN", /* C9 */\r
+ "UNKNOWN", /* CA */\r
+ "UNKNOWN", /* CB */\r
+ "UNKNOWN", /* CC */\r
+ "UNKNOWN", /* CD */\r
+ "UNKNOWN", /* CE */\r
+ "UNKNOWN", /* CF */\r
+ "UNKNOWN", /* D0 */\r
+ "UNKNOWN", /* D1 */\r
+ "UNKNOWN", /* D2 */\r
+ "UNKNOWN", /* D3 */\r
+ "UNKNOWN", /* D4 */\r
+ "UNKNOWN", /* D5 */\r
+ "UNKNOWN", /* D6 */\r
+ "UNKNOWN", /* D7 */\r
+ "UNKNOWN", /* D8 */\r
+ "UNKNOWN", /* D9 */\r
+ "UNKNOWN", /* DA */\r
+ "UNKNOWN", /* DB */\r
+ "UNKNOWN", /* DC */\r
+ "UNKNOWN", /* DD */\r
+ "UNKNOWN", /* DE */\r
+ "UNKNOWN", /* DF */\r
+ "UNKNOWN", /* E0 */\r
+ "UNKNOWN", /* E1 */\r
+ "UNKNOWN", /* E2 */\r
+ "UNKNOWN", /* E3 */\r
+ "UNKNOWN", /* E4 */\r
+ "UNKNOWN", /* E5 */\r
+ "UNKNOWN", /* E6 */\r
+ "UNKNOWN", /* E7 */\r
+ "UNKNOWN", /* E8 */\r
+ "UNKNOWN", /* E9 */\r
+ "UNKNOWN", /* EA */\r
+ "UNKNOWN", /* EB */\r
+ "UNKNOWN", /* EC */\r
+ "UNKNOWN", /* ED */\r
+ "UNKNOWN", /* EE */\r
+ "UNKNOWN", /* EF */\r
+ "UNKNOWN", /* F0 */\r
+ "UNKNOWN", /* F1 */\r
+ "UNKNOWN", /* F2 */\r
+ "InformInfoRecord", /* F3 */\r
+ "UNKNOWN" /* F4 - always highest value */\r
+};\r
+\r
+#define OSM_SA_ATTR_STR_UNKNOWN_VAL 0xF4\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sa_method_str(\r
+ IN uint8_t method )\r
+{\r
+ if (method & 0x80)\r
+ {\r
+ method = method & 0x7f;\r
+ if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL )\r
+ method = OSM_SA_METHOD_STR_UNKNOWN_VAL;\r
+ /* it is a response - use the response table */\r
+ return( __ib_sa_resp_method_str[method] );\r
+ }\r
+ else\r
+ {\r
+ if( method >= OSM_SA_METHOD_STR_UNKNOWN_VAL )\r
+ method = OSM_SA_METHOD_STR_UNKNOWN_VAL;\r
+ return( __ib_sa_method_str[method] );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sm_method_str(\r
+ IN uint8_t method )\r
+{\r
+ if (method & 0x80) method = (method & 0x0F) | 0x10;\r
+ if( method >= OSM_SM_METHOD_STR_UNKNOWN_VAL )\r
+ method = OSM_SM_METHOD_STR_UNKNOWN_VAL;\r
+ return( __ib_sm_method_str[method] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sm_attr_str(\r
+ IN ib_net16_t attr )\r
+{\r
+ uint16_t host_attr;\r
+ host_attr = cl_ntoh16( attr );\r
+\r
+ if( host_attr >= OSM_SM_ATTR_STR_UNKNOWN_VAL )\r
+ host_attr = OSM_SM_ATTR_STR_UNKNOWN_VAL;\r
+\r
+ return( __ib_sm_attr_str[host_attr] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+ib_get_sa_attr_str(\r
+ IN ib_net16_t attr )\r
+{\r
+ uint16_t host_attr;\r
+ host_attr = cl_ntoh16( attr );\r
+\r
+ if( host_attr >= OSM_SA_ATTR_STR_UNKNOWN_VAL )\r
+ host_attr = OSM_SA_ATTR_STR_UNKNOWN_VAL;\r
+\r
+ return( __ib_sa_attr_str[host_attr] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_dbg_do_line(\r
+ IN char** pp_local,\r
+ IN const uint32_t buf_size,\r
+ IN const char* const p_prefix_str,\r
+ IN const char* const p_new_str,\r
+ IN uint32_t* const p_total_len )\r
+{\r
+ char line[LINE_LENGTH];\r
+ uint32_t len;\r
+\r
+ sprintf( line, "%s%s", p_prefix_str, p_new_str );\r
+ len = (uint32_t) strlen( line );\r
+ *p_total_len += len;\r
+ if( *p_total_len + sizeof('\0') > buf_size )\r
+ return( IB_INSUFFICIENT_MEMORY );\r
+\r
+ strcpy( *pp_local, line );\r
+ *pp_local += len;\r
+ return( IB_SUCCESS );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dbg_get_capabilities_str(\r
+ IN char* p_buf,\r
+ IN const uint32_t buf_size,\r
+ IN const char* const p_prefix_str,\r
+ IN const ib_port_info_t* const p_pi )\r
+{\r
+ uint32_t total_len = 0;\r
+ char *p_local = p_buf;\r
+\r
+ strcpy( p_local, "Capability Mask:\n" );\r
+ p_local += strlen( p_local );\r
+\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV0 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV0\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_IS_SM )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_IS_SM\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NOTICE )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_NOTICE\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_TRAP )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_TRAP\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_IPD )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_IPD\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_AUTO_MIG )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_AUTO_MIG\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_SL_MAP\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_MKEY )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_NV_MKEY\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_NV_PKEY )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_NV_PKEY\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_LED_INFO )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_LED_INFO\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_SM_DISAB )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_SM_DISAB\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SYS_IMG_GUID )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_SYS_IMG_GUID\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_PKEY_SW_EXT_PORT_TRAP )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_PKEY_SW_EXT_PORT_TRAP\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV13 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV13\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV14 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV14\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV15 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV15\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_COM_MGT )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_COM_MGT\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_SNMP )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_SNMP\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_REINIT )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_REINIT\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_DEV_MGT )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_DEV_MGT\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_VEND_CLS )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_VEND_CLS\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_DR_NTC )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_DR_NTC\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_CAP_NTC )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_CAP_NTC\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_BM )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_BM\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_LINK_RT_LATENCY )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_LINK_RT_LATENCY\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_HAS_CLIENT_REREG\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV26 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV26\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV27 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV27\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV28)\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV28\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV29 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV29\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV30 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV30\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+ if( p_pi->capability_mask & IB_PORT_CAP_RESV31 )\r
+ {\r
+ if( osm_dbg_do_line( &p_local, buf_size, p_prefix_str,\r
+ "IB_PORT_CAP_RESV31\n", &total_len ) != IB_SUCCESS )\r
+ return;\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_port_info(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_net64_t node_guid,\r
+ IN const ib_net64_t port_guid,\r
+ IN const uint8_t port_num,\r
+ IN const ib_port_info_t* const p_pi,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ char buf[BUF_SIZE];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "PortInfo dump:\n"\r
+ "\t\t\t\tport number.............0x%X\n"\r
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"\r
+ "\t\t\t\tbase_lid................0x%X\n"\r
+ "\t\t\t\tmaster_sm_base_lid......0x%X\n"\r
+ "\t\t\t\tcapability_mask.........0x%X\n"\r
+ "\t\t\t\tdiag_code...............0x%X\n"\r
+ "\t\t\t\tm_key_lease_period......0x%X\n"\r
+ "\t\t\t\tlocal_port_num..........0x%X\n"\r
+ "\t\t\t\tlink_width_enabled......0x%X\n"\r
+ "\t\t\t\tlink_width_supported....0x%X\n"\r
+ "\t\t\t\tlink_width_active.......0x%X\n"\r
+ "\t\t\t\tlink_speed_supported....0x%X\n"\r
+ "\t\t\t\tport_state..............%s\n"\r
+ "\t\t\t\tstate_info2.............0x%X\n"\r
+ "\t\t\t\tm_key_protect_bits......0x%X\n"\r
+ "\t\t\t\tlmc.....................0x%X\n"\r
+ "\t\t\t\tlink_speed..............0x%X\n"\r
+ "\t\t\t\tmtu_smsl................0x%X\n"\r
+ "\t\t\t\tvl_cap_init_type........0x%X\n"\r
+ "\t\t\t\tvl_high_limit...........0x%X\n"\r
+ "\t\t\t\tvl_arb_high_cap.........0x%X\n"\r
+ "\t\t\t\tvl_arb_low_cap..........0x%X\n"\r
+ "\t\t\t\tinit_rep_mtu_cap........0x%X\n"\r
+ "\t\t\t\tvl_stall_life...........0x%X\n"\r
+ "\t\t\t\tvl_enforce..............0x%X\n"\r
+ "\t\t\t\tm_key_violations........0x%X\n"\r
+ "\t\t\t\tp_key_violations........0x%X\n"\r
+ "\t\t\t\tq_key_violations........0x%X\n"\r
+ "\t\t\t\tguid_cap................0x%X\n"\r
+ "\t\t\t\tclient_reregister.......0x%X\n"\r
+ "\t\t\t\tsubnet_timeout..........0x%X\n"\r
+ "\t\t\t\tresp_time_value.........0x%X\n"\r
+ "\t\t\t\terror_threshold.........0x%X\n"\r
+ "",\r
+ port_num,\r
+ cl_ntoh64( node_guid ),\r
+ cl_ntoh64( port_guid ),\r
+ cl_ntoh64( p_pi->m_key ),\r
+ cl_ntoh64( p_pi->subnet_prefix ),\r
+ cl_ntoh16( p_pi->base_lid ),\r
+ cl_ntoh16( p_pi->master_sm_base_lid ),\r
+ cl_ntoh32( p_pi->capability_mask ),\r
+ cl_ntoh16( p_pi->diag_code ),\r
+ cl_ntoh16( p_pi->m_key_lease_period ),\r
+ p_pi->local_port_num,\r
+ p_pi->link_width_enabled,\r
+ p_pi->link_width_supported,\r
+ p_pi->link_width_active,\r
+ ib_port_info_get_link_speed_sup( p_pi ),\r
+ ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),\r
+ p_pi->state_info2,\r
+ ib_port_info_get_mpb( p_pi ),\r
+ ib_port_info_get_lmc( p_pi ),\r
+ p_pi->link_speed,\r
+ p_pi->mtu_smsl,\r
+ p_pi->vl_cap,\r
+ p_pi->vl_high_limit,\r
+ p_pi->vl_arb_high_cap,\r
+ p_pi->vl_arb_low_cap,\r
+ p_pi->mtu_cap,\r
+ p_pi->vl_stall_life,\r
+ p_pi->vl_enforce,\r
+ cl_ntoh16( p_pi->m_key_violations ),\r
+ cl_ntoh16( p_pi->p_key_violations ),\r
+ cl_ntoh16( p_pi->q_key_violations ),\r
+ p_pi->guid_cap,\r
+ ib_port_info_get_client_rereg( p_pi ),\r
+ ib_port_info_get_timeout( p_pi ),\r
+ p_pi->resp_time_value,\r
+ p_pi->error_threshold\r
+ );\r
+\r
+ /* show the capabilities mask */\r
+ osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );\r
+\r
+ osm_log( p_log, log_level, "%s", buf );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_portinfo_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_portinfo_record_t* const p_pir,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ char buf[BUF_SIZE];\r
+ const ib_port_info_t * const p_pi = &p_pir->port_info;\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "PortInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tEndPortLid..............0x%X\n"\r
+ "\t\t\t\tPortNum.................0x%X\n"\r
+ "\t\t\t\tReserved................0x%X\n"\r
+ "\t\t\t\tPortInfo dump:\n"\r
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tsubnet_prefix...........0x%016" PRIx64 "\n"\r
+ "\t\t\t\tbase_lid................0x%X\n"\r
+ "\t\t\t\tmaster_sm_base_lid......0x%X\n"\r
+ "\t\t\t\tcapability_mask.........0x%X\n"\r
+ "\t\t\t\tdiag_code...............0x%X\n"\r
+ "\t\t\t\tm_key_lease_period......0x%X\n"\r
+ "\t\t\t\tlocal_port_num..........0x%X\n"\r
+ "\t\t\t\tlink_width_enabled......0x%X\n"\r
+ "\t\t\t\tlink_width_supported....0x%X\n"\r
+ "\t\t\t\tlink_width_active.......0x%X\n"\r
+ "\t\t\t\tlink_speed_supported....0x%X\n"\r
+ "\t\t\t\tport_state..............%s\n"\r
+ "\t\t\t\tstate_info2.............0x%X\n"\r
+ "\t\t\t\tm_key_protect_bits......0x%X\n"\r
+ "\t\t\t\tlmc.....................0x%X\n"\r
+ "\t\t\t\tlink_speed..............0x%X\n"\r
+ "\t\t\t\tmtu_smsl................0x%X\n"\r
+ "\t\t\t\tvl_cap_init_type........0x%X\n"\r
+ "\t\t\t\tvl_high_limit...........0x%X\n"\r
+ "\t\t\t\tvl_arb_high_cap.........0x%X\n"\r
+ "\t\t\t\tvl_arb_low_cap..........0x%X\n"\r
+ "\t\t\t\tinit_rep_mtu_cap........0x%X\n"\r
+ "\t\t\t\tvl_stall_life...........0x%X\n"\r
+ "\t\t\t\tvl_enforce..............0x%X\n"\r
+ "\t\t\t\tm_key_violations........0x%X\n"\r
+ "\t\t\t\tp_key_violations........0x%X\n"\r
+ "\t\t\t\tq_key_violations........0x%X\n"\r
+ "\t\t\t\tguid_cap................0x%X\n"\r
+ "\t\t\t\tsubnet_timeout..........0x%X\n"\r
+ "\t\t\t\tresp_time_value.........0x%X\n"\r
+ "\t\t\t\terror_threshold.........0x%X\n"\r
+ "",\r
+ cl_ntoh16(p_pir->lid),\r
+ p_pir->port_num,\r
+ p_pir->resv,\r
+ cl_ntoh64( p_pi->m_key ),\r
+ cl_ntoh64( p_pi->subnet_prefix ),\r
+ cl_ntoh16( p_pi->base_lid ),\r
+ cl_ntoh16( p_pi->master_sm_base_lid ),\r
+ cl_ntoh32( p_pi->capability_mask ),\r
+ cl_ntoh16( p_pi->diag_code ),\r
+ cl_ntoh16( p_pi->m_key_lease_period ),\r
+ p_pi->local_port_num,\r
+ p_pi->link_width_enabled,\r
+ p_pi->link_width_supported,\r
+ p_pi->link_width_active,\r
+ ib_port_info_get_link_speed_sup( p_pi ),\r
+ ib_get_port_state_str( ib_port_info_get_port_state( p_pi ) ),\r
+ p_pi->state_info2,\r
+ ib_port_info_get_mpb( p_pi ),\r
+ ib_port_info_get_lmc( p_pi ),\r
+ p_pi->link_speed,\r
+ p_pi->mtu_smsl,\r
+ p_pi->vl_cap,\r
+ p_pi->vl_high_limit,\r
+ p_pi->vl_arb_high_cap,\r
+ p_pi->vl_arb_low_cap,\r
+ p_pi->mtu_cap,\r
+ p_pi->vl_stall_life,\r
+ p_pi->vl_enforce,\r
+ cl_ntoh16( p_pi->m_key_violations ),\r
+ cl_ntoh16( p_pi->p_key_violations ),\r
+ cl_ntoh16( p_pi->q_key_violations ),\r
+ p_pi->guid_cap,\r
+ ib_port_info_get_timeout( p_pi ),\r
+ p_pi->resp_time_value,\r
+ p_pi->error_threshold\r
+ );\r
+\r
+ /* show the capabilities mask */\r
+ osm_dbg_get_capabilities_str( buf, BUF_SIZE, "\t\t\t\t", p_pi );\r
+\r
+ osm_log( p_log, log_level, "%s", buf );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_guidinfo_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_guidinfo_record_t* const p_gir,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ const ib_guid_info_t * const p_gi = &p_gir->guid_info;\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "GUIDInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tLid.....................0x%X\n"\r
+ "\t\t\t\tBlockNum................0x%X\n"\r
+ "\t\t\t\tReserved................0x%X\n"\r
+ "\t\t\t\tGUIDInfo dump:\n"\r
+ "\t\t\t\tReserved................0x%X\n"\r
+ "\t\t\t\tGUID 0..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 1..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 2..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 3..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 4..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 5..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 6..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tGUID 7..................0x%016" PRIx64 "\n",\r
+ cl_ntoh16(p_gir->lid),\r
+ p_gir->block_num,\r
+ p_gir->resv,\r
+ cl_ntoh32(p_gir->reserved),\r
+ cl_ntoh64(p_gi->guid[0]),\r
+ cl_ntoh64(p_gi->guid[1]),\r
+ cl_ntoh64(p_gi->guid[2]),\r
+ cl_ntoh64(p_gi->guid[3]),\r
+ cl_ntoh64(p_gi->guid[4]),\r
+ cl_ntoh64(p_gi->guid[5]),\r
+ cl_ntoh64(p_gi->guid[6]),\r
+ cl_ntoh64(p_gi->guid[7])\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_node_info(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_node_info_t* const p_ni,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "NodeInfo dump:\n"\r
+ "\t\t\t\tbase_version............0x%X\n"\r
+ "\t\t\t\tclass_version...........0x%X\n"\r
+ "\t\t\t\tnode_type...............%s\n"\r
+ "\t\t\t\tnum_ports...............0x%X\n"\r
+ "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tpartition_cap...........0x%X\n"\r
+ "\t\t\t\tdevice_id...............0x%X\n"\r
+ "\t\t\t\trevision................0x%X\n"\r
+ "\t\t\t\tport_num................0x%X\n"\r
+ "\t\t\t\tvendor_id...............0x%X\n"\r
+ "",\r
+ p_ni->base_version,\r
+ p_ni->class_version,\r
+ ib_get_node_type_str( p_ni->node_type ),\r
+ p_ni->num_ports,\r
+ cl_ntoh64( p_ni->sys_guid ),\r
+ cl_ntoh64( p_ni->node_guid ),\r
+ cl_ntoh64( p_ni->port_guid ),\r
+ cl_ntoh16( p_ni->partition_cap ),\r
+ cl_ntoh16( p_ni->device_id ),\r
+ cl_ntoh32( p_ni->revision ),\r
+ ib_node_info_get_local_port_num( p_ni ),\r
+ cl_ntoh32( ib_node_info_get_vendor_id( p_ni ) )\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_node_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_node_record_t* const p_nr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ const ib_node_info_t * const p_ni = &p_nr->node_info;\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ char desc[sizeof(p_nr->node_desc.description) + 1];\r
+\r
+ memcpy(desc, p_nr->node_desc.description,\r
+ sizeof(p_nr->node_desc.description));\r
+ desc[sizeof(desc) - 1] = '\0';\r
+ osm_log( p_log, log_level,\r
+ "Node Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tLid.....................0x%X\n"\r
+ "\t\t\t\tReserved................0x%X\n"\r
+ "\t\t\t\tNodeInfo dump:\n"\r
+ "\t\t\t\tbase_version............0x%X\n"\r
+ "\t\t\t\tclass_version...........0x%X\n"\r
+ "\t\t\t\tnode_type...............%s\n"\r
+ "\t\t\t\tnum_ports...............0x%X\n"\r
+ "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tpartition_cap...........0x%X\n"\r
+ "\t\t\t\tdevice_id...............0x%X\n"\r
+ "\t\t\t\trevision................0x%X\n"\r
+ "\t\t\t\tport_num................0x%X\n"\r
+ "\t\t\t\tvendor_id...............0x%X\n"\r
+ "\t\t\t\tNodeDescription\n"\r
+ "\t\t\t\t%s\n"\r
+ "",\r
+ cl_ntoh16(p_nr->lid),\r
+ cl_ntoh16(p_nr->resv),\r
+ p_ni->base_version,\r
+ p_ni->class_version,\r
+ ib_get_node_type_str( p_ni->node_type ),\r
+ p_ni->num_ports,\r
+ cl_ntoh64( p_ni->sys_guid ),\r
+ cl_ntoh64( p_ni->node_guid ),\r
+ cl_ntoh64( p_ni->port_guid ),\r
+ cl_ntoh16( p_ni->partition_cap ),\r
+ cl_ntoh16( p_ni->device_id ),\r
+ cl_ntoh32( p_ni->revision ),\r
+ ib_node_info_get_local_port_num( p_ni ),\r
+ cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),\r
+ desc\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_path_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_path_rec_t* const p_pr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "PathRecord dump:\n"\r
+ "\t\t\t\tservice_id..............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tdgid....................0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tsgid....................0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tdlid....................0x%X\n"\r
+ "\t\t\t\tslid....................0x%X\n"\r
+ "\t\t\t\thop_flow_raw............0x%X\n"\r
+ "\t\t\t\ttclass..................0x%X\n"\r
+ "\t\t\t\tnum_path_revers.........0x%X\n"\r
+ "\t\t\t\tpkey....................0x%X\n"\r
+ "\t\t\t\tsl......................0x%X\n"\r
+ "\t\t\t\tmtu.....................0x%X\n"\r
+ "\t\t\t\trate....................0x%X\n"\r
+ "\t\t\t\tpkt_life................0x%X\n"\r
+ "\t\t\t\tpreference..............0x%X\n"\r
+ "\t\t\t\tresv2...................0x%X\n"\r
+ "\t\t\t\tresv3...................0x%X\n"\r
+ "",\r
+ *(uint64_t*)p_pr->service_id,\r
+ cl_ntoh64( p_pr->dgid.unicast.prefix ),\r
+ cl_ntoh64( p_pr->dgid.unicast.interface_id ),\r
+ cl_ntoh64( p_pr->sgid.unicast.prefix ),\r
+ cl_ntoh64( p_pr->sgid.unicast.interface_id ),\r
+ cl_ntoh16( p_pr->dlid ),\r
+ cl_ntoh16( p_pr->slid ),\r
+ cl_ntoh32( p_pr->hop_flow_raw ),\r
+ p_pr->tclass,\r
+ p_pr->num_path,\r
+ cl_ntoh16( p_pr->pkey ),\r
+ cl_ntoh16( p_pr->qos_class_sl ),\r
+ p_pr->mtu,\r
+ p_pr->rate,\r
+ p_pr->pkt_life,\r
+ p_pr->preference,\r
+ *(uint32_t*)&p_pr->resv2,\r
+ *((uint16_t*)&p_pr->resv2 + 2)\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_multipath_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_multipath_rec_t* const p_mpr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ int i;\r
+ char buf_line[1024];\r
+ ib_gid_t const *p_gid;\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ memset(buf_line, 0, sizeof(buf_line));\r
+ p_gid = p_mpr->gids;\r
+ if ( p_mpr->sgid_count )\r
+ {\r
+ for (i = 0; i < p_mpr->sgid_count; i++)\r
+ {\r
+ sprintf( buf_line, "%s\t\t\t\tsgid%02d.................."\r
+ "0x%016" PRIx64 " : 0x%016" PRIx64 "\n",\r
+ buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ),\r
+ cl_ntoh64( p_gid->unicast.interface_id ) );\r
+ p_gid++;\r
+ }\r
+ }\r
+ if ( p_mpr->dgid_count )\r
+ {\r
+ for (i = 0; i < p_mpr->dgid_count; i++)\r
+ {\r
+ sprintf( buf_line, "%s\t\t\t\tdgid%02d.................."\r
+ "0x%016" PRIx64 " : 0x%016" PRIx64 "\n",\r
+ buf_line, i + 1, cl_ntoh64( p_gid->unicast.prefix ),\r
+ cl_ntoh64( p_gid->unicast.interface_id ) );\r
+ p_gid++;\r
+ }\r
+ }\r
+ osm_log( p_log, log_level,\r
+ "MultiPath Record dump:\n"\r
+ "\t\t\t\thop_flow_raw............0x%X\n"\r
+ "\t\t\t\ttclass..................0x%X\n"\r
+ "\t\t\t\tnum_path_revers.........0x%X\n"\r
+ "\t\t\t\tpkey....................0x%X\n"\r
+ "\t\t\t\tresv0...................0x%X\n"\r
+ "\t\t\t\tsl......................0x%X\n"\r
+ "\t\t\t\tmtu.....................0x%X\n"\r
+ "\t\t\t\trate....................0x%X\n"\r
+ "\t\t\t\tpkt_life................0x%X\n"\r
+ "\t\t\t\tresv1...................0x%X\n"\r
+ "\t\t\t\tindependence............0x%X\n"\r
+ "\t\t\t\tsgid_count..............0x%X\n"\r
+ "\t\t\t\tdgid_count..............0x%X\n"\r
+ "%s\n"\r
+ "",\r
+ cl_ntoh32( p_mpr->hop_flow_raw ),\r
+ p_mpr->tclass,\r
+ p_mpr->num_path,\r
+ cl_ntoh16( p_mpr->pkey ),\r
+ p_mpr->resv0,\r
+ cl_ntoh16( p_mpr->sl ),\r
+ p_mpr->mtu,\r
+ p_mpr->rate,\r
+ p_mpr->pkt_life,\r
+ p_mpr->resv1,\r
+ p_mpr->independence,\r
+ p_mpr->sgid_count,\r
+ p_mpr->dgid_count,\r
+ buf_line\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_mc_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_member_rec_t* const p_mcmr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "MCMember Record dump:\n"\r
+ "\t\t\t\tMGID....................0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tPortGid.................0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tqkey....................0x%X\n"\r
+ "\t\t\t\tmlid....................0x%X\n"\r
+ "\t\t\t\tmtu.....................0x%X\n"\r
+ "\t\t\t\tTClass..................0x%X\n"\r
+ "\t\t\t\tpkey....................0x%X\n"\r
+ "\t\t\t\trate....................0x%X\n"\r
+ "\t\t\t\tpkt_life................0x%X\n"\r
+ "\t\t\t\tSLFlowLabelHopLimit.....0x%X\n"\r
+ "\t\t\t\tScopeState..............0x%X\n"\r
+ "\t\t\t\tProxyJoin...............0x%X\n"\r
+ "",\r
+ cl_ntoh64( p_mcmr->mgid.unicast.prefix ),\r
+ cl_ntoh64( p_mcmr->mgid.unicast.interface_id ),\r
+ cl_ntoh64( p_mcmr->port_gid.unicast.prefix ),\r
+ cl_ntoh64( p_mcmr->port_gid.unicast.interface_id ),\r
+ cl_ntoh32( p_mcmr->qkey ),\r
+ cl_ntoh16( p_mcmr->mlid ),\r
+ p_mcmr->mtu,\r
+ p_mcmr->tclass,\r
+ cl_ntoh16( p_mcmr->pkey ),\r
+ p_mcmr->rate,\r
+ p_mcmr->pkt_life,\r
+ cl_ntoh32( p_mcmr->sl_flow_hop ),\r
+ p_mcmr->scope_state,\r
+ p_mcmr->proxy_join\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_service_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_service_record_t* const p_sr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ char buf_service_key[35];\r
+ char buf_service_name[65];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ sprintf(buf_service_key,\r
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",\r
+ p_sr->service_key[0],\r
+ p_sr->service_key[1],\r
+ p_sr->service_key[2],\r
+ p_sr->service_key[3],\r
+ p_sr->service_key[4],\r
+ p_sr->service_key[5],\r
+ p_sr->service_key[6],\r
+ p_sr->service_key[7],\r
+ p_sr->service_key[8],\r
+ p_sr->service_key[9],\r
+ p_sr->service_key[10],\r
+ p_sr->service_key[11],\r
+ p_sr->service_key[12],\r
+ p_sr->service_key[13],\r
+ p_sr->service_key[14],\r
+ p_sr->service_key[15]);\r
+ strncpy(buf_service_name, (char *)p_sr->service_name, 64);\r
+ buf_service_name[64] = '\0';\r
+\r
+ osm_log( p_log, log_level,\r
+ "Service Record dump:\n"\r
+ "\t\t\t\tServiceID...............0x%016" PRIx64 "\n"\r
+ "\t\t\t\tServiceGID..............0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tServiceP_Key............0x%X\n"\r
+ "\t\t\t\tServiceLease............0x%X\n"\r
+ "\t\t\t\tServiceKey..............%s\n"\r
+ "\t\t\t\tServiceName.............%s\n"\r
+ "\t\t\t\tServiceData8.1..........0x%X\n"\r
+ "\t\t\t\tServiceData8.2..........0x%X\n"\r
+ "\t\t\t\tServiceData8.3..........0x%X\n"\r
+ "\t\t\t\tServiceData8.4..........0x%X\n"\r
+ "\t\t\t\tServiceData8.5..........0x%X\n"\r
+ "\t\t\t\tServiceData8.6..........0x%X\n"\r
+ "\t\t\t\tServiceData8.7..........0x%X\n"\r
+ "\t\t\t\tServiceData8.8..........0x%X\n"\r
+ "\t\t\t\tServiceData8.9..........0x%X\n"\r
+ "\t\t\t\tServiceData8.10.........0x%X\n"\r
+ "\t\t\t\tServiceData8.11.........0x%X\n"\r
+ "\t\t\t\tServiceData8.12.........0x%X\n"\r
+ "\t\t\t\tServiceData8.13.........0x%X\n"\r
+ "\t\t\t\tServiceData8.14.........0x%X\n"\r
+ "\t\t\t\tServiceData8.15.........0x%X\n"\r
+ "\t\t\t\tServiceData8.16.........0x%X\n"\r
+ "\t\t\t\tServiceData16.1.........0x%X\n"\r
+ "\t\t\t\tServiceData16.2.........0x%X\n"\r
+ "\t\t\t\tServiceData16.3.........0x%X\n"\r
+ "\t\t\t\tServiceData16.4.........0x%X\n"\r
+ "\t\t\t\tServiceData16.5.........0x%X\n"\r
+ "\t\t\t\tServiceData16.6.........0x%X\n"\r
+ "\t\t\t\tServiceData16.7.........0x%X\n"\r
+ "\t\t\t\tServiceData16.8.........0x%X\n"\r
+ "\t\t\t\tServiceData32.1.........0x%X\n"\r
+ "\t\t\t\tServiceData32.2.........0x%X\n"\r
+ "\t\t\t\tServiceData32.3.........0x%X\n"\r
+ "\t\t\t\tServiceData32.4.........0x%X\n"\r
+ "\t\t\t\tServiceData64.1.........0x%016" PRIx64 "\n"\r
+ "\t\t\t\tServiceData64.2.........0x%016" PRIx64 "\n"\r
+ "",\r
+ cl_ntoh64( p_sr->service_id ),\r
+ cl_ntoh64( p_sr->service_gid.unicast.prefix ),\r
+ cl_ntoh64( p_sr->service_gid.unicast.interface_id ),\r
+ cl_ntoh16( p_sr->service_pkey ),\r
+ cl_ntoh32( p_sr->service_lease ),\r
+ buf_service_key,\r
+ buf_service_name,\r
+ p_sr->service_data8[0], p_sr->service_data8[1],\r
+ p_sr->service_data8[2], p_sr->service_data8[3],\r
+ p_sr->service_data8[4], p_sr->service_data8[5],\r
+ p_sr->service_data8[6], p_sr->service_data8[7],\r
+ p_sr->service_data8[8], p_sr->service_data8[9],\r
+ p_sr->service_data8[10], p_sr->service_data8[11],\r
+ p_sr->service_data8[12], p_sr->service_data8[13],\r
+ p_sr->service_data8[14], p_sr->service_data8[15],\r
+ cl_ntoh16(p_sr->service_data16[0]),\r
+ cl_ntoh16(p_sr->service_data16[1]),\r
+ cl_ntoh16(p_sr->service_data16[2]),\r
+ cl_ntoh16(p_sr->service_data16[3]),\r
+ cl_ntoh16(p_sr->service_data16[4]),\r
+ cl_ntoh16(p_sr->service_data16[5]),\r
+ cl_ntoh16(p_sr->service_data16[6]),\r
+ cl_ntoh16(p_sr->service_data16[7]),\r
+ cl_ntoh32(p_sr->service_data32[0]),\r
+ cl_ntoh32(p_sr->service_data32[1]),\r
+ cl_ntoh32(p_sr->service_data32[2]),\r
+ cl_ntoh32(p_sr->service_data32[3]),\r
+ cl_ntoh64(p_sr->service_data64[0]),\r
+ cl_ntoh64(p_sr->service_data64[1])\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_inform_info(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_inform_info_t* const p_ii,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ uint32_t qpn;\r
+ uint8_t resp_time_val;\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+\r
+ ib_inform_info_get_qpn_resp_time(p_ii->g_or_v.generic.qpn_resp_time_val,\r
+ &qpn, &resp_time_val);\r
+\r
+ if (p_ii->is_generic)\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "InformInfo dump:\n"\r
+ "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+ "\t\t\t\tlid_range_begin.........0x%X\n"\r
+ "\t\t\t\tlid_range_end...........0x%X\n"\r
+ "\t\t\t\tis_generic..............0x%X\n"\r
+ "\t\t\t\tsubscribe...............0x%X\n"\r
+ "\t\t\t\ttrap_type...............0x%X\n"\r
+ "\t\t\t\ttrap_num................%u\n"\r
+ "\t\t\t\tqpn.....................0x%06X\n"\r
+ "\t\t\t\tresp_time_val...........0x%X\n"\r
+ "\t\t\t\tnode_type...............0x%06X\n"\r
+ "",\r
+ cl_ntoh64( p_ii->gid.unicast.prefix ),\r
+ cl_ntoh64( p_ii->gid.unicast.interface_id ),\r
+ cl_ntoh16( p_ii->lid_range_begin ),\r
+ cl_ntoh16( p_ii->lid_range_end ),\r
+ p_ii->is_generic,\r
+ p_ii->subscribe,\r
+ cl_ntoh16( p_ii->trap_type ),\r
+ cl_ntoh16( p_ii->g_or_v.generic.trap_num ),\r
+ cl_ntoh32(qpn),\r
+ resp_time_val,\r
+ cl_ntoh32(ib_inform_info_get_node_type( p_ii ))\r
+ );\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "InformInfo dump:\n"\r
+ "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+ "\t\t\t\tlid_range_begin.........0x%X\n"\r
+ "\t\t\t\tlid_range_end...........0x%X\n"\r
+ "\t\t\t\tis_generic..............0x%X\n"\r
+ "\t\t\t\tsubscribe...............0x%X\n"\r
+ "\t\t\t\ttrap_type...............0x%X\n"\r
+ "\t\t\t\tdev_id..................0x%X\n"\r
+ "\t\t\t\tqpn.....................0x%06X\n"\r
+ "\t\t\t\tresp_time_val...........0x%X\n"\r
+ "\t\t\t\tvendor_id...............0x%06X\n"\r
+ "",\r
+ cl_ntoh64( p_ii->gid.unicast.prefix ),\r
+ cl_ntoh64( p_ii->gid.unicast.interface_id ),\r
+ cl_ntoh16( p_ii->lid_range_begin ),\r
+ cl_ntoh16( p_ii->lid_range_end ),\r
+ p_ii->is_generic,\r
+ p_ii->subscribe,\r
+ cl_ntoh16( p_ii->trap_type ),\r
+ cl_ntoh16( p_ii->g_or_v.vend.dev_id ),\r
+ cl_ntoh32(qpn),\r
+ resp_time_val,\r
+ cl_ntoh32(ib_inform_info_get_node_type( p_ii ))\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_inform_info_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_inform_info_record_t* const p_iir,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ uint32_t qpn;\r
+ uint8_t resp_time_val;\r
+\r
+ ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val,\r
+ &qpn, &resp_time_val);\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+\r
+ ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val,\r
+ &qpn, &resp_time_val);\r
+\r
+ if (p_iir->inform_info.is_generic)\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "InformInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tSubscriberEnum..........0x%X\n"\r
+ "\t\t\t\tInformInfo dump:\n"\r
+ "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+ "\t\t\t\tlid_range_begin.........0x%X\n"\r
+ "\t\t\t\tlid_range_end...........0x%X\n"\r
+ "\t\t\t\tis_generic..............0x%X\n"\r
+ "\t\t\t\tsubscribe...............0x%X\n"\r
+ "\t\t\t\ttrap_type...............0x%X\n"\r
+ "\t\t\t\ttrap_num................%u\n"\r
+ "\t\t\t\tqpn.....................0x%06X\n"\r
+ "\t\t\t\tresp_time_val...........0x%X\n"\r
+ "\t\t\t\tnode_type...............0x%06X\n"\r
+ "",\r
+ cl_ntoh64( p_iir->subscriber_gid.unicast.prefix ),\r
+ cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ),\r
+ cl_ntoh16( p_iir->subscriber_enum ),\r
+ cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ),\r
+ cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ),\r
+ cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+ cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+ p_iir->inform_info.is_generic,\r
+ p_iir->inform_info.subscribe,\r
+ cl_ntoh16( p_iir->inform_info.trap_type ),\r
+ cl_ntoh16( p_iir->inform_info.g_or_v.generic.trap_num ),\r
+ cl_ntoh32(qpn),\r
+ resp_time_val,\r
+ cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info ))\r
+ );\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "InformInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tSubscriberGID...........0x%016" PRIx64 " : "\r
+ "0x%016" PRIx64 "\n"\r
+ "\t\t\t\tSubscriberEnum..........0x%X\n"\r
+ "\t\t\t\tInformInfo dump:\n"\r
+ "\t\t\t\tgid.....................0x%016" PRIx64 " : 0x%016" PRIx64 "\n"\r
+ "\t\t\t\tlid_range_begin.........0x%X\n"\r
+ "\t\t\t\tlid_range_end...........0x%X\n"\r
+ "\t\t\t\tis_generic..............0x%X\n"\r
+ "\t\t\t\tsubscribe...............0x%X\n"\r
+ "\t\t\t\ttrap_type...............0x%X\n"\r
+ "\t\t\t\tdev_id..................0x%X\n"\r
+ "\t\t\t\tqpn.....................0x%06X\n"\r
+ "\t\t\t\tresp_time_val...........0x%X\n"\r
+ "\t\t\t\tvendor_id...............0x%06X\n"\r
+ "",\r
+ cl_ntoh64( p_iir->subscriber_gid.unicast.prefix ),\r
+ cl_ntoh64( p_iir->subscriber_gid.unicast.interface_id ),\r
+ cl_ntoh16( p_iir->subscriber_enum ),\r
+ cl_ntoh64( p_iir->inform_info.gid.unicast.prefix ),\r
+ cl_ntoh64( p_iir->inform_info.gid.unicast.interface_id ),\r
+ cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+ cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+ p_iir->inform_info.is_generic,\r
+ p_iir->inform_info.subscribe,\r
+ cl_ntoh16( p_iir->inform_info.trap_type ),\r
+ cl_ntoh16( p_iir->inform_info.g_or_v.vend.dev_id ),\r
+ cl_ntoh32(qpn),\r
+ resp_time_val,\r
+ cl_ntoh32(ib_inform_info_get_node_type( &p_iir->inform_info ))\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_link_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_link_record_t* const p_lr,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "Link Record dump:\n"\r
+ "\t\t\t\tfrom_lid................0x%X\n"\r
+ "\t\t\t\tfrom_port_num...........0x%X\n"\r
+ "\t\t\t\tto_port_num.............0x%X\n"\r
+ "\t\t\t\tto_lid..................0x%X\n"\r
+ "",\r
+ cl_ntoh16( p_lr->from_lid ),\r
+ p_lr->from_port_num,\r
+ p_lr->to_port_num,\r
+ cl_ntoh16( p_lr->to_lid )\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_switch_info(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_switch_info_t* const p_si,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, OSM_LOG_VERBOSE,\r
+ "SwitchInfo dump:\n"\r
+ "\t\t\t\tlin_cap.................0x%X\n"\r
+ "\t\t\t\trand_cap................0x%X\n"\r
+ "\t\t\t\tmcast_cap...............0x%X\n"\r
+ "\t\t\t\tlin_top.................0x%X\n"\r
+ "\t\t\t\tdef_port................0x%X\n"\r
+ "\t\t\t\tdef_mcast_pri_port......0x%X\n"\r
+ "\t\t\t\tdef_mcast_not_port......0x%X\n"\r
+ "\t\t\t\tlife_state..............0x%X\n"\r
+ "\t\t\t\tlids_per_port...........0x%X\n"\r
+ "\t\t\t\tpartition_enf_cap.......0x%X\n"\r
+ "\t\t\t\tflags...................0x%X\n"\r
+ "",\r
+ cl_ntoh16( p_si->lin_cap ),\r
+ cl_ntoh16( p_si->rand_cap ),\r
+ cl_ntoh16( p_si->mcast_cap ),\r
+ cl_ntoh16( p_si->lin_top ),\r
+ p_si->def_port,\r
+ p_si->def_mcast_pri_port,\r
+ p_si->def_mcast_not_port,\r
+ p_si->life_state,\r
+ cl_ntoh16( p_si->lids_per_port ),\r
+ cl_ntoh16( p_si->enforce_cap ),\r
+ p_si->flags\r
+ );\r
+ }\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_switch_info_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_switch_info_record_t* const p_sir,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "SwitchInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tlid.....................0x%X\n"\r
+ "\t\t\t\tSwitchInfo dump:\n"\r
+ "\t\t\t\tlin_cap.................0x%X\n"\r
+ "\t\t\t\trand_cap................0x%X\n"\r
+ "\t\t\t\tmcast_cap...............0x%X\n"\r
+ "\t\t\t\tlin_top.................0x%X\n"\r
+ "\t\t\t\tdef_port................0x%X\n"\r
+ "\t\t\t\tdef_mcast_pri_port......0x%X\n"\r
+ "\t\t\t\tdef_mcast_not_port......0x%X\n"\r
+ "\t\t\t\tlife_state..............0x%X\n"\r
+ "\t\t\t\tlids_per_port...........0x%X\n"\r
+ "\t\t\t\tpartition_enf_cap.......0x%X\n"\r
+ "\t\t\t\tflags...................0x%X\n"\r
+ "",\r
+ cl_ntoh16( p_sir->lid ),\r
+ cl_ntoh16( p_sir->switch_info.lin_cap ),\r
+ cl_ntoh16( p_sir->switch_info.rand_cap ),\r
+ cl_ntoh16( p_sir->switch_info.mcast_cap ),\r
+ cl_ntoh16( p_sir->switch_info.lin_top ),\r
+ p_sir->switch_info.def_port,\r
+ p_sir->switch_info.def_mcast_pri_port,\r
+ p_sir->switch_info.def_mcast_not_port,\r
+ p_sir->switch_info.life_state,\r
+ cl_ntoh16( p_sir->switch_info.lids_per_port ),\r
+ cl_ntoh16( p_sir->switch_info.enforce_cap ),\r
+ p_sir->switch_info.flags\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_pkey_block(\r
+ IN osm_log_t* const p_log,\r
+ IN uint64_t port_guid,\r
+ IN uint16_t block_num,\r
+ IN uint8_t port_num,\r
+ IN const ib_pkey_table_t* const p_pkey_tbl,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ int i;\r
+ char buf_line[1024];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ buf_line[0] = '\0';\r
+ for (i = 0; i < 32; i++)\r
+ sprintf( buf_line,"%s 0x%04x |",\r
+ buf_line, cl_ntoh16(p_pkey_tbl->pkey_entry[i]));\r
+\r
+ osm_log( p_log, log_level,\r
+ "P_Key table dump:\n"\r
+ "\t\t\tport_guid...........0x%016" PRIx64 "\n"\r
+ "\t\t\tblock_num...........0x%X\n"\r
+ "\t\t\tport_num............0x%X\n\tP_Key Table: %s\n",\r
+ cl_ntoh64( port_guid ),\r
+ block_num,\r
+ port_num,\r
+ buf_line\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_slvl_map_table(\r
+ IN osm_log_t* const p_log,\r
+ IN uint64_t port_guid,\r
+ IN uint8_t in_port_num,\r
+ IN uint8_t out_port_num,\r
+ IN const ib_slvl_table_t* const p_slvl_tbl,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ uint8_t i;\r
+ char buf_line1[1024];\r
+ char buf_line2[1024];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ buf_line1[0] = '\0';\r
+ buf_line2[0] = '\0';\r
+ for (i = 0; i < 16; i++)\r
+ sprintf( buf_line1,"%s %-2u |", buf_line1, i);\r
+ for (i = 0; i < 16; i++)\r
+ sprintf( buf_line2,"%s0x%01X |",\r
+ buf_line2, ib_slvl_table_get(p_slvl_tbl, i));\r
+ osm_log( p_log, log_level,\r
+ "SLtoVL dump:\n"\r
+ "\t\t\tport_guid............0x%016" PRIx64 "\n"\r
+ "\t\t\tin_port_num..........0x%X\n"\r
+ "\t\t\tout_port_num.........0x%X\n\tSL: | %s\n\tVL: | %s\n",\r
+ cl_ntoh64( port_guid ),\r
+ in_port_num,\r
+ out_port_num,\r
+ buf_line1, buf_line2\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_vl_arb_table(\r
+ IN osm_log_t* const p_log,\r
+ IN uint64_t port_guid,\r
+ IN uint8_t block_num,\r
+ IN uint8_t port_num,\r
+ IN const ib_vl_arb_table_t* const p_vla_tbl,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ int i;\r
+ char buf_line1[1024];\r
+ char buf_line2[1024];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ buf_line1[0] = '\0';\r
+ buf_line2[0] = '\0';\r
+ for (i = 0; i < 32; i++)\r
+ sprintf( buf_line1,"%s 0x%01X |",\r
+ buf_line1, p_vla_tbl->vl_entry[i].vl);\r
+ for (i = 0; i < 32; i++)\r
+ sprintf( buf_line2,"%s 0x%01X |",\r
+ buf_line2, p_vla_tbl->vl_entry[i].weight);\r
+ osm_log( p_log, log_level,\r
+ "VlArb dump:\n"\r
+ "\t\t\tport_guid...........0x%016" PRIx64 "\n"\r
+ "\t\t\tblock_num...........0x%X\n"\r
+ "\t\t\tport_num............0x%X\n\tVL : | %s\n\tWEIGHT:| %s\n",\r
+ cl_ntoh64( port_guid ),\r
+ block_num,\r
+ port_num,\r
+ buf_line1, buf_line2\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sm_info(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_sm_info_t* const p_smi,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, OSM_LOG_DEBUG,\r
+ "SMInfo dump:\n"\r
+ "\t\t\t\tguid....................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tact_count...............%u\n"\r
+ "\t\t\t\tpriority................%u\n"\r
+ "\t\t\t\tsm_state................%u\n"\r
+ "",\r
+ cl_ntoh64( p_smi->guid ),\r
+ cl_ntoh64( p_smi->sm_key ),\r
+ cl_ntoh32( p_smi->act_count ),\r
+ ib_sminfo_get_priority( p_smi ),\r
+ ib_sminfo_get_state( p_smi )\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sm_info_record(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_sminfo_record_t* const p_smir,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ osm_log( p_log, OSM_LOG_DEBUG,\r
+ "SMInfo Record dump:\n"\r
+ "\t\t\t\tRID\n"\r
+ "\t\t\t\tLid.....................0x%X\n"\r
+ "\t\t\t\tReserved................0x%X\n"\r
+ "\t\t\t\tSMInfo dump:\n"\r
+ "\t\t\t\tguid....................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tact_count...............%u\n"\r
+ "\t\t\t\tpriority................%u\n"\r
+ "\t\t\t\tsm_state................%u\n"\r
+ "",\r
+ cl_ntoh16( p_smir->lid ),\r
+ cl_ntoh16( p_smir->resv0 ),\r
+ cl_ntoh64( p_smir->sm_info.guid ),\r
+ cl_ntoh64( p_smir->sm_info.sm_key ),\r
+ cl_ntoh32( p_smir->sm_info.act_count ),\r
+ ib_sminfo_get_priority( &p_smir->sm_info ),\r
+ ib_sminfo_get_state( &p_smir->sm_info )\r
+ );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_notice(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_mad_notice_attr_t *p_ntci,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ char buff[1024];\r
+ buff[0] = '\0';\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ if (ib_notice_is_generic(p_ntci))\r
+ {\r
+ /* immediate data based on the trap */\r
+ switch (cl_ntoh16(p_ntci->g_or_v.generic.trap_num)) {\r
+ case 64:\r
+ case 65:\r
+ case 66:\r
+ case 67:\r
+ sprintf(buff,\r
+ "\t\t\t\tsrc_gid..................0x%016" PRIx64\r
+ ":0x%016" PRIx64 "\n",\r
+ cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.prefix),\r
+ cl_ntoh64(p_ntci->data_details.ntc_64_67.gid.unicast.interface_id));\r
+ break;\r
+ case 128:\r
+ sprintf(buff,\r
+ "\t\t\t\tsw_lid...................0x%04X\n",\r
+ cl_ntoh16(p_ntci->data_details.ntc_128.sw_lid));\r
+ break;\r
+ case 129:\r
+ case 130:\r
+ case 131:\r
+ sprintf(buff,\r
+ "\t\t\t\tlid......................0x%04X\n"\r
+ "\t\t\t\tport_num.................%u\n",\r
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),\r
+ p_ntci->data_details.ntc_129_131.port_num);\r
+ break;\r
+ case 144:\r
+ sprintf(buff,\r
+ "\t\t\t\tlid......................0x%04x\n"\r
+ "\t\t\t\tnew_cap_mask.............0x%08x\n",\r
+ cl_ntoh16(p_ntci->data_details.ntc_144.lid),\r
+ cl_ntoh32(p_ntci->data_details.ntc_144.new_cap_mask));\r
+ break;\r
+ case 145:\r
+ sprintf(buff,\r
+ "\t\t\t\tlid......................0x%04X\n"\r
+ "\t\t\t\tnew_sys_guid.............0x%016" PRIx64 "\n",\r
+ cl_ntoh16(p_ntci->data_details.ntc_145.lid),\r
+ cl_ntoh64(p_ntci->data_details.ntc_145.new_sys_guid));\r
+ break;\r
+ }\r
+\r
+ osm_log( p_log, log_level,\r
+ "Generic Notice dump:\n"\r
+ "\t\t\t\ttype.....................0x%02X\n"\r
+ "\t\t\t\tprod_type................%u\n"\r
+ "\t\t\t\ttrap_num.................%u\n%s"\r
+ "",\r
+ ib_notice_get_type(p_ntci),\r
+ cl_ntoh32(ib_notice_get_prod_type(p_ntci)),\r
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num),\r
+ buff\r
+ );\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "Vendor Notice dump:\n"\r
+ "\t\t\t\ttype.....................0x%04x\n"\r
+ "\t\t\t\tvendor...................%u\n"\r
+ "\t\t\t\tdevice_id................%u\n"\r
+ "",\r
+ cl_ntoh16(ib_notice_get_type(p_ntci)),\r
+ cl_ntoh32(ib_notice_get_vend_id(p_ntci)),\r
+ cl_ntoh16(p_ntci->g_or_v.vend.dev_id)\r
+ );\r
+ }\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_dr_smp(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_smp_t* const p_smp,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ uint32_t i;\r
+ char buf[BUF_SIZE];\r
+ char line[BUF_SIZE];\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ sprintf( buf,\r
+ "SMP dump:\n"\r
+ "\t\t\t\tbase_ver................0x%X\n"\r
+ "\t\t\t\tmgmt_class..............0x%X\n"\r
+ "\t\t\t\tclass_ver...............0x%X\n"\r
+ "\t\t\t\tmethod..................0x%X (%s)\n",\r
+ p_smp->base_ver,\r
+ p_smp->mgmt_class,\r
+ p_smp->class_ver,\r
+ p_smp->method, ib_get_sm_method_str(p_smp->method));\r
+\r
+ if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)\r
+ {\r
+ sprintf( line,\r
+ "\t\t\t\tD bit...................0x%X\n"\r
+ "\t\t\t\tstatus..................0x%X\n",\r
+ ib_smp_is_d(p_smp),\r
+ ib_smp_get_status(p_smp));\r
+ }\r
+ else\r
+ {\r
+ sprintf( line,\r
+ "\t\t\t\tstatus..................0x%X\n",\r
+ cl_ntoh16(p_smp->status));\r
+ }\r
+ strcat( buf, line );\r
+\r
+ sprintf( line,\r
+ "\t\t\t\thop_ptr.................0x%X\n"\r
+ "\t\t\t\thop_count...............0x%X\n"\r
+ "\t\t\t\ttrans_id................0x%" PRIx64 "\n"\r
+ "\t\t\t\tattr_id.................0x%X (%s)\n"\r
+ "\t\t\t\tresv....................0x%X\n"\r
+ "\t\t\t\tattr_mod................0x%X\n"\r
+ "\t\t\t\tm_key...................0x%016" PRIx64 "\n",\r
+ p_smp->hop_ptr,\r
+ p_smp->hop_count,\r
+ cl_ntoh64(p_smp->trans_id),\r
+ cl_ntoh16(p_smp->attr_id),\r
+ ib_get_sm_attr_str( p_smp->attr_id ),\r
+ cl_ntoh16(p_smp->resv),\r
+ cl_ntoh32(p_smp->attr_mod),\r
+ cl_ntoh64(p_smp->m_key)\r
+ );\r
+ strcat( buf, line );\r
+\r
+ if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)\r
+ {\r
+ sprintf( line,\r
+ "\t\t\t\tdr_slid.................0x%X\n"\r
+ "\t\t\t\tdr_dlid.................0x%X\n",\r
+ cl_ntoh16(p_smp->dr_slid),\r
+ cl_ntoh16(p_smp->dr_dlid)\r
+ );\r
+ strcat( buf, line );\r
+\r
+ strcat( buf, "\n\t\t\t\tInitial path: " );\r
+\r
+ for( i = 0; i <= p_smp->hop_count; i++ )\r
+ {\r
+ sprintf( line, "[%X]", p_smp->initial_path[i] );\r
+ strcat( buf, line );\r
+ }\r
+\r
+ strcat( buf, "\n\t\t\t\tReturn path: " );\r
+\r
+ for( i = 0; i <= p_smp->hop_count; i++ )\r
+ {\r
+ sprintf( line, "[%X]", p_smp->return_path[i] );\r
+ strcat( buf, line );\r
+ }\r
+\r
+ strcat( buf, "\n\t\t\t\tReserved: " );\r
+\r
+ for( i = 0; i < 7; i++ )\r
+ {\r
+ sprintf( line, "[%0X]", p_smp->resv1[i] );\r
+ strcat( buf, line );\r
+ }\r
+\r
+ strcat( buf, "\n" );\r
+\r
+ for( i = 0; i < 64; i += 16 )\r
+ {\r
+ sprintf( line, "\n\t\t\t\t%02X %02X %02X %02X "\r
+ "%02X %02X %02X %02X"\r
+ " %02X %02X %02X %02X %02X %02X %02X %02X\n",\r
+ p_smp->data[i],\r
+ p_smp->data[i+1],\r
+ p_smp->data[i+2],\r
+ p_smp->data[i+3],\r
+ p_smp->data[i+4],\r
+ p_smp->data[i+5],\r
+ p_smp->data[i+6],\r
+ p_smp->data[i+7],\r
+ p_smp->data[i+8],\r
+ p_smp->data[i+9],\r
+ p_smp->data[i+10],\r
+ p_smp->data[i+11],\r
+ p_smp->data[i+12],\r
+ p_smp->data[i+13],\r
+ p_smp->data[i+14],\r
+ p_smp->data[i+15] );\r
+\r
+ strcat( buf, line );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* not a Direct Route so provide source and destination lids */\r
+ strcat(buf, "\t\t\t\tMAD IS LID ROUTED\n");\r
+ }\r
+\r
+ osm_log( p_log, log_level,\r
+ "%s\n", buf );\r
+\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_sa_mad(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_sa_mad_t* const p_mad,\r
+ IN const osm_log_level_t log_level )\r
+{\r
+ char buf[BUF_SIZE];\r
+\r
+ /* make sure the mad is valid */\r
+ if (p_mad == NULL)\r
+ {\r
+ osm_log( p_log, log_level,\r
+ "NULL MAD POINTER\n");\r
+ return;\r
+ }\r
+\r
+ if( osm_log_is_active( p_log, log_level ) )\r
+ {\r
+ sprintf( buf,\r
+ "SA MAD dump:\n"\r
+ "\t\t\t\tbase_ver................0x%X\n"\r
+ "\t\t\t\tmgmt_class..............0x%X\n"\r
+ "\t\t\t\tclass_ver...............0x%X\n"\r
+ "\t\t\t\tmethod..................0x%X (%s)\n"\r
+ "\t\t\t\tstatus..................0x%X\n"\r
+ "\t\t\t\tresv....................0x%X\n"\r
+ "\t\t\t\ttrans_id................0x%" PRIx64 "\n"\r
+ "\t\t\t\tattr_id.................0x%X (%s)\n"\r
+ "\t\t\t\tresv1...................0x%X\n"\r
+ "\t\t\t\tattr_mod................0x%X\n"\r
+ "\t\t\t\trmpp_version............0x%X\n"\r
+ "\t\t\t\trmpp_type...............0x%X\n"\r
+ "\t\t\t\trmpp_flags..............0x%X\n"\r
+ "\t\t\t\trmpp_status.............0x%X\n"\r
+ "\t\t\t\tseg_num.................0x%X\n"\r
+ "\t\t\t\tpayload_len/new_win.....0x%X\n"\r
+ "\t\t\t\tsm_key..................0x%016" PRIx64 "\n"\r
+ "\t\t\t\tattr_offset.............0x%X\n"\r
+ "\t\t\t\tresv2...................0x%X\n"\r
+ "\t\t\t\tcomp_mask...............0x%016" PRIx64 "\n",\r
+ p_mad->base_ver,\r
+ p_mad->mgmt_class,\r
+ p_mad->class_ver,\r
+ p_mad->method, ib_get_sa_method_str(p_mad->method),\r
+ cl_ntoh16(p_mad->status),\r
+ cl_ntoh16(p_mad->resv),\r
+ cl_ntoh64(p_mad->trans_id),\r
+ cl_ntoh16(p_mad->attr_id),\r
+ ib_get_sa_attr_str( p_mad->attr_id ),\r
+ cl_ntoh16(p_mad->resv1),\r
+ cl_ntoh32(p_mad->attr_mod),\r
+ p_mad->rmpp_version,\r
+ p_mad->rmpp_type,\r
+ p_mad->rmpp_flags,\r
+ p_mad->rmpp_status,\r
+ cl_ntoh32(p_mad->seg_num),\r
+ cl_ntoh32(p_mad->paylen_newwin),\r
+ cl_ntoh64(p_mad->sm_key),\r
+ cl_ntoh16(p_mad->attr_offset),\r
+ cl_ntoh16(p_mad->resv3),\r
+ cl_ntoh64(p_mad->comp_mask)\r
+ );\r
+\r
+ strcat( buf, "\n" );\r
+\r
+ osm_log( p_log, log_level,\r
+ "%s\n", buf );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_dr_path(\r
+ IN osm_log_t* const p_log,\r
+ IN const osm_dr_path_t* const p_path,\r
+ IN const osm_log_level_t log_level)\r
+{\r
+ uint32_t i;\r
+ char buf[BUF_SIZE];\r
+ char line[BUF_SIZE];\r
+\r
+ if( osm_log_is_active( p_log, log_level) )\r
+ {\r
+ sprintf( buf, "Directed Path Dump of %u hop path:"\r
+ "\n\t\t\t\tPath = ", p_path->hop_count );\r
+\r
+ for( i = 0; i <= p_path->hop_count; i++ )\r
+ {\r
+ sprintf( line, "[%X]", p_path->path[i] );\r
+ strcat( buf, line );\r
+ }\r
+ osm_log( p_log, log_level,\r
+ "%s\n", buf );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_dump_smp_dr_path(\r
+ IN osm_log_t* const p_log,\r
+ IN const ib_smp_t* const p_smp,\r
+ IN const osm_log_level_t log_level\r
+ )\r
+{\r
+ uint32_t i;\r
+ char buf[BUF_SIZE];\r
+ char line[BUF_SIZE];\r
+\r
+ if( osm_log_is_active( p_log, log_level) )\r
+ {\r
+ sprintf( buf, "Received SMP on a %u hop path:"\r
+ "\n\t\t\t\tInitial path = ", p_smp->hop_count );\r
+\r
+ for( i = 0; i <= p_smp->hop_count; i++ )\r
+ {\r
+ sprintf( line, "[%X]", p_smp->initial_path[i] );\r
+ strcat( buf, line );\r
+ }\r
+\r
+ strcat( buf, "\n\t\t\t\tReturn path = " );\r
+\r
+ for( i = 0; i <= p_smp->hop_count; i++ )\r
+ {\r
+ sprintf( line, "[%X]", p_smp->return_path[i] );\r
+ strcat( buf, line );\r
+ }\r
+\r
+ osm_log( p_log, log_level,\r
+ "%s\n", buf );\r
+ }\r
+}\r
+\r
+const char* const __osm_sm_state_str[] =\r
+{\r
+ "OSM_SM_STATE_NO_STATE", /* 0 */\r
+ "OSM_SM_STATE_INIT", /* 1 */\r
+ "OSM_SM_STATE_IDLE", /* 2 */\r
+ "OSM_SM_STATE_SWEEP_LIGHT", /* 3 */\r
+ "OSM_SM_STATE_SWEEP_LIGHT_WAIT", /* 4 */\r
+ "OSM_SM_STATE_SWEEP_HEAVY_SELF", /* 5 */\r
+ "OSM_SM_STATE_SWEEP_HEAVY_SUBNET", /* 6 */\r
+ "OSM_SM_STATE_SET_SM_UCAST_LID", /* 7 */\r
+ "OSM_SM_STATE_SET_SM_UCAST_LID_WAIT", /* 8 */\r
+ "OSM_SM_STATE_SET_SM_UCAST_LID_DONE", /* 9 */\r
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS", /* 10 */\r
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT", /* 11 */\r
+ "OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE", /* 12 */\r
+ "OSM_SM_STATE_SET_UCAST_TABLES", /* 13 */\r
+ "OSM_SM_STATE_SET_UCAST_TABLES_WAIT", /* 14 */\r
+ "OSM_SM_STATE_SET_UCAST_TABLES_DONE", /* 15 */\r
+ "OSM_SM_STATE_SET_MCAST_TABLES", /* 16 */\r
+ "OSM_SM_STATE_SET_MCAST_TABLES_WAIT", /* 17 */\r
+ "OSM_SM_STATE_SET_MCAST_TABLES_DONE", /* 18 */\r
+ "OSM_SM_STATE_SET_LINK_PORTS", /* 19 */\r
+ "OSM_SM_STATE_SET_LINK_PORTS_WAIT", /* 20 */\r
+ "OSM_SM_STATE_SET_LINK_PORTS_DONE", /* 21 */\r
+ "OSM_SM_STATE_SET_ARMED", /* 22 */\r
+ "OSM_SM_STATE_SET_ARMED_WAIT", /* 23 */\r
+ "OSM_SM_STATE_SET_ARMED_DONE", /* 24 */\r
+ "OSM_SM_STATE_SET_ACTIVE", /* 25 */\r
+ "OSM_SM_STATE_SET_ACTIVE_WAIT", /* 26 */\r
+ "OSM_SM_STATE_LOST_NEGOTIATION", /* 27 */\r
+ "OSM_SM_STATE_STANDBY", /* 28 */\r
+ "OSM_SM_STATE_SUBNET_UP", /* 29 */\r
+ "OSM_SM_STATE_PROCESS_REQUEST", /* 30 */\r
+ "OSM_SM_STATE_PROCESS_REQUEST_WAIT", /* 31 */\r
+ "OSM_SM_STATE_PROCESS_REQUEST_DONE", /* 32 */\r
+ "OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED",/* 33 */\r
+ "OSM_SM_STATE_SET_PKEY", /* 34 */\r
+ "OSM_SM_STATE_SET_PKEY_WAIT", /* 35 */\r
+ "OSM_SM_STATE_SET_PKEY_DONE", /* 36 */\r
+ "UNKNOWN STATE!!" /* 37 */\r
+};\r
+\r
+const char* const __osm_sm_signal_str[] =\r
+{\r
+ "OSM_SIGNAL_NONE", /* 0 */\r
+ "OSM_SIGNAL_SWEEP", /* 1 */\r
+ "OSM_SIGNAL_CHANGE_DETECTED", /* 2 */\r
+ "OSM_SIGNAL_NO_PENDING_TRANSACTIONS", /* 3 */\r
+ "OSM_SIGNAL_DONE", /* 4 */\r
+ "OSM_SIGNAL_DONE_PENDING", /* 5 */\r
+ "OSM_SIGNAL_LOST_SM_NEGOTIATION", /* 6 */\r
+ "OSM_SIGNAL_LIGHT_SWEEP_FAIL", /* 7 */\r
+ "OSM_SIGNAL_IDLE_TIME_PROCESS", /* 8 */\r
+ "OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST", /* 9 */\r
+ "OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED", /* 10 */\r
+ "OSM_SIGNAL_EXIT_STBY", /* 11 */\r
+ "UNKNOWN SIGNAL!!" /* 12 */\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_state_str(\r
+ IN osm_sm_state_t state )\r
+{\r
+ if( state > OSM_SM_STATE_MAX )\r
+ state = OSM_SM_STATE_MAX;\r
+ return( __osm_sm_state_str[state] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_signal_str(\r
+ IN osm_signal_t signal )\r
+{\r
+ if( signal > OSM_SIGNAL_MAX )\r
+ signal = OSM_SIGNAL_MAX;\r
+ return( __osm_sm_signal_str[signal] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+static const char* const __osm_disp_msg_str[] =\r
+{\r
+ "OSM_MSG_REQ",\r
+ "OSM_MSG_MAD_NODE_INFO",\r
+ "OSM_MSG_MAD_PORT_INFO,",\r
+ "OSM_MSG_MAD_SWITCH_INFO",\r
+ "OSM_MSG_MAD_NODE_DESC",\r
+ "OSM_MSG_NO_SMPS_OUTSTANDING",\r
+ "OSM_MSG_MAD_NODE_RECORD",\r
+ "OSM_MSG_MAD_PORTINFO_RECORD",\r
+ "OSM_MSG_MAD_SERVICE_RECORD",\r
+ "OSM_MSG_MAD_PATH_RECORD",\r
+ "OSM_MSG_MAD_MCMEMBER_RECORD",\r
+ "OSM_MSG_MAD_LINK_RECORD",\r
+ "OSM_MSG_MAD_SMINFO_RECORD",\r
+ "OSM_MSG_MAD_CLASS_PORT_INFO",\r
+ "OSM_MSG_MAD_INFORM_INFO",\r
+ "OSM_MSG_MAD_LFT_RECORD",\r
+ "OSM_MSG_MAD_LFT",\r
+ "OSM_MSG_MAD_SM_INFO",\r
+ "OSM_MSG_MAD_NOTICE",\r
+ "OSM_MSG_LIGHT_SWEEP_FAIL",\r
+ "OSM_MSG_MAD_MFT",\r
+ "OSM_MSG_MAD_PKEY_TBL_RECORD",\r
+ "OSM_MSG_MAD_VL_ARB_RECORD",\r
+ "OSM_MSG_MAD_SLVL_TBL_RECORD",\r
+ "OSM_MSG_MAD_PKEY",\r
+ "OSM_MSG_MAD_VL_ARB",\r
+ "OSM_MSG_MAD_SLVL",\r
+ "OSM_MSG_MAD_GUIDINFO_RECORD",\r
+ "OSM_MSG_MAD_INFORM_INFO_RECORD",\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+ "OSM_MSG_MAD_MULTIPATH_RECORD",\r
+#endif\r
+ "UNKNOWN!!"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_disp_msg_str(\r
+ IN cl_disp_msgid_t msg )\r
+{\r
+ if( msg > OSM_MSG_MAX )\r
+ msg = OSM_MSG_MAX;\r
+ return( __osm_disp_msg_str[msg] );\r
+}\r
+\r
+static const char* const __osm_port_state_str_fixed_width[] =\r
+{\r
+ "NOC",\r
+ "DWN",\r
+ "INI",\r
+ "ARM",\r
+ "ACT",\r
+ "???"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_port_state_str_fixed_width(\r
+ IN uint8_t port_state )\r
+{\r
+ if( port_state > IB_LINK_ACTIVE )\r
+ port_state = IB_LINK_ACTIVE + 1;\r
+ return( __osm_port_state_str_fixed_width[port_state] );\r
+}\r
+\r
+static const char* const __osm_node_type_str_fixed_width[] =\r
+{\r
+ "??",\r
+ "CA",\r
+ "SW",\r
+ "RT",\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_node_type_str_fixed_width(\r
+ IN uint32_t node_type )\r
+{\r
+ if( node_type >= IB_NOTICE_NODE_TYPE_ROUTER )\r
+ node_type = 0;\r
+ return( __osm_node_type_str_fixed_width[node_type] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_manufacturer_str(\r
+ IN uint64_t const guid_ho )\r
+{\r
+ static const char* intel_str = "Intel ";\r
+ static const char* mellanox_str = "Mellanox ";\r
+ static const char* redswitch_str = "Redswitch ";\r
+ static const char* silverstorm_str = "SilverStorm";\r
+ static const char* topspin_str = "Topspin ";\r
+ static const char* fujitsu_str = "Fujitsu ";\r
+ static const char* voltaire_str = "Voltaire ";\r
+ static const char* yotta_str = "YottaYotta ";\r
+ static const char* pathscale_str = "PathScale ";\r
+ static const char* ibm_str = "IBM ";\r
+ static const char* divergenet_str = "DivergeNet ";\r
+ static const char* flextronics_str = "Flextronics";\r
+ static const char* agilent_str = "Agilent ";\r
+ static const char* obsidian_str = "Obsidian ";\r
+ static const char* baymicro_str = "BayMicro ";\r
+ static const char* lsilogic_str = "LSILogic ";\r
+ static const char* ddn_str = "DataDirect ";\r
+ static const char* panta_str = "Panta ";\r
+ static const char* hp_str = "HP ";\r
+ static const char* rioworks_str = "Rioworks ";\r
+ static const char* unknown_str = "Unknown ";\r
+\r
+ switch( (uint32_t)(guid_ho >> (5 * 8)) )\r
+ {\r
+ case OSM_VENDOR_ID_INTEL:\r
+ return( intel_str );\r
+ case OSM_VENDOR_ID_MELLANOX:\r
+ return( mellanox_str );\r
+ case OSM_VENDOR_ID_REDSWITCH:\r
+ return( redswitch_str );\r
+ case OSM_VENDOR_ID_SILVERSTORM:\r
+ return( silverstorm_str );\r
+ case OSM_VENDOR_ID_TOPSPIN:\r
+ return( topspin_str );\r
+ case OSM_VENDOR_ID_FUJITSU:\r
+ case OSM_VENDOR_ID_FUJITSU2:\r
+ return( fujitsu_str );\r
+ case OSM_VENDOR_ID_VOLTAIRE:\r
+ return( voltaire_str );\r
+ case OSM_VENDOR_ID_YOTTAYOTTA:\r
+ return( yotta_str );\r
+ case OSM_VENDOR_ID_PATHSCALE:\r
+ return( pathscale_str );\r
+ case OSM_VENDOR_ID_IBM:\r
+ return( ibm_str );\r
+ case OSM_VENDOR_ID_DIVERGENET:\r
+ return( divergenet_str );\r
+ case OSM_VENDOR_ID_FLEXTRONICS:\r
+ return( flextronics_str );\r
+ case OSM_VENDOR_ID_AGILENT:\r
+ return( agilent_str );\r
+ case OSM_VENDOR_ID_OBSIDIAN:\r
+ return( obsidian_str );\r
+ case OSM_VENDOR_ID_BAYMICRO:\r
+ return( baymicro_str );\r
+ case OSM_VENDOR_ID_LSILOGIC:\r
+ return( lsilogic_str );\r
+ case OSM_VENDOR_ID_DDN:\r
+ return( ddn_str );\r
+ case OSM_VENDOR_ID_PANTA:\r
+ return( panta_str );\r
+ case OSM_VENDOR_ID_HP:\r
+ return( hp_str );\r
+ case OSM_VENDOR_ID_RIOWORKS:\r
+ return( rioworks_str );\r
+ default:\r
+ return( unknown_str );\r
+ }\r
+}\r
+\r
+static const char* const __osm_mtu_str_fixed_width[] =\r
+{\r
+ "??? ",\r
+ "256 ",\r
+ "512 ",\r
+ "1024",\r
+ "2048",\r
+ "4096"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_mtu_str(\r
+ IN uint8_t const mtu )\r
+{\r
+ if( mtu > IB_MTU_LEN_4096 )\r
+ return( __osm_mtu_str_fixed_width[0] );\r
+ else\r
+ return( __osm_mtu_str_fixed_width[mtu] );\r
+}\r
+\r
+static const char* const __osm_lwa_str_fixed_width[] =\r
+{\r
+ "???",\r
+ "1x ",\r
+ "4x ",\r
+ "???",\r
+ "???",\r
+ "???",\r
+ "???",\r
+ "???",\r
+ "12x"\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_lwa_str(\r
+ IN uint8_t const lwa )\r
+{\r
+ if( lwa > 8 )\r
+ return( __osm_lwa_str_fixed_width[0] );\r
+ else\r
+ return( __osm_lwa_str_fixed_width[lwa] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static const char* const __osm_lsa_str_fixed_width[] =\r
+{\r
+ "???",\r
+ "2.5",\r
+ "5 ",\r
+ "???",\r
+ "10 "\r
+};\r
+\r
+const char*\r
+osm_get_lsa_str(\r
+ IN uint8_t const lsa )\r
+{\r
+ if( lsa > 4 )\r
+ return( __osm_lsa_str_fixed_width[0] );\r
+ else\r
+ return( __osm_lsa_str_fixed_width[lsa] );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+const char* const __osm_sm_mgr_signal_str[] =\r
+{\r
+ "OSM_SM_SIGNAL_INIT", /* 0 */\r
+ "OSM_SM_SIGNAL_DISCOVERY_COMPLETED", /* 2 */\r
+ "OSM_SM_SIGNAL_POLLING_TIMEOUT", /* 3 */\r
+ "OSM_SM_SIGNAL_DISCOVER", /* 4 */\r
+ "OSM_SM_SIGNAL_DISABLE", /* 5 */\r
+ "OSM_SM_SIGNAL_HANDOVER", /* 6 */\r
+ "OSM_SM_SIGNAL_HANDOVER_SENT", /* 7 */\r
+ "OSM_SM_SIGNAL_ACKNOWLEDGE", /* 8 */\r
+ "OSM_SM_SIGNAL_STANDBY", /* 9 */\r
+ "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED", /* 10 */\r
+ "OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE", /* 11 */\r
+ "OSM_SM_SIGNAL_WAIT_FOR_HANDOVER", /* 12 */\r
+ "UNKNOWN STATE!!" /* 13 */\r
+\r
+};\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char*\r
+osm_get_sm_mgr_signal_str(\r
+ IN osm_sm_signal_t signal )\r
+{\r
+ if( signal > OSM_SM_SIGNAL_MAX )\r
+ signal = OSM_SM_SIGNAL_MAX;\r
+ return( __osm_sm_mgr_signal_str[signal] );\r
+}\r
+\r
+const char* const __osm_sm_mgr_state_str[] =\r
+{\r
+ "IB_SMINFO_STATE_NOTACTIVE", /* 0 */\r
+ "IB_SMINFO_STATE_DISCOVERING", /* 1 */\r
+ "IB_SMINFO_STATE_STANDBY", /* 2 */\r
+ "IB_SMINFO_STATE_MASTER", /* 3 */\r
+ "IB_SMINFO_STATE_INIT", /* 4 */\r
+ "UNKNOWN STATE!!" /* 5 */\r
+\r
+};\r
+\r
+const char*\r
+osm_get_sm_mgr_state_str(\r
+ IN uint16_t state )\r
+{\r
+ if( state > IB_SMINFO_STATE_INIT )\r
+ state = IB_SMINFO_STATE_INIT + 1;\r
+ return( __osm_sm_mgr_state_str[state] );\r
+}\r
+\r
+\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_log.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementaion of osm_log_t.
+ * This object represents the log file.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <opensm/osm_log.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+static int log_exit_count = 0;
+
+#ifndef WIN32
+#include <sys/time.h>
+#include <unistd.h>
+#include <complib/cl_timer.h>
+
+static 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 WIN32 */
+
+#ifndef WIN32
+
+static void truncate_log_file(osm_log_t* const 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* const p_log)
+{
+ fprintf(stderr, "truncate_log_file: cannot truncate on windows system (yet)\n");
+}
+#endif /* ndef WIN32 */
+
+int osm_log_printf(osm_log_t *p_log, osm_log_level_t level,
+ const char *fmt, ...)
+{
+ va_list args;
+ int ret;
+
+ if (!(p_log->level&level))
+ return 0;
+
+ va_start(args, fmt);
+ ret = vfprintf(stdout, fmt, args);
+ va_end(args);
+
+ if (p_log->flush || level&OSM_LOG_ERROR)
+ fflush( stdout );
+
+ return ret;
+}
+
+void
+osm_log(
+ IN osm_log_t* const p_log,
+ IN const osm_log_level_t verbosity,
+ IN const char *p_str, ... )
+{
+ char buffer[LOG_ENTRY_SIZE_MAX];
+ va_list args;
+ int ret;
+
+#ifdef WIN32
+ SYSTEMTIME st;
+ uint32_t pid = GetCurrentThreadId();
+#else
+ pid_t pid = 0;
+ time_t tim;
+ struct tm result;
+ uint64_t time_usecs;
+ uint32_t usecs;
+
+ time_usecs = cl_get_time_stamp();
+ tim = time_usecs/1000000;
+ usecs = time_usecs % 1000000;
+ localtime_r(&tim, &result);
+#endif /* WIN32 */
+
+ /* If this is a call to syslog - always print it */
+ if ( verbosity & (OSM_LOG_SYS | p_log->level) )
+ {
+ va_start( args, p_str );
+ vsprintf( buffer, p_str, args );
+ va_end(args);
+
+ /* this is a call to the syslog */
+ if (verbosity & OSM_LOG_SYS)
+ {
+ cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
+
+ /* SYSLOG should go to stdout too */
+ if (p_log->out_port != stdout)
+ {
+ printf("%s\n", buffer);
+ fflush( stdout );
+ }
+#ifdef WIN32
+ OsmReportState(buffer);
+#endif /* WIN32 */
+ }
+
+ /* 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 WIN32
+ GetLocalTime(&st);
+ _retry:
+ ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+ st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+ pid, buffer );
+#else
+ pid = pthread_self();
+ _retry:
+ ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
+ (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
+ result.tm_mday, result.tm_hour,
+ result.tm_min, result.tm_sec,
+ usecs, pid, buffer );
+#endif
+
+ /* flush log */
+ if (ret > 0 && (p_log->flush || (verbosity & OSM_LOG_ERROR)) &&
+ 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* const p_log,
+ IN const 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 );
+ }
+}
+
+boolean_t
+osm_is_debug(void)
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+ib_api_status_t
+osm_log_init_v2(
+ IN osm_log_t* const p_log,
+ IN const boolean_t flush,
+ IN const uint8_t log_flags,
+ IN const char *log_file,
+ IN const unsigned long max_size,
+ IN const boolean_t accum_log_file )
+{
+ struct stat st;
+
+ p_log->level = log_flags;
+ p_log->flush = flush;
+ p_log->count = 0;
+ p_log->max_size = 0;
+
+ 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 (accum_log_file)
+ p_log->out_port = fopen(log_file, "a+");
+ else
+ p_log->out_port = fopen(log_file, "w+");
+
+ if (!p_log->out_port)
+ {
+ if (accum_log_file)
+ printf("Cannot open %s for appending. Permission denied\n", log_file);
+ else
+ printf("Cannot open %s for writing. Permission denied\n", log_file);
+
+ return(IB_UNKNOWN_ERROR);
+ }
+
+ if (fstat(fileno(p_log->out_port), &st) == 0)
+ p_log->count = st.st_size;
+
+ p_log->max_size = max_size;
+ }
+
+ openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+ 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* const p_log,
+ IN const boolean_t flush,
+ IN const uint8_t log_flags,
+ IN const char *log_file,
+ IN const boolean_t accum_log_file )
+{
+ return osm_log_init_v2( p_log, flush, log_flags, log_file, 0, accum_log_file );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mad_pool.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+
+#define OSM_MAD_POOL_MIN_SIZE 256
+#define OSM_MAD_POOL_GROW_SIZE 256
+
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+__osm_mad_pool_ctor(
+ IN void* const p_object,
+ IN void* context,
+ OUT cl_pool_item_t** const pp_pool_item )
+{
+ osm_madw_t *p_madw = p_object;
+
+ UNUSED_PARAM( context );
+ osm_madw_construct( p_madw );
+ /* CHECK THIS. DOCS DON'T DESCRIBE THIS OUT PARAM. */
+ *pp_pool_item = &p_madw->pool_item;
+ return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_construct(
+ IN osm_mad_pool_t* const p_pool )
+{
+ CL_ASSERT( p_pool );
+
+ memset( p_pool, 0, sizeof(*p_pool) );
+ cl_qlock_pool_construct( &p_pool->madw_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_destroy(
+ IN osm_mad_pool_t* const p_pool )
+{
+ CL_ASSERT( p_pool );
+
+ /* HACK: we still rarely see some mads leaking - so ignore this */
+ /* cl_qlock_pool_destroy( &p_pool->madw_pool ); */
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mad_pool_init(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mad_pool_init );
+
+ p_pool->p_log = p_log;
+
+ status = cl_qlock_pool_init(
+ &p_pool->madw_pool,
+ OSM_MAD_POOL_MIN_SIZE,
+ 0,
+ OSM_MAD_POOL_GROW_SIZE,
+ sizeof( osm_madw_t ),
+ __osm_mad_pool_ctor,
+ NULL,
+ p_pool );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_init: ERR 0702: "
+ "Grow pool initialization failed (%s)\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_t *p_madw;
+ ib_mad_t *p_mad;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get );
+
+ CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+ CL_ASSERT( total_size );
+
+ /*
+ First, acquire a mad wrapper from the mad wrapper pool.
+ */
+ p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+ if( p_madw == NULL )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get: ERR 0703: "
+ "Unable to acquire MAD wrapper object\n" );
+ 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 )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get: ERR 0704: "
+ "Unable to acquire wire MAD\n" );
+
+ /* Don't leak wrappers! */
+ cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)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 );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get: Acquired p_madw = %p, p_mad = %p, "
+ "size = %u\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_bind_handle_t h_bind,
+ IN const uint32_t total_size,
+ IN const ib_mad_t* const p_mad,
+ IN const osm_mad_addr_t* const p_mad_addr )
+{
+ osm_madw_t *p_madw;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper );
+
+ 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 = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+ if( p_madw == NULL )
+ {
+ osm_log( p_pool->p_log, OSM_LOG_ERROR,
+ "osm_mad_pool_get_wrapper: ERR 0705: "
+ "Unable to acquire MAD wrapper object\n" );
+ 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 );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get_wrapper: Acquired p_madw = %p, p_mad = %p "
+ "size = %u\n", p_madw, p_madw->p_mad, total_size );
+
+ Exit:
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_madw_t*
+osm_mad_pool_get_wrapper_raw(
+ IN osm_mad_pool_t* const p_pool )
+{
+ osm_madw_t *p_madw;
+
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_get_wrapper_raw );
+
+ p_madw = (osm_madw_t*)cl_qlock_pool_get( &p_pool->madw_pool );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_get_wrapper_raw: "
+ "Getting p_madw = %p\n", p_madw );
+
+ osm_madw_init( p_madw, 0, 0, 0 );
+ osm_madw_set_mad( p_madw, 0 );
+ cl_atomic_inc( &p_pool->mads_out );
+
+ OSM_LOG_EXIT( p_pool->p_log );
+ return( p_madw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mad_pool_put(
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_pool->p_log, osm_mad_pool_put );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_pool->p_log, OSM_LOG_DEBUG,
+ "osm_mad_pool_put: Releasing p_madw = %p, p_mad = %p\n",
+ p_madw, p_madw->p_mad );
+
+ /*
+ 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
+ */
+ cl_qlock_pool_put( &p_pool->madw_pool, (cl_pool_item_t*)p_madw );
+ cl_atomic_dec( &p_pool->mads_out );
+
+ OSM_LOG_EXIT( p_pool->p_log );
+}
+
+
--- /dev/null
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
--- /dev/null
+!if $(FREEBUILD)\r
+TARGETNAME=osmv_ibal_3_0_0\r
+!else\r
+TARGETNAME=osmv_ibal_3_0_0d\r
+!endif\r
+TARGETTYPE=LIBRARY\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+USE_NTDLL=1\r
+USE_NATIVE_EH=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+ osm_vendor_al.c \\r
+ osm_vendor_mlx_sa.c \\r
+ winosm_common.c\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+ $(LIBPATH)\*\ibal.lib \\r
+ $(LIBPATH)\*\complib.lib \r
+!else\r
+ $(LIBPATH)\*\ibald.lib \\r
+ $(LIBPATH)\*\complibd.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+ $(OSM_HOME)\include; \\r
+ $(OSM_HOME); \\r
+ $(WINIBHOME)\inc; \\r
+ $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) \r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES)\r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
--- /dev/null
+/*\r
+ * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_vendor_al.c 1375 2008-07-13 08:55:53Z leonidk $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Implementation of osm_req_t.\r
+ * This object represents the generic attribute requester.\r
+ * This object is part of the opensm family of objects.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.8 $\r
+ */\r
+\r
+/*\r
+ Next available error code: 0x300\r
+*/\r
+#ifdef __WIN__\r
+/* Suppress all warning regarding casting void* to specific pointer object */\r
+#pragma warning(disable : 4305)\r
+#endif\r
+\r
+#include <vendor/osm_vendor_select.h>\r
+\r
+#ifdef OSM_VENDOR_INTF_AL\r
+\r
+#include <complib/cl_memory.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_thread.h>\r
+#include <complib/cl_math.h>\r
+#include <complib/cl_debug.h>\r
+#include <iba/ib_types.h>\r
+#include <opensm/osm_madw.h>\r
+#include <opensm/osm_log.h>\r
+#include <opensm/osm_mad_pool.h>\r
+#include <vendor/osm_vendor_api.h>\r
+\r
+/****s* OpenSM: Vendor AL/osm_al_bind_info_t\r
+ * NAME\r
+ * osm_al_bind_info_t\r
+ *\r
+ * DESCRIPTION\r
+ * Structure containing bind information.\r
+ *\r
+ * SYNOPSIS\r
+ */\r
+typedef struct _osm_al_bind_info\r
+{\r
+ osm_vendor_t *p_vend;\r
+ void *client_context;\r
+ ib_qp_handle_t h_qp;\r
+ ib_mad_svc_handle_t h_svc;\r
+ uint8_t port_num;\r
+ ib_pool_key_t pool_key;\r
+ osm_vend_mad_recv_callback_t rcv_callback;\r
+ osm_vend_mad_send_err_callback_t send_err_callback;\r
+ osm_mad_pool_t *p_osm_pool;\r
+ ib_av_handle_t h_dr_av;\r
+\r
+} osm_al_bind_info_t;\r
+/*\r
+ * FIELDS\r
+ * p_vend\r
+ * Pointer to the vendor object.\r
+ *\r
+ * client_context\r
+ * User's context passed during osm_bind\r
+ *\r
+ * h_qp\r
+ * Handle the QP for this bind.\r
+ *\r
+ * h_qp_svc\r
+ * Handle the QP mad service for this bind.\r
+ *\r
+ * port_num\r
+ * Port number (within the HCA) of the bound port.\r
+ *\r
+ * pool_key\r
+ * Pool key returned by all for this QP.\r
+ *\r
+ * h_dr_av\r
+ * Address vector handle used for all directed route SMPs.\r
+ *\r
+ * SEE ALSO\r
+ *********/\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+inline static ib_api_status_t\r
+__osm_al_convert_wcs(\r
+ IN ib_wc_status_t const wc_status )\r
+{\r
+ switch( wc_status )\r
+ {\r
+ case IB_WCS_SUCCESS:\r
+ return( IB_SUCCESS );\r
+\r
+ case IB_WCS_TIMEOUT_RETRY_ERR:\r
+ return( IB_TIMEOUT );\r
+\r
+ default:\r
+ return( IB_ERROR );\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void AL_API\r
+__osm_set_vend_wrap( IN osm_al_bind_info_t* const p_bind,\r
+ IN ib_mad_element_t* const p_elem,\r
+ OUT osm_vend_wrap_t* p_vw)\r
+{\r
+ p_vw->h_bind = p_bind;\r
+ p_vw->size = p_elem->size;\r
+ p_vw->p_elem = p_elem;\r
+ p_vw->h_av = 0;\r
+ p_vw->p_resp_madw = NULL;\r
+\r
+}\r
+ \r
+\r
+static void AL_API\r
+__osm_al_ca_err_callback(\r
+ IN ib_async_event_rec_t *p_async_rec )\r
+{\r
+ osm_vendor_t *p_vend = (osm_vendor_t*)p_async_rec->context;\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_err_callback );\r
+\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_al_ca_err_callback: ERR 3B01: "\r
+ "Event on channel adapter (%s).\n",\r
+ ib_get_async_event_str( p_async_rec->code ) );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void AL_API\r
+__osm_al_ca_destroy_callback(\r
+ IN void *context )\r
+{\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)context;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_ca_destroy_callback );\r
+\r
+ osm_log( p_vend->p_log, OSM_LOG_INFO,\r
+ "__osm_al_ca_destroy_callback: "\r
+ "Closing local channel adapter.\n" );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+\r
+static void AL_API\r
+__osm_al_err_callback(\r
+ IN ib_async_event_rec_t *p_async_rec )\r
+{\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t*)p_async_rec->context;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_err_callback );\r
+\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_al_err_callback: ERR 3B02: "\r
+ "Error on QP (%s).\n",\r
+ ib_get_async_event_str( p_async_rec->code ) );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/* \r
+ Send_cb will handle the following cases :\r
+ Element Status | Send Response (no reponse expected) | Send Request (response expeceted) \r
+ ================|===========================================|==========================================\r
+ ERROR | Free : AV , madw(send_err_cb) | Free : AV , madw , resp_madw \r
+ SUCCESS | Free : AV , madw | Free : AV , madw\r
+\r
+ Element Status | Receive Response (no reponse expected) \r
+ ================|===========================================\r
+ ERROR | Free : AV , madw(send_err_cb) \r
+ SUCCESS | Free : AV , madw, resp_madw (both through rcv_callback) \r
+ \r
+*/ \r
+static void AL_API\r
+__osm_al_send_callback(\r
+ IN const ib_mad_svc_handle_t h_mad_svc,\r
+ IN void *mad_svc_context,\r
+ IN ib_mad_element_t *p_elem )\r
+{\r
+ osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;\r
+ osm_vendor_t* const p_vend = p_bind->p_vend;\r
+ osm_madw_t* const p_madw = (osm_madw_t*)p_elem->context1;\r
+ osm_vend_wrap_t* p_vw = osm_madw_get_vend_ptr( p_madw );\r
+ ib_mad_t *p_mad = ib_get_mad_buf( p_elem );\r
+ ib_av_attr_t av_attr;\r
+ ib_pd_handle_t h_pd;\r
+ ib_api_status_t status_elem,status;\r
+ osm_madw_t *p_new_madw;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_send_callback );\r
+ UNUSED_PARAM(h_mad_svc);\r
+ CL_ASSERT( p_vw );\r
+ CL_ASSERT( p_vw->h_av );\r
+ /* since we use context1 , safely , and its the only place that remove the clean \r
+ p_elem,p_madw , h_av no checks are required */\r
+ status_elem = __osm_al_convert_wcs(p_elem->status);\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_send_callback: "\r
+ "Destroying av handle %p.\n", p_elem->h_av );\r
+ /* Check first if its a direct route handle , in this case skip */\r
+ if (p_elem->h_av != p_bind->h_dr_av) \r
+ {\r
+ ib_destroy_av( p_elem->h_av );\r
+ }\r
+ /* Since the free order is first resp_madw then madw (PARENT) we should check\r
+ this case first */\r
+ if (p_elem->resp_expected)\r
+ {\r
+ p_madw->status = status_elem;\r
+ if ( status_elem != IB_SUCCESS )\r
+ {\r
+ /*\r
+ Return any wrappers to the pool that may have been\r
+ pre-emptively allocated to handle a receive.\r
+ */\r
+ osm_log(p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_al_send_callback: ERR 3333 "\r
+ " Mad Completed with WQE Error : %s.\n",ib_get_wc_status_str(p_elem->status));\r
+ if( p_vw->p_resp_madw )\r
+ {\r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+ p_vw->p_resp_madw = NULL;\r
+ }\r
+\r
+ p_bind->send_err_callback( p_bind->client_context, p_madw );\r
+ }\r
+ else\r
+ {\r
+ /* We are in response flow of receive , need to apply the rcv_callback \r
+ The rcv_callback will free the resp_madw , req_madw , p_elem of receive\r
+ and request */\r
+ osm_log(p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_send_callback: "\r
+ "The Mad is a response , thus handeled in __osm_al_send_callback\n");\r
+ p_new_madw = p_vw->p_resp_madw;\r
+ p_bind->rcv_callback( p_new_madw, p_bind->client_context,\r
+ p_madw );\r
+\r
+ }\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_send_callback: "\r
+ "Returning MAD to pool, TID = 0x%" PRIx64 ".\n",\r
+ cl_ntoh64( p_mad->trans_id ) );\r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+ if ( status_elem != IB_SUCCESS )\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_al_send_callback: ERR 3b0b "\r
+ "request mad had failed.\n");\r
+ goto Exit;\r
+ }\r
+\r
+\r
+\r
+\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/*\r
+ Receive_cb will be applied in the following cases :\r
+ Element Status | Receive Response (no reponse expected) | Receive Request (response expeceted) \r
+ ================|==============================================|=======================================\r
+ ERROR | NOT APPLIED | NOT_APPLIED\r
+ SUCCESS | Free : Resp_madw , copy_req_madw | Allocate new_madw (for response then in send_cb free)\r
+ */\r
+ static void AL_API\r
+__osm_al_rcv_callback(\r
+ IN const ib_mad_svc_handle_t h_mad_svc,\r
+ IN void *mad_svc_context,\r
+ IN ib_mad_element_t *p_elem )\r
+{\r
+ osm_al_bind_info_t* const p_bind = (osm_al_bind_info_t*)mad_svc_context;\r
+ osm_vendor_t* const p_vend = p_bind->p_vend;\r
+ osm_madw_t *p_old_madw,*p_copy_old_madw;\r
+ osm_madw_t *p_new_madw;\r
+ osm_vend_wrap_t* p_old_vw;\r
+ osm_vend_wrap_t* p_new_vw;\r
+ ib_mad_t *p_new_mad;\r
+ osm_mad_addr_t mad_addr;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_al_rcv_callback );\r
+ UNUSED_PARAM(h_mad_svc);\r
+ CL_ASSERT( p_elem->context1 == NULL );\r
+ CL_ASSERT( p_elem->context2 == NULL );\r
+ /*\r
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_al_rcv_callback: "\r
+ "Handling Transaction : 0x%" PRIx64 " .\n",\r
+ cl_ntoh64(p_elem->p_mad_buf->trans_id));\r
+ */\r
+ p_new_mad = ib_get_mad_buf( p_elem );\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_rcv_callback: "\r
+ "Acquired implicitly MAD %p.\n", p_new_mad );\r
+\r
+ /*\r
+ In preperation for initializing the new mad wrapper,\r
+ Initialize the mad_addr structure for the received wire MAD.\r
+ */\r
+ mad_addr.dest_lid = p_elem->remote_lid;\r
+ mad_addr.path_bits = p_elem->path_bits;\r
+\r
+ /* TO DO - figure out which #define to use for the 2.5 Gb rate... */\r
+ mad_addr.static_rate = 0;\r
+\r
+ if( p_new_mad->mgmt_class == IB_MCLASS_SUBN_LID ||\r
+ p_new_mad->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+ {\r
+ mad_addr.addr_type.smi.source_lid = p_elem->remote_lid;\r
+ }\r
+ else\r
+ {\r
+ mad_addr.addr_type.gsi.remote_qp = p_elem->remote_qp;\r
+ mad_addr.addr_type.gsi.remote_qkey = p_elem->remote_qkey;\r
+ mad_addr.addr_type.gsi.pkey = p_elem->pkey_index;\r
+ mad_addr.addr_type.gsi.service_level = p_elem->remote_sl;\r
+ mad_addr.addr_type.gsi.global_route = FALSE;\r
+ }\r
+\r
+ /*\r
+ If this MAD is a response to a previous request,\r
+ then grab our pre-allocated MAD wrapper.\r
+ Otherwise, allocate a new MAD wrapper.\r
+ context1 - contains the request madw\r
+ */\r
+ if( ib_mad_is_response( p_new_mad ) )\r
+ {\r
+ /*\r
+ The acquiring was done in the ib_get_mad_buf function. \r
+ If this is a request - then we impllicitly allocate the MAD.\r
+ In this case - it was allocated in the lower layer. The message\r
+ is for tracking down messages - locate how/where this mad was\r
+ allocated.\r
+ */\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_rcv_callback: "\r
+ "The Mad is a response , thus handeled in __osm_al_send_callback\n");\r
+ CL_ASSERT( p_elem->send_context1 != NULL );\r
+ CL_ASSERT( p_elem->send_context2 == NULL );\r
+\r
+ p_old_madw = (osm_madw_t*)p_elem->send_context1;\r
+ p_old_vw = osm_madw_get_vend_ptr( p_old_madw );\r
+ p_new_madw = p_old_vw->p_resp_madw;\r
+\r
+ CL_ASSERT( p_new_madw );\r
+ osm_madw_init( p_new_madw, p_bind, p_elem->size,\r
+ &mad_addr );\r
+ osm_madw_set_mad( p_new_madw, p_new_mad );\r
+ p_new_vw = osm_madw_get_vend_ptr( p_new_madw );\r
+ __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);\r
+ goto Exit;\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_rcv_callback: "\r
+ "The Mad is a request , thus handeled in __osm_al_rcv_callback\n");\r
+ CL_ASSERT( p_elem->send_context1 == NULL );\r
+ CL_ASSERT( p_elem->send_context2 == NULL );\r
+\r
+ p_new_madw = osm_mad_pool_get_wrapper( p_bind->p_osm_pool,\r
+ p_bind, p_elem->size, p_new_mad, &mad_addr );\r
+ CL_ASSERT(p_new_madw);\r
+ p_new_vw = osm_madw_get_vend_ptr( p_new_madw );\r
+\r
+ __osm_set_vend_wrap(p_bind,p_elem,p_new_vw);\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_rcv_callback: "\r
+ "Calling receive callback function %p.\n",\r
+ p_bind->rcv_callback );\r
+\r
+\r
+ p_bind->rcv_callback( p_new_madw, p_bind->client_context,\r
+ ((osm_madw_t*)p_elem->send_context1) );\r
+ }\r
+\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_init(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN osm_log_t* const p_log,\r
+ IN const uint32_t timeout )\r
+{\r
+ ib_api_status_t status;\r
+ OSM_LOG_ENTER( p_log, osm_vendor_init );\r
+\r
+ p_vend->p_log = p_log;\r
+\r
+ /*\r
+ Open our instance of AL.\r
+ */\r
+ status = ib_open_al( &p_vend->h_al );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_init: ERR 3B03: "\r
+ "Error opening AL (%s).\n",\r
+ ib_get_err_str( status ) );\r
+\r
+ goto Exit;\r
+ }\r
+\r
+ p_vend->timeout = timeout;\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_vendor_t*\r
+osm_vendor_new(\r
+ IN osm_log_t* const p_log,\r
+ IN const uint32_t timeout )\r
+{\r
+ ib_api_status_t status;\r
+ osm_vendor_t *p_vend;\r
+\r
+ OSM_LOG_ENTER( p_log, osm_vendor_new );\r
+\r
+ p_vend = cl_zalloc( sizeof(*p_vend) );\r
+ if( p_vend == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_new: ERR 3B04: "\r
+ "Unable to allocate vendor object.\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ status = osm_vendor_init( p_vend, p_log, timeout );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_free( p_vend );\r
+ p_vend = NULL;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_log );\r
+ return( p_vend );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_delete(\r
+ IN osm_vendor_t** const pp_vend )\r
+{\r
+ /* TO DO - fill this in */\r
+ ib_close_al( (*pp_vend)->h_al );\r
+ cl_free( *pp_vend );\r
+ *pp_vend = NULL;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_ca_info_init(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN osm_ca_info_t* const p_ca_info,\r
+ IN const ib_net64_t ca_guid )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_ca_info_init );\r
+\r
+ p_ca_info->guid = ca_guid;\r
+\r
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_ca_info_init: "\r
+ "Querying CA 0x%" PRIx64 ".\n",\r
+ cl_ntoh64( ca_guid ) );\r
+ }\r
+/* attr size by verbs definition is required to be (uint32_t *) under opensm is only being set as 1 */\r
+ status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, NULL,\r
+ (uint32_t*)&p_ca_info->attr_size );\r
+ if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_ca_info_init: ERR 3B05: "\r
+ "Unexpected status getting CA attributes (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_ca_info->attr_size );\r
+\r
+ p_ca_info->p_attr = cl_malloc( p_ca_info->attr_size );\r
+ if( p_ca_info->p_attr == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_ca_info_init: ERR 3B06: "\r
+ "Unable to allocate attribute storage.\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ status = ib_query_ca_by_guid( p_vend->h_al, ca_guid, p_ca_info->p_attr,\r
+ (uint32_t*)&p_ca_info->attr_size );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_ca_info_init: ERR 3B07: "\r
+ "Unexpected status getting CA attributes (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( status );\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_ca_info_destroy(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN osm_ca_info_t* const p_ca_info )\r
+{\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_destroy );\r
+\r
+ if( p_ca_info->p_attr )\r
+ cl_free( p_ca_info->p_attr );\r
+\r
+ cl_free( p_ca_info );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_ca_info_t*\r
+osm_ca_info_new(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN const ib_net64_t ca_guid )\r
+{\r
+ ib_api_status_t status;\r
+ osm_ca_info_t *p_ca_info;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_ca_info_new );\r
+\r
+ CL_ASSERT( ca_guid );\r
+\r
+ p_ca_info = cl_zalloc( sizeof(*p_ca_info) );\r
+ if( p_ca_info == NULL )\r
+ goto Exit;\r
+\r
+ status = __osm_ca_info_init( p_vend, p_ca_info, ca_guid );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_ca_info_destroy( p_vend, p_ca_info );\r
+ p_ca_info = NULL;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( p_ca_info );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_vendor_get_ca_guids(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN ib_net64_t** const p_guids,\r
+ IN size_t* const p_num_guids )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_get_ca_guids );\r
+\r
+ CL_ASSERT( p_guids );\r
+ CL_ASSERT( p_num_guids );\r
+\r
+ status = ib_get_ca_guids( p_vend->h_al, NULL, p_num_guids );\r
+ if( (status != IB_INSUFFICIENT_MEMORY ) && (status != IB_SUCCESS ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_get_ca_guids: ERR 3B08: "\r
+ "Unexpected status getting CA GUID array (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ if( *p_num_guids == 0 )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_get_ca_guids: ERR 3B09: "\r
+ "No available channel adapters.\n" );\r
+ status = IB_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+\r
+ *p_guids = cl_malloc( *p_num_guids * sizeof(**p_guids) );\r
+ if( *p_guids == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_get_ca_guids: ERR 3B10: "\r
+ "Unable to allocate CA GUID array.\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ status = ib_get_ca_guids( p_vend->h_al, *p_guids, p_num_guids );\r
+ CL_ASSERT( *p_num_guids );\r
+\r
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_vendor_get_ca_guids: "\r
+ "Detected %u local channel adapters.\n", *p_num_guids );\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( status );\r
+}\r
+\r
+/****f* OpenSM: CA Info/osm_ca_info_get_pi_ptr\r
+ * NAME\r
+ * osm_ca_info_get_pi_ptr\r
+ *\r
+ * DESCRIPTION\r
+ * Returns a pointer to the port attribute of the specified port\r
+ * owned by this CA.\r
+ *\r
+ * SYNOPSIS\r
+ */\r
+static ib_port_attr_t*\r
+__osm_ca_info_get_port_attr_ptr(\r
+ IN const osm_ca_info_t* const p_ca_info,\r
+ IN const uint8_t index )\r
+{\r
+ return( &p_ca_info->p_attr->p_port_attr[index] );\r
+}\r
+/*\r
+ * PARAMETERS\r
+ * p_ca_info\r
+ * [in] Pointer to a CA Info object.\r
+ *\r
+ * index\r
+ * [in] Port "index" for which to retrieve the port attribute.\r
+ * The index is the offset into the ca's internal array\r
+ * of port attributes.\r
+ *\r
+ * RETURN VALUE\r
+ * Returns a pointer to the port attribute of the specified port\r
+ * owned by this CA.\r
+ * Also allocate p_vend->p_ca_info if not allocated and init it .\r
+ *\r
+ * NOTES\r
+ *\r
+ * SEE ALSO\r
+ *********/\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_get_all_port_attr(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN ib_port_attr_t* const p_attr_array,\r
+ IN uint32_t* const p_num_ports )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ uint32_t ca;\r
+ size_t ca_count;\r
+ uint32_t port_count = 0;\r
+ uint8_t port_num;\r
+ uint32_t total_ports = 0;\r
+ ib_net64_t *p_ca_guid = NULL;\r
+ osm_ca_info_t *p_ca_info;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_all_port_attr );\r
+\r
+ CL_ASSERT( p_vend );\r
+ \r
+ /*\r
+ 1) Determine the number of CA's\r
+ 2) If not allready allocated - allocate an array big enough to hold the\r
+ ca info object , the ca info will be overwrite to contain the new ca info\r
+ 3) Call again to retrieve the guids.\r
+ */\r
+ status = __osm_vendor_get_ca_guids( p_vend, &p_ca_guid, &ca_count );\r
+\r
+ if (p_vend->p_ca_info == NULL) \r
+ {\r
+ p_vend->p_ca_info = cl_zalloc( ca_count * sizeof(*(p_vend->p_ca_info)) );\r
+ \r
+ if( p_vend->p_ca_info == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_get_all_port_attr: ERR 3B11: "\r
+ "Unable to allocate CA information array.\n" );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ p_vend->ca_count = ca_count;\r
+\r
+ /*\r
+ For each CA, retrieve the port info attributes\r
+ */\r
+ for( ca = 0; ca < ca_count; ca++ )\r
+ {\r
+ p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+ status = __osm_ca_info_init(\r
+ p_vend,\r
+ p_ca_info,\r
+ p_ca_guid[ca] );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_get_all_port_attr: ERR 3B12: "\r
+ "Unable to initialize CA Info object (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ }\r
+\r
+ total_ports += osm_ca_info_get_num_ports( p_ca_info );\r
+ }\r
+\r
+ /*\r
+ If the user supplied enough storage, return the port guids,\r
+ otherwise, return the appropriate error.\r
+ */\r
+ if( *p_num_ports >= total_ports )\r
+ {\r
+ for( ca = 0; ca < ca_count; ca++ )\r
+ {\r
+ uint32_t num_ports;\r
+\r
+ p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+\r
+ for( port_num = 0; port_num < num_ports; port_num++ )\r
+ {\r
+ p_attr_array[port_count] = \r
+ *__osm_ca_info_get_port_attr_ptr( p_ca_info, port_num );\r
+ /* convert lid to host order */\r
+ p_attr_array[port_count].lid = cl_ntoh16(p_attr_array[port_count].lid);\r
+ port_count++;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ status = IB_INSUFFICIENT_MEMORY;\r
+ }\r
+\r
+\r
+ *p_num_ports = total_ports;\r
+\r
+\r
+ Exit:\r
+ if( p_ca_guid )\r
+ cl_free( p_ca_guid );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_net64_t\r
+osm_vendor_get_ca_guid(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN const ib_net64_t port_guid )\r
+{\r
+ uint8_t index;\r
+ uint8_t num_ports;\r
+ uint32_t num_guids = 0;\r
+ osm_ca_info_t *p_ca_info;\r
+ uint32_t ca;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_ca_guid );\r
+\r
+ CL_ASSERT( port_guid );\r
+ /*\r
+ First, locate the HCA that owns this port.\r
+ */\r
+ if( p_vend->p_ca_info == NULL )\r
+ {\r
+ /*\r
+ Initialize the osm_ca_info_t array which allows\r
+ us to match port GUID to CA.\r
+ */\r
+ osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );\r
+ }\r
+\r
+ CL_ASSERT( p_vend->p_ca_info );\r
+ CL_ASSERT( p_vend->ca_count );\r
+\r
+ for( ca = 0; ca < p_vend->ca_count; ca++ )\r
+ {\r
+ p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+ CL_ASSERT( num_ports );\r
+\r
+ for( index = 0; index < num_ports; index++ )\r
+ {\r
+ if( port_guid ==\r
+ osm_ca_info_get_port_guid( p_ca_info, index ) )\r
+ {\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( osm_ca_info_get_ca_guid( p_ca_info ) );\r
+ }\r
+ }\r
+ }\r
+\r
+ /*\r
+ No local CA owns this guid!\r
+ */\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_get_ca_guid: ERR 3B13: "\r
+ "Unable to determine CA guid.\n" );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( 0 );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+uint8_t\r
+osm_vendor_get_port_num(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN const ib_net64_t port_guid )\r
+{\r
+ uint8_t index;\r
+ uint8_t num_ports;\r
+ uint32_t num_guids = 0;\r
+ osm_ca_info_t *p_ca_info;\r
+ uint32_t ca;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get_port_num );\r
+\r
+ CL_ASSERT( port_guid );\r
+ /*\r
+ First, locate the HCA that owns this port.\r
+ */\r
+ if( p_vend->p_ca_info == NULL )\r
+ {\r
+ /*\r
+ Initialize the osm_ca_info_t array which allows\r
+ us to match port GUID to CA.\r
+ */\r
+ osm_vendor_get_all_port_attr( p_vend, NULL, &num_guids );\r
+ }\r
+\r
+ CL_ASSERT( p_vend->p_ca_info );\r
+ CL_ASSERT( p_vend->ca_count );\r
+\r
+ for( ca = 0; ca < p_vend->ca_count; ca++ )\r
+ {\r
+ p_ca_info = &p_vend->p_ca_info[ca];\r
+\r
+ num_ports = osm_ca_info_get_num_ports( p_ca_info );\r
+ CL_ASSERT( num_ports );\r
+\r
+ for( index = 0; index < num_ports; index++ )\r
+ {\r
+ if( port_guid ==\r
+ osm_ca_info_get_port_guid( p_ca_info, index ) )\r
+ {\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( osm_ca_info_get_port_num( p_ca_info, index ) );\r
+ }\r
+ }\r
+ }\r
+ \r
+ /*\r
+ No local CA owns this guid!\r
+ */\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_get_port_num: ERR 3B30: "\r
+ "Unable to determine CA guid.\n" );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( 0 );\r
+}\r
+\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_vendor_open_ca(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN const ib_net64_t port_guid )\r
+{\r
+ ib_net64_t ca_guid;\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, __osm_vendor_open_ca );\r
+\r
+ ca_guid = osm_vendor_get_ca_guid( p_vend, port_guid );\r
+ if( ca_guid == 0 )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_open_ca: ERR 3B31: "\r
+ "Bad port GUID value 0x%" PRIx64 ".\n",\r
+ cl_ntoh64( port_guid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ osm_log( p_vend->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_vendor_open_ca: "\r
+ "Opening HCA 0x%" PRIx64 ".\n", cl_ntoh64( ca_guid ) );\r
+\r
+ status = ib_open_ca( p_vend->h_al,\r
+ ca_guid,\r
+ __osm_al_ca_err_callback,\r
+ p_vend,\r
+ &p_vend->h_ca );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_open_ca: ERR 3B15: "\r
+ "Unable to open CA (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_vend->h_ca );\r
+\r
+ status = ib_alloc_pd(\r
+ p_vend->h_ca,\r
+ IB_PDT_ALIAS,\r
+ p_vend,\r
+ &p_vend->h_pd );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ ib_close_ca( p_vend->h_ca,__osm_al_ca_destroy_callback );\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "__osm_vendor_open_ca: ERR 3B16: "\r
+ "Unable to allocate protection domain (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_vend->h_pd );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_vendor_init_av(\r
+ IN const osm_al_bind_info_t* p_bind,\r
+ IN ib_av_attr_t* p_av )\r
+{\r
+ cl_memclr( p_av, sizeof(*p_av) );\r
+ p_av->port_num = p_bind->port_num;\r
+ p_av->dlid = IB_LID_PERMISSIVE;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+osm_bind_handle_t\r
+osm_vendor_bind(\r
+ IN osm_vendor_t* const p_vend,\r
+ IN osm_bind_info_t* const p_user_bind,\r
+ IN osm_mad_pool_t* const p_mad_pool,\r
+ IN osm_vend_mad_recv_callback_t mad_recv_callback,\r
+ IN osm_vend_mad_send_err_callback_t send_err_callback,\r
+ IN void* context )\r
+{\r
+ ib_net64_t port_guid;\r
+ osm_al_bind_info_t *p_bind = 0;\r
+ ib_api_status_t status;\r
+ ib_qp_create_t qp_create;\r
+ ib_mad_svc_t mad_svc;\r
+ ib_av_attr_t av;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_bind );\r
+\r
+ CL_ASSERT( p_user_bind );\r
+ CL_ASSERT( p_mad_pool );\r
+ CL_ASSERT( mad_recv_callback );\r
+ CL_ASSERT( send_err_callback );\r
+\r
+ port_guid = p_user_bind->port_guid;\r
+ osm_log( p_vend->p_log, OSM_LOG_INFO,\r
+ "osm_vendor_bind: "\r
+ "Binding to port 0x%" PRIx64 ".\n",\r
+ cl_ntoh64( port_guid ) );\r
+\r
+ if( p_vend->h_ca == 0 )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_bind: "\r
+ "Opening CA that owns port 0x%" PRIx64 ".\n", cl_ntoh64( port_guid ));\r
+\r
+ status = __osm_vendor_open_ca( p_vend, port_guid );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_bind: ERR 3B17: "\r
+ "Unable to Open CA (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ p_bind = cl_zalloc( sizeof(*p_bind) );\r
+ if( p_bind == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_bind: ERR 3B18: "\r
+ "Unable to allocate internal bind object.\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ p_bind->p_vend = p_vend;\r
+ p_bind->client_context = context;\r
+ p_bind->port_num = osm_vendor_get_port_num( p_vend, port_guid );\r
+ p_bind->rcv_callback = mad_recv_callback;\r
+ p_bind->send_err_callback = send_err_callback;\r
+ p_bind->p_osm_pool = p_mad_pool;\r
+\r
+ CL_ASSERT( p_bind->port_num );\r
+\r
+ /*\r
+ Get the proper QP.\r
+ */\r
+ cl_memclr( &qp_create, sizeof(qp_create) );\r
+\r
+ switch( p_user_bind->mad_class )\r
+ {\r
+ case IB_MCLASS_SUBN_LID:\r
+ case IB_MCLASS_SUBN_DIR:\r
+ qp_create.qp_type = IB_QPT_QP0_ALIAS;\r
+ break;\r
+\r
+ case IB_MCLASS_SUBN_ADM:\r
+ default:\r
+ qp_create.qp_type = IB_QPT_QP1_ALIAS;\r
+ break;\r
+ }\r
+\r
+ qp_create.sq_depth = p_user_bind->send_q_size;\r
+ qp_create.rq_depth = p_user_bind->recv_q_size;\r
+ qp_create.sq_sge = OSM_AL_SQ_SGE;\r
+ qp_create.rq_sge = OSM_AL_RQ_SGE;\r
+ status = ib_get_spl_qp(\r
+ p_vend->h_pd,\r
+ port_guid,\r
+ &qp_create,\r
+ p_bind,\r
+ __osm_al_err_callback,\r
+ &p_bind->pool_key,\r
+ &p_bind->h_qp );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_bind: ERR 3B19: "\r
+ "Unable to get QP handle (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ cl_free( p_bind );\r
+ p_bind = 0;\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_bind->h_qp );\r
+ CL_ASSERT( p_bind->pool_key );\r
+\r
+ cl_memclr( &mad_svc, sizeof(mad_svc) );\r
+\r
+ mad_svc.mad_svc_context = p_bind;\r
+ mad_svc.pfn_mad_send_cb = __osm_al_send_callback; \r
+ mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;\r
+ mad_svc.mgmt_class = p_user_bind->mad_class;\r
+ mad_svc.mgmt_version = p_user_bind->class_version;\r
+ mad_svc.support_unsol = p_user_bind->is_responder;\r
+ mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;\r
+ mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;\r
+ mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;\r
+ mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;\r
+ mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;\r
+\r
+\r
+ status = ib_reg_mad_svc(\r
+ p_bind->h_qp,\r
+ &mad_svc,\r
+ &p_bind->h_svc );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_bind: ERR 3B21: "\r
+ "Unable to register QP0 MAD service (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ cl_free( p_bind );\r
+ p_bind = 0;\r
+ goto Exit;\r
+ }\r
+\r
+ __osm_vendor_init_av( p_bind, &av );\r
+\r
+ status = ib_create_av( p_vend->h_pd, &av, &(p_bind->h_dr_av) );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_bind: ERR 3B22: "\r
+ "Unable to create address vector (%s).\n",\r
+ ib_get_err_str( status ) );\r
+\r
+ cl_free( p_bind );\r
+ p_bind = 0;\r
+ goto Exit;\r
+ }\r
+\r
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_bind: "\r
+ "Allocating av handle %p.\n", p_bind->h_dr_av );\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( (osm_bind_handle_t)p_bind );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+/* osm_vendor_unbind is added due to OSM-1.8.0 gen2 merging\r
+ The functionality will be added when the Gen2 osm_vendor_unbind\r
+ will be implemented.\r
+*/ \r
+void\r
+osm_vendor_unbind(\r
+ IN osm_bind_handle_t h_bind)\r
+{\r
+ osm_al_bind_info_t *p_bind = ( osm_al_bind_info_t * ) h_bind;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_unbind );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log);\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_mad_t*\r
+osm_vendor_get(\r
+ IN osm_bind_handle_t h_bind,\r
+ IN const uint32_t mad_size,\r
+ IN osm_vend_wrap_t* const p_vw )\r
+{\r
+ ib_mad_t *p_mad;\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_get );\r
+\r
+ CL_ASSERT( p_vw );\r
+\r
+ p_vw->size = mad_size;\r
+ p_vw->h_bind = h_bind;\r
+\r
+ /*\r
+ Retrieve a MAD element from the pool and give the user direct\r
+ access to its buffer.\r
+ */\r
+ status = ib_get_mad( p_bind->pool_key, mad_size, &p_vw->p_elem );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_get: ERR 3B25: "\r
+ "Unable to acquire MAD (%s).\n",\r
+ ib_get_err_str( status ) );\r
+\r
+ p_mad = NULL;\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_vw->p_elem );\r
+ p_mad = ib_get_mad_buf( p_vw->p_elem );\r
+\r
+ if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_get: "\r
+ "Acquired MAD %p, size = %u.\n", p_mad, mad_size );\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( p_mad );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_put(\r
+ IN osm_bind_handle_t h_bind,\r
+ IN osm_vend_wrap_t* const p_vw )\r
+{\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_put );\r
+\r
+ CL_ASSERT( p_vw );\r
+ CL_ASSERT( p_vw->p_elem );\r
+ CL_ASSERT( p_vw->h_bind == h_bind );\r
+\r
+ if( osm_log_get_level( p_vend->p_log ) >= OSM_LOG_DEBUG )\r
+ {\r
+ \r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_put: "\r
+ "Retiring MAD %p.\n", ib_get_mad_buf( p_vw->p_elem ) );\r
+ // "Retiring MAD %p.\n", p_mad);\r
+ }\r
+\r
+ status = ib_put_mad( p_vw->p_elem );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_put: ERR 3B26: "\r
+ "Unable to retire MAD (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ }\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_send(\r
+ IN osm_bind_handle_t h_bind,\r
+ IN osm_madw_t* const p_madw,\r
+ IN boolean_t const resp_expected )\r
+{\r
+ osm_al_bind_info_t* const p_bind = h_bind;\r
+ osm_vendor_t* const p_vend = p_bind->p_vend;\r
+ osm_vend_wrap_t* const p_vw = osm_madw_get_vend_ptr( p_madw );\r
+ osm_mad_addr_t* const p_mad_addr = osm_madw_get_mad_addr_ptr( p_madw );\r
+ ib_mad_t* const p_mad = osm_madw_get_mad_ptr( p_madw );\r
+ ib_api_status_t status;\r
+ ib_mad_element_t *p_elem;\r
+ ib_av_attr_t av;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_send );\r
+\r
+ CL_ASSERT( p_vw->h_bind == h_bind );\r
+ CL_ASSERT( p_vw->p_elem );\r
+\r
+ p_elem = p_vw->p_elem;\r
+\r
+ /*\r
+ If a response is expected to this MAD, then preallocate\r
+ a mad wrapper to contain the wire MAD received in the\r
+ response. Allocating a wrapper here allows for easier\r
+ failure paths than after we already received the wire mad.\r
+ In order to seperate the receive callback and the send callback\r
+ dependency , we copy the request madw and send it as context2\r
+ Which in time in the receive callback will replace the req_madw \r
+ to allow avoid races with send callback\r
+ */\r
+ if( resp_expected )\r
+ {\r
+ p_vw->p_resp_madw = osm_mad_pool_get_wrapper_raw(\r
+ p_bind->p_osm_pool );\r
+ if( p_vw->p_resp_madw == NULL )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_send: ERR 3B27: "\r
+ "Unable to allocate MAD wrapper.\n" );\r
+ status = IB_INSUFFICIENT_RESOURCES;\r
+ goto Exit;\r
+ }\r
+ \r
+ }\r
+ else\r
+ p_vw->p_resp_madw = NULL;\r
+\r
+ /*\r
+ For all sends other than directed route SM MADs,\r
+ acquire an address vector for the destination.\r
+ */\r
+ if( p_mad->mgmt_class != IB_MCLASS_SUBN_DIR )\r
+ {\r
+ cl_memclr( &av, sizeof(av) );\r
+ av.port_num = p_bind->port_num;\r
+ av.dlid = p_mad_addr->dest_lid;\r
+ av.static_rate = p_mad_addr->static_rate;\r
+ av.path_bits = p_mad_addr->path_bits;\r
+\r
+ if( (p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&\r
+ (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) )\r
+ {\r
+ av.sl = p_mad_addr->addr_type.gsi.service_level;\r
+\r
+\r
+ if(p_mad_addr->addr_type.gsi.global_route)\r
+ {\r
+ av.grh_valid = TRUE;\r
+ /* ANIL */\r
+ /* av.grh = p_mad_addr->addr_type.gsi.grh_info; */\r
+ }\r
+ }\r
+\r
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_send: "\r
+ "av.port_num 0x%X, "\r
+ "av.dlid 0x%X, "\r
+ "av.static_rate %d, "\r
+ "av.path_bits %d.\n",\r
+ av.port_num, cl_ntoh16(av.dlid),\r
+ av.static_rate, av.path_bits);\r
+ }\r
+\r
+ status = ib_create_av( p_vend->h_pd, &av, &(p_vw->h_av) );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_send: ERR 3B28: "\r
+ "Unable to create address vector (%s).\n",\r
+ ib_get_err_str( status ) );\r
+\r
+ if( p_vw->p_resp_madw )\r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+ /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */\r
+ if (p_madw) \r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+ goto Exit;\r
+ }\r
+\r
+ if( osm_log_is_active( p_vend->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_send: "\r
+ "Allocating av handle %p.\n", p_vw->h_av );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ p_vw->h_av = p_bind->h_dr_av;\r
+ }\r
+\r
+ p_elem->h_av = p_vw->h_av;\r
+\r
+ p_elem->context1 = p_madw;\r
+ p_elem->context2 = NULL;\r
+\r
+ p_elem->immediate_data = 0;\r
+ p_elem->p_grh = NULL;\r
+ p_elem->resp_expected = resp_expected;\r
+ p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;\r
+\r
+ p_elem->send_opt = IB_SEND_OPT_SIGNALED;\r
+ p_elem->timeout_ms = p_vend->timeout;\r
+\r
+ /* Completion information. */\r
+ p_elem->status = 0; /* Not trusting AL */\r
+\r
+\r
+ if( (p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||\r
+ (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR) )\r
+ {\r
+ p_elem->remote_qp = 0;\r
+ p_elem->remote_qkey = 0;\r
+ }\r
+ else\r
+ {\r
+ p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;\r
+ p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;\r
+ osm_log(p_vend->p_log, OSM_LOG_DEBUG,\r
+ "osm_vendor_send: "\r
+ "remote qp = 0x%X, remote qkey = 0x%X.\n",\r
+ cl_ntoh32(p_elem->remote_qp),\r
+ cl_ntoh32(p_elem->remote_qkey) );\r
+ }\r
+\r
+ status = ib_send_mad( p_bind->h_svc, p_elem, NULL );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_send: ERR 3B29: "\r
+ "Send failed , cleaning up (%s).\n",\r
+ ib_get_err_str( status ) );\r
+ /* When we destroy the av - we should take the pointer from local allocation since\r
+ we do not "trust" IBAL to keep track in p_elem */\r
+\r
+ if (p_vw->h_av && (p_vw->h_av != p_bind->h_dr_av) )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_DEBUG,\r
+ "__osm_al_send: "\r
+ "Destroying av handle %p.\n", p_vw->h_av );\r
+ ib_destroy_av( p_vw->h_av );\r
+ }\r
+ if( p_vw->p_resp_madw )\r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_vw->p_resp_madw );\r
+ /* Since we in immediate error the vendor layer is expected to handle the rollback , i.e free of madw */\r
+ if (p_madw) \r
+ osm_mad_pool_put( p_bind->p_osm_pool, p_madw );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_vendor_local_lid_change(\r
+ IN osm_bind_handle_t h_bind )\r
+{\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_local_lid_change );\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+ return( IB_SUCCESS );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_vendor_set_sm(\r
+ IN osm_bind_handle_t h_bind,\r
+ IN boolean_t is_sm_val )\r
+{\r
+ osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *)h_bind;\r
+ osm_vendor_t *p_vend = p_bind->p_vend;\r
+ ib_api_status_t status;\r
+ ib_port_attr_mod_t attr_mod;\r
+\r
+ OSM_LOG_ENTER( p_vend->p_log, osm_vendor_set_sm );\r
+\r
+ cl_memclr( &attr_mod, sizeof(attr_mod) );\r
+\r
+ attr_mod.cap.sm = is_sm_val;\r
+\r
+ status = ib_modify_ca( p_vend->h_ca, p_bind->port_num,\r
+ IB_CA_MOD_IS_SM, &attr_mod );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_vend->p_log, OSM_LOG_ERROR,\r
+ "osm_vendor_set_sm: ERR 3B34: "\r
+ "Unable set 'IS_SM' bit to:%u in port attributes (%s).\n",\r
+ is_sm_val, ib_get_err_str( status ) );\r
+ }\r
+\r
+ OSM_LOG_EXIT( p_vend->p_log );\r
+}\r
+\r
+#endif /* OSM_VENDOR_INTF_AL */\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vendor_mlx_sa.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+/* 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
+*/
+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, __osmv_sa_mad_rcv_cb );
+
+ if (! p_req_madw)
+ {
+ osm_log( p_bind->p_log, OSM_LOG_DEBUG,
+ "__osmv_sa_mad_rcv_cb: "
+ "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,
+ "__osmv_sa_mad_rcv_cb: ERR 0501: "
+ "Remote error:0x%04X .\n", 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,
+ "__osmv_sa_mad_rcv_cb: 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 */
+ query_res.result_cnt =
+ (uintn_t)
+ ( ( 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,
+ "__osmv_sa_mad_rcv_cb: Count = %u = %u / %u (%u)\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
+*/
+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, __osmv_sa_mad_err_cb );
+
+ /* 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 );
+
+ if (p_query_req_copy) 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.
+ *****************************************************************************/
+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, __osmv_get_lid_and_sm_lid_by_port_guid );
+
+ /* 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,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "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,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: 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,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "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,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
+ "Fail 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,
+ "__osmv_get_lid_and_sm_lid_by_port_guid: "
+ "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, osmv_bind_sa );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_bind_sa: "
+ "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 = TRUE;
+ bind_info.is_trap_processor = FALSE;
+ bind_info.is_report_processor = TRUE;
+ 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,
+ "osmv_bind_sa: ERR 0505: "
+ "Fail to allocate new bidn 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,
+ "osmv_bind_sa: ERR 0506: "
+ "Fail to bind to vendor SMI.\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,
+ "osmv_bind_sa: ERR 0507: "
+ "Fail 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,
+ "osmv_bind_sa: 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 */
+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;
+
+ OSM_LOG_ENTER( p_log, __osmv_send_sa_req );
+
+ /*
+ 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,
+ "__osmv_send_sa_req: ERR 0509: "
+ "Fail 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,
+ "__osmv_send_sa_req: 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 )
+ {
+ memcpy( p_sa_mad->data, p_sa_mad_data->p_attr,
+ ib_get_attr_size(p_sa_mad_data->attr_offset));
+ }
+
+ /*
+ 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->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
+ p_madw->mad_addr.addr_type.gsi.pkey = IB_DEFAULT_PKEY;
+ 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 arroud 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));
+ *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,
+ "__osmv_send_sa_req: "
+ "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
+ )
+{
+ osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *)h_bind;
+ osmv_sa_mad_data_t sa_mad_data;
+ osmv_user_query_t *p_user_query;
+ ib_service_record_t svc_rec;
+ ib_node_record_t node_rec;
+ ib_portinfo_record_t port_info;
+ ib_path_rec_t path_rec;
+ ib_class_port_info_t class_port_info;
+ osm_log_t *p_log = p_bind->p_log;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osmv_query_sa );
+
+ /* Set the request information. */
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+ sa_mad_data.attr_mod = 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,
+ "osmv_query_sa DBG:001 %s", "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;
+ sa_mad_data.attr_offset = p_user_query->attr_offset;
+ 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;
+#if (0)
+#ifdef OSM_VENDOR_INTF_AL
+ /* HACK for OFED OSM: convert lid order from network to
+ host for IB_MAD_ATTR_PORTINFO_RECORD */
+ if ( (sa_mad_data.attr_id == IB_MAD_ATTR_PORTINFO_RECORD) &&
+ (sa_mad_data.comp_mask & IB_PIR_COMPMASK_LID))
+ {
+ ib_portinfo_record_t * p_pir = (ib_portinfo_record_t *)sa_mad_data.p_attr;
+ p_pir->lid = cl_ntoh16(p_pir->lid);
+ }
+#endif
+#endif
+ break;
+
+ case OSMV_QUERY_ALL_SVC_RECS:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "SVC_REC_BY_NAME\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+ sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.comp_mask = 0;
+ sa_mad_data.p_attr = &svc_rec;
+ break;
+
+ case OSMV_QUERY_SVC_REC_BY_NAME:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s", "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.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.p_attr = &svc_rec;
+ memcpy( 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,
+ "osmv_query_sa DBG:001 %s", "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.attr_offset =
+ ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ sa_mad_data.p_attr = &svc_rec;
+ 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,
+ "osmv_query_sa DBG:001 %s","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.attr_offset =
+ ib_get_attr_offset( sizeof( ib_class_port_info_t ) );
+ sa_mad_data.comp_mask = 0;
+ sa_mad_data.p_attr = &class_port_info;
+
+ break;
+
+ case OSMV_QUERY_NODE_REC_BY_NODE_GUID:
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmv_query_sa DBG:001 %s","NODE_REC_BY_NODE_GUID\n" );
+ sa_mad_data.method = IB_MAD_METHOD_GETTABLE;
+ sa_mad_data.attr_id = IB_MAD_ATTR_NODE_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_node_record_t ) );
+ sa_mad_data.comp_mask = IB_NR_COMPMASK_NODEGUID;
+ sa_mad_data.p_attr = &node_rec;
+ 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,
+ "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+ sa_mad_data.comp_mask = IB_PIR_COMPMASK_LID;
+ sa_mad_data.p_attr = &port_info;
+ 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,
+ "osmv_query_sa DBG:001 %s","PORT_REC_BY_LID_AND_NUM\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_portinfo_record_t ) );
+ 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,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_VLARB_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_vl_arb_table_record_t ) );
+ 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,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_VLARB_BY_LID_PORT_BLOCK\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_SLVL_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_slvl_table_record_t ) );
+ 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,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_PORT_GUIDS\n" );
+ memset(&path_rec, 0, sizeof(ib_path_rec_t ));
+ sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+ sa_mad_data.p_attr = &path_rec;
+ ib_gid_set_default( &path_rec.dgid,
+ ( ( osmv_guid_pair_t * ) ( p_query_req->
+ p_query_input ) )->
+ dest_guid );
+ ib_gid_set_default( &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,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_GIDS\n" );
+ memset(&path_rec, 0, sizeof(ib_path_rec_t ));
+ sa_mad_data.attr_id = IB_MAD_ATTR_PATH_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DGID | IB_PR_COMPMASK_SGID );
+ sa_mad_data.p_attr = &path_rec;
+ memcpy( &path_rec.dgid,
+ &( ( osmv_gid_pair_t * ) ( p_query_req->p_query_input ) )->
+ dest_gid, sizeof( ib_gid_t ) );
+ memcpy( &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,
+ "osmv_query_sa DBG:001 %s","PATH_REC_BY_LIDS\n" );
+ memset(&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.attr_offset =
+ ib_get_attr_offset( sizeof( ib_path_rec_t ) );
+ sa_mad_data.comp_mask = ( IB_PR_COMPMASK_DLID | IB_PR_COMPMASK_SLID );
+ sa_mad_data.p_attr = &path_rec;
+ path_rec.dlid =
+ ( ( osmv_lid_pair_t * ) ( p_query_req->p_query_input ) )->dest_lid;
+ 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,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_SET\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ 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,
+ "osmv_query_sa DBG:001 %s","OSMV_QUERY_UD_MULTICAST_DELETE\n" );
+ sa_mad_data.attr_id = IB_MAD_ATTR_MCMEMBER_RECORD;
+ sa_mad_data.attr_offset =
+ ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ sa_mad_data.comp_mask = p_user_query->comp_mask;
+ sa_mad_data.p_attr = p_user_query->p_attr;
+ break;
+
+ default:
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmv_query_sa DBG:001 %s","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;
+}
+
+
+/*****************************************************************************
+ *****************************************************************************/
+
+
+
--- /dev/null
+#include <vendor/winosm_common.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <complib/cl_memory.h>
+
+int optind=1;
+int opterr=1;
+int optopt='?';
+int iArg=1;
+
+char*
+GetOsmTempPath(void)
+{
+ char* temp_path;
+ int length;
+ temp_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+ length = GetTempPath(OSM_MAX_LOG_NAME_SIZE,temp_path);
+ if (length > OSM_MAX_LOG_NAME_SIZE)
+ {
+ cl_free(temp_path);
+ temp_path = (char*)cl_malloc(length+1);
+ GetTempPath(length+1,temp_path);
+ }
+ return temp_path;
+}
+
+char*
+GetOsmCachePath(void)
+{
+ char* cache_path;
+ char* tmp_file_name;
+ char* winib_home, tmp;
+ HANDLE hFile;
+
+ winib_home = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+ winib_home = getenv("WinIB_HOME");
+ if (winib_home == NULL)
+ {
+ /* The WinIB_HOME variable isn't defined. Use the
+ default temp path */
+ return GetOsmTempPath();
+ }
+ cache_path = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+ strcpy(cache_path, winib_home);
+
+ strcat(cache_path, "\\etc\\");
+ tmp_file_name = (char*)cl_malloc(OSM_MAX_LOG_NAME_SIZE);
+ strcpy(tmp_file_name, cache_path);
+ strcat(tmp_file_name, "opensm.opts");
+ hFile = CreateFile(tmp_file_name,
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ {
+ cl_free(cache_path);
+ return GetOsmTempPath();
+ }
+ /* Such file exists. This means the directory is usable */
+ CloseHandle(hFile);
+
+ return cache_path;
+}
+
+/****************************************************************************/
+int getopt_long_only(int argc, char *const*argv,
+ const char *optstring,
+ const struct option *longopts, int *longindex)
+{
+ char chOpt;
+ char tmp_str[256];
+ char* tmp_arg = NULL;
+ char* tok=NULL;
+ int i;
+ char tokens[2] = {'='};
+
+ if (iArg == argc)
+ {
+
+ return (EOF);
+ }
+
+ if (argv[iArg][0] != '-')
+ {
+ /* Does not start with a - - we are done scanning */
+
+ return (EOF);
+ }
+
+ /*termination of scanning */
+ if (!strcmp("--",argv[iArg])) {
+ return EOF;
+
+ }
+
+
+ /* char option : -d 5 */
+ if ((argv[iArg][0] == '-') &&(argv[iArg][1] != '-') ) {
+ optarg = get_char_option(optstring,argv,argc,iArg,&optind,&chOpt);
+ iArg = optind;
+
+ return chOpt;
+ }
+
+ /* Look for this string in longopts */
+ strcpy(tmp_str,&(argv[iArg][2]));
+
+ /*get the option */
+ tok = strtok(tmp_str,tokens);
+
+ for (i = 0; longopts[i].name; i++)
+ {
+ if (strcmp (tok, longopts[i].name) == 0)
+ {
+ /* We have a match */
+ if (longindex != NULL )
+ *longindex = i;
+
+ if (longopts[i].flag != NULL) {
+ *(longopts[i].flag) = longopts[i].val;
+ }
+
+
+
+ if (longopts[i].has_arg != no_argument)
+ {
+ /*get the argument */
+
+ if (strchr(argv[iArg],'=') != NULL)
+ {
+ optarg = strtok(NULL,tokens);
+ }else { /*the next arg in cmd line is the param */
+ tmp_arg = argv[iArg+1];
+ if (*tmp_arg == '-') {
+
+ /*no param is found */
+ chOpt = '?';
+ if ((longopts[i].has_arg == required_argument) && opterr)
+ {
+ fprintf (stderr, "Option %s requires argument\n",tok);
+ }
+
+ }else
+ {
+ optarg = tmp_arg;
+ iArg++;
+ optind++;
+ }
+ }
+
+ }/*longopts */
+
+ iArg++;
+ optind++;
+ if (longopts[i].flag == 0)
+ return (longopts[i].val);
+ else return 0;
+
+ }/*end if strcmp */
+ }
+
+ return ('?');
+}
+
+/******************************************************************************/
+static char* get_char_option(const char* optstring,char*const* argv,int argc,
+ int iArg, int* opt_ind,char* opt_p)
+ {
+ char chOpt;
+ char* tmp_str;
+ char* prm = NULL;
+
+ chOpt = argv[iArg][1];
+
+
+ /*non valid argument*/
+ if (!isalpha(chOpt))
+ {
+ chOpt = EOF;
+ goto end;
+ }
+
+ tmp_str = strchr(optstring, chOpt);
+
+ /*the argument wasn't found in optstring */
+ if (tmp_str == NULL){
+ chOpt = EOF;
+ optopt = chOpt;
+ goto end;
+ }
+
+ /* don't need argument */
+ if (tmp_str[1]!= ':' ) {
+ goto end;
+ }
+
+ if (argv[iArg][2] != '\0')
+ {
+ // param is attached to option: -po8889
+ prm = &(argv[iArg][2]);
+ goto end;
+ }
+
+ // must look at next argv for param
+ /*at the end of arg list */
+ if ((iArg)+1 == argc) {
+ /* no param will be found */
+ if (tmp_str[2]== ':' ) {
+ /* optional argument ::*/
+ goto end;
+ }
+ else
+ {
+ chOpt = EOF;
+ goto end;
+ }
+ }
+
+ prm = &(argv[(iArg)+1][0]);
+ if (*prm == '-' )
+ {
+ // next argv is a new option, so param
+ // not given for current option
+ if (tmp_str[2]== ':' ) {
+ /* optional argument ::*/
+ goto end;
+ }
+ else
+ {
+ chOpt = EOF;
+ goto end;
+ }
+ }
+
+ // next argv is the param
+ (*opt_ind)++;
+
+
+end:
+ (*opt_ind)++;
+ *opt_p = chOpt;
+ return prm;
+}
+
+
+/******************************************************************************/
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\..\inc\openib.def\r
--- /dev/null
+TARGETNAME=opensm_3_0_0\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+SOURCES=\\r
+ osm.mc \\r
+ opensm.rc \\r
+ osm_files.c\\r
+ osm_drop_mgr.c\\r
+ osm_prtn_config.c\\r
+ osm_sa_mcmember_record.c\\r
+ osm_sa_path_record.c\\r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+ $(LIBPATH)\*\ibal.lib \\r
+ $(LIBPATH)\*\complib.lib \\r
+ $(TARGETPATH)\*\osmv_ibal_3_0_0.lib \\r
+ $(TARGETPATH)\*\opensm_ibal.lib\r
+\r
+!else\r
+ $(LIBPATH)\*\ibald.lib \\r
+ $(LIBPATH)\*\complibd.lib \\r
+ $(TARGETPATH)\*\osmv_ibal_3_0_0d.lib \\r
+ $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+ $(OSM_HOME)\include; \\r
+ $(OSM_HOME); \\r
+ $(WINIBHOME)\inc; \\r
+ $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+#MSC_OPTIMIZATION= /O0\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: cl_dispatcher.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of Dispatcher abstraction.
+ *
+ * Environment:
+ * All
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_timer.h>
+
+/* 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_thread_pool_construct( &p_disp->worker_threads );
+ 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. */
+ 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 );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: cl_event_wheel.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <math.h>
+#include <stdlib.h>
+#include <complib/cl_event_wheel.h>
+#include <complib/cl_debug.h>
+
+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;
+}
+
+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;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, __cl_event_wheel_callback);
+
+ /* might be during closing ... */
+ if (p_event_wheel->closing)
+ {
+ goto JustExit;
+ }
+
+ 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)/1000)+0.5);
+ osm_log (p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "__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)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "__cl_event_wheel_callback : ERR 6100: "
+ "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);
+ }
+ JustExit:
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+/*
+ * 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,
+ IN osm_log_t *p_log)
+{
+ cl_status_t cl_status = CL_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, cl_event_wheel_init );
+
+ /* initialize */
+ p_event_wheel->p_log = p_log;
+ 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)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_init : ERR 6101: "
+ "Failed to initialize cl_spinlock\n" );
+ goto Exit;
+ }
+ 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 */
+
+ if (cl_status != CL_SUCCESS)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_init : ERR 6102: "
+ "Failed to initialize cl_timer\n" );
+ goto Exit;
+ }
+ Exit:
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+ return(cl_status);
+}
+
+cl_status_t
+cl_event_wheel_init_ex(
+ IN cl_event_wheel_t* const p_event_wheel,
+ IN osm_log_t *p_log,
+ IN cl_spinlock_t *p_external_lock)
+{
+ cl_status_t cl_status;
+
+ cl_status = cl_event_wheel_init(p_event_wheel, p_log);
+ 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 *p_event;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_dump );
+
+ p_list_item = cl_qlist_head(&p_event_wheel->events_wheel);
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_dump: "
+ "event_wheel ptr:%p\n",
+ p_event_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);
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_dump: "
+ "Found event key:<0x%"PRIx64">, aging time:%" PRIu64"\n",
+ p_event->key, p_event->aging_time );
+ p_list_item = cl_qlist_next( p_list_item );
+ }
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+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;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_destroy );
+
+ /* 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);
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "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) );
+
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+}
+
+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;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_reg );
+
+ /* 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 ))
+ {
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "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++;
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "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 */
+ osm_log (p_event_wheel->p_log, OSM_LOG_INFO,
+ "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)
+ {
+ osm_log (p_event_wheel->p_log, OSM_LOG_ERROR,
+ "cl_event_wheel_reg : ERR 6103: "
+ "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 );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+
+ 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;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_unreg );
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "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) );
+
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_unreg: "
+ "Removed key:0x%"PRIx64"\n", key );
+
+ /* free the item */
+ free(p_event);
+ }
+ else
+ {
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "cl_event_wheel_unreg: "
+ "Did not find key:0x%"PRIx64"\n", key );
+ }
+
+ CL_SPINLOCK_RELEASE( &p_event_wheel->lock );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+
+}
+
+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;
+
+ OSM_LOG_ENTER( p_event_wheel->p_log, cl_event_wheel_num_regs );
+
+ /* try to find the key in the map */
+ osm_log( p_event_wheel->p_log, OSM_LOG_DEBUG,
+ "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 );
+ OSM_LOG_EXIT( p_event_wheel->p_log );
+ 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" Conetxt:%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" Conetxt:%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 */
+void __test_event_aging(uint64_t key, void *context)
+{
+ printf("*****************************************************\n");
+ printf("Aged key: 0x%"PRIx64" Conetxt:%s\n", key, (char *)context);
+}
+
+int
+main ()
+{
+ osm_log_t log;
+ cl_event_wheel_t event_wheel;
+ /* uint64_t key; */
+
+ /* construct */
+ osm_log_construct( &log );
+ cl_event_wheel_construct( &event_wheel );
+
+ /* init */
+ osm_log_init_v2( &log, TRUE, 0xff, NULL, 0, FALSE);
+ cl_event_wheel_init( &event_wheel, &log );
+
+ /* 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 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 1));
+ printf("Event 2 Registred: %u\n", cl_event_wheel_num_regs(&event_wheel, 2));
+
+ sleep(5);
+ /* destroy */
+ cl_event_wheel_destroy( &event_wheel );
+
+ return(0);
+}
+
+#endif /* __CL_EVENT_WHEEL_TEST__ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: main.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Command line interface for opensm.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.23 $
+ */
+#pragma warning(disable : 4996)
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include "stdio.h"
+#include <stdlib.h>
+#include <complib/cl_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_opensm.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_base.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 opensm object.
+ One opensm object is required per subnet.
+ Future versions could support multiple subnets by
+ instantiating more than one opensm object.
+*/
+osm_opensm_t osm;
+volatile unsigned int osm_exit_flag = 0;
+HANDLE osm_exit_event = NULL;
+
+#define GUID_ARRAY_SIZE 64
+#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
+
+typedef struct _osm_main_args_t
+{
+ int argc;
+ char** argv;
+ boolean_t is_service;
+} osm_main_args_t;
+
+osm_main_args_t osm_main_args;
+
+enum service_state {
+ SERVICE_STATE_STARTING,
+ SERVICE_STATE_STARTED_OK,
+ SERVICE_STATE_START_FAILED
+};
+
+enum service_state g_service_state = SERVICE_STATE_STARTING;
+
+void OsmReportState(IN const char *p_str)
+{
+ if ( !strcmp(p_str, "SUBNET UP\n") ||
+ !strcmp(p_str, "SM port is down\n") ||
+ !strcmp(p_str, "Errors during initialization\n") ||
+ !strcmp(p_str, "Entering STANDBY state\n") )
+ {
+ InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_STARTED_OK, SERVICE_STATE_STARTING);
+ return;
+ }
+
+ if ( !strcmp(p_str, "Found remote SM with non-matching sm_key. Exiting\n") ||
+ !strcmp(p_str, "Errors on subnet. Duplicate GUID found ""by link from a port to itself. ""See osm log for more details\n") ||
+ !strcmp(p_str, "Errors on subnet. SM found duplicated guids or 12x ""link with lane reversal badly configured. ""See osm log for more details\n") ||
+ !strcmp(p_str, "Fatal: Error restoring Guid-to-Lid persistent database\n") )
+
+ {
+ InterlockedCompareExchange((LONG *)&g_service_state , SERVICE_STATE_START_FAILED, SERVICE_STATE_STARTING);
+ return;
+ }
+
+ if( !strcmp(p_str, "OpenSM Rev:openib-1.2.0\n") ||
+ !strcmp(p_str, "OpenSM Rev:openib-2.0.3\n") ||
+ !strcmp(p_str, "OpenSM Rev:openib-3.0.0\n") ||
+ !strcmp(p_str, "Entering MASTER state\n") ||
+ !strcmp(p_str, "Exiting SM\n") )
+ {
+ // This are messages that it is safe to ignore
+ return;
+ }
+ CL_ASSERT(FALSE);
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage(void)
+{
+ printf( "\n------- OpenSM - Usage and options ----------------------\n" );
+ printf( "Usage: opensm [options]\n");
+ printf( "Options:\n" );
+ printf( "-c\n"
+ "--cache-options\n"
+ " Cache the given command line options into the file\n"
+ " /var/cache/osm/opensm.opts for use next invocation\n"
+ " The cache directory can be changed by the environment\n"
+ " variable OSM_CACHE_DIR\n\n");
+ printf( "-g[=]<GUID in hex>\n"
+ "--guid[=]<GUID in hex>\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( "-l <LMC>\n"
+ "--lmc <LMC>\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( "-p <PRIORITY>\n"
+ "--priority <PRIORITY>\n"
+ " This option specifies the SM's PRIORITY.\n"
+ " This will effect the handover cases, where master\n"
+ " is chosen by priority and GUID.\n\n" );
+ printf( "-smkey <SM_Key>\n"
+ " This option specifies the SM's SM_Key (64 bits).\n"
+ " This will effect SM authentication.\n\n" );
+ printf( "-r\n"
+ "--reassign_lids\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( "-R\n"
+ "--routing_engine <engine name>\n"
+ " This option chooses routing engine instead of Min Hop\n"
+ " algorithm (default). Supported engines: updn, file\n\n");
+ printf( "-U\n"
+ "--ucast_file <file name>\n"
+ " This option specifies name of the unicast dump file\n"
+ " from where switch forwarding tables will be loaded.\n\n");
+ printf ("-a\n"
+ "--add_guid_file <path to file>\n"
+ " Set the root nodes for the Up/Down routing algorithm\n"
+ " to the guids provided in the given file (one to a line)\n"
+ "\n");
+ printf( "-o\n"
+ "--once\n"
+ " This option causes OpenSM to configure the subnet\n"
+ " once, then exit. Ports remain in the ACTIVE state.\n\n" );
+ printf( "-s <interval>\n"
+ "--sweep <interval>\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( "-t <milliseconds>\n"
+ "--timeout <milliseconds>\n"
+ " This option specifies the time in milliseconds\n"
+ " used for transaction timeouts.\n"
+ " Specifying -t 0 disables timeouts.\n"
+ " Without -t, OpenSM defaults to a timeout value of\n"
+ " 200 milliseconds.\n\n" );
+ printf( "-maxsmps <number>\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( "-i <equalize-ignore-guids-file>\n"
+ "-ignore-guids <equalize-ignore-guids-file>\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( "-x\n"
+ "--honor_guid2lid\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( "-f\n"
+ "--log_file\n"
+ " This option defines the log to be the given file.\n"
+ " By default, the log goes to %temp%/log/osm.log.\n"
+ " For the log to go to standard output use -f stdout.\n\n");
+ printf( "-e\n"
+ "--erase_log_file\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( "-P\n"
+ "--Pconfig\n"
+ " This option defines the optional partition configuration file.\n"
+ " The default name is '%s'.\n\n", OSM_DEFAULT_PARTITION_CONFIG_FILE);
+ printf( "-Q\n"
+ "--no_qos\n"
+ " This option disables QoS setup.\n\n");
+ printf( "-N\n"
+ "--no_part_enforce\n"
+ " This option disables partition enforcement on switch external ports.\n\n");
+ printf( "-y\n"
+ "--stay_on_fatal\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( "-v\n"
+ "--verbose\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\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 <flags>\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( "-d <number>\n"
+ "--debug <number>\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( "-h\n"
+ "--help\n"
+ " Display this usage info then exit.\n\n" );
+ printf( "-?\n"
+ " Display this usage info then exit.\n\n" );
+ fflush( stdout );
+ osm_exit_flag = TRUE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu(void)
+{
+ printf("\n------- Interactive Menu -------\n");
+ printf("X - Exit.\n\n");
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+get_port_guid(
+ IN osm_opensm_t *p_osm, uint64_t port_guid,
+ IN boolean_t is_service)
+{
+ uint32_t i;
+ uint32_t choice = 0;
+ char junk[128];
+ boolean_t done_flag = FALSE;
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+ /*
+ 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 defined ( OSM_VENDOR_INTF_OPENIB )
+ /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
+ if ( port_guid == 0 )
+ {
+ printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+ return( attr_array[0].port_guid );
+ }
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and
+ use it as default port. */
+ if ( port_guid == 0 )
+ {
+ for ( i = 0; i < num_ports; i++ )
+ {
+ if (attr_array[i].link_state > IB_LINK_DOWN)
+ {
+ /* Use this port */
+ printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid));
+ return( attr_array[i].port_guid );
+ }
+ }
+ /* If we are running as a service, and all ports are doen we return the
+ first port (we can't open a window, as a service)*/
+ if (is_service) {
+ return( attr_array[0].port_guid );
+ }
+ }
+
+ /* More than one possible port - list all ports and let the user to choose. */
+ while( done_flag == FALSE )
+ {
+ printf( "\nChoose a local port number with which to bind:\n\n" );
+ /* If this is gen2 code - then port 0 has details of the default port used.
+ no need to print it.
+ If this is not gen2 code - need to print details of all ports. */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ for( i = 1; i < num_ports; i++ )
+ {
+ printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+ i, cl_ntoh64( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i-1 );
+# else
+ 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( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ fflush( stdout );
+ if (scanf( "%u", &choice ))
+ {
+ /* If gen2 code - choice can be between 1 to num_ports-1
+ if not gen2 code - choice can be between 1 to num_ports */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ if( choice >= num_ports )
+# else
+ if( choice > num_ports || choice < 1 )
+#endif /* OSM_VENDOR_INTF_OPENIB */
+ {
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ else
+ {
+ done_flag = TRUE;
+ }
+ }
+ else
+ {
+ /* get rid of the junk in the selection line */
+ scanf( "%s", junk );
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ }
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));
+ return( attr_array[choice].port_guid );
+# else
+ return( attr_array[choice - 1].port_guid );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+}
+
+/**********************************************************************
+ **********************************************************************/
+#define OSM_MAX_IGNORE_GUID_LINES_LEN 128
+int
+parse_ignore_guids_file(IN char *guids_file_name,
+ IN osm_opensm_t *p_osm)
+{
+ FILE *fh;
+ char line[OSM_MAX_IGNORE_GUID_LINES_LEN];
+ char *p_c, *p_ec;
+ uint32_t line_num = 0;
+ uint64_t port_guid;
+ ib_api_status_t status = IB_SUCCESS;
+ unsigned int port_num;
+
+ OSM_LOG_ENTER( &p_osm->log, parse_ignore_guids_file );
+
+ fh = fopen( guids_file_name, "r" );
+ if( fh == NULL )
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0601: "
+ "Unable to open ignore guids file (%s)\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ * Parse the file and add to the ignore guids map.
+ */
+ while( fgets( line, OSM_MAX_IGNORE_GUID_LINES_LEN, fh ) != NULL )
+ {
+ line_num++;
+ p_c = line;
+ while ( (*p_c == ' ') && (*p_c != '\0')) p_c++ ;
+ port_guid = cl_hton64( strtoull( p_c, &p_ec, 16 ) );
+ if (p_ec == p_c)
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0602: "
+ "Error in line (%u): %s\n" ,
+ line_num, line
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ while ( (*p_ec == ' ') && (*p_ec != '\0')) p_ec++ ;
+ if (! sscanf(p_ec, "%d", &port_num))
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0603: "
+ "Error in line (%u): %s\n" ,
+ line_num, p_ec
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ /* Make sure the port_num isn't greater than 256 */
+ if (port_num > 256)
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "parse_ignore_guids_file: ERR 0604: "
+ "Error in line (%u): %s. "
+ "port number is greater than 256 (%d) \n",
+ line_num, p_ec, port_num
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ /* ok insert it */
+ osm_port_prof_set_ignored_port(&p_osm->subn, port_guid, (uint8_t)port_num);
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "parse_ignore_guids_file: "
+ "Inserted Port: 0x%" PRIx64 " into ignored guids list\n" ,
+ port_guid
+ );
+
+ }
+
+ fclose( fh );
+
+ Exit:
+ OSM_LOG_EXIT( &p_osm->log );
+ return ( status );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+int
+opensm_main(
+ void *osm_main_args)
+{
+ int argc = ((osm_main_args_t*)osm_main_args)->argc;
+ char** argv = ((osm_main_args_t*)osm_main_args)->argv;
+ osm_subn_opt_t opt;
+ ib_net64_t sm_key = 0;
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_DEFAULT_LEVEL;
+ int long temp;
+ uint32_t dbg_lvl;
+ boolean_t run_once_flag = FALSE;
+ boolean_t mem_track = FALSE;
+ uint32_t next_option;
+ uint32_t exitTimeout;
+ boolean_t cache_options = FALSE;
+ char *ignore_guids_file_name = NULL;
+ uint32_t val;
+ const char * const short_option = "i:f:ed:g:l:L:s:t:a:R:U:P:NQvVhorcyx";
+
+
+ /*
+ 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[] =
+ {
+ { "service", 0, NULL, 'Z'},
+ { "debug", 1, NULL, 'd'},
+ { "guid", 1, NULL, 'g'},
+ { "ignore_guids", 1, NULL, 'i'},
+ { "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'},
+ { "no_qos", 0, NULL, 'Q'},
+ { "maxsmps", 1, NULL, 'n'},
+ { "console", 0, 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_file" ,1, NULL, 'U'},
+ { "add_guid_file", 1, NULL, 'a'},
+ { "cache-options", 0, NULL, 'c'},
+ { "stay_on_fatal", 0, NULL, 'y'},
+ { "honor_guid2lid", 0, NULL, 'x'},
+ { NULL, 0, NULL, 0 } /* Required at the end of the array */
+ };
+ printf("-------------------------------------------------\n");
+ printf("%s\n", OSM_VERSION);
+
+ osm_subn_set_default_opt(&opt);
+ osm_subn_parse_conf_file(&opt);
+
+ printf("Command Line Arguments:\n");
+ do
+ {
+ next_option = getopt_long_only(argc, argv, short_option,
+ long_option, NULL);
+ switch(next_option)
+ {
+ case 'Z':
+ /*
+ service option - nothing to do
+ */
+ 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.
+ */
+ ignore_guids_file_name = optarg;
+ printf(" Ignore Guids File = %s\n", ignore_guids_file_name);
+ 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':
+ opt.transaction_timeout = strtol(optarg, NULL, 0);
+ printf(" Transaction timeout = %d\n", opt.transaction_timeout);
+ break;
+
+ case 'n':
+ opt.max_wire_smps = strtol(optarg, NULL, 0);
+ if( opt.max_wire_smps <= 0 )
+ opt.max_wire_smps = 0x7FFFFFFF;
+ printf(" Max wire smp's = %d\n", opt.max_wire_smps);
+ break;
+
+ case 'q':
+ /*
+ * OpenSM interactive console
+ */
+ opt.console = TRUE;
+ printf(" Enabling OpenSM interactive console\n");
+ break;
+
+ 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 >= 10)
+ {
+ /* Please look at osm_subnet.h for list of testability modes. */
+ opt.testability_mode = dbg_lvl - 9;
+ }
+ else
+ printf( " OpenSM: Unknown debug option %d ignored\n",
+ dbg_lvl );
+ break;
+
+ case 'l':
+ temp = strtol(optarg, NULL, 0);
+ if( temp > 7 )
+ {
+ fprintf(stderr, "ERROR: LMC must be 7 or less.");
+ return( -1 );
+ }
+ opt.lmc = (uint8_t)temp;
+ printf(" LMC = %d\n", temp);
+ break;
+
+ case 'D':
+ log_flags = strtol(optarg, NULL, 0);
+ printf(" verbose option -D = 0x%x\n", log_flags);
+ break;
+
+ case 'f':
+ if (!strcmp(optarg, "stdout"))
+ /* output should be to standard output */
+ opt.log_file = NULL;
+ else
+ opt.log_file = optarg;
+ break;
+
+ case 'L':
+ opt.log_max_size = strtoul(optarg, NULL, 0) * (1024*1024);
+ printf(" Log file max size is %lu bytes\n", opt.log_max_size);
+ break;
+
+ case 'e':
+ opt.accum_log_file = FALSE;
+ printf(" Creating new log file\n");
+ break;
+
+ case 'P':
+ opt.partition_config_file = optarg;
+ break;
+
+ case 'N':
+ opt.no_partition_enforcement = TRUE;
+ break;
+
+ case 'Q':
+ opt.no_qos = TRUE;
+ break;
+
+ case 'y':
+ opt.exit_on_fatal = FALSE;
+ printf(" Staying on fatal initialization errors\n");
+ break;
+
+ case 'v':
+ log_flags = (log_flags <<1 )|1;
+ printf(" Verbose option -v (log flags = 0x%X)\n", log_flags );
+ break;
+
+ case 'V':
+ log_flags = 0xFFFFFFFF;
+ opt.force_log_flush = TRUE;
+ printf(" Big V selected\n");
+ break;
+
+ case 'p':
+ temp = strtol(optarg, NULL, 0);
+ if (0 > temp || 15 < temp) {
+ 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':
+ opt.routing_engine_name = optarg;
+ printf(" Activate \'%s\' routing engine\n", optarg);
+ break;
+
+ case 'U':
+ opt.ucast_dump_file = optarg;
+ printf(" Ucast dump file is \'%s\'\n", optarg);
+ break;
+
+ case 'a':
+ /*
+ Specifies port guids file
+ */
+ opt.updn_guid_file = optarg;
+ printf (" UPDN Guid File: %s\n", opt.updn_guid_file );
+ break;
+
+ case 'c':
+ cache_options = TRUE;
+ printf (" Caching command line options\n");
+ break;
+
+ case 'x':
+ opt.honor_guid2lid_file = TRUE;
+ printf (" Honor guid2lid file, if possible\n");
+ break;
+
+ case 'h':
+ case '?':
+ case ':':
+ show_usage();
+ return 0;
+ 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");
+
+ opt.log_flags = (uint8_t)log_flags;
+
+ status = osm_opensm_init( &osm, &opt );
+ if( status != IB_SUCCESS )
+ {
+ char buffer[LOG_ENTRY_SIZE_MAX];
+ 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);
+ sprintf(buffer, "Error from osm_opensm_init: %s. See opensm log file for more details", err_str);
+ /* We will just exit, and not go to Exit, since we don't
+ want the destroy to be called. */
+ cl_log_event("OpenSM", LOG_ERR, buffer , NULL, 0);
+ g_service_state = SERVICE_STATE_START_FAILED;
+ 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, ((osm_main_args_t*)osm_main_args)->is_service );
+
+ if ( opt.guid == 0 )
+ {
+ printf( "Error: Could not get port guid \n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if ( cache_options == TRUE )
+ osm_subn_write_conf_file( &opt );
+
+ status = osm_opensm_bind( &osm, opt.guid );
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from osm_opensm_bind (0x%X)\n", status );
+ goto Exit;
+ }
+
+ /*
+ * Define some port guids to ignore during path equalization
+ */
+ if (ignore_guids_file_name != NULL)
+ {
+ status = parse_ignore_guids_file(ignore_guids_file_name, &osm);
+ if( status != IB_SUCCESS )
+ {
+ printf( "\nError from parse_ignore_guids_file (0x%X)\n", status );
+ goto Exit;
+ }
+ }
+
+ osm_opensm_sweep( &osm );
+
+ status = osm_opensm_wait_for_subnet_up(
+ &osm, EVENT_NO_TIMEOUT, TRUE );
+
+ if( status != CL_SUCCESS )
+ {
+ printf( "\nError from osm_opensm_wait_for_subnet_up (0x%X)\n", status );
+ goto Exit;
+ }
+
+ if( run_once_flag == FALSE )
+ {
+ /*
+ Sit here forever
+ In the future, some sort of console interactivity could
+ be implemented in this loop.
+ */
+ WaitForSingleObject(osm_exit_event, INFINITE);
+ osm_exit_flag = TRUE;
+ }
+
+ /* wait for all transactions to end */
+ CL_ASSERT( ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0) < 0x100000000ULL );
+ exitTimeout =
+ (uint32_t) ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0);
+
+ if (exitTimeout < 3) exitTimeout = 3;
+
+ /*
+ printf( "\n------- OpenSM Exiting (in %u seconds) -------\n",
+ exitTimeout);
+ sleep(exitTimeout);
+ */
+
+ 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);
+
+ Exit:
+ g_service_state = SERVICE_STATE_START_FAILED;
+ osm_opensm_destroy( &osm );
+
+ exit( 0 );
+}
+
+SERVICE_STATUS OsmServiceStatus;
+SERVICE_STATUS_HANDLE OsmServiceStatusHandle;
+
+VOID SvcDebugOut(LPSTR String, DWORD Status);
+VOID WINAPI OsmServiceCtrlHandler (DWORD opcode);
+__stdcall OsmServiceStart (DWORD argc, LPTSTR *argv);
+
+DWORD OsmServiceInitialization (DWORD argc, LPTSTR *argv,
+ DWORD *specificError);
+
+int __cdecl
+main (
+ int argc,
+ char* argv[] )
+{
+ int i;
+ boolean_t run_as_service = FALSE;
+ osm_main_args.argc = argc;
+ osm_main_args.argv = argv;
+ /* If there are arguments that the executable is ran with, then this is
+ not running as service - just run the opensm_main. */
+ for (i = 0 ; i< argc ; i++)
+ if (!strcmp(argv[i], "--service"))
+ {
+ run_as_service = TRUE;
+ osm_main_args.is_service = TRUE;
+ break;
+ }
+ osm_exit_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if(osm_exit_event == NULL)
+ {
+ printf( "\nCreateEvent failed gle=%d\n", GetLastError());
+ return( 1 );
+ }
+
+ if (!run_as_service)
+ {
+ /* Running as executable */
+ osm_main_args.is_service = FALSE;
+ return opensm_main(&osm_main_args);
+ }
+ else
+ {
+ /* Running as service */
+ SERVICE_TABLE_ENTRY DispatchTable[] =
+ {
+ { "OsmService", OsmServiceStart },
+ { NULL, NULL }
+ };
+ // Give older versions of opensm a chance to stop
+ Sleep(3000);
+
+ if (!StartServiceCtrlDispatcher( DispatchTable))
+ {
+ SvcDebugOut(" [OSM_SERVICE] StartServiceCtrlDispatcher (%d)\n",
+ GetLastError());
+ }
+ }
+}
+
+VOID SvcDebugOut(LPSTR String, DWORD Status)
+{
+ CHAR Buffer[1024];
+ if (strlen(String) < 1000)
+ {
+ sprintf(Buffer, String, Status);
+ OutputDebugStringA(Buffer);
+ }
+}
+
+VOID WINAPI OsmServiceCtrlHandler (DWORD Opcode)
+{
+ DWORD status;
+
+ switch(Opcode)
+ {
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ // Do whatever it takes to stop here.
+ osm_exit_flag = TRUE;
+ SetEvent(osm_exit_event);
+ OsmServiceStatus.dwWin32ExitCode = 0;
+ OsmServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ OsmServiceStatus.dwCheckPoint = 0;
+ OsmServiceStatus.dwWaitHint = 0;
+
+ if (!SetServiceStatus (OsmServiceStatusHandle,
+ &OsmServiceStatus))
+ {
+ status = GetLastError();
+ SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",
+ status);
+ }
+
+ SvcDebugOut(" [OSM_SERVICE] Leaving OsmService \n",0);
+ return;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ // Fall through to send current status.
+ break;
+
+ default:
+ SvcDebugOut(" [OSM_SERVICE] Unrecognized opcode %ld\n",
+ Opcode);
+ }
+
+ // Send current status.
+ if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus))
+ {
+ status = GetLastError();
+ SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",
+ status);
+ }
+ return;
+}
+
+__stdcall OsmServiceStart (DWORD argc, LPTSTR *argv)
+{
+ DWORD status;
+ DWORD specificError;
+
+ OsmServiceStatus.dwServiceType = SERVICE_WIN32;
+ OsmServiceStatus.dwCurrentState = SERVICE_START_PENDING;
+ OsmServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+ SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
+ OsmServiceStatus.dwWin32ExitCode = 0;
+ OsmServiceStatus.dwServiceSpecificExitCode = 0;
+ OsmServiceStatus.dwCheckPoint = 0;
+ OsmServiceStatus.dwWaitHint = 2000;
+
+ OsmServiceStatusHandle = RegisterServiceCtrlHandler(
+ "OsmService",
+ OsmServiceCtrlHandler);
+
+ if (OsmServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
+ {
+ SvcDebugOut(" [OSM_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
+ return 0;
+ }
+
+ // Initialization code goes here.
+ status = OsmServiceInitialization(argc,argv, &specificError);
+ while (status == NO_ERROR && g_service_state == SERVICE_STATE_STARTING)
+ {
+ Sleep(1000);
+ OsmServiceStatus.dwCheckPoint++;
+ if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus))
+ {
+ status = GetLastError();
+ SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status);
+ }
+
+ }
+ CL_ASSERT(g_service_state == SERVICE_STATE_STARTED_OK ||
+ g_service_state == SERVICE_STATE_START_FAILED ||
+ status != NO_ERROR);
+
+ // Handle error condition
+ if (status != NO_ERROR || g_service_state == SERVICE_STATE_START_FAILED)
+ {
+ OsmServiceStatus.dwCurrentState = SERVICE_STOPPED;
+ OsmServiceStatus.dwCheckPoint = 0;
+ OsmServiceStatus.dwWaitHint = 0;
+ OsmServiceStatus.dwWin32ExitCode = status;
+ OsmServiceStatus.dwServiceSpecificExitCode = specificError;
+
+ SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus);
+ return 0;
+ }
+
+ // Initialization complete - report running status.
+ OsmServiceStatus.dwCurrentState = SERVICE_RUNNING;
+ OsmServiceStatus.dwCheckPoint = 0;
+ OsmServiceStatus.dwWaitHint = 0;
+
+ if (!SetServiceStatus (OsmServiceStatusHandle, &OsmServiceStatus))
+ {
+ status = GetLastError();
+ SvcDebugOut(" [OSM_SERVICE] SetServiceStatus error %ld\n",status);
+ }
+
+ // This is where the service does its work.
+ SvcDebugOut(" [OSM_SERVICE] Returning the Main Thread \n",0);
+
+ return 1;
+}
+
+// Stub initialization function.
+DWORD OsmServiceInitialization(DWORD argc, LPTSTR *argv,
+ DWORD *specificError)
+{
+ if (CreateThread(NULL, 0, opensm_main, &osm_main_args, 0, NULL) == NULL)
+ {
+ SvcDebugOut(" [OSM_SERVICE] failed to create thread (%d)\n",
+ GetLastError());
+ return(1);
+ }
+ return(0);
+}
--- /dev/null
+#\r
+# DEVICE ATTRIBUTES OPTIONS\r
+#\r
+# The port GUID on which the OpenSM is running.\r
+#guid <PORT GUID>\r
+\r
+# M_Key value sent to all ports qualifing all Set(PortInfo).\r
+#m_key 0x0000000000000000\r
+\r
+# The lease period used for the M_Key on this subnet in [msec]\r
+#m_key_lease_period 0\r
+\r
+# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\r
+#sm_key 0x0100000000000000\r
+\r
+# Subnet prefix used on this subnet\r
+#subnet_prefix 0xfe80000000000000\r
+\r
+# The LMC value used on this subnet\r
+#lmc 0\r
+\r
+# The code of maximal time a packet can live in a switch\r
+# The actual time is 4.096usec * 2^<packet_life_time code>\r
+# The value 0x14 disables this mechanism\r
+#packet_life_time 0x12\r
+\r
+# The code of maximal time a packet can wait at the head of\r
+# transmission queue. \r
+# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\r
+# The value 0x14 disables this mechanism\r
+#head_of_queue_lifetime 0x12\r
+\r
+# The maximal time a packet can wait at the head of queue on \r
+# switch port connected to a HCA\r
+#leaf_head_of_queue_lifetime 0x0c\r
+\r
+# Limit the maximal operational VLs\r
+#max_op_vls 5\r
+\r
+# The subnet_timeout code that will be set for all the ports\r
+# The actual timeout is 4.096usec * 2^<subnet_timeout code>\r
+#subnet_timeout 18\r
+\r
+# Threshold of local phy errors for sending Trap 129\r
+#local_phy_errors_threshold 0x08\r
+\r
+# Threshold of credits over-run errors for sending Trap 129\r
+#overrun_errors_threshold 0x08\r
+\r
+#\r
+# SWEEP OPTIONS\r
+#\r
+# The number of seconds between subnet sweeps (0 disables it)\r
+#sweep_interval 10\r
+\r
+# If TRUE cause all lids to be re-assigned\r
+#reassign_lids FALSE\r
+\r
+# If TRUE ignore existing LFT entries on first sweep (default).\r
+# Otherwise only non minimal hop cases are modified.\r
+# NOTE: A standby SM clears its first sweep flag - since the\r
+# master SM already sweeps...\r
+#reassign_lfts TRUE\r
+\r
+# If true forces every sweep to be a heavy sweep\r
+#force_heavy_sweep FALSE\r
+\r
+# If true every trap will cause a heavy sweep.\r
+# NOTE: successive same traps (>10) are supressed\r
+#sweep_on_trap TRUE\r
+\r
+#\r
+# ROUTING OPTIONS\r
+#\r
+# If true do not count switches as link subscriptions\r
+#port_profile_switch_nodes FALSE\r
+\r
+# Activate the Up/Down routing algorithm\r
+#updn_activate FALSE\r
+\r
+#\r
+# HANDOVER - MULTIPLE SM's OPTIONS\r
+#\r
+# SM priority used for deciding who is the master\r
+#sm_priority 1\r
+\r
+# If TRUE other SM's on the subnet should be ignored\r
+#ignore_other_sm FALSE\r
+\r
+# Timeout in [sec] between two polls of active master SM\r
+#sminfo_polling_timeout 10000\r
+\r
+# Number of failing polls of remote SM that declares it dead\r
+#polling_retry_number 4\r
+\r
+#\r
+# TIMING AND THREADING OPTIONS\r
+#\r
+# Number of MADs sent in parallel\r
+#max_wire_smps 4\r
+\r
+# The time taken to a transaction to finish in [msec]\r
+#transaction_timeout 200\r
+\r
+# Maximal time in [msec] a message can stay in the incoming message queue.\r
+# If there is more then one message in the queue and the last message\r
+# stayed in the queue more then this value any SA request will be \r
+# immediately returned with a BUSY status.\r
+#max_msg_fifo_timeout 10000\r
+\r
+# Use a single thread for handling SA queries\r
+#single_thread FALSE\r
+\r
+#\r
+# DEBUG FEATURES\r
+#\r
+# The log flags used\r
+#log_flags 0x03\r
+\r
+# Force flush of the log file after each log message\r
+#force_log_flush TRUE\r
+\r
+# Log file to be used\r
+#log_file <LOG_FILE>\r
+\r
+#accum_log_file TRUE\r
+\r
+# The directory to hold the file OpenSM dumps\r
+#dump_files_dir <DUMP_FILES_DIR>\r
+\r
+# If TRUE if OpenSM should disable multicast support\r
+#no_multicast_option FALSE\r
+\r
+# No multicast routing is performed if TRUE\r
+#disable_multicast FALSE\r
+\r
+# If TRUE opensm will exit on fatal initialization issues\r
+#exit_on_fatal TRUE\r
+\r
--- /dev/null
+/*\r
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: opensm.rc 2624 2009-12-07 18:06:48Z stansmith $\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE VFT_APP\r
+#define VER_FILESUBTYPE VFT2_UNKNOWN\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR "Debug OpenSM Subnet Manager (3.0.0)"\r
+#define VER_INTERNALNAME_STR "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR "opensm.exe"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR "OpenSM Subnet Manager (3.0.0)"\r
+#define VER_INTERNALNAME_STR "opensm.exe"\r
+#define VER_ORIGINALFILENAME_STR "opensm.exe"\r
+#endif\r
+#include <common.ver>\r
--- /dev/null
+;/*++
+;=============================================================================
+;Copyright (c) 2005 Mellanox Technologies
+;
+;Module Name:
+;
+; osm.mc
+;
+;Abstract:
+;
+; OpenSM event log messages
+;
+;Authors:
+;
+; Leonid Keller
+;
+;Environment:
+;
+; Kernel Mode .
+;
+;=============================================================================
+;--*/
+;
+
+MessageId=0x0000 SymbolicName=EVENT_OSM_ANY_INFO
+Language=English
+%1
+.
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_console.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE /* for getline */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include <opensm/osm_console.h>
+
+#define OSM_COMMAND_LINE_LEN 120
+#define OSM_COMMAND_PROMPT "$ "
+
+struct command {
+ char *name;
+ void (*help_function)(void);
+ void (*parse_function)(char **p_last, osm_opensm_t *p_osm);
+};
+
+static const struct command console_cmds[];
+
+static inline char *next_token(char **p_last)
+{
+ return strtok_r(NULL, " \t\n", p_last);
+}
+
+static void help_command()
+{
+ int i;
+
+ printf("Supported commands and syntax:\n");
+ printf("help [<command>]\n");
+ /* skip help command */
+ for (i = 1; console_cmds[i].name; i++)
+ console_cmds[i].help_function();
+}
+
+static void help_loglevel()
+{
+ printf("loglevel [<log-level>]\n");
+}
+
+static void help_priority()
+{
+ printf("priority [<sm-priority>]\n");
+}
+
+/* more help routines go here */
+
+static void help_parse(char **p_last, osm_opensm_t *p_osm)
+{
+ char *p_cmd;
+ int i, found = 0;
+
+ p_cmd = next_token(p_last);
+ if (!p_cmd)
+ help_command();
+ else {
+ for (i = 1; console_cmds[i].name; i++) {
+ if (!strcmp(p_cmd, console_cmds[i].name)) {
+ found = 1;
+ console_cmds[i].help_function();
+ break;
+ }
+ }
+ if (!found) {
+ printf("Command %s not found\n\n", p_cmd);
+ help_command();
+ }
+ }
+}
+
+static void loglevel_parse(char **p_last, osm_opensm_t *p_osm)
+{
+ char *p_cmd;
+ int level;
+
+ p_cmd = next_token(p_last);
+ if (!p_cmd)
+ printf("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)) {
+ printf("Setting log level to 0x%x\n", level);
+ osm_log_set_level(&p_osm->log, level);
+ } else
+ printf("Invalid log level 0x%x\n", level);
+ }
+}
+
+static void priority_parse(char **p_last, osm_opensm_t *p_osm)
+{
+ char *p_cmd;
+ int priority;
+
+ p_cmd = next_token(p_last);
+ if (!p_cmd)
+ printf("Current sm-priority is %d\n", p_osm->subn.opt.sm_priority);
+ else {
+ priority = strtol(p_cmd, NULL, 0);
+ if (0 > priority || 15 < priority)
+ printf("Invalid sm-priority %d; must be between 0 and 15\n", priority);
+ else {
+ printf("Setting sm-priority to %d\n", priority);
+ p_osm->subn.opt.sm_priority = (uint8_t)priority;
+ /* Does the SM state machine need a kick now ? */
+ }
+ }
+}
+
+/* more parse routines go here */
+
+static const struct command console_cmds[] =
+{
+ { "help", &help_command, &help_parse},
+ { "loglevel", &help_loglevel, &loglevel_parse},
+ { "priority", &help_priority, &priority_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;
+
+ /* find first token which is the command */
+ p_cmd = strtok_r(line, " \t\n", &p_last);
+ if (p_cmd) {
+ for (i = 0; console_cmds[i].name; i++) {
+ if (!strcmp(p_cmd, console_cmds[i].name)) {
+ found = 1;
+ console_cmds[i].parse_function(&p_last, p_osm);
+ break;
+ }
+ }
+ if (!found) {
+ printf("Command %s not found\n\n", p_cmd);
+ help_command();
+ }
+ } else {
+ printf("Error parsing command line: %s\n", line);
+ return;
+ }
+}
+
+void osm_console_prompt(void)
+{
+ printf("%s", OSM_COMMAND_PROMPT);
+ fflush(stdout);
+}
+
+void osm_console(osm_opensm_t *p_osm)
+{
+ struct pollfd pollfd;
+ char *p_line;
+ size_t len;
+ ssize_t n;
+
+ pollfd.fd = 0;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+
+ if (poll(&pollfd, 1, 10000) <= 0)
+ return;
+
+ if (pollfd.revents|POLLIN) {
+ p_line = NULL;
+ /* Get input line */
+ n = getline(&p_line, &len, stdin);
+ if (n > 0) {
+ /* Parse and act on input */
+ parse_cmd_line(p_line, p_osm);
+ free(p_line);
+ } else {
+ printf("Input error\n");
+ fflush(stdin);
+ }
+ osm_console_prompt();
+ }
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_db_files.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implemntation of the osm_db interface using simple text files
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/st.h>
+#include <opensm/osm_db.h>
+
+/****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;
+} 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 {
+ 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* const 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* const 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* const 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* const p_db,
+ IN osm_log_t *p_log )
+{
+ osm_db_imp_t *p_db_imp;
+ struct stat dstat;
+
+ OSM_LOG_ENTER( p_log, osm_db_init );
+
+ p_db_imp = (osm_db_imp_t *)malloc(sizeof(osm_db_imp_t));
+ CL_ASSERT( p_db_imp != NULL);
+
+ 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__
+ /* Check if the directory exists. If not - create it. */
+ CreateDirectory(p_db_imp->db_dir_name, NULL);
+#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))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_init: ERR 6101: "
+ " Failed to create the db directory:%s\n",
+ p_db_imp->db_dir_name);
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ }
+#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;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+osm_db_domain_t*
+osm_db_domain_init(
+ IN osm_db_t* const p_db,
+ IN char *domain_name)
+{
+ osm_db_domain_t *p_domain;
+ osm_db_domain_imp_t *p_domain_imp;
+ int dir_name_len;
+ osm_log_t *p_log = p_db->p_log;
+ FILE *p_file;
+
+ OSM_LOG_ENTER( p_log, osm_db_domain_init );
+
+ /* allocate a new domain object */
+ p_domain = (osm_db_domain_t *)malloc(sizeof(osm_db_domain_t));
+ CL_ASSERT( p_domain != NULL );
+
+ p_domain_imp =
+ (osm_db_domain_imp_t *)malloc(sizeof(osm_db_domain_imp_t));
+ CL_ASSERT( p_domain_imp != NULL );
+
+ dir_name_len = strlen(((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+
+ /* set the domain file name */
+ p_domain_imp->file_name =
+ (char *)malloc(sizeof(char)*(dir_name_len) + strlen(domain_name) + 2);
+ CL_ASSERT(p_domain_imp->file_name != NULL);
+ strcpy(p_domain_imp->file_name,((osm_db_imp_t*)p_db->p_db_imp)->db_dir_name);
+ strcat(p_domain_imp->file_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,
+ "osm_db_domain_init: 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->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, *p_accum_val = NULL;
+ unsigned int line_num;
+
+ OSM_LOG_ENTER( p_log, osm_db_restore );
+
+ /* 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,
+ "osm_db_restore: 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,
+ "osm_db_restore: 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,
+ "osm_db_restore: 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 = (char *)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 =
+ (char*)malloc(sizeof(char)*(strlen(p_rest_of_line) + 1));
+ strcpy(p_accum_val, p_rest_of_line);
+ }
+ else
+ {
+ p_accum_val = (char*)malloc(2);
+ strcpy(p_accum_val, "\0");
+ }
+ }
+ else if (sLine[0] != '\n')
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: 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,
+ (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_restore: ERR 6106: "
+ " Key:%s already exists in:%s with value:%s."
+ " Removing it\n",
+ p_key,
+ p_domain_imp->file_name,
+ p_prev_val);
+ }
+ else
+ {
+ p_prev_val = NULL;
+ }
+
+ /* store our key and value */
+ st_insert(p_domain_imp->p_hash,
+ (st_data_t)p_key, (st_data_t)p_accum_val);
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_restore: "
+ "Got key:%s value:%s\n", p_key, p_accum_val);
+ }
+ else
+ {
+ /* accumulate into the value */
+ p_prev_val = p_accum_val;
+ p_accum_val =
+ (char *)malloc(strlen(p_prev_val) + strlen(sLine) + 1);
+ strcpy(p_accum_val, p_prev_val);
+ free(p_prev_val);
+ 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;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_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)
+{
+ osm_log_t *p_log = p_domain->p_db->p_log;
+ osm_db_domain_imp_t *p_domain_imp;
+ FILE *p_file;
+ int status = 0;
+ char *p_tmp_file_name;
+
+ OSM_LOG_ENTER( p_log, osm_db_store );
+
+ p_domain_imp = (osm_db_domain_imp_t *)p_domain->p_domain_imp;
+ p_tmp_file_name =
+ (char *)malloc(sizeof(char)*(strlen(p_domain_imp->file_name)+8));
+ strcpy(p_tmp_file_name, p_domain_imp->file_name);
+ strcat(p_tmp_file_name,".tmp");
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+
+ /* open up the output file */
+ p_file = fopen(p_tmp_file_name, "w");
+ if (! p_file)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6107: "
+ " Failed to open the db file:%s for writing\n",
+ p_domain_imp->file_name);
+ status = 1;
+ goto Exit;
+ }
+
+ st_foreach(p_domain_imp->p_hash, __osm_dump_tbl_entry, (st_data_t)p_file);
+ fclose(p_file);
+
+ /* move the domain file */
+ status = remove(p_domain_imp->file_name);
+ if (status)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6109: "
+ " Failed to remove file:%s (err:%u)\n",
+ p_domain_imp->file_name, status);
+ }
+
+ status = rename(p_tmp_file_name, p_domain_imp->file_name);
+ if (status)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_store: ERR 6108: "
+ " Failed to rename the db file to:%s (err:%u)\n",
+ p_domain_imp->file_name, status);
+ }
+ Exit:
+ cl_spinlock_release( &p_domain_imp->lock );
+ free(p_tmp_file_name);
+ 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 */
+int
+__osm_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, __osm_clear_tbl_entry, (st_data_t)NULL);
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+__osm_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,
+ __osm_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 *const 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, (st_data_t*)&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 *const p_key,
+ IN char *const 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, (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_update: "
+ " 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;
+ }
+ 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);
+
+ cl_spinlock_release( &p_domain_imp->lock );
+
+ return 0;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+int
+osm_db_delete(
+ IN osm_db_domain_t *p_domain,
+ IN char *const 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, osm_db_delete );
+
+ cl_spinlock_acquire( &p_domain_imp->lock );
+ if (st_delete(p_domain_imp->p_hash,
+ (st_data_t*)&p_key, (st_data_t*)&p_prev_val))
+ {
+ if (st_lookup(p_domain_imp->p_hash,
+ (st_data_t)p_key, (st_data_t*)&p_prev_val))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_db_delete: "
+ " 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);
+ res = 0;
+ }
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_db_update: "
+ " 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 <stdlib.h>
+#include <math.h>
+
+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 (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))
+ printf("failed to store\n");
+
+ osm_db_destroy( &db );
+ cl_list_destroy( &keys );
+}
+#endif
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_db_pack.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_db_pack.h>
+
+static inline void
+__osm_pack_guid(uint64_t guid, char *p_guid_str)
+{
+ sprintf(p_guid_str, "0x%016" PRIx64, guid);
+}
+
+static inline uint64_t
+__osm_unpack_guid(char *p_guid_str)
+{
+#if __WORDSIZE == 64
+ return (strtoul(p_guid_str, NULL, 0));
+#else
+ return (strtoull(p_guid_str, NULL, 0));
+#endif
+}
+
+static inline void
+__osm_pack_lids(uint16_t min_lid, uint16_t max_lid, char *p_lid_str)
+{
+ sprintf(p_lid_str, "0x%04x 0x%04x", min_lid, max_lid);
+}
+
+static inline int
+__osm_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);
+ CL_ASSERT( tmp < 0x10000 );
+ *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);
+ CL_ASSERT( tmp < 0x10000 );
+ *p_max_lid = (uint16_t)tmp;
+
+ return 0;
+}
+
+int
+osm_db_guid2lid_guids(
+ IN osm_db_domain_t* const 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 = __osm_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* const 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;
+
+ __osm_pack_guid(guid, guid_str);
+ p_lid_str = osm_db_lookup(p_g2l, guid_str);
+ if (! p_lid_str)
+ return 1;
+ if (__osm_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* const p_g2l,
+ IN uint64_t guid,
+ IN uint16_t min_lid,
+ IN uint16_t max_lid)
+{
+ char guid_str[20];
+ char lid_str[16];
+
+ __osm_pack_guid(guid, guid_str);
+ __osm_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* const p_g2l,
+ IN uint64_t guid )
+{
+ char guid_str[20];
+ __osm_pack_guid(guid, guid_str);
+ return( osm_db_delete( p_g2l, guid_str) );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_drop_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_drop_mgr_t.
+ * This object represents the Drop Manager object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_ptr_vector.h>
+#include <opensm/osm_drop_mgr.h>
+#include <opensm/osm_router.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_construct(
+ IN osm_drop_mgr_t* const p_mgr )
+{
+ CL_ASSERT( p_mgr );
+ memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_destroy(
+ IN osm_drop_mgr_t* const p_mgr )
+{
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_destroy );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_drop_mgr_init(
+ IN osm_drop_mgr_t* const p_mgr,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_drop_mgr_init );
+
+ osm_drop_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_router(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN const ib_net64_t portguid )
+{
+ osm_router_t *p_rtr;
+ cl_qmap_t* p_rtr_guid_tbl;
+
+ p_rtr_guid_tbl = &p_mgr->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( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_router: "
+ "Cleaned router for port guid 0x%016" PRIx64 "\n",
+ cl_ntoh64( portguid ) );
+ osm_router_delete( &p_rtr );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_port(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_port_t* p_port )
+{
+ ib_net64_t port_guid;
+ osm_port_t *p_port_check;
+ cl_list_t* p_new_ports_list;
+ cl_list_iterator_t cl_list_item;
+ cl_qmap_t* p_port_guid_tbl;
+ cl_qmap_t* p_sm_guid_tbl;
+ osm_mcm_info_t* p_mcm;
+ osm_mgrp_t* p_mgrp;
+ cl_ptr_vector_t* p_port_lid_tbl;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint32_t port_num;
+ uint32_t remote_port_num;
+ uint32_t num_physp;
+ osm_node_t *p_node;
+ osm_node_t *p_remote_node;
+ osm_physp_t *p_physp;
+ osm_physp_t *p_remote_physp;
+ osm_remote_sm_t *p_sm;
+ ib_gid_t port_gid;
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_remove_port );
+
+ port_guid = osm_port_get_guid( p_port );
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Unreachable port 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+
+ /*
+ Remove this port from the new_ports_list, if it exists there.
+ Remove this port from the guid and LID tables.
+ Remove also from the sm guid table - if the object
+ exists there.
+ */
+ p_new_ports_list = &p_mgr->p_subn->new_ports_list;
+ cl_list_item = cl_list_head(p_new_ports_list);
+ while( cl_list_item != cl_list_end(p_new_ports_list) )
+ {
+ if ( (osm_port_t*)(cl_list_obj(cl_list_item)) == p_port )
+ {
+ /* Found the port in the new_ports_list. Remove it from there. */
+ cl_list_remove_item(p_new_ports_list, cl_list_item);
+ break;
+ }
+ cl_list_item = cl_list_next(cl_list_item);
+ }
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_port_check = (osm_port_t*)cl_qmap_remove( p_port_guid_tbl, port_guid );
+ if( p_port_check != p_port )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_port: ERR 0101: "
+ "Port 0x%016" PRIx64 " not in guid table\n",
+ cl_ntoh64( port_guid ) );
+ goto Exit;
+ }
+
+ p_sm_guid_tbl = &p_mgr->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( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Cleaned SM for port guid\n" );
+
+ free(p_sm);
+ }
+
+ __osm_drop_mgr_remove_router( p_mgr, port_guid );
+
+ osm_port_get_lid_range_ho( p_port, &min_lid_ho, &max_lid_ho );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Clearing abandoned LID range [0x%X,0x%X]\n",
+ min_lid_ho, max_lid_ho );
+
+ p_port_lid_tbl = &p_mgr->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 );
+
+ /*
+ For each Physical Port associated with this port:
+ Unlink the remote Physical Port, if any
+ Re-initialize each Physical Port.
+ */
+
+ num_physp = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_physp; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, (uint8_t)port_num );
+
+ if( p_physp )
+ {
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ osm_port_t* p_remote_port;
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+ p_remote_node = osm_physp_get_node_ptr( p_remote_physp );
+ remote_port_num = osm_physp_get_port_num( p_remote_physp );
+ p_remote_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, p_remote_physp->port_guid );
+
+ if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ /* 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 (osm_port_discovery_count_get( p_remote_port ) &&
+ osm_physp_get_port_state( p_remote_physp ) == IB_LINK_ACTIVE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Forcing delayed heavy sweep. Remote "
+ "port 0x%016" PRIx64 " port num: 0x%X "
+ "was recognized in ACTIVE state\n",
+ cl_ntoh64( p_remote_physp->port_guid ),
+ remote_port_num );
+ p_mgr->p_subn->force_delayed_heavy_sweep = TRUE;
+ }
+ }
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_remove_port: "
+ "Unlinking local node 0x%016" PRIx64 ", port 0x%X"
+ "\n\t\t\t\tand remote node 0x%016" PRIx64
+ ", port 0x%X\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 );
+
+ osm_node_unlink( p_node, (uint8_t)port_num,
+ p_remote_node, (uint8_t)remote_port_num );
+
+ /* 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 ( osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH )
+ {
+ if ( p_remote_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ osm_port_discovery_count_reset( p_remote_port );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_drop_mgr_remove_port: "
+ "Resetting discovery count of node: "
+ "0x%016" PRIx64 " port num:0x%X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ remote_port_num );
+ }
+ }
+ }
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_drop_mgr_remove_port: "
+ "Clearing physical port number 0x%X\n",
+ port_num );
+
+ osm_physp_destroy( p_physp );
+ }
+ }
+
+ p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+ while( p_mcm != (osm_mcm_info_t *)cl_qlist_end( &p_port->mcm_list ) )
+ {
+ p_mgrp = (osm_mgrp_t *)cl_qmap_get( &p_mgr->p_subn->mgrp_mlid_tbl,
+ p_mcm->mlid );
+ if(p_mgrp != (osm_mgrp_t *)cl_qmap_end( &p_mgr->p_subn->mgrp_mlid_tbl ) )
+ {
+ osm_mgrp_remove_port(p_mgr->p_subn, p_mgr->p_log, p_mgrp, p_port->guid );
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ }
+ p_mcm = (osm_mcm_info_t*)cl_qlist_remove_head( &p_port->mcm_list );
+ }
+
+ /* initialize the p_node - may need to get node_desc later */
+ p_node = p_port->p_node;
+
+ osm_port_delete( &p_port );
+
+ /* issue a notice - trap 65 */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* 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(65);
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+ /* following C14-72.1.2 and table 119 p725 */
+ /* we need to provide the GID */
+ port_gid.unicast.prefix = p_mgr->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 = p_mgr->p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_mgr->p_log, p_mgr->p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_port: ERR 0103: "
+ "Error sending trap reports (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ if (osm_log_is_active( p_mgr->p_log, OSM_LOG_INFO ))
+ {
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+ if (p_node)
+ {
+ memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+ }
+ osm_log( p_mgr->p_log, OSM_LOG_INFO,
+ "__osm_drop_mgr_remove_port: "
+ "Removed port with GUID:0x%016" PRIx64
+ " LID range [0x%X,0x%X] of node:%s\n",
+ cl_ntoh64( port_gid.unicast.interface_id ),
+ min_lid_ho, max_lid_ho, p_node ? desc : "UNKNOWN" );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_remove_switch(
+ IN const osm_drop_mgr_t* const p_mgr,
+ 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( p_mgr->p_log, __osm_drop_mgr_remove_switch );
+
+ node_guid = osm_node_get_node_guid( p_node );
+ p_sw_guid_tbl = &p_mgr->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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_remove_switch: 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( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_drop_mgr_process_node(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ osm_physp_t *p_physp;
+ osm_port_t *p_port;
+ osm_node_t *p_node_check;
+ cl_qmap_t *p_node_guid_tbl;
+ uint32_t port_num;
+ uint32_t max_ports;
+ ib_net64_t port_guid;
+ cl_qmap_t* p_port_guid_tbl;
+ boolean_t return_val = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_process_node );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_process_node: "
+ "Unreachable node 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+
+ /*
+ Delete all the logical and physical port objects
+ associated with this node.
+ */
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ 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( osm_physp_is_valid( p_physp ) )
+ {
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ p_port = (osm_port_t*)cl_qmap_get( p_port_guid_tbl, port_guid );
+
+ if( p_port != (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ __osm_drop_mgr_remove_port( p_mgr, p_port );
+ }
+ }
+
+ return_val = TRUE;
+
+ if (p_node->sw)
+ __osm_drop_mgr_remove_switch( p_mgr, p_node );
+
+ p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+ p_node_check = (osm_node_t*)cl_qmap_remove( p_node_guid_tbl,
+ osm_node_get_node_guid( p_node ) );
+ if( p_node_check != p_node )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_process_node: 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( p_mgr->p_log );
+ return( return_val );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_drop_mgr_check_node(
+ IN const osm_drop_mgr_t* const p_mgr,
+ IN osm_node_t* p_node )
+{
+ ib_net64_t node_guid;
+ osm_physp_t *p_physp;
+ osm_port_t *p_port;
+ cl_qmap_t* p_port_guid_tbl;
+ ib_net64_t port_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_drop_mgr_check_node );
+
+ node_guid = osm_node_get_node_guid( p_node );
+
+ if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_drop_mgr_check_node: ERR 0107: "
+ "Node 0x%016" PRIx64 " is not a switch node\n",
+ cl_ntoh64( node_guid ) );
+ goto Exit;
+ }
+
+ /* 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( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " no switch in table\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ /* Make sure we have a port object for port zero */
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_physp = osm_node_get_physp_ptr( p_node, 0 );
+ if ( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " no valid physical port 0\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ p_port = (osm_port_t*)cl_qmap_get(
+ p_port_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " has no port object\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ if ( osm_port_discovery_count_get( p_port ) == 0 )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_drop_mgr_check_node: "
+ "Node 0x%016" PRIx64 " port has discovery count zero\n",
+ cl_ntoh64( node_guid ) );
+
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_drop_mgr_process(
+ IN const osm_drop_mgr_t* const p_mgr )
+{
+ cl_qmap_t *p_node_guid_tbl;
+ cl_qmap_t *p_port_guid_tbl;
+ cl_list_t *p_lsweep_ports;
+ osm_port_t *p_port;
+ osm_port_t *p_next_port;
+ osm_node_t *p_node;
+ osm_node_t *p_next_node;
+ ib_net64_t port_guid;
+ ib_net64_t node_guid;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_drop_mgr_process );
+
+ p_node_guid_tbl = &p_mgr->p_subn->node_guid_tbl;
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+ p_lsweep_ports = &p_mgr->p_subn->light_sweep_physp_list;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->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 ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ node_guid = osm_node_get_node_guid( p_node );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking node 0x%016" PRIx64 "\n",
+ cl_ntoh64( node_guid ) );
+ }
+
+ /*
+ 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( osm_node_discovery_count_get( p_node ) == 0 )
+ __osm_drop_mgr_process_node( p_mgr, p_node );
+ }
+
+ /*
+ 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 );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ node_guid = osm_node_get_node_guid( p_node );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking full discovery of node 0x%016" PRIx64 "\n",
+ cl_ntoh64( node_guid ) );
+ }
+
+ if ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH )
+ continue;
+
+ /* We are handling a switch node */
+ __osm_drop_mgr_check_node( p_mgr, 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 ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ port_guid = osm_port_get_guid( p_port );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_drop_mgr_process: "
+ "Checking port 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ }
+
+ /*
+ If the port is unreachable, remove it from the guid table.
+ */
+ if( osm_port_discovery_count_get( p_port ) == 0 )
+ __osm_drop_mgr_remove_port( p_mgr, p_port );
+ }
+
+ /*
+ scan through all the ports left - if the port is not DOWN and
+ it does not have a valid remote port - we need to track it for
+ next light sweep scan...
+ */
+ cl_list_remove_all( p_lsweep_ports );
+ 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 );
+
+ 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 (osm_physp_is_valid(p_physp) &&
+ (osm_physp_get_port_state(p_physp) != IB_LINK_DOWN) &&
+ ! osm_physp_get_remote(p_physp))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_drop_mgr_process: ERR 0108: "
+ "Unknown remote side for node 0x%016" PRIx64
+ " port %u. Adding to light sweep sampling list\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node )),
+ port_num);
+
+ osm_dump_dr_path(p_mgr->p_log,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ OSM_LOG_ERROR);
+
+ cl_list_insert_head( p_lsweep_ports, p_physp );
+ }
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
--- /dev/null
+#include <osm_db_files.c>\r
+#include <osm_db_pack.c>\r
+#include <osm_fwd_tbl.c>\r
+#include <osm_inform.c>\r
+#include <osm_lid_mgr.c>\r
+#include <osm_lin_fwd_rcv.c>\r
+#include <osm_lin_fwd_rcv_ctrl.c>\r
+#include <osm_lin_fwd_tbl.c>\r
+\r#include <osm_link_mgr.c>\r
+#include <osm_matrix.c>\r
+#include <osm_mcast_fwd_rcv.c>\r
+#include <osm_mcast_fwd_rcv_ctrl.c>\r
+#include <osm_mcast_mgr.c>\r
+#include <osm_mcast_tbl.c>\r
+#include <osm_mcm_info.c>\r
+#include <osm_mcm_port.c>\r
+#include <osm_mtree.c>\r
+#include <osm_multicast.c>\r
+#include <osm_node.c>\r
+#include <osm_node_desc_rcv.c>\r
+#include <osm_node_desc_rcv_ctrl.c>\r
+#include <osm_node_info_rcv.c>\r
+#include <osm_node_info_rcv_ctrl.c>\r
+#include <osm_opensm.c>\r
+#include <osm_pkey.c>\r
+#include <osm_pkey_mgr.c>\r
+#include <osm_prtn.c>\r
+#include <osm_pkey_rcv.c>\r
+#include <osm_pkey_rcv_ctrl.c>\r
+#include <osm_qos.c>\r
+#include <osm_port.c>\r
+#include <osm_port_info_rcv.c>\r
+#include <osm_port_info_rcv_ctrl.c>\r
+#include <osm_remote_sm.c>\r
+#include <osm_req.c>\r
+#include <osm_req_ctrl.c>\r
+#include <osm_resp.c>\r
+#include <osm_sa.c>\r
+#include <osm_router.c>\r
+#include <osm_sa_class_port_info.c>\r
+#include <osm_sa_class_port_info_ctrl.c>\r
+#include <osm_sa_guidinfo_record.c>\r
+#include <osm_sa_guidinfo_record_ctrl.c>\r
+#include <osm_sa_informinfo.c>\r
+#include <osm_sa_informinfo_ctrl.c>\r
+#include <osm_sa_lft_record.c>\r
+#include <osm_sa_lft_record_ctrl.c>\r
+#include <osm_sa_link_record.c>\r
+#include <osm_sa_link_record_ctrl.c>\r
+\r#include <osm_sa_mad_ctrl.c>\r
+\r#include <osm_sa_mcmember_record_ctrl.c>\r
+\r#include <osm_sa_mft_record.c>\r
+\r#include <osm_sa_mft_record_ctrl.c>\r
+\r#include <osm_sa_node_record.c>\r
+\r#include <osm_sa_node_record_ctrl.c>\r
+\r#include <osm_sa_path_record_ctrl.c>\r
+\r#include <osm_sa_pkey_record.c>\r
+\r#include <osm_sa_pkey_record_ctrl.c>\r
+\r#include <osm_sa_portinfo_record.c>\r
+\r#include <osm_sa_portinfo_record_ctrl.c>\r
+\r#include <osm_sa_response.c>\r
+\r#include <osm_sa_service_record.c>\r
+\r#include <osm_sa_service_record_ctrl.c>\r
+\r#include <osm_sa_slvl_record.c>\r
+\r#include <osm_sa_slvl_record_ctrl.c>\r
+\r#include <osm_sa_sminfo_record.c>\r
+\r#include <osm_sa_sminfo_record_ctrl.c>\r
+\r#include <osm_sa_sw_info_record.c>\r
+\r#include <osm_sa_sw_info_record_ctrl.c>\r
+\r#include <osm_sa_vlarb_record.c>\r
+\r#include <osm_sa_vlarb_record_ctrl.c>\r
+\r#include <osm_service.c>\r
+\r#include <osm_slvl_map_rcv.c>\r
+\r#include <osm_slvl_map_rcv_ctrl.c>\r
+\r#include <osm_sm.c>\r
+#include <osm_sminfo_rcv.c>\r
+#include <osm_sminfo_rcv_ctrl.c>\r
+#include <osm_sm_mad_ctrl.c>\r
+#include <osm_sm_state_mgr.c>\r
+#include <osm_state_mgr.c>\r
+#include <osm_state_mgr_ctrl.c>\r
+#include <osm_subnet.c>\r
+#include <osm_sweep_fail_ctrl.c>\r
+#include <osm_sw_info_rcv.c>\r
+#include <osm_sw_info_rcv_ctrl.c>\r
+#include <osm_switch.c>\r
+#include <osm_trap_rcv.c>\r
+#include <osm_trap_rcv_ctrl.c>\r
+#include <osm_ucast_mgr.c>\r
+#include <osm_ucast_updn.c>\r
+#include <osm_ucast_file.c>\r
+#include <osm_ucast_ftree.c>\r
+#include <osm_vl15intf.c>\r
+#include <osm_vl_arb_rcv.c>\r
+#include <osm_vl_arb_rcv_ctrl.c>\r
+#include <st.c>\r
+#include <main.c>\r
+#include <cl_event_wheel.c>\r
+#include <cl_dispatcher.c>\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_fwd_tbl_t.
+ * This object represents a unicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_fwd_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_fwd_tbl_init(
+ IN osm_fwd_tbl_t* const p_tbl,
+ IN const ib_switch_info_t* const p_si )
+{
+ uint16_t tbl_cap;
+ ib_api_status_t status = IB_SUCCESS;
+
+ /*
+ Determine the type and size of the forwarding table
+ used by this switch, then initialize accordingly.
+ The current implementation only supports switches
+ with linear forwarding tables.
+ */
+ tbl_cap = cl_ntoh16( p_si->lin_cap );
+
+ if( tbl_cap == 0 )
+ {
+ /*
+ This switch does not support linear forwarding
+ tables. Error out for now.
+ */
+ status = IB_UNSUPPORTED;
+ goto Exit;
+ }
+
+ p_tbl->p_rnd_tbl = NULL;
+
+ p_tbl->p_lin_tbl = osm_lin_tbl_new( tbl_cap );
+
+ if( p_tbl->p_lin_tbl == NULL )
+ {
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ Exit:
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_fwd_tbl_destroy(
+ IN osm_fwd_tbl_t* const p_tbl )
+{
+ if( p_tbl->p_lin_tbl )
+ {
+ CL_ASSERT( p_tbl->p_rnd_tbl == NULL );
+ osm_lin_tbl_delete( &p_tbl->p_lin_tbl );
+ }
+ else
+ {
+ osm_rand_tbl_delete( &p_tbl->p_rnd_tbl );
+ }
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_inform.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of inform record functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.18 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_trap_rcv.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+
+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_construct(
+ IN osm_infr_t* const p_infr )
+{
+ memset( p_infr, 0, sizeof(osm_infr_t) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_destroy(
+ IN osm_infr_t* const p_infr )
+{
+ free( p_infr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_init(
+ IN osm_infr_t* const p_infr,
+ IN const osm_infr_t *p_infr_rec )
+{
+ CL_ASSERT( p_infr );
+
+ /* what else do we need in the inform_record ??? */
+
+ /* copy the contents of the provided informinfo */
+ memcpy( p_infr, p_infr_rec, sizeof(osm_infr_t) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+ {
+ osm_infr_init( p_infr, p_infr_rec );
+ }
+
+ return( p_infr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__dump_all_informs(
+ IN osm_subn_t const *p_subn,
+ IN osm_log_t *p_log)
+{
+ cl_list_item_t* p_list_item;
+
+ OSM_LOG_ENTER( p_log, __dump_all_informs );
+
+ if( !osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ goto Exit;
+
+ 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( p_log,
+ &((osm_infr_t*)p_list_item)->inform_record.inform_info,
+ OSM_LOG_DEBUG );
+ p_list_item = cl_qlist_next( p_list_item );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Match an infr by the InformInfo and Address vector
+ **********************************************************************/
+static cl_status_t
+__match_inf_rec(
+ IN const cl_list_item_t* const 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;
+ osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log;
+ cl_status_t status = CL_NOT_FOUND;
+ ib_gid_t all_zero_gid;
+
+ OSM_LOG_ENTER( p_log, __match_inf_rec);
+
+ if ( memcmp( &p_infr->report_addr,
+ &p_infr_rec->report_addr,
+ sizeof(p_infr_rec->report_addr)) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by Address\n" );
+ goto Exit;
+ }
+
+ memset( &all_zero_gid, 0, sizeof(ib_gid_t) );
+
+ /* if inform_info.gid is not zero, ignore lid range */
+ if ( !memcmp( &p_infr_rec->inform_record.inform_info.gid,
+ &all_zero_gid,
+ sizeof(p_infr_rec->inform_record.inform_info.gid)) )
+ {
+ if ( memcmp( &p_infr->inform_record.inform_info.gid,
+ &p_infr_rec->inform_record.inform_info.gid,
+ sizeof(p_infr->inform_record.inform_info.gid)) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.gid\n" );
+ goto Exit;
+ }
+ }
+ else
+ {
+ if ( (p_infr->inform_record.inform_info.lid_range_begin !=
+ p_infr_rec->inform_record.inform_info.lid_range_begin) ||
+ (p_infr->inform_record.inform_info.lid_range_end !=
+ p_infr_rec->inform_record.inform_info.lid_range_end) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.LIDRange\n" );
+ goto Exit;
+ }
+ }
+
+ if ( p_infr->inform_record.inform_info.trap_type !=
+ p_infr_rec->inform_record.inform_info.trap_type )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.TrapType\n" );
+ goto Exit;
+ }
+
+ if ( p_infr->inform_record.inform_info.is_generic !=
+ p_infr_rec->inform_record.inform_info.is_generic )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.IsGeneric\n" );
+ goto Exit;
+ }
+
+ if (p_infr->inform_record.inform_info.is_generic)
+ {
+ if ( p_infr->inform_record.inform_info.g_or_v.generic.trap_num !=
+ p_infr_rec->inform_record.inform_info.g_or_v.generic.trap_num )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Generic.TrapNumber\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val !=
+ p_infr_rec->inform_record.inform_info.g_or_v.generic.qpn_resp_time_val )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Generic.QPNRespTimeVal\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_msb !=
+ p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_msb )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Generic.NodeTypeMSB\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.generic.node_type_lsb !=
+ p_infr_rec->inform_record.inform_info.g_or_v.generic.node_type_lsb )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Generic.NodeTypeLSB\n" );
+ else
+ status = CL_SUCCESS;
+ }
+ else
+ {
+ if ( p_infr->inform_record.inform_info.g_or_v.vend.dev_id !=
+ p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Vendor.DeviceID\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val !=
+ p_infr_rec->inform_record.inform_info.g_or_v.vend.qpn_resp_time_val )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Vendor.QPNRespTimeVal\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_msb !=
+ p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_msb )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "Differ by InformInfo.Vendor.VendorIdMSB\n" );
+ else if ( p_infr->inform_record.inform_info.g_or_v.vend.vendor_id_lsb !=
+ p_infr_rec->inform_record.inform_info.g_or_v.vend.vendor_id_lsb )
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_inf_rec: "
+ "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* const p_infr_rec )
+{
+ cl_list_item_t* p_list_item;
+
+ OSM_LOG_ENTER( p_log, osm_infr_get_by_rec );
+
+ __dump_all_informs( p_subn, p_log );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_get_by_rec: "
+ "Looking for Inform Record\n" );
+ osm_dump_inform_info( p_log, &(p_infr_rec->inform_record.inform_info),
+ OSM_LOG_DEBUG );
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_get_by_rec: "
+ "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_infr_insert_to_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "Inserting new InformInfo Record into Database\n" );
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "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( p_log,
+ &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG );
+#endif
+
+ cl_qlist_insert_head( &p_subn->sa_infr_list,
+ &p_infr->list_item );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_insert_to_db: "
+ "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)
+{
+ OSM_LOG_ENTER( p_log, osm_infr_remove_from_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_infr_remove_from_db: "
+ "Removing InformInfo Subscribing GID:0x%016" PRIx64 " : 0x%016" PRIx64
+ " Enum:0x%X from Database\n",
+ cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.prefix),
+ cl_ntoh64(p_infr->inform_record.subscriber_gid.unicast.interface_id),
+ p_infr->inform_record.subscriber_enum
+ );
+
+ osm_dump_inform_info( p_log, &(p_infr->inform_record.inform_info), OSM_LOG_DEBUG );
+
+ cl_qlist_remove_item( &p_subn->sa_infr_list,
+ &p_infr->list_item );
+
+ osm_infr_destroy( p_infr );
+
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ * Send a report:
+ * Given a target address to send to and the notice.
+ * We need to send SubnAdmReport
+ **********************************************************************/
+static ib_api_status_t
+__osm_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;
+ osm_log_t * p_log = p_infr_rec->p_infr_rcv->p_log;
+
+ OSM_LOG_ENTER( p_log, __osm_send_report );
+
+ /* 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,
+ "__osm_send_report: "
+ "Forwarding Notice Event from LID:0x%X"
+ " to InformInfo LID: 0x%X TID:0x%X\n",
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid),
+ trap_fwd_trans_id
+ );
+
+ /* get the MAD to send */
+ p_report_madw = osm_mad_pool_get( p_infr_rec->p_infr_rcv->p_mad_pool,
+ p_infr_rec->h_bind,
+ MAD_BLOCK_SIZE,
+ &(p_infr_rec->report_addr) );
+
+ p_report_madw->resp_expected = TRUE;
+
+ if( !p_report_madw )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_send_report: ERR 0203: "
+ "osm_mad_pool_get failed\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* advance trap trans id (cant simply ++ on some systems inside ntoh) */
+ 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,
+ cl_hton64( (uint64_t)cl_atomic_inc( &trap_fwd_trans_id ) ),
+ 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 */
+ status = osm_vendor_send( p_report_madw->h_bind, p_report_madw, TRUE );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_send_report: ERR 0204: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return(status);
+}
+
+/**********************************************************************
+ * 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* const 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;
+ cl_list_t* p_infr_to_remove_list = p_infr_match->p_remove_infr_list;
+ 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);
+ cl_status_t status = CL_NOT_FOUND;
+ osm_log_t *p_log = p_infr_rec->p_infr_rcv->p_log;
+ osm_subn_t *p_subn = p_infr_rec->p_infr_rcv->p_subn;
+ ib_gid_t source_gid;
+ osm_port_t* p_src_port;
+ osm_port_t* p_dest_port;
+
+ OSM_LOG_ENTER( p_log, __match_notice_to_inf_rec );
+
+ /* 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,
+ "__match_notice_to_inf_rec: "
+ "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,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by LID Range. Needed: 0x%X <= 0x%X <= 0x%X\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,
+ "__match_notice_to_inf_rec: "
+ "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,
+ "__match_notice_to_inf_rec: "
+ "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,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Trap Num\n" );
+ goto Exit;
+ }
+
+ /* ProducerType ProducerType match or 0xFFFFFF */
+ if ( (cl_ntoh32(ib_inform_info_get_node_type(p_ii)) != 0xFFFFFF) &&
+ (ib_inform_info_get_node_type(p_ii) != ib_notice_get_prod_type(p_ntc)) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Node Type: II=0x%06X Trap=0x%06X\n",
+ cl_ntoh32(ib_inform_info_get_node_type(p_ii)),
+ cl_ntoh32(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,
+ "__match_notice_to_inf_rec: "
+ "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,
+ "__match_notice_to_inf_rec: "
+ "Mismatch by Vendor ID\n" );
+ goto Exit;
+ }
+ }
+
+ /* Check if there is a pkey match. o13-17.1.1 */
+ /* Check if the issuer of the trap is the SM. If it is, then the gid
+ comparison should be done on the trap source (saved as the gid in the
+ data details field).
+ If the issuer gid is not the SM - then it is the guid of the trap
+ source */
+ if ( (cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == p_subn->opt.subnet_prefix) &&
+ (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == p_subn->sm_port_guid) )
+ {
+ /* The issuer is the SM then this is trap 64-67 - compare the gid
+ with 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_src_port = (osm_port_t*)cl_qmap_get( &p_subn->port_guid_tbl,
+ source_gid.unicast.interface_id );
+
+ if( p_src_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "__match_notice_to_inf_rec: "
+ "Cannot find source port with GUID:0x%016" PRIx64 "\n",
+ cl_ntoh64(source_gid.unicast.interface_id) );
+ goto Exit;
+ }
+
+ p_dest_port =
+ cl_ptr_vector_get( &p_subn->port_lid_tbl,
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+ if( !p_dest_port )
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "__match_notice_to_inf_rec: "
+ "Cannot find destination port with LID:0x%04x\n",
+ cl_ntoh16(p_infr_rec->report_addr.dest_lid) );
+ goto Exit;
+ }
+
+ if (osm_port_share_pkey( p_log, p_src_port, p_dest_port ) == FALSE )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "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,
+ "__match_notice_to_inf_rec: "
+ "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;
+ }
+
+ /* send the report to the address provided in the inform record */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__match_notice_to_inf_rec: "
+ "MATCH! Sending Report...\n" );
+ __osm_send_report( p_infr_rec, p_ntc );
+ status = CL_SUCCESS;
+
+ 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
+ **********************************************************************/
+ib_api_status_t
+osm_report_notice(
+ IN osm_log_t* const 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, osm_report_notice );
+
+ /*
+ * 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,
+ "osm_report_notice: "
+ "Ignoring Notice Reports since Inform List is not initialized yet!\n" );
+ return IB_ERROR;
+ }
+
+ /* an official Event information log */
+ if ( ib_notice_is_generic(p_ntc) )
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "osm_report_notice: "
+ "Reporting Generic Notice type:%u num:%u"
+ " from LID:0x%04X GID:0x%016" PRIx64
+ ",0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntc),
+ cl_ntoh16(p_ntc->g_or_v.generic.trap_num),
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+ );
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "osm_report_notice: "
+ "Reporting Vendor Notice type:%u vend:%u dev:%u"
+ " from LID:0x%04X GID:0x%016" PRIx64
+ ",0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntc),
+ cl_ntoh32(ib_notice_get_vend_id(p_ntc)),
+ cl_ntoh16(p_ntc->g_or_v.vend.dev_id),
+ cl_ntoh16(p_ntc->issuer_lid),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.prefix),
+ cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id)
+ );
+ }
+
+ /* 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);
+
+ OSM_LOG_EXIT( p_log );
+
+ return(IB_SUCCESS);
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lid_mgr.c 1738 2008-11-06 20:24:37Z tzachid $
+ */
+
+
+/*
+ * 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:
+ * __osm_lid_mgr_get_port_lid( p_mgr, port, &min_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 __osm_lid_mgr_get_port_lid 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 __osm_lid_mgr_get_port_min_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
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lid_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_db_pack.h>
+#include <stdlib.h>
+
+/**********************************************************************
+ 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* const p_mgr )
+{
+ memset( p_mgr, 0, sizeof(*p_mgr) );
+ cl_ptr_vector_construct( &p_mgr->used_lids );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_mgr_destroy(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ cl_list_item_t *p_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_destroy );
+
+ cl_ptr_vector_destroy( &p_mgr->used_lids );
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+ {
+ free((osm_lid_mgr_range_t *)p_item);
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ }
+ 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
+__osm_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, __osm_lid_mgr_validate_db );
+
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ cl_qlist_init( &guids );
+
+ if (osm_db_guid2lid_guids( p_mgr->p_g2l, &guids ))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0310: "
+ "could not get guid list\n");
+ goto Exit;
+ }
+
+ p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+ while ((cl_list_item_t*)p_item != 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,
+ "__osm_lid_mgr_validate_db: 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_unicast_lid_ho))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0312: "
+ "Illegal LID range [0x%x:0x%x] 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,
+ "__osm_lid_mgr_validate_db: ERR 0313: "
+ "LID range [0x%x:0x%x] 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 (( cl_ptr_vector_get_size( &p_mgr->used_lids ) > lid ) &&
+ ( cl_ptr_vector_get( &p_mgr->used_lids, lid ) ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0314: "
+ "0x%04x for guid:0x%016" PRIx64
+ " was previously used\n",
+ lid, p_item->guid
+ );
+ lids_ok = FALSE;
+ }
+ }
+ }
+
+ if (!lids_ok)
+ {
+ if (osm_db_guid2lid_delete( p_mgr->p_g2l, p_item->guid ))
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_validate_db: ERR 0315: "
+ "failed to delete entry for guid:0x%016" PRIx64
+ "\n",
+ p_item->guid
+ );
+ }
+ else
+ {
+ /* mark it was visited */
+ for (lid = min_lid; lid <= max_lid; lid++)
+ cl_ptr_vector_set( &p_mgr->used_lids, lid, (void *)1);
+ }
+ } /* got a lid */
+ p_item = (osm_db_guid_elem_t*)cl_qlist_remove_head(&guids);
+ } /* all guids */
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_mgr_init(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_db_t* const p_db,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lid_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+ CL_ASSERT( p_db );
+
+ osm_lid_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_db = p_db;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ /* 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,
+ "osm_lid_mgr_init: ERR 0316: "
+ "Error initializing Guid-to-Lid persistent database\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ cl_ptr_vector_init( &p_mgr->used_lids, 100, 40 );
+ 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.
+ * This is because of Windows write caching option.
+ * As a result, we might see corrupted guid2lid file.
+ */
+ if (p_subn->opt.exit_on_fatal)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_SYS,
+ "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,
+ "osm_lid_mgr_init: ERR 0317: "
+ "Error restoring Guid-to-Lid persistent database\n");
+ }
+ }
+
+ /* we need to make sure we did not get duplicates with
+ current lmc */
+ __osm_lid_mgr_validate_db(p_mgr);
+ }
+
+Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+static uint16_t
+__osm_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
+__osm_lid_mgr_init_sweep(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ cl_ptr_vector_t *p_discovered_vec = &p_mgr->p_subn->port_lid_tbl;
+ cl_ptr_vector_t *p_persistent_vec = &p_mgr->used_lids;
+ uint16_t max_defined_lid;
+ uint16_t max_persistent_lid;
+ uint16_t max_discovered_lid;
+ uint16_t lid;
+ uint16_t disc_min_lid;
+ uint16_t disc_max_lid;
+ uint16_t db_min_lid;
+ uint16_t 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;
+ uint16_t req_lid, num_lids;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_init_sweep );
+
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ /* if we came out of standby we need to discard any previous guid2lid
+ info we might have.
+ Do this only if the honor_guid2lid_file option is FALSE. If not, then
+ need to honor this file. */
+ if ( p_mgr->p_subn->coming_out_of_standby == TRUE )
+ {
+ if ( p_mgr->p_subn->opt.honor_guid2lid_file == FALSE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "Ignore guid2lid file when coming out of standby\n");
+ osm_db_clear( p_mgr->p_g2l );
+ for (lid = 0; lid < cl_ptr_vector_get_size(&p_mgr->used_lids); lid++)
+ cl_ptr_vector_set(p_persistent_vec, lid, NULL);
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "Honor current guid2lid file when coming out of standby\n");
+ osm_db_clear( p_mgr->p_g2l );
+ if (osm_db_restore(p_mgr->p_g2l))
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_lid_mgr_init_sweep: ERR 0306: "
+ "Error restoring Guid-to-Lid persistent database. Ignoring it\n");
+ }
+ }
+
+ /* we need to cleanup the empty ranges list */
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ while ( p_item != cl_qlist_end( &p_mgr->free_ranges ) )
+ {
+ free( (osm_lid_mgr_range_t *)p_item );
+ p_item = cl_qlist_remove_head( &p_mgr->free_ranges );
+ }
+
+ /* 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,
+ "__osm_lid_mgr_init_sweep: "
+ "Skipping all lids as we are reassigning them\n");
+ p_range =
+ (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t));
+ 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 = __osm_trim_lid(disc_min_lid);
+ disc_max_lid = __osm_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))
+ {
+ 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,
+ "__osm_lid_mgr_init_sweep: "
+ "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++ )
+ cl_ptr_vector_set(p_persistent_vec, lid, NULL);
+ }
+ }
+ }
+
+ /*
+ 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 = (uint16_t)cl_ptr_vector_get_size(p_persistent_vec);
+
+ /* but the vectors have one extra entry for lid=0 */
+ if (max_discovered_lid) max_discovered_lid--;
+ if (max_persistent_lid) max_persistent_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) && cl_ptr_vector_get(p_persistent_vec, lid))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "0x%04x is not free as its mapped by the persistent db\n",
+ lid);
+ is_free = FALSE;
+ }
+ else
+ {
+ /* check this is a discovered port */
+ if (lid <= max_discovered_lid && (p_port = (osm_port_t *)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 a 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,
+ "__osm_lid_mgr_init_sweep: "
+ "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,
+ "__osm_lid_mgr_init_sweep: "
+ "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) && cl_ptr_vector_get(p_persistent_vec, req_lid))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "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 =
+ (osm_lid_mgr_range_t *)malloc(sizeof(osm_lid_mgr_range_t));
+ p_range->min_lid = lid;
+ p_range->max_lid = lid;
+ }
+ }
+ else
+ {
+ /* this lid is used so we need to finalize the previous free range */
+ if (p_range)
+ {
+ cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "new free lid range [0x%x:0x%x]\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 =
+ (osm_lid_mgr_range_t *)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.
+ */
+ p_range->min_lid = lid;
+ }
+ p_range->max_lid = p_mgr->p_subn->max_unicast_lid_ho - 1;
+ cl_qlist_insert_tail( &p_mgr->free_ranges, &p_range->item );
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_init_sweep: "
+ "final free lid range [0x%x:0x%x]\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
+__osm_lid_mgr_is_range_not_persistent(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN const uint16_t lid,
+ IN const uint16_t num_lids )
+{
+ uint16_t i;
+ cl_status_t status;
+ osm_port_t *p_port;
+ const uint8_t start_lid = (uint8_t)(1 << p_mgr->p_subn->opt.lmc);
+ const cl_ptr_vector_t* const p_tbl = &p_mgr->used_lids;
+
+ if( lid < start_lid )
+ return( FALSE );
+
+ for( i = lid; i < lid + num_lids; i++ )
+ {
+ status = cl_ptr_vector_at( p_tbl, i, (void*)&p_port );
+ if( status == CL_SUCCESS )
+ {
+ if(p_port != NULL)
+ return( FALSE );
+ }
+ else
+ {
+ /*
+ We are out of range in the array.
+ Consider all further entries "free".
+ */
+ return( TRUE );
+ }
+ }
+
+ return( TRUE );
+}
+
+/**********************************************************************
+find a free lid range
+**********************************************************************/
+static void
+__osm_lid_mgr_find_free_lid_range(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN const uint8_t num_lids,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const 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,
+ "__osm_lid_mgr_find_free_lid_range: "
+ "LMC = %u, number LIDs = %u\n",
+ p_mgr->p_subn->opt.lmc, num_lids );
+
+ lmc_num_lids = (1 << p_mgr->p_subn->opt.lmc );
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ /*
+ 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 );
+ }
+ 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,
+ "__osm_lid_mgr_find_free_lid_range: ERR 0307: "
+ "OPENSM RAN OUT OF LIDS!!!\n" );
+ CL_ASSERT( 0 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_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 = __osm_trim_lid(min_lid);
+ max_lid = __osm_trim_lid(max_lid);
+ for (lid = min_lid; lid <= max_lid; lid++)
+ {
+ if ((lid < max_tbl_lid ) &&
+ (p_port == (osm_port_t*)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
+__osm_lid_mgr_get_port_lid(
+ IN osm_lid_mgr_t* const p_mgr,
+ IN osm_port_t * const p_port,
+ OUT uint16_t* const p_min_lid,
+ OUT uint16_t* const 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, __osm_lid_mgr_get_port_lid );
+
+ if (p_mgr->p_subn->opt.lmc)
+ lmc_mask = ~((1 << p_mgr->p_subn->opt.lmc) - 1);
+ else
+ lmc_mask = 0xffff;
+
+ /* 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 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,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" matches its known lid:0x%04x\n",
+ guid, min_lid );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " with lid:0x%04x does not match its known lid:0x%04x\n",
+ guid, cl_ntoh16(osm_port_get_base_lid(p_port)), min_lid);
+ __osm_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 Exit;
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "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 pesistent 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 &&
+ ! ((p_mgr->p_subn->first_time_master_sweep == TRUE) &&
+ (p_mgr->p_subn->opt.reassign_lids == TRUE )))
+ {
+ /* make sure lid is valid */
+ if ((num_lids == 1) || ((min_lid & lmc_mask) == min_lid))
+ {
+ /* is it free */
+ if (__osm_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,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" lid range:[0x%x-0x%x] is free\n",
+ guid, *p_min_lid, *p_max_lid );
+ goto NewLidSet;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " existing lid range:[0x%x:0x%x] is not free\n",
+ guid, min_lid, min_lid + num_lids - 1 );
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64
+ " existing lid range:[0x%x:0x%x] is not lmc aligned\n",
+ guid, min_lid, min_lid + num_lids - 1 );
+ }
+ }
+
+ /* first cleanup the existing discovered lid range */
+ __osm_lid_mgr_cleanup_discovered_port_lid_range( p_mgr, p_port );
+
+ /* find an empty space */
+ __osm_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,
+ "__osm_lid_mgr_get_port_lid: "
+ "0x%016" PRIx64" assigned a new lid range:[0x%x-0x%x]\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++)
+ cl_ptr_vector_set(&p_mgr->used_lids, lid, (void*)1);
+
+ Exit:
+ /* 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
+__osm_lid_mgr_set_remote_pi_state_to_init(
+ IN osm_lid_mgr_t * const p_mgr,
+ IN osm_physp_t* const p_physp)
+{
+ ib_port_info_t *p_pi;
+ osm_physp_t *p_rem_physp = osm_physp_get_remote(p_physp);
+
+ if ( p_rem_physp == NULL )
+ return;
+
+ if (osm_physp_is_valid( p_rem_physp ))
+ {
+ p_pi = osm_physp_get_port_info_ptr( p_rem_physp );
+ /* but in some rare cases the remote side might be irresponsive */
+ if (p_pi)
+ ib_port_info_set_port_state( p_pi, IB_LINK_INIT );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__osm_lid_mgr_set_physp_pi(
+ IN osm_lid_mgr_t * const p_mgr,
+ IN osm_port_t* const p_port,
+ IN osm_physp_t* const p_physp,
+ IN ib_net16_t const 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 new_port = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_set_physp_pi );
+
+ /*
+ Don't bother doing anything if this Physical Port is not valid.
+ This allows simplified code in the caller.
+ */
+ if( p_physp == NULL )
+ goto Exit;
+
+ if( !osm_physp_is_valid( 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).
+ */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_set_physp_pi: "
+ "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 = osm_physp_get_port_info_ptr( p_physp );
+
+ /*
+ 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.
+ */
+
+ memset( payload, 0, IB_SMP_DATA_SIZE );
+
+ /* Correction by FUJITSU */
+ if( port_num != 0 )
+ {
+ memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+ }
+
+ /*
+ Correction following a bug injected by the previous
+ FUJITSU line:
+
+ 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
+ */
+ /* these values can be set only for hca ports, so if we are
+ on a switch node, set these values to zero */
+ if ( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH )
+ p_pi->state_info2 = 0x0;
+ else
+ {
+ p_pi->state_info2 = 0x02;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ 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;
+ }
+
+ ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+
+ p_pi->m_key = p_mgr->p_subn->opt.m_key;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->m_key, &p_old_pi->m_key, sizeof(p_pi->m_key) ))
+ send_set = TRUE;
+
+ p_pi->subnet_prefix = p_mgr->p_subn->opt.subnet_prefix;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->subnet_prefix, &p_old_pi->subnet_prefix,
+ sizeof(p_pi->subnet_prefix) ))
+ send_set = TRUE;
+
+ p_pi->base_lid = lid;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
+ sizeof(p_pi->base_lid) ))
+ send_set = TRUE;
+
+ /* we are updating the ports with our local sm_base_lid */
+ p_pi->master_sm_base_lid = p_mgr->p_subn->sm_base_lid;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->master_sm_base_lid, &p_old_pi->master_sm_base_lid,
+ sizeof(p_pi->master_sm_base_lid) ))
+ send_set = TRUE;
+
+ p_pi->m_key_lease_period = p_mgr->p_subn->opt.m_key_lease_period;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ 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;
+
+ /*
+ we want to set the timeout for both the switch port 0
+ and the HCA ports
+ */
+ ib_port_info_set_timeout( p_pi, p_mgr->p_subn->opt.subnet_timeout );
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (ib_port_info_get_timeout( p_pi ) != ib_port_info_get_timeout( p_old_pi ))
+ send_set = TRUE;
+
+ if( port_num != 0 )
+ {
+ /*
+ HCA's 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;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->link_width_enabled, &p_old_pi->link_width_enabled,
+ sizeof(p_pi->link_width_enabled) ))
+ send_set = TRUE;
+
+ if ( p_mgr->p_subn->opt.force_link_speed )
+ ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 );
+ else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi ))
+ ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK );
+ else
+ ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi ));
+ if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed,
+ sizeof(p_pi->link_speed) ))
+ send_set = TRUE;
+
+ /* M_KeyProtectBits are always zero */
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+ 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 );
+ mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp );
+
+ 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)))
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_set_physp_pi: "
+ "Sending Link Down due to op_vls or mtu change. MTU:%u,%u VL_CAP:%u,%u\n",
+ 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 the remote
+ port is also going through "down" state into "init"...
+ */
+ __osm_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
+ {
+ /*
+ For Port 0, NeighborMTU is relevant only for Enh. SP0.
+ In this case, we'll set the MTU according to the mtu_cap
+ */
+ 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,
+ "__osm_lid_mgr_set_physp_pi: "
+ "Updating neighbor_mtu on switch port 0 to:%u\n",
+ ib_port_info_get_neighbor_mtu( p_pi ) );
+
+ /* Determine if enhanced switch port 0 and if so set LMC */
+ if (osm_switch_sp0_is_lmc_capable(p_node->sw, p_mgr->p_subn))
+ {
+ /* M_KeyProtectBits are always zero */
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ /* Check to see if the value we are setting is different than
+ the value in the port_info. If it is, turn on send_set flag */
+ if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+ 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.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ /*
+ We need to set the cli_rereg bit when we are in first_time_master_sweep for
+ ports supporting the ClientReregistration Vol1 (v1.2) p811 14.4.11
+ 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 it is in
+ the p_subn->new_ports_list list.
+ */
+ if ( cl_is_object_in_list(&p_mgr->p_subn->new_ports_list, p_port) )
+ {
+ /* p_port is in new_ports_list, mark new_port as TRUE */
+ new_port = TRUE;
+ }
+
+ if ( ( p_mgr->p_subn->first_time_master_sweep == TRUE ||
+ new_port == TRUE ) &&
+ !p_mgr->p_subn->opt.no_clients_rereg &&
+ ( (p_old_pi->capability_mask & IB_PORT_CAP_HAS_CLIENT_REREG) != 0 ) )
+ ib_port_info_set_client_rereg( p_pi, 1 );
+ else
+ ib_port_info_set_client_rereg( p_pi, 0 );
+
+ /* 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.
+ 3. got_set_resp on the physical port is FALSE. This means we haven't seen
+ this port before and we need to send Set of PortInfo to it.
+ */
+ if (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+ p_physp->got_set_resp == FALSE)
+ {
+
+ p_mgr->send_set_reqs = TRUE;
+ status = osm_req_set( p_mgr->p_req,
+ 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 )),
+ CL_DISP_MSGID_NONE,
+ &context );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return (send_set || p_mgr->p_subn->first_time_master_sweep == TRUE ||
+ p_physp->got_set_resp == FALSE);
+}
+
+/**********************************************************************
+ Processes our own node
+ Lock must already be held.
+**********************************************************************/
+static boolean_t
+__osm_lid_mgr_process_our_sm_node(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_port_t *p_port;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ osm_physp_t *p_physp;
+ boolean_t res = TRUE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_lid_mgr_process_our_sm_node );
+
+ /*
+ Acquire our own port object.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( &p_mgr->p_subn->port_guid_tbl,
+ p_mgr->p_subn->sm_port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( &p_mgr->p_subn->port_guid_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_lid_mgr_process_our_sm_node: ERR 0308: "
+ "Can't acquire SM's port object, GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64( p_mgr->p_subn->sm_port_guid ) );
+ res = FALSE;
+ 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.
+ */
+ __osm_lid_mgr_get_port_lid(p_mgr, p_port, &min_lid_ho, &max_lid_ho);
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_lid_mgr_process_our_sm_node: "
+ "Current base LID is 0x%X\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 );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_lid_mgr_process_our_sm_node: "
+ "Assigning SM's port 0x%016" PRIx64
+ "\n\t\t\t\tto LID range [0x%X,0x%X]\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.
+ */
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+
+ __osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho ) );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return res;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_sm(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_signal_t signal = OSM_SIGNAL_DONE_PENDING;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_sm );
+
+ 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 */
+ __osm_lid_mgr_init_sweep( p_mgr );
+
+ if (p_mgr->p_subn->opt.pfn_ui_pre_lid_assign)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_lid_mgr_process_sm: "
+ "Invoking UI function pfn_ui_pre_lid_assign\n" );
+ p_mgr->p_subn->opt.pfn_ui_pre_lid_assign(
+ p_mgr->p_subn->opt.ui_pre_lid_assign_ctx );
+ }
+
+ /* Set the send_set_reqs of the p_mgr to FALSE, and
+ we'll see if any set requests were sent. If not -
+ can signal OSM_SIGNAL_DONE */
+ p_mgr->send_set_reqs = FALSE;
+ if ( __osm_lid_mgr_process_our_sm_node( p_mgr ) == FALSE )
+ /* The initialization failed */
+ signal = OSM_SIGNAL_DONE;
+
+ if ( p_mgr->send_set_reqs == FALSE )
+ signal = OSM_SIGNAL_DONE;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ 1 go through all ports in the subnet.
+ 1.1 call __osm_lid_mgr_get_port_min_lid
+ 1.2 if a change is required send the port info
+ 2 if any change send the signal PENDING...
+**********************************************************************/
+osm_signal_t
+osm_lid_mgr_process_subnet(
+ IN osm_lid_mgr_t* const p_mgr )
+{
+ osm_signal_t signal;
+ cl_qmap_t *p_port_guid_tbl;
+ osm_port_t *p_port;
+ ib_net64_t port_guid;
+ uint16_t min_lid_ho, max_lid_ho;
+ osm_physp_t *p_physp;
+ int lid_changed;
+
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_lid_mgr_process_subnet );
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ CL_ASSERT( p_mgr->p_subn->sm_port_guid );
+
+ /* Set the send_set_reqs of the p_mgr to FALSE, and
+ we'll see if any set requests were sent. If not -
+ can signal OSM_SIGNAL_DONE */
+ p_mgr->send_set_reqs = FALSE;
+
+ 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,
+ "osm_lid_mgr_process_subnet: "
+ "Skipping our own port 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ }
+ else
+ {
+ /*
+ get the port lid range - we need to send it on first active sweep or
+ if there was a change (the result of the __osm_lid_mgr_get_port_lid)
+ */
+ lid_changed =
+ __osm_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,
+ "osm_lid_mgr_process_subnet: "
+ "Assigned port 0x%016" PRIx64
+ ", LID [0x%X,0x%X]\n", cl_ntoh64( port_guid ),
+ min_lid_ho, max_lid_ho );
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ /* the proc returns the fact it sent a set port info */
+ if (__osm_lid_mgr_set_physp_pi( p_mgr, p_port, p_physp, cl_hton16( min_lid_ho )))
+ p_mgr->send_set_reqs = TRUE;
+ }
+ } /* all ports */
+
+ /* store the guid to lid table in persistent db */
+ osm_db_store( p_mgr->p_g2l );
+
+ if ( p_mgr->send_set_reqs == FALSE )
+ signal = OSM_SIGNAL_DONE;
+ else
+ signal = OSM_SIGNAL_DONE_PENDING;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lft_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_lin_fwd_rcv.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_construct(
+ IN osm_lft_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_destroy(
+ IN osm_lft_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_init(
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lft_rcv_init );
+
+ osm_lft_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_process(
+ IN const osm_lft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ 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;
+ ib_api_status_t status;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lft_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_block = (uint8_t*)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;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid );
+
+ if( !p_sw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_process: ERR 0401: "
+ "LFT received for nonexistent node "
+ "0x%" PRIx64 "\n", cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+ status = osm_switch_set_ft_block( p_sw, p_block, block_num );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_process: ERR 0402: "
+ "Setting forwarding table block failed (%s)"
+ "\n\t\t\t\tSwitch 0x%" PRIx64 "\n",
+ ib_get_err_str( status ),
+ cl_ntoh64( node_guid ) );
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_lin_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lft_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lft_rcv_process( ((osm_lft_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_construct(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lft_rcv_ctrl_destroy(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lft_rcv_ctrl_init(
+ IN osm_lft_rcv_ctrl_t* const p_ctrl,
+ IN osm_lft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lft_rcv_ctrl_init );
+
+ osm_lft_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LFT,
+ __osm_lft_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lft_rcv_ctrl_init: ERR 1601: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_lin_fwd_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lin_fwd_tbl_t.
+ * This object represents an linear forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_lin_fwd_tbl.h>
+
+
+inline size_t
+__osm_lin_tbl_compute_obj_size(
+ IN const uint32_t num_ports )
+{
+ return( sizeof(osm_lin_fwd_tbl_t) + (num_ports - 1) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_lin_fwd_tbl_t*
+osm_lin_tbl_new(
+ IN uint16_t const size )
+{
+ osm_lin_fwd_tbl_t* p_tbl;
+
+ /*
+ The capacity reported by the switch includes LID 0,
+ so add 1 to the end of the range here for this assert.
+ */
+ CL_ASSERT( size <= IB_LID_UCAST_END_HO + 1 );
+ p_tbl = (osm_lin_fwd_tbl_t*)malloc(
+ __osm_lin_tbl_compute_obj_size( size ) );
+
+ /*
+ Initialize the table to OSM_NO_PATH, which means "invalid port"
+ */
+ memset( p_tbl, OSM_NO_PATH, __osm_lin_tbl_compute_obj_size( size ) );
+ if( p_tbl != NULL )
+ {
+ p_tbl->size = (uint16_t)size;
+ }
+ return( p_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lin_tbl_delete(
+ IN osm_lin_fwd_tbl_t** const pp_tbl )
+{
+ free( *pp_tbl );
+ *pp_tbl = NULL;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_link_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_link_mgr_t.
+ * This file implements the Link Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_link_mgr.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_construct(
+ IN osm_link_mgr_t* const p_mgr )
+{
+ memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_link_mgr_destroy(
+ IN osm_link_mgr_t* const p_mgr )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_destroy );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_link_mgr_init(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_link_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_link_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_link_mgr_set_physp_pi(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_physp_t* const p_physp,
+ IN uint8_t const port_state )
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_port_info_t* const 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 port_num;
+ uint8_t mtu;
+ uint8_t op_vls;
+ boolean_t esp0 = FALSE;
+ boolean_t send_set = FALSE;
+ osm_physp_t *p_remote_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_set_physp_pi );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+
+ port_num = osm_physp_get_port_num( p_physp );
+
+ if( port_num == 0 )
+ {
+ ib_switch_info_t* p_sw_info;
+
+ /*
+ HCA's don't have a port 0, and for switch port 0,
+ we need to check if this is enhanced port 0 or base port 0.
+ For base port 0 the following parameters are not valid. (p824, table 145)
+ */
+ if (!p_node->sw)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_link_mgr_set_physp_pi: ERR 4201: "
+ "Cannot find switch by guid: 0x%" PRIx64 "\n",
+ cl_ntoh64( p_node->node_info.node_guid ) );
+ goto Exit;
+ }
+
+ p_sw_info = osm_switch_get_si_ptr(p_node->sw);
+ if (ib_switch_info_is_enhanced_port0( p_sw_info ) == FALSE)
+ {
+ /* This means the switch doesn't support enhanced port zero.
+ Can skip it. */
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_link_mgr_set_physp_pi: "
+ "Skipping port 0, GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ goto Exit;
+ }
+ esp0 = TRUE;
+ }
+
+ /*
+ PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
+ */
+
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ memset( payload, 0, IB_SMP_DATA_SIZE );
+
+ /* Correction by FUJITSU */
+ memcpy( payload, p_old_pi, sizeof(ib_port_info_t) );
+
+ /*
+ Correction following a bug injected by the previous
+ FUJITSU line:
+
+ 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 - 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;
+
+ /* 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 or Enh. SP0 */
+ if( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ||
+ port_num == 0 )
+ {
+ 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) ))
+ 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_pi->base_lid = osm_physp_get_base_lid( p_physp );
+ if (memcmp( &p_pi->base_lid, &p_old_pi->base_lid,
+ sizeof(p_pi->base_lid) ))
+ send_set = TRUE;
+
+ /* we are initializing the ports with our local sm_base_lid */
+ 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_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;
+
+ if (esp0 == FALSE)
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ else
+ {
+ if (p_mgr->p_subn->opt.lmc_esp0)
+ p_pi->mkey_lmc = p_mgr->p_subn->opt.lmc;
+ else
+ p_pi->mkey_lmc = 0;
+ }
+ if (memcmp( &p_pi->mkey_lmc, &p_old_pi->mkey_lmc, sizeof(p_pi->mkey_lmc) ))
+ send_set = TRUE;
+
+ 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;
+ }
+
+ /*
+ Several timeout mechanisms:
+ */
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if (port_num != 0 && p_remote_physp &&
+ osm_physp_is_valid(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, p_mgr->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, p_mgr->p_subn->opt.leaf_head_of_queue_lifetime);
+ ib_port_info_set_vl_stall_count(
+ p_pi, p_mgr->p_subn->opt.leaf_vl_stall_count);
+ }
+ else
+ {
+ ib_port_info_set_hoq_lifetime(
+ p_pi, p_mgr->p_subn->opt.head_of_queue_lifetime);
+ ib_port_info_set_vl_stall_count(
+ p_pi, p_mgr->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,
+ 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;
+
+ /*
+ 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 ( p_mgr->p_subn->opt.force_link_speed )
+ ib_port_info_set_link_speed_enabled( p_pi, IB_LINK_SPEED_ACTIVE_2_5 );
+ else if (ib_port_info_get_link_speed_enabled( p_old_pi ) != ib_port_info_get_link_speed_sup( p_pi ))
+ ib_port_info_set_link_speed_enabled( p_pi, IB_PORT_LINK_SPEED_ENABLED_MASK );
+ else
+ ib_port_info_set_link_speed_enabled( p_pi, ib_port_info_get_link_speed_enabled( p_old_pi ));
+ if (memcmp( &p_pi->link_speed, &p_old_pi->link_speed,
+ sizeof(p_pi->link_speed) ))
+ 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 );
+ mtu = osm_physp_calc_link_mtu( p_mgr->p_log, p_physp );
+
+ 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;
+
+ /* also the context can flag the need to check for errors. */
+ context.pi_context.ignore_errors = FALSE;
+ }
+ else
+ {
+ /*
+ Since the only change we try to do is to modify the port
+ state we can ignore the errors that might be caused by a
+ race in setting the state and the actual state the port is
+ in.
+ */
+ context.pi_context.ignore_errors = FALSE;
+ }
+
+ ib_port_info_set_port_state( p_pi, port_state );
+ if (port_state != IB_LINK_NO_CHANGE &&
+ ib_port_info_get_port_state(p_pi) !=
+ ib_port_info_get_port_state(p_old_pi) )
+ {
+ send_set = TRUE;
+ if (port_state == IB_LINK_ACTIVE)
+ context.pi_context.active_transition = TRUE;
+ else
+ context.pi_context.active_transition = FALSE;
+ }
+
+ 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.update_master_sm_base_lid = FALSE;
+ context.pi_context.light_sweep = 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 an hca port or a switch port zero and got_set_resp is FALSE
+ (in this case we sent a PortInfoSet in the osm_lid_mgr, but for some
+ reason we didn't get a response) - try and re-send.
+ 3. This is a switch port and:
+ a. first_time_master_sweep flag on the subnet is TRUE. This means the
+ SM just became master, and it then needs to send at PortInfoSet to
+ every port (and this is the first time we can send a PortInfoSet to
+ switch external ports).
+ b. got_set_resp on the physical port is FALSE. This means we haven't
+ seen this port before - need to send PortInfoSet to it.
+ */
+ if (send_set ||
+ (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH && p_physp->got_set_resp == FALSE) ||
+ (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num == 0 &&
+ p_physp->got_set_resp == FALSE) ||
+ (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num != 0 &&
+ (p_mgr->p_subn->first_time_master_sweep == TRUE || p_physp->got_set_resp == FALSE)))
+ {
+ p_mgr->send_set_reqs = TRUE;
+ status = osm_req_set( p_mgr->p_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ payload,
+ sizeof(payload),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32(port_num),
+ CL_DISP_MSGID_NONE,
+ &context );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_link_mgr_process_port(
+ IN osm_link_mgr_t* const p_mgr,
+ IN osm_port_t* const p_port,
+ IN const uint8_t link_state )
+{
+ uint32_t i;
+ uint32_t num_physp;
+ osm_physp_t *p_physp;
+ uint8_t current_state;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_link_mgr_process_port );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_link_mgr_process_port: "
+ "Port 0x%" PRIx64 " going to %s\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ 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_port_get_num_physp( p_port );
+ 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_port_get_phys_ptr( p_port, (uint8_t)i );
+ if( p_physp && osm_physp_is_valid( p_physp ) )
+ {
+ current_state = osm_physp_get_port_state( p_physp );
+
+ if( current_state == 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) ||
+ (current_state < link_state) )
+ {
+ p_mgr->send_set_reqs = FALSE;
+ __osm_link_mgr_set_physp_pi(
+ p_mgr,
+ p_physp,
+ link_state );
+
+ if ( p_mgr->send_set_reqs == TRUE )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_link_mgr_process_port: "
+ "Physical port 0x%X already %s. Skipping\n",
+ osm_physp_get_port_num( p_physp ),
+ ib_get_port_state_str( current_state ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_link_mgr_process(
+ IN osm_link_mgr_t* const p_mgr,
+ IN const uint8_t link_state )
+{
+ cl_qmap_t *p_port_guid_tbl;
+ osm_port_t *p_port;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_link_mgr_process );
+
+ p_port_guid_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ 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 ) )
+ {
+ if( __osm_link_mgr_process_port( p_mgr, p_port, link_state ) ==
+ OSM_SIGNAL_DONE_PENDING )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_matrix.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lid_matrix_t.
+ * This file implements the LID Matrix object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_matrix.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_destroy(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ cl_vector_destroy( &p_lmx->lid_vec );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+cl_status_t
+__osm_lid_matrix_vec_init(
+ IN void* const p_elem,
+ IN void* context )
+{
+ osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+
+ memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+ return( CL_SUCCESS );
+}
+
+/**********************************************************************
+ Initializer function called by cl_vector
+**********************************************************************/
+void
+__osm_lid_matrix_vec_clear(
+ IN const size_t index,
+ IN void* const p_elem,
+ IN void* context )
+{
+ osm_lid_matrix_t* const p_lmx = (osm_lid_matrix_t*)context;
+
+ UNUSED_PARAM( index );
+ memset( p_elem, OSM_NO_PATH, p_lmx->num_ports + 1);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lid_matrix_clear(
+ IN osm_lid_matrix_t* const p_lmx )
+{
+ cl_vector_apply_func( &p_lmx->lid_vec,
+ __osm_lid_matrix_vec_clear, p_lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lid_matrix_init(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint8_t num_ports )
+{
+ cl_vector_t *p_vec;
+ cl_status_t status;
+
+ CL_ASSERT( p_lmx );
+ CL_ASSERT( num_ports );
+
+ p_lmx->num_ports = num_ports;
+
+ p_vec = &p_lmx->lid_vec;
+ /*
+ Initialize the vector for the number of ports plus an
+ extra entry to hold the "least-hops" count for that LID.
+ */
+ status = cl_vector_init( p_vec,
+ 0, /* min_size, */
+ 1, /* grow_size */
+ sizeof(uint8_t)*(num_ports + 1), /* element size */
+ __osm_lid_matrix_vec_init, /* init function */
+ NULL, /* destory func */
+ p_lmx /* context */
+ );
+
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+cl_status_t
+osm_lid_matrix_set(
+ IN osm_lid_matrix_t* const p_lmx,
+ IN const uint16_t lid_ho,
+ IN const uint8_t port_num,
+ IN const uint8_t val )
+{
+ uint8_t *p_port_array;
+ cl_status_t status;
+
+ CL_ASSERT( port_num < p_lmx->num_ports );
+ status = cl_vector_set_min_size( &p_lmx->lid_vec, lid_ho + 1 );
+ if( status == CL_SUCCESS )
+ {
+ p_port_array = (uint8_t *)cl_vector_get_ptr( &p_lmx->lid_vec, lid_ho );
+ p_port_array[port_num] = val;
+ if( p_port_array[p_lmx->num_ports] > val )
+ p_port_array[p_lmx->num_ports] = val;
+ }
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_fwd_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_fwd_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_construct(
+ IN osm_mft_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_destroy(
+ IN osm_mft_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_init(
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mft_rcv_init );
+
+ osm_mft_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_process(
+ IN const osm_mft_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mft_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_block = (uint16_t*)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;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mft_rcv_process: "
+ "Setting MFT block %u, position %u"
+ "\n\t\t\t\tSwitch 0x%016" PRIx64 ", TID 0x%" PRIx64 "\n",
+ block_num, position, cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_sw = osm_get_switch_by_guid( p_rcv->p_subn, node_guid );
+
+ if( !p_sw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_process: 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_process: ERR 0802: "
+ "Setting MFT block failed (%s)"
+ "\n\t\t\t\tSwitch 0x%016" PRIx64
+ ", block %u, position %u\n",
+ ib_get_err_str( status ),
+ cl_ntoh64( node_guid ),
+ block_num, position );
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_fwd_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mft_rcv_ctrl_t.
+ * This object represents the LFT Receive controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_mcast_fwd_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mft_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mft_rcv_process( ((osm_mft_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_construct(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mft_rcv_ctrl_destroy(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mft_rcv_ctrl_init(
+ IN osm_mft_rcv_ctrl_t* const p_ctrl,
+ IN osm_mft_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mft_rcv_ctrl_init );
+
+ osm_mft_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MFT,
+ __osm_mft_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mft_rcv_ctrl_init: ERR 0901: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcast_mgr_t.
+ * This file implements the Multicast Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+typedef struct _osm_mcast_work_obj
+{
+ cl_list_item_t list_item;
+ osm_port_t* p_port;
+} osm_mcast_work_obj_t;
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mcast_work_obj_t*
+__osm_mcast_work_obj_new(
+ IN const osm_port_t* const p_port )
+{
+ /*
+ TO DO - get these objects from a lockpool.
+ */
+ 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 = (osm_port_t*)p_port;
+ }
+
+ return( p_obj );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_work_obj_delete(
+ IN osm_mcast_work_obj_t* p_wobj )
+{
+ free( p_wobj );
+}
+
+/**********************************************************************
+ Recursively remove nodes from the tree
+**********************************************************************/
+static void
+__osm_mcast_mgr_purge_tree_node(
+ IN osm_mtree_node_t* p_mtn )
+{
+ uint8_t i;
+
+ for( i = 0; i < p_mtn->max_children; i++ )
+ {
+ if( p_mtn->child_array[i] &&
+ (p_mtn->child_array[i] != OSM_MTREE_LEAF) )
+ __osm_mcast_mgr_purge_tree_node( p_mtn->child_array[i] );
+
+ p_mtn->child_array[i] = NULL;
+
+ }
+
+ free( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_tree(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp )
+{
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_tree );
+
+ if( p_mgrp->p_root )
+ __osm_mcast_mgr_purge_tree_node( p_mgrp->p_root );
+
+ p_mgrp->p_root = NULL;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static float
+osm_mcast_mgr_compute_avg_hops(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw )
+{
+ float avg_hops = 0;
+ uint32_t hops = 0;
+ uint32_t num_ports = 0;
+ uint16_t base_lid_ho;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_avg_hops );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ For each member of the multicast group, compute the
+ number of hops to its base LID.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_compute_avg_hops: ERR 0A18: "
+ "No port object for port 0x%016" PRIx64 "\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+ hops += osm_switch_get_least_hops( p_sw, base_lid_ho );
+ num_ports++;
+ }
+
+ /*
+ We should be here if there aren't any ports in the group.
+ */
+ CL_ASSERT( num_ports );
+
+ if( num_ports != 0 )
+ {
+ avg_hops = (float)(hops / num_ports);
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( avg_hops );
+}
+
+/**********************************************************************
+ Calculate the maximal "min hops" from the given switch to any
+ of the group HCAs
+ **********************************************************************/
+static float
+osm_mcast_mgr_compute_max_hops(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp,
+ const osm_switch_t* const p_sw )
+{
+ uint32_t max_hops = 0;
+ uint32_t hops = 0;
+ uint16_t base_lid_ho;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_compute_max_hops );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ For each member of the multicast group, compute the
+ number of hops to its base LID.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get(
+ p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_compute_max_hops: ERR 0A1A: "
+ "No port object for port 0x%016" PRIx64 "\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ base_lid_ho = cl_ntoh16( osm_port_get_base_lid( p_port ) );
+ hops = osm_switch_get_least_hops( p_sw, base_lid_ho );
+ if (hops > max_hops) max_hops = hops;
+ }
+
+ if( max_hops == 0 )
+ {
+ /*
+ We should be here if there aren't any ports in the group.
+ */
+ max_hops = 10001; /* see later - we use it to realize no hops */
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return(float)(max_hops);
+}
+
+/**********************************************************************
+ 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*
+__osm_mcast_mgr_find_optimal_switch(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp )
+{
+ cl_qmap_t* p_sw_tbl;
+ const osm_switch_t* p_sw;
+ const osm_switch_t* p_best_sw = NULL;
+ float hops = 0;
+ float best_hops = 10000; /* any big # will do */
+ uint64_t sw_guid_ho;
+#ifdef OSM_VENDOR_INTF_ANAFA
+ boolean_t use_avg_hops = TRUE; /* anafa2 - bug hca on switch */ /* use max hops for root */
+#else
+ boolean_t use_avg_hops = FALSE; /* use max hops for root */
+#endif
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_optimal_switch );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ CL_ASSERT( !osm_mgrp_is_empty( p_mgrp ) );
+
+ 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;
+
+ if (use_avg_hops)
+ hops = osm_mcast_mgr_compute_avg_hops( p_mgr, p_mgrp, p_sw );
+ else
+ hops = osm_mcast_mgr_compute_max_hops( p_mgr, p_mgrp, p_sw );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "Switch 0x%016" PRIx64 ", hops = %f\n",
+ sw_guid_ho, hops );
+ }
+
+ if( hops < best_hops )
+ {
+ p_best_sw = p_sw;
+ best_hops = hops;
+ }
+ }
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ if( p_best_sw )
+ {
+ sw_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_best_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "Best switch is 0x%" PRIx64 ", hops = %f\n",
+ sw_guid_ho, best_hops );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_find_optimal_switch: "
+ "No multicast capable switches detected\n" );
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( (osm_switch_t*)p_best_sw );
+}
+
+/**********************************************************************
+ This function returns the existing or optimal root swtich for the tree.
+**********************************************************************/
+static osm_switch_t*
+__osm_mcast_mgr_find_root_switch(
+ osm_mcast_mgr_t* const p_mgr,
+ const osm_mgrp_t* const p_mgrp )
+{
+ const osm_switch_t* p_sw = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_find_root_switch );
+
+ /*
+ 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 = __osm_mcast_mgr_find_optimal_switch( p_mgr, p_mgrp );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( (osm_switch_t*)p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_construct(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_destroy(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_destroy );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_mgr_init(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mcast_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_mcast_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__osm_mcast_mgr_set_tbl(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw )
+{
+ osm_node_t* p_node;
+ osm_dr_path_t* p_path;
+ osm_madw_context_t mad_context;
+ ib_api_status_t status;
+ uint32_t block_id_ho = 0;
+ int16_t block_num = 0;
+ uint32_t position = 0;
+ uint32_t max_position;
+ osm_mcast_tbl_t* p_tbl;
+ ib_net16_t block[IB_MCAST_BLOCK_SIZE];
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_set_tbl );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( p_node );
+
+ p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ CL_ASSERT( p_path );
+
+ /*
+ Send multicast forwarding table blocks to the switch
+ as long as the switch indicates it has blocks needing
+ configuration.
+ */
+
+ mad_context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+ mad_context.mft_context.set_method = TRUE;
+
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+ max_position = p_tbl->max_position;
+
+ while( osm_mcast_tbl_get_block( p_tbl, block_num,
+ (uint8_t)position, block ) )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_set_tbl: "
+ "Writing MFT block 0x%X\n", block_id_ho );
+ }
+
+ block_id_ho = block_num + (position << 28);
+
+ status = osm_req_set( p_mgr->p_req,
+ p_path,
+ (void*)block,
+ sizeof(block),
+ IB_MAD_ATTR_MCAST_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_set_tbl: ERR 0A02: "
+ "Sending multicast fwd. tbl. block failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ signal = OSM_SIGNAL_DONE_PENDING;
+
+ if( ++position > max_position )
+ {
+ position = 0;
+ block_num++;
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
+/**********************************************************************
+ This is part of the recursive function to compute the paths in the
+ spanning tree that eminate from this switch. On input, the p_list
+ contains the group members that must be routed from this switch.
+**********************************************************************/
+static void
+__osm_mcast_mgr_subdivide(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp,
+ osm_switch_t* const p_sw,
+ cl_qlist_t* const p_list,
+ cl_qlist_t* const list_array,
+ uint8_t const array_size )
+{
+ uint8_t port_num;
+ uint16_t mlid_ho;
+ uint16_t lid_ho;
+ boolean_t ignore_existing;
+ osm_mcast_work_obj_t* p_wobj;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_subdivide );
+
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+ /*
+ For Multicast Groups, we want not 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 ) )
+ {
+ lid_ho = cl_ntoh16( osm_port_get_base_lid( p_wobj->p_port ) );
+
+ port_num = osm_switch_recommend_mcast_path(
+ p_sw, lid_ho, 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.
+ */
+ uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_subdivide: ERR 0A03: "
+ "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+ "\t\t\t\tNo multicast paths from this switch for port "
+ "with LID 0x%X\n",
+ mlid_ho, node_guid_ho, lid_ho );
+
+ __osm_mcast_work_obj_delete( p_wobj );
+ continue;
+ }
+
+ if( port_num > array_size )
+ {
+ uint64_t node_guid_ho = cl_ntoh64( osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_subdivide: ERR 0A04: "
+ "Error routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+ "\t\t\t\tNo multicast paths from this switch to port "
+ "with LID 0x%X\n",
+ mlid_ho, node_guid_ho, lid_ho );
+
+ __osm_mcast_work_obj_delete( p_wobj );
+
+ /* This is means OpenSM has a bug. */
+ CL_ASSERT( FALSE );
+ continue;
+ }
+
+ cl_qlist_insert_tail( &list_array[port_num], &p_wobj->list_item );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_purge_list(
+ osm_mcast_mgr_t* const p_mgr,
+ cl_qlist_t* const p_list )
+{
+ osm_mcast_work_obj_t* p_wobj;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_purge_list );
+
+ while( (p_wobj = (osm_mcast_work_obj_t*)cl_qlist_remove_head( p_list ) )
+ != (osm_mcast_work_obj_t*)cl_qlist_end( p_list ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_purge_list: ERR 0A06: "
+ "Unable to route for port 0x%" PRIx64 "\n",
+ osm_port_get_guid( p_wobj->p_port ) );
+ __osm_mcast_work_obj_delete( p_wobj );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ 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*
+__osm_mcast_mgr_branch(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp,
+ osm_switch_t* const p_sw,
+ cl_qlist_t* const p_list,
+ uint8_t depth,
+ uint8_t const upstream_port,
+ uint8_t* const 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;
+ uint64_t node_guid_ho;
+ osm_mcast_work_obj_t* p_wobj;
+ cl_qlist_t* p_port_list;
+ size_t count;
+ uint16_t mlid_ho;
+ osm_mcast_tbl_t* p_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_branch );
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_list );
+ CL_ASSERT( p_max_depth );
+
+ node_guid = osm_node_get_node_guid( osm_switch_get_node_ptr( p_sw ) );
+ node_guid_ho = cl_ntoh64( node_guid );
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_branch: "
+ "Routing MLID 0x%X through switch 0x%" PRIx64 "\n"
+ "\t\t\t\t%u nodes at depth %u\n",
+ mlid_ho,
+ node_guid_ho,
+ cl_qlist_count( p_list ), depth );
+ }
+
+ CL_ASSERT( cl_qlist_count( p_list ) > 0 );
+
+ depth++;
+
+ 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A14: "
+ "Switch 0x%" PRIx64 " does not support multicast\n",
+ node_guid_ho );
+
+ /*
+ Deallocate all the work objects on this branch of the tree.
+ */
+ __osm_mcast_mgr_purge_list( p_mgr, 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A15: "
+ "Insufficient memory to build multicast tree\n" );
+
+ /*
+ Deallocate all the work objects on this branch of the tree.
+ */
+ __osm_mcast_mgr_purge_list( p_mgr, 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_branch: ERR 0A16: "
+ "Unable to allocate list array\n" );
+ __osm_mcast_mgr_purge_list( p_mgr, p_list );
+ 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] );
+
+ __osm_mcast_mgr_subdivide( p_mgr, p_mgrp, 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 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Adding upstream port 0x%X\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;
+ const 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. */
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Routing %zu destination(s) via switch port 0x%X\n",
+ count, i );
+ }
+
+ /*
+ 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 (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 */
+ continue;
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_remote_node = osm_node_get_remote_node( p_node, i, NULL );
+
+ 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 );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ CL_ASSERT( p_remote_physp );
+ CL_ASSERT( osm_physp_is_valid( p_remote_physp ) );
+
+ p_mtn->child_array[i] = __osm_mcast_mgr_branch(
+ p_mgr, p_mgrp, 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 ) );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_mcast_mgr_branch: "
+ "Found leaf for port 0x%016" PRIx64 "\n"
+ "\t\t\t\ton switch port 0x%X\n",
+ cl_ntoh64( osm_port_get_guid( p_wobj->p_port ) ), i );
+ }
+
+ __osm_mcast_work_obj_delete( p_wobj );
+ }
+ }
+
+ free( list_array );
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mcast_mgr_build_spanning_tree(
+ osm_mcast_mgr_t* const p_mgr,
+ osm_mgrp_t* const p_mgrp )
+{
+ const cl_qmap_t* p_mcm_tbl;
+ const cl_qmap_t* p_port_tbl;
+ const osm_port_t* p_port;
+ const osm_mcm_port_t* p_mcm_port;
+ uint32_t num_ports;
+ cl_qlist_t port_list;
+ osm_switch_t* p_sw;
+ osm_mcast_work_obj_t* p_wobj;
+ ib_api_status_t status = IB_SUCCESS;
+ uint8_t max_depth = 0;
+ uint32_t count;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_build_spanning_tree );
+
+ cl_qlist_init( &port_list );
+
+ /*
+ 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_mcast_mgr_purge_tree( p_mgr, p_mgrp );
+
+ p_mcm_tbl = &p_mgrp->mcm_port_tbl;
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ num_ports = cl_qmap_count( p_mcm_tbl );
+ if( num_ports == 0 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_build_spanning_tree: "
+ "MLID 0x%X has no members--nothing to do\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+ }
+ 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( p_mgr, p_mgrp );
+ if( p_sw == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A08: "
+ "Unable to locate a suitable switch for group 0x%X\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ));
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ Build the first "subset" containing all member ports.
+ */
+ for( p_mcm_port = (osm_mcm_port_t*)cl_qmap_head( p_mcm_tbl );
+ p_mcm_port != (osm_mcm_port_t*)cl_qmap_end( p_mcm_tbl );
+ p_mcm_port = (osm_mcm_port_t*)cl_qmap_next(&p_mcm_port->map_item))
+ {
+ /*
+ Acquire the port object for this port guid, then create
+ the new worker object to build the list.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl,
+ ib_gid_get_guid( &p_mcm_port->port_gid ) );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A09: "
+ "No port object for port 0x%016" PRIx64 "\n",
+ cl_ntoh64( ib_gid_get_guid( &p_mcm_port->port_gid ) ) );
+ continue;
+ }
+
+ p_wobj = __osm_mcast_work_obj_new( p_port );
+ if( p_wobj == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_mcast_mgr_build_spanning_tree: ERR 0A10: "
+ "Insufficient memory to route port 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ continue;
+ }
+
+ cl_qlist_insert_tail( &port_list, &p_wobj->list_item );
+ }
+
+ count = cl_qlist_count( &port_list );
+ p_mgrp->p_root = __osm_mcast_mgr_branch( p_mgr, p_mgrp, p_sw,
+ &port_list, 0, 0, &max_depth );
+
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcast_mgr_build_spanning_tree: "
+ "Configured MLID 0x%X for %u ports, max tree depth = %u\n",
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ),
+ count, max_depth );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+#if 0
+/* unused */
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_mgr_set_table(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const osm_mtree_node_t* const 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( p_mgr->p_log, osm_mcast_mgr_set_table );
+
+ mlid_ho = cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) );
+ p_sw = osm_mtree_node_get_switch_ptr( p_mtn );
+
+ CL_ASSERT( p_sw );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_mcast_mgr_set_table: "
+ "Configuring MLID 0x%X on switch 0x%" PRIx64 "\n",
+ mlid_ho, osm_node_get_node_guid(
+ osm_switch_get_node_ptr( p_sw ) ) );
+ }
+
+ /*
+ 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( p_mgr->p_log );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mcast_mgr_clear(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp )
+{
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_sw_tbl;
+ osm_mcast_tbl_t* p_mcast_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_mcast_mgr_clear );
+
+ /*
+ Walk the switches and clear the routing entries for
+ this MLID.
+ */
+ p_sw_tbl = &p_mgr->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, cl_ntoh16(p_mgrp->mlid) );
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ OSM_LOG_EXIT( p_mgr->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(
+ IN osm_mcast_mgr_t* const p_mgr,
+ 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;
+ osm_switch_t* p_sw;
+ 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;
+ cl_qmap_t* p_port_tbl;
+ osm_mcast_tbl_t* p_mcast_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_single );
+
+ CL_ASSERT( mlid );
+ CL_ASSERT( port_guid );
+
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ mlid_ho = cl_ntoh16( mlid );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "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_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A01: "
+ "Unable to acquire port object for 0x%" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ if( p_physp == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A05: "
+ "Unable to acquire phsyical port object for 0x%" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A07: "
+ "Unable to acquire valid physical 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A11: "
+ "Unable to acquire remote phsyical port object "
+ "for 0x%" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ if( !osm_physp_is_valid( p_remote_physp ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A21: "
+ "Unable to acquire valid remote physical 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A22: "
+ "Remote node not a switch node 0x%" PRIx64 "\n",
+ cl_ntoh64( sw_guid ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_sw = p_remote_node->sw;
+ if( !p_sw )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: 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_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_sw );
+ osm_mcast_tbl_set( p_mcast_tbl, mlid_ho, port_num );
+ }
+ else
+ {
+ if( join_state & IB_JOIN_STATE_SEND_ONLY )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "Success. Nothing to do for send"
+ "only member\n" );
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_single: ERR 0A13: "
+ "Unknown join state 0x%X\n", join_state );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_single: "
+ "Unable to add port\n" );
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+#endif
+
+/**********************************************************************
+ lock must already be held on entry
+**********************************************************************/
+static ib_api_status_t
+osm_mcast_mgr_process_tree(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp,
+ IN osm_mcast_req_type_t req_type,
+ ib_net64_t port_guid )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net16_t mlid;
+ boolean_t ui_mcast_fdb_assign_func_defined;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_tree );
+
+ mlid = osm_mgrp_get_mlid( p_mgrp );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "Processing multicast group 0x%X\n", cl_ntoh16( mlid ));
+ }
+
+ /*
+ If there are no switches in the subnet, then we have nothing to do.
+ */
+ if( cl_qmap_count( &p_mgr->p_subn->sw_guid_tbl ) == 0 )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "No switches in subnet. Nothing to do\n" );
+ }
+ goto Exit;
+ }
+
+ if (p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign)
+ ui_mcast_fdb_assign_func_defined = TRUE;
+ else
+ ui_mcast_fdb_assign_func_defined = FALSE;
+
+ /*
+ Clear the multicast tables to start clean, then build
+ the spanning tree which sets the mcast table bits for each
+ port in the group.
+ We will clean the multicast tables if a ui_mcast function isn't
+ defined, or if such function is defined, but we got here
+ through a MC_CREATE request - this means we are creating a new
+ multicast group - clean all old data.
+ */
+ if ( ui_mcast_fdb_assign_func_defined == FALSE ||
+ req_type == OSM_MCAST_REQ_TYPE_CREATE )
+ __osm_mcast_mgr_clear( p_mgr, p_mgrp );
+
+ /* If a UI function is defined, then we will call it here.
+ If not - the use the regular build spanning tree function */
+ if ( ui_mcast_fdb_assign_func_defined == FALSE )
+ {
+ status = __osm_mcast_mgr_build_spanning_tree( p_mgr, p_mgrp );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_tree: ERR 0A17: "
+ "Unable to create spanning tree (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_tree: "
+ "Invoking UI function pfn_ui_mcast_fdb_assign\n");
+ }
+
+ p_mgr->p_subn->opt.pfn_ui_mcast_fdb_assign(
+ p_mgr->p_subn->opt.ui_mcast_fdb_assign_ctx,
+ mlid, req_type, port_guid );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+mcast_mgr_dump_sw_routes(
+ IN const osm_mcast_mgr_t* const p_mgr,
+ IN const osm_switch_t* const p_sw,
+ IN FILE *file )
+{
+ 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];
+
+ OSM_LOG_ENTER( p_mgr->p_log, mcast_mgr_dump_sw_routes );
+
+ if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ goto Exit;
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+ sprintf( sw_hdr, "\nSwitch 0x%016" PRIx64 "\n"
+ "LID : 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++;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+struct mcast_mgr_dump_context {
+ osm_mcast_mgr_t *p_mgr;
+ FILE *file;
+};
+
+static void
+mcast_mgr_dump_table(cl_map_item_t *p_map_item, void *context)
+{
+ osm_switch_t *p_sw = (osm_switch_t *)p_map_item;
+ struct mcast_mgr_dump_context *cxt = context;
+
+ mcast_mgr_dump_sw_routes(cxt->p_mgr, p_sw, cxt->file);
+}
+
+static void
+mcast_mgr_dump_mcast_routes(osm_mcast_mgr_t *p_mgr)
+{
+ char file_name[1024];
+ struct mcast_mgr_dump_context dump_context;
+ FILE *file;
+
+ if (!osm_log_is_active(p_mgr->p_log, OSM_LOG_ROUTING))
+ return;
+
+ snprintf(file_name, sizeof(file_name), "%s/%s",
+ p_mgr->p_subn->opt.dump_files_dir, "osm.mcfdbs");
+
+ file = fopen(file_name, "w");
+ if (!file) {
+ osm_log(p_mgr->p_log, OSM_LOG_ERROR,
+ "mcast_dump_mcast_routes: ERR 0A18: "
+ "cannot create mcfdb file \'%s\': %s\n",
+ file_name, strerror(errno));
+ return;
+ }
+
+ dump_context.p_mgr = p_mgr;
+ dump_context.file = file;
+
+ cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl,
+ mcast_mgr_dump_table, &dump_context);
+
+ fclose(file);
+}
+
+/**********************************************************************
+ Process the entire group.
+
+ NOTE : The lock should be held externally!
+ **********************************************************************/
+static osm_signal_t
+osm_mcast_mgr_process_mgrp(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN osm_mgrp_t* const p_mgrp,
+ IN osm_mcast_req_type_t req_type,
+ IN ib_net64_t port_guid )
+{
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+ ib_api_status_t status;
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_sw_tbl;
+ boolean_t pending_transactions = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp, req_type, port_guid );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process_mgrp: ERR 0A19: "
+ "Unable to create spanning tree (%s)\n",
+ ib_get_err_str( status ) );
+
+ goto Exit;
+ }
+
+ /*
+ Walk the switches and download the tables for each.
+ */
+ p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+ while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+ if( signal == OSM_SIGNAL_DONE_PENDING )
+ pending_transactions = TRUE;
+
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ mcast_mgr_dump_mcast_routes( p_mgr );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ if( pending_transactions == TRUE )
+ return( OSM_SIGNAL_DONE_PENDING );
+ else
+ return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process(
+ IN osm_mcast_mgr_t* const p_mgr )
+{
+ osm_signal_t signal;
+ osm_switch_t* p_sw;
+ cl_qmap_t* p_sw_tbl;
+ cl_qmap_t* p_mcast_tbl;
+ osm_mgrp_t* p_mgrp;
+ ib_api_status_t status;
+ boolean_t pending_transactions = FALSE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ p_mcast_tbl = &p_mgr->p_subn->mgrp_mlid_tbl;
+ /*
+ While holding the lock, iterate over all the established
+ multicast groups, servicing each in turn.
+
+ Then, download the multicast tables to the switches.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+
+ p_mgrp = (osm_mgrp_t*)cl_qmap_head( p_mcast_tbl );
+ while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( p_mcast_tbl ) )
+ {
+ /* We reached here due to some change that caused a heavy sweep
+ of the subnet. Not due to a specific multicast request.
+ So the request type is subnet_change and the port guid is 0. */
+ status = osm_mcast_mgr_process_tree( p_mgr, p_mgrp,
+ OSM_MCAST_REQ_TYPE_SUBNET_CHANGE, 0);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_mcast_mgr_process: ERR 0A20: "
+ "Unable to create spanning tree (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ /*
+ Walk the switches and download the tables for each.
+ */
+ p_sw = (osm_switch_t*)cl_qmap_head( p_sw_tbl );
+ while( p_sw != (osm_switch_t*)cl_qmap_end( p_sw_tbl ) )
+ {
+ signal = __osm_mcast_mgr_set_tbl( p_mgr, p_sw );
+ if( signal == OSM_SIGNAL_DONE_PENDING )
+ pending_transactions = TRUE;
+
+ p_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+ }
+
+ mcast_mgr_dump_mcast_routes( p_mgr );
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ if( pending_transactions == TRUE )
+ return( OSM_SIGNAL_DONE_PENDING );
+ else
+ return( OSM_SIGNAL_DONE );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+osm_mgrp_t *
+__get_mgrp_by_mlid(
+ IN osm_mcast_mgr_t* const p_mgr,
+ IN ib_net16_t const mlid)
+{
+ cl_map_item_t *map_item;
+
+ map_item = cl_qmap_get(&p_mgr->p_subn->mgrp_mlid_tbl, mlid);
+ if(map_item == cl_qmap_end(&p_mgr->p_subn->mgrp_mlid_tbl))
+ {
+ return NULL;
+ }
+ return (osm_mgrp_t *)map_item;
+}
+
+/**********************************************************************
+ This is the function that is invoked during idle time to handle the
+ process request. Context1 is simply the osm_mcast_mgr_t*, Context2
+ hold the mlid, port guid and action (join/leave/delete) required.
+ **********************************************************************/
+osm_signal_t
+osm_mcast_mgr_process_mgrp_cb(
+ IN void* const Context1,
+ IN void* const Context2 )
+{
+ osm_mcast_mgr_t* p_mgr = (osm_mcast_mgr_t*)Context1;
+ osm_mgrp_t* p_mgrp;
+ ib_net16_t mlid;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+ osm_mcast_mgr_ctxt_t* p_ctxt = (osm_mcast_mgr_ctxt_t*)Context2;
+ osm_mcast_req_type_t req_type = p_ctxt->req_type;
+ ib_net64_t port_guid = p_ctxt->port_guid;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_mcast_mgr_process_mgrp_cb );
+
+ /* nice copy no warning on size diff */
+ memcpy(&mlid, &p_ctxt->mlid, sizeof(mlid));
+
+ /* we can destroy the context now */
+ free(p_ctxt);
+
+ /* we need a lock to make sure the p_mgrp is not change other ways */
+ CL_PLOCK_EXCL_ACQUIRE( p_mgr->p_lock );
+ p_mgrp = __get_mgrp_by_mlid( p_mgr, mlid);
+
+ /* since we delayed the execution we prefer to pass the
+ mlid as the mgrp identifier and then find it or abort */
+
+ if (p_mgrp)
+ {
+
+ /* if there was no change from the last time we processed the group
+ we can skip doing anything
+ */
+ if ( p_mgrp->last_change_id == p_mgrp->last_tree_id)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Skip processing mgrp with lid:0x%X change id:%u\n",
+ cl_ntoh16(mlid), p_mgrp->last_change_id );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Processing mgrp with lid:0x%X change id:%u\n",
+ cl_ntoh16(mlid), p_mgrp->last_change_id );
+
+ signal =
+ osm_mcast_mgr_process_mgrp( p_mgr, p_mgrp, req_type, port_guid );
+ p_mgrp->last_tree_id = p_mgrp->last_change_id;
+ }
+
+ /* Remove MGRP only if osm_mcm_port_t count is 0 and
+ * Not a well known group
+ */
+ if((0x0 == cl_qmap_count(&p_mgrp->mcm_port_tbl)) &&
+ (p_mgrp->well_known == FALSE))
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_mcast_mgr_process_mgrp_cb: "
+ "Destroying mgrp with lid:0x%X\n",
+ cl_ntoh16(mlid) );
+
+ /* Send a Report to any InformInfo registered for
+ Trap 67 : MCGroup delete */
+ osm_mgrp_send_delete_notice( p_mgr->p_subn, p_mgr->p_log, p_mgrp );
+
+ cl_qmap_remove_item(&p_mgr->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_mgrp );
+
+ osm_mgrp_destroy(p_mgrp);
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return signal;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcast_tbl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcast_tbl_t.
+ * This object represents an multicast forwarding table.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_mcast_tbl.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcast_tbl_init(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN uint8_t const num_ports,
+ IN uint16_t const 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( IB_SUCCESS );
+ }
+
+ 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);
+
+ p_tbl->max_mlid_ho = (uint16_t)(IB_LID_MCAST_START_HO + capacity);
+
+ /*
+ 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.
+ */
+ p_tbl->p_mask_tbl = malloc( p_tbl->num_entries *
+ (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 );
+
+ if( p_tbl->p_mask_tbl == NULL )
+ return( IB_INSUFFICIENT_MEMORY );
+
+ memset(p_tbl->p_mask_tbl, 0,
+ p_tbl->num_entries * (IB_MCAST_POSITION_MAX + 1) * IB_MCAST_MASK_SIZE / 8 );
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_destroy(
+ IN osm_mcast_tbl_t* const p_tbl )
+{
+ free( p_tbl->p_mask_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcast_tbl_set(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port )
+{
+ uintn_t mlid_offset;
+ uintn_t mask_offset;
+ uintn_t bit_mask;
+ int16_t block_num;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+ CL_ASSERT( mlid_ho <= p_tbl->max_mlid_ho );
+ CL_ASSERT( p_tbl->p_mask_tbl );
+
+ 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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_is_port(
+ IN const osm_mcast_tbl_t* const p_tbl,
+ IN const uint16_t mlid_ho,
+ IN const uint8_t port_num )
+{
+ uintn_t mlid_offset;
+ uintn_t mask_offset;
+ uintn_t 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* const p_tbl,
+ IN const uint16_t mlid_ho )
+{
+ uintn_t 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* const p_tbl,
+ IN const ib_net16_t* const p_block,
+ IN const int16_t block_num,
+ IN const 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 > p_tbl->max_mlid_ho )
+ 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* const p_tbl,
+ IN const uint16_t mlid_ho )
+{
+ uint8_t i;
+ uintn_t mlid_offset;
+
+ CL_ASSERT( p_tbl );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+
+ if( p_tbl->p_mask_tbl && (mlid_ho <= p_tbl->max_mlid_ho) )
+ {
+ mlid_offset = mlid_ho - IB_LID_MCAST_START_HO;
+ for( i = 0; i <= p_tbl->max_position; i++ )
+ (*p_tbl->p_mask_tbl)[mlid_offset][i] = 0;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mcast_tbl_get_block(
+ IN osm_mcast_tbl_t* const p_tbl,
+ IN int16_t const block_num,
+ IN uint8_t const position,
+ OUT ib_net16_t* const 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 );
+ }
+
+ mlid_start_ho = (uint16_t)(block_num * IB_MCAST_BLOCK_SIZE);
+
+ if( mlid_start_ho + IB_MCAST_BLOCK_SIZE > p_tbl->max_mlid_ho )
+ return( IB_INVALID_PARAMETER );
+
+ for( i = 0; i < IB_MCAST_BLOCK_SIZE; i++ )
+ p_block[i] = (*p_tbl->p_mask_tbl)[mlid_start_ho + i][position];
+
+ return( TRUE );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcm_info.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Declaration of osm_mcm_info_t.
+ * This object represents a Multicast Forwarding Information object.
+ * This object is part of the OpenSM family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <opensm/osm_mcm_info.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_destroy(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ CL_ASSERT( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_init(
+ IN osm_mcm_info_t* const p_mcm,
+ IN const ib_net16_t mlid )
+{
+ CL_ASSERT( p_mcm );
+ p_mcm->mlid = mlid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_info_t*
+osm_mcm_info_new(
+ IN const ib_net16_t mlid )
+{
+ osm_mcm_info_t* p_mcm;
+
+ p_mcm = (osm_mcm_info_t*)malloc( sizeof(*p_mcm) );
+ if( p_mcm )
+ {
+ memset(p_mcm, 0, sizeof(*p_mcm) );
+ osm_mcm_info_init( p_mcm, mlid );
+ }
+
+ return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_info_delete(
+ IN osm_mcm_info_t* const p_mcm )
+{
+ osm_mcm_info_destroy( p_mcm );
+ free( p_mcm );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mcm_port.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_mcm_port.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_construct(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ memset( p_mcm, 0, sizeof(*p_mcm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_destroy(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ /*
+ Nothing to do?
+ */
+ UNUSED_PARAM( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_init(
+ IN osm_mcm_port_t* const p_mcm,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join )
+{
+ CL_ASSERT( p_mcm );
+ CL_ASSERT( p_port_gid );
+ CL_ASSERT( scope_state );
+
+ osm_mcm_port_construct( p_mcm );
+ p_mcm->port_gid = *p_port_gid;
+ p_mcm->scope_state = scope_state;
+ p_mcm->proxy_join = proxy_join;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mcm_port_new(
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t scope_state,
+ IN const boolean_t proxy_join )
+{
+ osm_mcm_port_t* p_mcm;
+
+ p_mcm = malloc( sizeof(*p_mcm) );
+ if( p_mcm )
+ {
+ osm_mcm_port_init( p_mcm, p_port_gid,
+ scope_state, proxy_join );
+ }
+
+ return( p_mcm );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcm_port_delete(
+ IN osm_mcm_port_t* const p_mcm )
+{
+ CL_ASSERT( p_mcm );
+
+ osm_mcm_port_destroy( p_mcm );
+ free( p_mcm );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_mtree.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mtree_node_t.
+ * This file implements the Multicast Tree object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_mtree.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_node_init(
+ IN osm_mtree_node_t* const p_mtn,
+ IN const osm_switch_t* const p_sw )
+{
+ uint32_t i;
+
+ CL_ASSERT( p_mtn );
+ CL_ASSERT( p_sw );
+
+ osm_mtree_node_construct( p_mtn );
+
+ p_mtn->p_sw = (osm_switch_t*)p_sw;
+ p_mtn->max_children = osm_switch_get_num_ports( p_sw );
+
+ for( i = 0; i < p_mtn->max_children; i++ )
+ p_mtn->child_array[i] = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mtree_node_t*
+osm_mtree_node_new(
+ IN const osm_switch_t* const p_sw )
+{
+ osm_mtree_node_t *p_mtn;
+
+ p_mtn = malloc( sizeof(osm_mtree_node_t) +
+ sizeof(void*) * (osm_switch_get_num_ports( p_sw ) - 1) );
+
+ if( p_mtn != NULL )
+ osm_mtree_node_init( p_mtn, p_sw );
+
+ return( p_mtn );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mtree_destroy(
+ IN osm_mtree_node_t *p_mtn )
+{
+ uint32_t i;
+
+ if (p_mtn == NULL)
+ return;
+
+ if ( p_mtn->child_array != NULL )
+ 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_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) )
+ __osm_mtree_dump(p_mtn->child_array[i]);
+ }
+ }
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_multicast.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of multicast functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_mcm_port.h>
+#include <opensm/osm_mtree.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+/* osm_mcast_req_type_t values converted to test for easier printing. */
+const char* osm_mcast_req_type_str[] =
+{
+ "OSM_MCAST_REQ_TYPE_CREATE",
+ "OSM_MCAST_REQ_TYPE_JOIN",
+ "OSM_MCAST_REQ_TYPE_LEAVE",
+ "OSM_MCAST_REQ_TYPE_SUBNET_CHANGE"
+};
+
+const char*
+osm_get_mcast_req_type_str(
+ IN osm_mcast_req_type_t req_type )
+{
+ if ( req_type > OSM_MCAST_REQ_TYPE_SUBNET_CHANGE )
+ req_type = OSM_MCAST_REQ_TYPE_SUBNET_CHANGE;
+ return( osm_mcast_req_type_str[req_type] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_construct(
+ IN osm_mgrp_t* const p_mgrp )
+{
+ memset( p_mgrp, 0, sizeof(*p_mgrp) );
+ cl_qmap_init( &p_mgrp->mcm_port_tbl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_destroy(
+ IN osm_mgrp_t* const p_mgrp )
+{
+ osm_mcm_port_t *p_mcm_port;
+ osm_mcm_port_t *p_next_mcm_port;
+
+ CL_ASSERT(p_mgrp);
+
+ 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 );
+ }
+ /* destroy the mtree_node structure */
+ osm_mtree_destroy(p_mgrp->p_root);
+
+ free(p_mgrp);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_init(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net16_t mlid )
+{
+ CL_ASSERT( p_mgrp );
+ CL_ASSERT( cl_ntoh16( mlid ) >= IB_LID_MCAST_START_HO );
+
+ osm_mgrp_construct( p_mgrp );
+ p_mgrp->mlid = mlid;
+ p_mgrp->last_change_id = 0;
+ p_mgrp->last_tree_id = 0;
+ p_mgrp->to_be_deleted = FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mgrp_t*
+osm_mgrp_new(
+ IN const ib_net16_t mlid )
+{
+ osm_mgrp_t* p_mgrp;
+
+ p_mgrp = (osm_mgrp_t*)malloc( sizeof(*p_mgrp) );
+ if( p_mgrp )
+ osm_mgrp_init( p_mgrp, mlid );
+
+ return( p_mgrp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_mcm_port_t*
+osm_mgrp_add_port(
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_gid_t* const p_port_gid,
+ IN const uint8_t join_state,
+ IN boolean_t proxy_join )
+{
+ ib_net64_t port_guid;
+ osm_mcm_port_t *p_mcm_port;
+ cl_map_item_t *prev_item;
+ uint8_t prev_join_state;
+ uint8_t prev_scope;
+
+ p_mcm_port = osm_mcm_port_new( p_port_gid, join_state, proxy_join );
+ if( p_mcm_port )
+ {
+ port_guid = p_port_gid->unicast.interface_id;
+
+ /*
+ 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( &p_mgrp->mcm_port_tbl,
+ port_guid, &p_mcm_port->map_item );
+
+ /* if already exists - revert the insertion and only update join state */
+ if( prev_item != &p_mcm_port->map_item )
+ {
+
+ osm_mcm_port_delete( p_mcm_port );
+ p_mcm_port =(osm_mcm_port_t *) prev_item;
+
+ /*
+ o15.0.1.11
+ Join state of the end port should be the or of the
+ previous setting with the current one
+ */
+ ib_member_get_scope_state(p_mcm_port->scope_state, &prev_scope, &prev_join_state);
+ p_mcm_port->scope_state =
+ ib_member_set_scope_state(prev_scope, prev_join_state | join_state);
+
+ }
+ else
+ {
+ /* track the fact we modified the group ports */
+ p_mgrp->last_change_id++;
+ }
+ }
+
+ return( p_mcm_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_remove_port(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid )
+{
+ cl_map_item_t *p_map_item;
+
+ CL_ASSERT(p_mgrp);
+
+ p_map_item = cl_qmap_get( &p_mgrp->mcm_port_tbl, port_guid );
+
+ if( p_map_item != cl_qmap_end( &p_mgrp->mcm_port_tbl ) )
+ {
+ cl_qmap_remove_item( &p_mgrp->mcm_port_tbl,
+ p_map_item );
+ osm_mcm_port_delete((osm_mcm_port_t*)p_map_item);
+
+ /* track the fact we modified the group */
+ p_mgrp->last_change_id++;
+ }
+
+ /*
+ no more ports so the group will be deleted after re-route
+ but only if it is not a well known group and not already deleted
+ */
+ if ((cl_is_qmap_empty( &p_mgrp->mcm_port_tbl )) &&
+ (p_mgrp->well_known == FALSE) &&
+ (p_mgrp->to_be_deleted == FALSE))
+ {
+ p_mgrp->to_be_deleted = TRUE;
+
+ /* Send a Report to any InformInfo registered for
+ Trap 67 : MCGroup delete */
+ osm_mgrp_send_delete_notice( p_subn, p_log, p_mgrp );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_mgrp_is_port_present(
+ IN const osm_mgrp_t* const p_mgrp,
+ IN const ib_net64_t port_guid,
+ OUT osm_mcm_port_t ** const pp_mcm_port )
+{
+ cl_map_item_t *p_map_item;
+
+ CL_ASSERT(p_mgrp);
+
+ p_map_item = cl_qmap_get(&p_mgrp->mcm_port_tbl,
+ port_guid);
+
+ if (p_map_item != cl_qmap_end(&p_mgrp->mcm_port_tbl))
+ {
+ if (pp_mcm_port)
+ *pp_mcm_port = (osm_mcm_port_t *)p_map_item;
+ return TRUE;
+ }
+ if (pp_mcm_port)
+ *pp_mcm_port = NULL;
+ return FALSE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mgrp_apply_func_sub(
+ const osm_mgrp_t* const p_mgrp,
+ const osm_mtree_node_t* const p_mtn,
+ osm_mgrp_func_t p_func,
+ void* context )
+{
+ uint8_t i = 0;
+ uint8_t max_children;
+ osm_mtree_node_t* p_child_mtn;
+
+ /*
+ Call the user, then recurse.
+ */
+ p_func( p_mgrp, p_mtn, context );
+
+ max_children = osm_mtree_node_get_max_children( p_mtn );
+ for( i = 0; i < max_children; i++ )
+ {
+ p_child_mtn = osm_mtree_node_get_child( p_mtn, i );
+ if( p_child_mtn )
+ __osm_mgrp_apply_func_sub( p_mgrp, p_child_mtn, p_func, context );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_apply_func(
+ const osm_mgrp_t* const p_mgrp,
+ osm_mgrp_func_t p_func,
+ void* context )
+{
+ osm_mtree_node_t* p_mtn;
+
+ CL_ASSERT( p_mgrp );
+ CL_ASSERT( p_func );
+
+ p_mtn = p_mgrp->p_root;
+
+ if( p_mtn )
+ __osm_mgrp_apply_func_sub( p_mgrp, p_mtn, p_func, context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_delete_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp )
+{
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mgrp_send_delete_notice );
+
+ /* prepare the needed info */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* 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(67); /* delete of mcg */
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_subn->sm_base_lid;
+ /* following o14-12.1.11 and table 120 p726 */
+ /* we need to provide the MGID */
+ memcpy(&(notice.data_details.ntc_64_67.gid),
+ &(p_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 = p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_log, p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mgrp_send_delete_notice: ERR 7601: "
+ "Error sending trap reports (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mgrp_send_create_notice(
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_mgrp_t *p_mgrp )
+{
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mgrp_send_create_notice );
+
+ /* prepare the needed info */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* Generic SubnMgt type */
+ ib_notice_set_prod_type_ho(¬ice, 4); /* A Class Manager generator */
+ notice.g_or_v.generic.trap_num = CL_HTON16(66); /* create of mcg */
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_subn->sm_base_lid;
+ /* following o14-12.1.11 and table 120 p726 */
+ /* we need to provide the MGID */
+ memcpy(&(notice.data_details.ntc_64_67.gid),
+ &(p_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 = p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_subn->sm_port_guid;
+
+ status = osm_report_notice(p_log, p_subn, ¬ice);
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mgrp_send_create_notice: ERR 7602: "
+ "Error sending trap reports (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_node_t.
+ * This object represents an Infiniband Node.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_init_physp(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_physp_t *p_physp;
+ ib_net64_t port_guid;
+ ib_smp_t *p_smp;
+ ib_node_info_t *p_ni;
+ uint8_t port_num;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_guid = p_ni->port_guid;
+ port_num = ib_node_info_get_local_port_num( p_ni );
+
+ CL_ASSERT( port_num < p_node->physp_tbl_size );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ osm_physp_init( p_physp, 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* const p_madw )
+{
+ osm_node_t *p_node;
+ ib_smp_t *p_smp;
+ ib_node_info_t *p_ni;
+ uint8_t i;
+ uint32_t size;
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ p_ni = (ib_node_info_t*)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 != 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;
+
+ /*
+ 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 HCA's 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( osm_node_get_physp_ptr( p_node, i ) );
+
+ osm_node_init_physp( p_node, p_madw );
+ }
+
+ return( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_destroy(
+ IN osm_node_t *p_node )
+{
+ uint16_t i;
+
+ /* Cleanup all PhysPorts */
+ if( p_node != NULL )
+ {
+ /*
+ Cleanup all physports
+ */
+ for( i = 0; i < p_node->physp_tbl_size; i++ )
+ {
+ osm_physp_t *p_physp = osm_node_get_physp_ptr( p_node, i );
+ if (p_physp)
+ osm_physp_destroy( p_physp );
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_delete(
+ IN OUT osm_node_t** const p_node )
+{
+ osm_node_destroy( *p_node );
+ free( *p_node );
+ *p_node = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_node_link(
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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 );
+
+ 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const 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_is_valid( p_physp ) &&
+ osm_physp_is_valid( p_remote_physp ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_node_has_any_link(
+ IN osm_node_t* const p_node,
+ IN const 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 const osm_node_t* const p_node,
+ IN const 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( !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 const osm_node_t* const p_node,
+ IN const 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( osm_physp_is_valid( p_physp ) )
+ {
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ return( osm_physp_get_base_lid( p_remote_physp ) );
+ }
+
+ return( 0 );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_desc_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nd_rcv_t.
+ * This object represents the NodeDescription Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_desc_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_process_nd(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const ib_node_desc_t* const p_nd )
+{
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_nd_rcv_process_nd );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ memcpy( desc, p_nd, sizeof(*p_nd) );
+ /* Guarantee null termination before printing. */
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_nd_rcv_process_nd: "
+ "Node 0x%" PRIx64 "\n\t\t\t\tDescription = %s\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node )), desc );
+ }
+
+ memcpy( &p_node->node_desc.description, p_nd, sizeof(*p_nd) );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_construct(
+ IN osm_nd_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_destroy(
+ IN osm_nd_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_init(
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_nd_rcv_init );
+
+ osm_nd_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_process(
+ IN const osm_nd_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_node_desc_t *p_nd;
+ ib_smp_t *p_smp;
+ osm_node_t *p_node;
+ ib_net64_t node_guid;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nd_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_nd = (ib_node_desc_t*)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( p_rcv->p_lock );
+ p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, node_guid );
+
+ if( p_node == (osm_node_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nd_rcv_process: ERR 0B01: "
+ "NodeDescription received for nonexistent node "
+ "0x%" PRIx64 "\n", cl_ntoh64(node_guid) );
+ }
+ else
+ {
+ __osm_nd_rcv_process_nd( p_rcv, p_node, p_nd );
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_desc_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nd_rcv_ctrl_t.
+ * This object represents the NodeDescription request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_node_desc_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nd_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_nd_rcv_process( ((osm_nd_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_construct(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nd_rcv_ctrl_destroy(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nd_rcv_ctrl_init(
+ IN osm_nd_rcv_ctrl_t* const p_ctrl,
+ IN osm_nd_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_nd_rcv_ctrl_init );
+
+ osm_nd_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_DESC,
+ __osm_nd_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_nd_rcv_ctrl_init: ERR 0C01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ni_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_router.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_set_links(
+ IN const osm_ni_rcv_t* const p_rcv,
+ osm_node_t* p_node,
+ const uint8_t port_num,
+ const osm_ni_context_t* const p_ni_context )
+{
+ cl_qmap_t *p_guid_tbl;
+ osm_node_t *p_neighbor_node;
+ osm_node_t *p_old_neighbor_node;
+ uint8_t old_neighbor_port_num;
+ osm_physp_t *p_physp, *p_old_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_set_links );
+
+ /*
+ 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 )
+ {
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_neighbor_node = (osm_node_t*)cl_qmap_get( p_guid_tbl,
+ p_ni_context->node_guid );
+ if( p_neighbor_node == (osm_node_t*)cl_qmap_end( p_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D10: "
+ "Unexpected removal of neighbor node "
+ "0x%" PRIx64 "\n",
+ cl_ntoh64( p_ni_context->node_guid ) );
+ }
+ else
+ {
+ /*
+ We have seen this neighbor node before, but we might
+ not have seen this port on the neighbor node before.
+ We should not set links to an uninitialized port on the
+ neighbor, so check validity up front. If it's not
+ valid, do nothing, since we'll see this link again
+ when we probe the neighbor.
+ */
+ if( 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Link already exists\n" );
+ }
+ else
+ {
+ if( osm_node_has_any_link( p_node, port_num ) &&
+ p_rcv->p_subn->force_immediate_heavy_sweep == FALSE )
+ {
+ /*
+ Uh oh...
+ This means that we found 2 nodes with the same guid,
+ or a 12x link with lane reversal that is not configured correctly.
+ If the force_immediate_heavy_sweep == TRUE, then this might be a case
+ of port being moved (causing trap 128), and thus rediscovered.
+ In this case, just continue. There will be another heavy sweep
+ immediately after, when the subnet is stable again.
+ */
+ char line[BUF_SIZE];
+ char dr_new_path[BUF_SIZE];
+ char dr_old_path[BUF_SIZE];
+ uint32_t i;
+ osm_dr_path_t *p_path = NULL, *p_old_path = NULL;
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ sprintf( dr_new_path, "no_path_available" );
+ if (p_physp)
+ {
+ p_path = osm_physp_get_dr_path_ptr( p_physp );
+ if ( p_path )
+ {
+ sprintf( dr_new_path, "new path:" );
+ for (i = 0; i <= p_path->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_path->path[i] );
+ strcat( dr_new_path, line );
+ }
+ }
+ }
+
+ p_old_neighbor_node = osm_node_get_remote_node(
+ p_node, port_num, &old_neighbor_port_num );
+ p_old_physp = osm_node_get_physp_ptr(
+ p_old_neighbor_node,
+ old_neighbor_port_num);
+ sprintf( dr_old_path, "no_path_available" );
+ if (p_old_physp)
+ {
+ p_old_path = osm_physp_get_dr_path_ptr( p_old_physp );
+ if ( p_old_path )
+ {
+ sprintf( dr_old_path, "old_path:" );
+ for (i = 0; i <= p_old_path->hop_count; i++ )
+ {
+ sprintf( line, "[%X]", p_old_path->path[i] );
+ strcat( dr_old_path, line );
+ }
+ }
+ }
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D01: "
+ "Found duplicated guids or 12x link "
+ "with lane reversal badly configured.\n"
+ "Overriding existing link to:"
+ "node 0x%" PRIx64 ", port number 0x%X connected to:\n"
+ "\t\t\t\told node 0x%" PRIx64 ", "
+ "port number 0x%X %s\n"
+ "\t\t\t\tnew node 0x%" PRIx64 ", "
+ "port number 0x%X %s\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( osm_node_get_node_guid(
+ p_old_neighbor_node ) ),
+ old_neighbor_port_num ,
+ dr_old_path,
+ cl_ntoh64( p_ni_context->node_guid ),
+ p_ni_context->port_num,
+ dr_new_path
+ );
+
+ osm_log( p_rcv->p_log, OSM_LOG_SYS,
+ "FATAL: duplicated guids or 12x lane reversal\n");
+
+ if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_SYS, "Exiting\n");
+ exit( 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))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_set_links: ERR 0D18: "
+ "Duplicate GUID found by link from a port to itself:"
+ "node 0x%" PRIx64 ", port number 0x%X\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_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(p_physp),
+ OSM_LOG_ERROR);
+
+ osm_log( p_rcv->p_log, OSM_LOG_SYS,
+ "Errors on subnet. Duplicate GUID found "
+ "by link from a port to itself. "
+ "See osm log for more details\n");
+
+ if ( p_rcv->p_subn->opt.exit_on_fatal == TRUE )
+ exit( 1 );
+ }
+ else
+ {
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Creating new link between: "
+ "\n\t\t\t\tnode 0x%" PRIx64 ", "
+ "port number 0x%X and"
+ "\n\t\t\t\tnode 0x%" PRIx64 ", "
+ "port number 0x%X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ port_num,
+ cl_ntoh64( p_ni_context->node_guid ),
+ p_ni_context->port_num );
+ }
+
+ CL_ASSERT( osm_node_get_node_guid( p_neighbor_node ) ==
+ p_ni_context->node_guid );
+
+ osm_node_link( p_node, port_num, p_neighbor_node,
+ p_ni_context->port_num );
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_set_links: "
+ "Nothing to link for our own node 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_node(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_physp;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_node );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)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 );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+ osm_dr_path_get_bind_handle(
+ osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+ context.pi_context.node_guid = p_ni->node_guid;
+ context.pi_context.port_guid = p_ni->port_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new_node: ERR 0D02: "
+ "Failure initiating PortInfo request (%s)\n",
+ ib_get_err_str(status));
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_get_node_desc(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_physp;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_get_node_desc );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)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 );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_madw_get_bind_handle( p_madw ) ==
+ osm_dr_path_get_bind_handle(
+ osm_physp_get_dr_path_ptr( p_physp ) ) );
+
+ context.nd_context.node_guid = osm_node_get_node_guid( p_node );
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_NODE_DESC,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_get_node_desc: ERR 0D03: "
+ "Failure initiating NodeDescription request (%s)\n",
+ ib_get_err_str(status));
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_ca_or_router(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_ca_or_router );
+
+ __osm_ni_rcv_process_new_node( p_rcv, 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 )
+ {
+ p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_ca_or_router(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_port_t *p_port;
+ osm_port_t *p_port_check;
+ cl_qmap_t *p_guid_tbl;
+ osm_madw_context_t context;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+ ib_api_status_t status;
+ osm_dr_path_t *p_dr_path;
+ osm_bind_handle_t h_bind;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_ca_or_router );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+ port_num = ib_node_info_get_local_port_num( p_ni );
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ h_bind = osm_madw_get_bind_handle( p_madw );
+
+ /*
+ Determine if we have encountered this node through a
+ previously undiscovered port. If so, build the new
+ port object.
+ */
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, p_ni->port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_existing_ca_or_router: "
+ "Creating new port object with GUID 0x%" PRIx64 "\n",
+ cl_ntoh64( p_ni->port_guid ) );
+
+ osm_node_init_physp( p_node, p_madw );
+
+ p_port = osm_port_new( p_ni, p_node );
+ if( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing_ca_or_router: 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( p_guid_tbl,
+ p_ni->port_guid, &p_port->map_item );
+ if( p_port_check != p_port )
+ {
+ /*
+ We should never be here!
+ Somehow, this port GUID already exists in the table.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D12: "
+ "Port 0x%" PRIx64 " already in the database!\n",
+ cl_ntoh64( p_ni->port_guid ) );
+
+ osm_port_delete( &p_port );
+ goto Exit;
+ }
+
+ /* If we are a master, then this means the port is new on the subnet.
+ Add it to the new_ports_list - 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 ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ cl_status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D08: "
+ "Error %s adding to list\n",
+ CL_STATUS_MSG( cl_status ) );
+ osm_port_delete( &p_port );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_existing_ca_or_router: "
+ "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+ cl_ntoh64(osm_node_get_node_guid( p_port->p_node )) );
+ }
+ }
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ }
+ else
+ {
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+
+ if ( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D19: "
+ "Invalid physical port. Aborting discovery\n");
+ 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, h_bind, p_smp->hop_count,
+ p_smp->initial_path );
+ }
+
+ context.pi_context.node_guid = p_ni->node_guid;
+ context.pi_context.port_guid = p_ni->port_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+
+ status = osm_req_get( p_rcv->p_gen_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing_ca_or_router: ERR 0D13: "
+ "Failure initiating PortInfo request (%s)\n",
+ ib_get_err_str(status));
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ni_rcv_process_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_dr_path_t dr_path;
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_switch );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ osm_dr_path_init( &dr_path,
+ osm_madw_get_bind_handle( p_madw ),
+ 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;
+
+ /* Request a SwitchInfo attribute */
+ status = osm_req_get( p_rcv->p_gen_req,
+ &dr_path,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue despite error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_switch: ERR 0D06: "
+ "Failure initiating SwitchInfo request (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_existing_switch );
+
+ /*
+ If this switch has already been probed during this sweep,
+ then don't bother reprobing it.
+ There is one exception - if the node has been visited, but
+ for some reason we don't have the switch object (this can happen
+ if the SwitchInfo mad didn't reach the SM) then we want
+ to retry to probe the switch.
+ */
+ if( osm_node_discovery_count_get( p_node ) == 1 )
+ __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+ else
+ {
+ /* Make sure we have SwitchInfo on this node */
+ if( !p_node->sw || osm_switch_discovery_count_get( p_node->sw ) == 0 )
+ {
+ /* we don't have the SwitchInfo - retry to get it */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_existing_switch: "
+ "Retry to get SwitchInfo on node GUID:0x%"
+ PRIx64 "\n", cl_ntoh64(osm_node_get_node_guid(p_node)) );
+ __osm_ni_rcv_process_switch( p_rcv, p_node, p_madw );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new_switch(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new_switch );
+
+ __osm_ni_rcv_process_switch( p_rcv, 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 )
+ {
+ p_rcv->p_subn->sm_port_guid = p_node->node_info.port_guid;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must NOT be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_new(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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_node_guid_tbl;
+ cl_qmap_t *p_port_guid_tbl;
+ 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;
+ uint8_t port_num;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_ni_rcv_process_new );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)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( p_rcv->p_log, p_smp, OSM_LOG_VERBOSE );
+
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_new: "
+ "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 ) );
+
+ p_node = osm_node_new( p_madw );
+ if( p_node == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: 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( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D14: "
+ "Unable to create new port object\n" );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+
+ /* If there were RouterInfo or other router attribute,
+ this would be elsewhere */
+ if ( p_ni->node_type == IB_NODE_TYPE_ROUTER )
+ {
+ p_rtr = osm_router_new( p_port );
+ if ( p_rtr == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D1A: "
+ "Unable to create new router object\n" );
+ }
+ }
+
+ /*
+ Add the new port object to the database.
+ */
+ p_port_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ p_port_check = (osm_port_t*)cl_qmap_insert( p_port_guid_tbl,
+ p_ni->port_guid,
+ &p_port->map_item );
+ if( p_port_check != p_port )
+ {
+ /*
+ We should never be here!
+ Somehow, this port GUID already exists in the table.
+ */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D15: "
+ "Duplicate Port GUID 0x%" PRIx64 "! Found by the two directed routes:\n",
+ cl_ntoh64( p_ni->port_guid ) );
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(
+ osm_port_get_default_phys_ptr ( p_port) ),
+ OSM_LOG_ERROR);
+ osm_dump_dr_path(p_rcv->p_log,
+ osm_physp_get_dr_path_ptr(
+ osm_port_get_default_phys_ptr ( p_port_check) ),
+ OSM_LOG_ERROR);
+ if ( p_rtr )
+ osm_router_delete( &p_rtr );
+ osm_port_delete( &p_port );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+
+ /* If we are a master, then this means the port is new on the subnet.
+ Add it to the new_ports_list - 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 ( p_rcv->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ status = cl_list_insert_tail( &p_rcv->p_subn->new_ports_list, p_port );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D05: "
+ "Error %s adding to new_ports_list\n",
+ CL_STATUS_MSG( status ) );
+ if ( p_rtr )
+ osm_router_delete( &p_rtr );
+ osm_port_delete( &p_port );
+ osm_node_delete( &p_node );
+ goto Exit;
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_ni_rcv_process_new: "
+ "Adding port GUID:0x%016" PRIx64 " to new_ports_list\n",
+ cl_ntoh64( osm_node_get_node_guid( p_port->p_node ) ) );
+ }
+ }
+
+ if ( p_rtr && p_ni->node_type == IB_NODE_TYPE_ROUTER )
+ {
+ p_rtr_guid_tbl = &p_rcv->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( p_rtr_check != p_rtr )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: ERR 0D1B: "
+ "Unable to add port GUID:0x%016" PRIx64 " to router table\n",
+ cl_ntoh64( p_ni->port_guid ) );
+ }
+ }
+
+ p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_node_check = (osm_node_t*)cl_qmap_insert( p_node_guid_tbl,
+ p_ni->node_guid,
+ &p_node->map_item );
+ if( 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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_new: "
+ "Discovery race detected at node 0x%" PRIx64 "\n",
+ cl_ntoh64( p_ni->node_guid ) );
+ osm_node_delete( &p_node );
+ p_node = p_node_check;
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+ goto Exit;
+ }
+ else
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+ osm_node_discovery_count_inc( p_node );
+ __osm_ni_rcv_get_node_desc( p_rcv, p_node, p_madw );
+
+ switch( p_ni->node_type )
+ {
+ case IB_NODE_TYPE_CA:
+ case IB_NODE_TYPE_ROUTER:
+ __osm_ni_rcv_process_new_ca_or_router( p_rcv, p_node, p_madw );
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ __osm_ni_rcv_process_new_switch( p_rcv, p_node, p_madw );
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_new: 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( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_ni_rcv_process_existing(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const 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( p_rcv->p_log, __osm_ni_rcv_process_existing );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)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 );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_ni_rcv_process_existing: "
+ "Rediscovered %s node 0x%" PRIx64
+ "\n\t\t\t\tTID 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 ),
+ osm_node_discovery_count_get( p_node ) );
+ }
+
+ /*
+ If we haven't already encountered this existing node
+ on this particular sweep, then process further.
+ */
+ osm_node_discovery_count_inc( p_node );
+
+ switch( p_ni->node_type )
+ {
+ case IB_NODE_TYPE_CA:
+ case IB_NODE_TYPE_ROUTER:
+ __osm_ni_rcv_process_existing_ca_or_router( p_rcv, p_node, p_madw );
+ break;
+
+ case IB_NODE_TYPE_SWITCH:
+ __osm_ni_rcv_process_existing_switch( p_rcv, p_node, p_madw );
+ break;
+
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_ni_rcv_process_existing: ERR 0D09: "
+ "Unknown node type %u with GUID 0x%" PRIx64 "\n",
+ p_ni->node_type, cl_ntoh64( p_ni->node_guid ) );
+ break;
+ }
+
+ __osm_ni_rcv_set_links( p_rcv, p_node, port_num, p_ni_context );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_construct(
+ IN osm_ni_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_destroy(
+ IN osm_ni_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_init(
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_ni_rcv_init );
+
+ osm_ni_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_gen_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_process(
+ IN const osm_ni_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ ib_node_info_t *p_ni;
+ ib_smp_t *p_smp;
+ osm_node_t *p_node;
+ boolean_t process_new_flag = FALSE;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_ni_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_ni = (ib_node_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_NODE_INFO );
+
+ if (p_ni->node_guid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_process: ERR 0D16: "
+ "Got Zero Node GUID! Found on the directed route:\n");
+ osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+ goto Exit;
+ }
+
+ if (p_ni->port_guid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_process: ERR 0D17: "
+ "Got Zero Port GUID! Found on the directed route:\n");
+ osm_dump_smp_dr_path(p_rcv->p_log, p_smp, OSM_LOG_ERROR);
+ goto Exit;
+ }
+
+ p_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+
+ /*
+ Determine if this node has already been discovered,
+ and process accordingly.
+ During processing of this node, hold the shared lock.
+ */
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_node = (osm_node_t*)cl_qmap_get( p_guid_tbl, p_ni->node_guid );
+
+ osm_dump_node_info( p_rcv->p_log, p_ni, OSM_LOG_DEBUG );
+
+ if( p_node == (osm_node_t*)cl_qmap_end(p_guid_tbl) )
+ {
+ __osm_ni_rcv_process_new( p_rcv, p_madw );
+ process_new_flag = TRUE;
+ }
+ else
+ __osm_ni_rcv_process_existing( p_rcv, p_node, p_madw );
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /*
+ * If we processed a new node - need to signal to the state_mgr that
+ * change detected. BUT - we cannot call the osm_state_mgr_process
+ * from within the lock of p_rcv->p_lock (can cause a deadlock).
+ */
+ if ( process_new_flag )
+ osm_state_mgr_process( p_rcv->p_state_mgr, OSM_SIGNAL_CHANGE_DETECTED );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_node_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ni_rcv_ctrl_t.
+ * This object represents the NodeInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_node_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_ni_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_ni_rcv_process( ((osm_ni_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_construct(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ni_rcv_ctrl_destroy(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ni_rcv_ctrl_init(
+ IN osm_ni_rcv_ctrl_t* const p_ctrl,
+ IN osm_ni_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_ni_rcv_ctrl_init );
+
+ osm_ni_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_INFO,
+ __osm_ni_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_ni_rcv_ctrl_init: ERR 0E01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_opensm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_opensm_t.
+ * This object represents the opensm super object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_dispatcher.h>
+#include <complib/cl_passivelock.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_version.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_vl15intf.h>
+
+struct routing_engine_module {
+ const char *name;
+ int (*setup)(osm_opensm_t *p_osm);
+};
+
+extern int osm_ucast_updn_setup(osm_opensm_t *p_osm);
+extern int osm_ucast_file_setup(osm_opensm_t *p_osm);
+extern int osm_ucast_ftree_setup(osm_opensm_t *p_osm);
+
+static int osm_ucast_null_setup(osm_opensm_t *p_osm);
+
+const static struct routing_engine_module routing_modules[] = {
+ { "null", osm_ucast_null_setup },
+ { "updn", osm_ucast_updn_setup },
+ { "file", osm_ucast_file_setup },
+ { "ftree", osm_ucast_ftree_setup },
+ { NULL, NULL }
+};
+
+static int setup_routing_engine(osm_opensm_t *p_osm, const char *name)
+{
+ const struct routing_engine_module *r;
+
+ for (r = routing_modules; r->name && *r->name; r++) {
+ if(!strcmp(r->name, name)) {
+ p_osm->routing_engine.name = r->name;
+ if (r->setup(p_osm)) {
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "setup_routing_engine: setup of routing"
+ " engine \'%s\' failed\n", name);
+ return -2;
+ }
+ osm_log (&p_osm->log, OSM_LOG_DEBUG,
+ "setup_routing_engine: "
+ "\'%s\' routing engine set up\n",
+ p_osm->routing_engine.name);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int osm_ucast_null_setup(osm_opensm_t *p_osm)
+{
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "osm_ucast_null_setup: nothing yet - "
+ "will use default routing engine\n");
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_construct(
+ IN osm_opensm_t * const p_osm )
+{
+ memset( p_osm, 0, sizeof( *p_osm ) );
+ osm_subn_construct( &p_osm->subn );
+ osm_sm_construct( &p_osm->sm );
+ osm_sa_construct( &p_osm->sa );
+ osm_db_construct( &p_osm->db );
+ osm_mad_pool_construct( &p_osm->mad_pool );
+ osm_vl15_construct( &p_osm->vl15 );
+ osm_log_construct( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_opensm_destroy(
+ IN osm_opensm_t * const 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 );
+
+ /* shut down the SA
+ * - unbind from QP1 messages
+ */
+ osm_sa_shutdown( &p_osm->sa );
+
+ /* shut down the SM
+ * - make sure the SM sweeper thread exited
+ * - unbind from QP0 messages
+ */
+ osm_sm_shutdown( &p_osm->sm );
+
+ /* 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 );
+
+ /* dump SA DB */
+ osm_sa_db_file_dump(p_osm);
+
+ /* do the destruction in reverse order as init */
+ if (p_osm->routing_engine.delete)
+ p_osm->routing_engine.delete(p_osm->routing_engine.context);
+ osm_sa_destroy( &p_osm->sa );
+ osm_sm_destroy( &p_osm->sm );
+ osm_db_destroy( &p_osm->db );
+ osm_vl15_destroy( &p_osm->vl15, &p_osm->mad_pool );
+ osm_mad_pool_destroy( &p_osm->mad_pool );
+ osm_vendor_delete( &p_osm->p_vendor );
+ osm_subn_destroy( &p_osm->subn );
+ cl_disp_destroy( &p_osm->disp );
+
+ cl_plock_destroy( &p_osm->lock );
+
+ osm_log_destroy( &p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_init(
+ IN osm_opensm_t * const p_osm,
+ IN const osm_subn_opt_t * const p_opt )
+{
+ ib_api_status_t status;
+
+ /* Can't use log macros here, since we're initializing the log. */
+ osm_opensm_construct( p_osm );
+
+ 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 );
+
+ /* If there is a log level defined - add the OSM_VERSION to it. */
+ osm_log( &p_osm->log,
+ osm_log_get_level( &p_osm->log ) & ( OSM_LOG_SYS ^ 0xFF ), "%s\n",
+ OSM_VERSION );
+ /* Write the OSM_VERSION to the SYS_LOG */
+ osm_log( &p_osm->log, OSM_LOG_SYS, "%s\n", OSM_VERSION ); /* Format Waived */
+
+ osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: [\n" ); /* Format Waived */
+
+ status = cl_plock_init( &p_osm->lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ if( p_opt->single_thread )
+ {
+ osm_log( &p_osm->log, OSM_LOG_INFO,
+ "osm_opensm_init: 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;
+
+ 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;
+ goto Exit;
+ }
+
+ status = osm_mad_pool_init( &p_osm->mad_pool, &p_osm->log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vl15_init( &p_osm->vl15,
+ p_osm->p_vendor,
+ &p_osm->log, &p_osm->stats, p_opt->max_wire_smps,
+ &p_osm->subn, &p_osm->disp, &p_osm->lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ /* the DB is in use by the SM and SA so init before */
+ status = osm_db_init( &p_osm->db, &p_osm->log );
+ 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_osm->lock );
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ if( p_opt->routing_engine_name &&
+ setup_routing_engine(p_osm, p_opt->routing_engine_name)) {
+ osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+ "osm_opensm_init: cannot find or setup routing engine"
+ " \'%s\'. Default will be used instead\n",
+ p_opt->routing_engine_name);
+ goto Exit;
+ }
+
+ Exit:
+ osm_log( &p_osm->log, OSM_LOG_FUNCS, "osm_opensm_init: ]\n" ); /* Format Waived */
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_opensm_bind(
+ IN osm_opensm_t * const p_osm,
+ IN const ib_net64_t guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( &p_osm->log, osm_opensm_bind );
+
+ 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;
+ Exit:
+ OSM_LOG_EXIT( &p_osm->log );
+ return ( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of opensm pkey manipulation functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_construct(
+ IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+ 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->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_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->used_blocks = 0;
+ p_pkey_tbl->max_blocks = 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));
+}
+
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_tbl_cleanup_pending(
+ IN osm_pkey_tbl_t *p_pkey_tbl)
+{
+ cl_list_item_t *p_item;
+
+ p_item = cl_qlist_remove_head(&p_pkey_tbl->pending);
+ while (p_item != cl_qlist_end(&p_pkey_tbl->pending))
+ {
+ free((osm_pending_pkey_t *)p_item);
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+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)
+{
+ uint16_t b, i;
+ ib_pkey_table_t *p_pkey_block;
+ uint16_t *p_prev_pkey;
+ ib_net16_t pkey;
+
+ /* 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)
+ 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 on 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;
+
+ /*
+ 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, ib_pkey_get_base(pkey));
+
+ /* we only insert if no previous or it is not full member */
+ if ((p_prev_pkey == NULL) ||
+ (cl_ntoh16(*p_prev_pkey) < cl_ntoh16(pkey)))
+ cl_map_insert( &p_pkey_tbl->keys,
+ ib_pkey_get_base(pkey),
+ &(p_pkey_block->pkey_entry[i])
+ );
+ }
+ }
+ return(IB_SUCCESS);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ 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
+__osm_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* const p_physp1,
+ IN const osm_physp_t* const p_physp2,
+ IN const ib_net16_t pkey )
+{
+ ib_net16_t *pkey1, *pkey2;
+
+ 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 && __osm_match_pkey(pkey1, pkey2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net16_t
+osm_physp_find_common_pkey(
+ IN const osm_physp_t* const p_physp1,
+ IN const osm_physp_t* const p_physp2 )
+{
+ 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 (__osm_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 );
+ }
+
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_physp_t* const p_physp_1,
+ IN const osm_physp_t* const p_physp_2 )
+{
+ 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));
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_port_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_port_t* const p_port_1,
+ IN const osm_port_t* const p_port_2 ) {
+
+ osm_physp_t *p_physp1, *p_physp2;
+ boolean_t ret;
+
+ OSM_LOG_ENTER( p_log, osm_port_share_pkey );
+
+ if (!p_port_1 || !p_port_2)
+ {
+ ret = FALSE;
+ goto Exit;
+ }
+
+ p_physp1 = osm_port_get_default_phys_ptr(p_port_1);
+ p_physp2 = osm_port_get_default_phys_ptr(p_port_2);
+
+ if (!p_physp1 || !p_physp2)
+ {
+ ret = FALSE;
+ goto Exit;
+ }
+
+ ret = osm_physp_share_pkey(p_log, p_physp1, p_physp2);
+
+Exit:
+ OSM_LOG_EXIT(p_log);
+ return ret;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_lid_share_pkey(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t * const p_subn,
+ IN const ib_net16_t lid1,
+ IN const uint8_t port_num1,
+ IN const ib_net16_t lid2,
+ IN const uint8_t port_num2 ) {
+
+ osm_physp_t *p_physp1, *p_physp2;
+ osm_port_t *p_port1, *p_port2;
+ osm_node_t *p_node1, *p_node2;
+ const cl_ptr_vector_t* const p_port_lid_tbl = &(p_subn->port_lid_tbl);
+
+ OSM_LOG_ENTER( p_log, osm_lid_share_pkey );
+
+ p_port1 = cl_ptr_vector_get(p_port_lid_tbl, lid1);
+ p_port2 = cl_ptr_vector_get(p_port_lid_tbl, lid2);
+
+ p_node1 = p_port1->p_node;
+ p_node2 = p_port2->p_node;
+
+ if (osm_node_get_type( p_node1 ) == IB_NODE_TYPE_SWITCH)
+ {
+ p_physp1 = osm_node_get_physp_ptr( p_node1, port_num1 );
+ }
+ else
+ {
+ p_physp1 = osm_port_get_default_phys_ptr(p_port1);
+ }
+
+ if (osm_node_get_type( p_node2 ) == IB_NODE_TYPE_SWITCH)
+ {
+ p_physp2 = osm_node_get_physp_ptr( p_node2, port_num2 );
+ }
+ else
+ {
+ p_physp2 = osm_port_get_default_phys_ptr(p_port2);
+ }
+
+ return(osm_physp_share_pkey(p_log, p_physp1, p_physp2));
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_physp_has_pkey(
+ IN osm_log_t* p_log,
+ IN const ib_net16_t pkey,
+ IN const osm_physp_t* const 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_physp_has_pkey );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "Search for PKey: 0x%4x\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,
+ "osm_physp_has_pkey: "
+ "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,
+ "osm_physp_has_pkey: "
+ "PKey 0x%04x was found\n", cl_ntoh16(pkey));
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_has_pkey: "
+ "PKey 0x%04x was not found\n", cl_ntoh16(pkey));
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return res;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of the P_Key Manager (Partititon Manager).
+ * This is part of the OpenSM.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_pkey_mgr.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ The max number of 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_blocks(
+ IN const osm_subn_t *p_subn,
+ 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 + 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 const osm_req_t *p_req,
+ 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;
+ char *stat = NULL;
+ osm_pending_pkey_t *p_pending;
+
+ p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp );
+ p_pending = (osm_pending_pkey_t *)malloc( sizeof( osm_pending_pkey_t ) );
+ if (!p_pending)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_process_physical_port: 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;
+ p_orig_pkey = cl_map_get( &p_pkey_tbl->keys, ib_pkey_get_base( pkey ) );
+ if (!p_orig_pkey)
+ {
+ p_pending->is_new = TRUE;
+ cl_qlist_insert_tail( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending );
+ stat = "inserted";
+ }
+ 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,
+ "pkey_mgr_process_physical_port: ERR 0503: "
+ "Failed to obtain P_Key 0x%04x block and index for node "
+ "0x%016" PRIx64 " port %u\n",
+ ib_pkey_get_base( pkey ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ return;
+ }
+ cl_qlist_insert_head( &p_pkey_tbl->pending, (cl_list_item_t*)p_pending );
+ stat = "updated";
+ }
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "pkey_mgr_process_physical_port: "
+ "pkey 0x%04x was %s for node 0x%016" PRIx64
+ " port %u\n",
+ cl_ntoh16( pkey ), stat,
+ 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,
+ const osm_req_t *p_req,
+ 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 && osm_physp_is_valid( p_physp ) )
+ pkey_mgr_process_physical_port( p_log, p_req, pkey, p_physp );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+pkey_mgr_update_pkey_entry(
+ IN const osm_req_t *p_req,
+ 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 );
+ uint32_t attr_mod;
+
+ 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 )
+ attr_mod |= osm_physp_get_port_num( p_physp ) << 16;
+ return osm_req_set( p_req, osm_physp_get_dr_path_ptr( p_physp ),
+ ( uint8_t * ) block, sizeof( *block ),
+ IB_MAD_ATTR_P_KEY_TABLE,
+ cl_hton32( attr_mod ), CL_DISP_MSGID_NONE, &context );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+pkey_mgr_enforce_partition(
+ IN osm_log_t *p_log,
+ IN const osm_req_t *p_req,
+ IN const osm_physp_t *p_physp,
+ IN const boolean_t enforce)
+{
+ osm_madw_context_t context;
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ ib_port_info_t *p_pi;
+ ib_api_status_t status;
+
+ if (!(p_pi = osm_physp_get_port_info_ptr( p_physp )))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_enforce_partition: ERR 0507: "
+ "No port info for "
+ "node 0x%016" PRIx64 " port %u\n",
+ cl_ntoh64(
+ osm_node_get_node_guid(
+ osm_physp_get_node_ptr( p_physp ))),
+ osm_physp_get_port_num( p_physp ) );
+ return FALSE;
+ }
+
+ if ((p_pi->vl_enforce & 0xc) == (0xc)*(enforce == TRUE))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "pkey_mgr_enforce_partition: "
+ "No need to update PortInfo for "
+ "node 0x%016" PRIx64 " port %u\n",
+ cl_ntoh64(
+ osm_node_get_node_guid(
+ osm_physp_get_node_ptr( p_physp ))),
+ osm_physp_get_port_num( p_physp ) );
+ return FALSE;
+ }
+
+ memset( payload, 0, IB_SMP_DATA_SIZE );
+ memcpy( payload, p_pi, sizeof(ib_port_info_t) );
+
+ p_pi = (ib_port_info_t*)payload;
+ if (enforce == TRUE)
+ p_pi->vl_enforce |= 0xc;
+ else
+ p_pi->vl_enforce &= ~0xc;
+ p_pi->state_info2 = 0;
+ ib_port_info_set_port_state( p_pi, IB_LINK_NO_CHANGE );
+
+ 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.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ status = osm_req_set( p_req, 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 ) ),
+ CL_DISP_MSGID_NONE, &context );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_enforce_partition: ERR 0511: "
+ "Failed to set PortInfo for "
+ "node 0x%016" PRIx64 " port %u\n",
+ cl_ntoh64(
+ osm_node_get_node_guid(
+ osm_physp_get_node_ptr( p_physp ))),
+ osm_physp_get_port_num( p_physp ) );
+ return FALSE;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "pkey_mgr_enforce_partition: "
+ "Set PortInfo for "
+ "node 0x%016" PRIx64 " port %u\n",
+ cl_ntoh64(
+ osm_node_get_node_guid(
+ osm_physp_get_node_ptr( p_physp ))),
+ osm_physp_get_port_num( p_physp ) );
+ return TRUE;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t pkey_mgr_update_port(
+ osm_log_t *p_log,
+ osm_req_t *p_req,
+ 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;
+ boolean_t ret_val = FALSE;
+ osm_pending_pkey_t *p_pending;
+ boolean_t found;
+ ib_pkey_table_t empty_block;
+
+ memset(&empty_block, 0, sizeof(ib_pkey_table_t));
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ if ( !osm_physp_is_valid( p_physp ) )
+ return FALSE;
+
+ p_node = osm_physp_get_node_ptr( p_physp );
+ p_pkey_tbl = osm_physp_get_mod_pkey_tbl( p_physp );
+ num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
+ max_num_of_blocks = pkey_mgr_get_physp_max_blocks( p_req->p_subn, p_physp );
+ if ( p_pkey_tbl->max_blocks > max_num_of_blocks )
+ {
+ osm_log( p_log, OSM_LOG_INFO,
+ "pkey_mgr_update_port: "
+ "Max number of blocks reduced from %u to %u "
+ "for node 0x%016" PRIx64 " port %u\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_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 ))
+ {
+ if (p_pending->is_new == FALSE)
+ {
+ block_index = p_pending->block;
+ pkey_index = p_pending->index;
+ found = TRUE;
+ }
+ else
+ {
+ found = osm_pkey_find_next_free_entry( p_pkey_tbl,
+ &last_free_block_index,
+ &last_free_pkey_index );
+ if (!found)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_update_port: ERR 0504: "
+ "Failed to find empty space for new pkey 0x%04x "
+ "for node 0x%016" PRIx64 " port %u\n",
+ cl_ntoh16( p_pending->pkey ),
+ cl_ntoh64( osm_node_get_node_guid( p_node )),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ else
+ {
+ block_index = last_free_block_index;
+ pkey_index = last_free_pkey_index++;
+ }
+ }
+
+ 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,
+ "pkey_mgr_update_port: ERR 0505: "
+ "Failed to set PKey 0x%04x in block %u idx %u "
+ "for node 0x%016" PRIx64 " port %u\n",
+ p_pending->pkey, block_index, pkey_index,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ free(p_pending);
+ p_pending = (osm_pending_pkey_t *)cl_qlist_remove_head( &p_pkey_tbl->pending );
+ }
+
+ /* 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( p_req, p_physp, new_block, block_index );
+ if (status == IB_SUCCESS)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "pkey_mgr_update_port: "
+ "Updated "
+ "pkey table block %d for node 0x%016" PRIx64 " port %u\n",
+ block_index,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ ret_val = TRUE;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_update_port: ERR 0506: "
+ "pkey_mgr_update_pkey_entry() failed to update "
+ "pkey table block %d for node 0x%016" PRIx64 " port %u\n",
+ block_index,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+pkey_mgr_update_peer_port(
+ osm_log_t *p_log,
+ const osm_req_t *p_req,
+ const osm_subn_t *p_subn,
+ const osm_port_t * const p_port,
+ boolean_t enforce )
+{
+ osm_physp_t *p_physp, *peer;
+ osm_node_t *p_node;
+ ib_pkey_table_t *block, *peer_block;
+ const osm_pkey_tbl_t *p_pkey_tbl;
+ osm_pkey_tbl_t *p_peer_pkey_tbl;
+ uint16_t block_index;
+ uint16_t num_of_blocks;
+ uint16_t peer_max_blocks;
+ ib_api_status_t status = IB_SUCCESS;
+ boolean_t ret_val = FALSE;
+ boolean_t port_info_set = FALSE;
+ ib_pkey_table_t empty_block;
+
+ memset(&empty_block, 0, sizeof(ib_pkey_table_t));
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+ if (!osm_physp_is_valid( p_physp ))
+ return FALSE;
+ peer = osm_physp_get_remote( p_physp );
+ if ( !peer || !osm_physp_is_valid( peer ) )
+ return FALSE;
+ p_node = osm_physp_get_node_ptr( peer );
+ if ( !p_node->sw || !p_node->sw->switch_info.enforce_cap )
+ return FALSE;
+
+ p_pkey_tbl = osm_physp_get_pkey_tbl( p_physp );
+ p_peer_pkey_tbl = osm_physp_get_mod_pkey_tbl( peer );
+ num_of_blocks = osm_pkey_tbl_get_num_blocks( p_pkey_tbl );
+ peer_max_blocks = pkey_mgr_get_physp_max_blocks( p_subn, peer );
+ if (peer_max_blocks < p_pkey_tbl->used_blocks)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_update_peer_port: ERR 0508: "
+ "Not enough pkey entries (%u < %u) on switch 0x%016" PRIx64
+ " port %u. Clearing Enforcement bit\n",
+ peer_max_blocks, num_of_blocks,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( peer ) );
+ enforce = FALSE;
+ }
+
+ if ( pkey_mgr_enforce_partition( p_log, p_req, peer, enforce ) )
+ port_info_set = TRUE;
+
+ if (enforce == FALSE)
+ return port_info_set;
+
+ p_peer_pkey_tbl->used_blocks = p_pkey_tbl->used_blocks;
+ for (block_index = 0; block_index < p_pkey_tbl->used_blocks; block_index++)
+ {
+ block = osm_pkey_tbl_new_block_get( p_pkey_tbl, block_index );
+ if (!block)
+ block = &empty_block;
+
+ peer_block = osm_pkey_tbl_block_get( p_peer_pkey_tbl, block_index );
+ if ( !peer_block || memcmp( peer_block, block, sizeof( *peer_block ) ) )
+ {
+ status = pkey_mgr_update_pkey_entry( p_req, peer, block, block_index );
+ if ( status == IB_SUCCESS )
+ ret_val = TRUE;
+ else
+ osm_log( p_log, OSM_LOG_ERROR,
+ "pkey_mgr_update_peer_port: ERR 0509: "
+ "pkey_mgr_update_pkey_entry() failed to update "
+ "pkey table block %d for node 0x%016" PRIx64
+ " port %u\n",
+ block_index,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( peer ) );
+ }
+ }
+
+ if ( (ret_val == TRUE) && osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "pkey_mgr_update_peer_port: "
+ "Pkey table was updated for node 0x%016" PRIx64
+ " port %u\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ osm_physp_get_port_num( peer ) );
+ }
+
+ if (port_info_set)
+ return TRUE;
+ return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+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_signal_t signal = OSM_SIGNAL_DONE;
+ osm_node_t *p_node;
+
+ CL_ASSERT( p_osm );
+
+ OSM_LOG_ENTER( &p_osm->log, osm_pkey_mgr_process );
+
+ 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,
+ "osm_pkey_mgr_process: ERR 0510: "
+ "osm_prtn_make_partitions() failed\n" );
+ 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.req,
+ p_prtn, FALSE );
+ pkey_mgr_process_partition_table( &p_osm->log, &p_osm->sm.req,
+ 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.req, p_port ) )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ p_node = osm_port_get_parent_node( p_port );
+ if ( ( osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH ) &&
+ pkey_mgr_update_peer_port( &p_osm->log, &p_osm->sm.req,
+ &p_osm->subn, p_port,
+ !p_osm->subn.opt.no_partition_enforcement ) )
+ signal = OSM_SIGNAL_DONE_PENDING;
+ }
+
+ _err:
+ CL_PLOCK_RELEASE( &p_osm->lock );
+ OSM_LOG_EXIT( &p_osm->log );
+ return ( signal );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_pkey_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_construct(
+ IN osm_pkey_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_destroy(
+ IN osm_pkey_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_init(
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rcv_init );
+
+ osm_pkey_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void
+osm_pkey_rcv_process(
+ IN const osm_pkey_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rcv_process );
+
+ 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_pkey_table_t*)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 );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_process: 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 = osm_port_get_parent_node( p_port );
+ 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 = osm_port_get_default_phys_ptr(p_port);
+ port_num = p_port->default_port_num;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to
+ update the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_rcv_process: "
+ "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( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_process: ERR 4807: "
+ "Got invalid port number 0x%X\n",
+ port_num );
+ goto Exit;
+ }
+
+ osm_dump_pkey_block( p_rcv->p_log,
+ port_guid, block_num,
+ port_num, p_pkey_tbl,
+ OSM_LOG_DEBUG );
+
+ osm_physp_set_pkey_tbl( p_rcv->p_log, p_rcv->p_subn,
+ p_physp, p_pkey_tbl, block_num );
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_pkey_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_pkey_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pkey_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pkey_rcv_process( ((osm_pkey_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_construct(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rcv_ctrl_destroy(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rcv_ctrl_init(
+ IN osm_pkey_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rcv_ctrl_init );
+
+ osm_pkey_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PKEY,
+ __osm_pkey_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pkey_rcv_ctrl_init: ERR 4901: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_physp_t.
+ * This object represents an Infiniband Port.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_mcm_info.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_physp_construct(
+ IN osm_physp_t* const 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* const p_physp )
+{
+ size_t num_slvl, i;
+
+ /* the physp might be un-initialized */
+ if (p_physp->port_guid)
+ {
+ /* 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* const p_physp,
+ IN const ib_net64_t port_guid,
+ IN const uint8_t port_num,
+ IN const struct _osm_node* const p_node,
+ IN const osm_bind_handle_t h_bind,
+ IN const uint8_t hop_count,
+ IN const uint8_t* const 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->p_node = (struct _osm_node*)p_node;
+
+ osm_dr_path_init(
+ &p_physp->dr_path,
+ h_bind,
+ 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)
+ 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_destroy(
+ IN osm_port_t* const p_port )
+{
+ /* cleanup all mcm recs attached */
+ osm_port_remove_all_mgrp( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_init(
+ IN osm_port_t* const p_port,
+ IN const ib_node_info_t* p_ni,
+ IN const osm_node_t* const p_parent_node )
+{
+ uint32_t port_index;
+ ib_net64_t port_guid;
+ osm_physp_t *p_physp;
+ uint32_t size;
+
+ CL_ASSERT( p_port );
+ CL_ASSERT( p_ni );
+ CL_ASSERT( p_parent_node );
+
+ osm_port_construct( p_port );
+
+ p_port->p_node = (struct _osm_node *)p_parent_node;
+ port_guid = p_ni->port_guid;
+ p_port->guid = port_guid;
+
+ /*
+ See comment in port_new for info about this...
+ */
+ size = p_ni->num_ports;
+
+ p_port->physp_tbl_size = (uint8_t)(size + 1);
+
+ /*
+ Get the pointers to the physical node objects "owned" by this
+ logical port GUID.
+ For switches, all the ports are owned; for HCA's and routers,
+ only the singular part that has this GUID is owned.
+ */
+ p_port->default_port_num = 0xFF;
+ for( port_index = 0; port_index < p_port->physp_tbl_size; port_index++ )
+ {
+ p_physp = osm_node_get_physp_ptr( p_parent_node, port_index );
+ if( osm_physp_is_valid( p_physp ) &&
+ port_guid == osm_physp_get_port_guid( p_physp ) )
+ {
+ p_port->tbl[port_index] = p_physp;
+ /*
+ Because much of the PortInfo data is only valid
+ for port 0 on switches, try to keep the lowest
+ possible value of default_port_num.
+ */
+ if( port_index < p_port->default_port_num )
+ p_port->default_port_num = (uint8_t)port_index;
+ }
+ else
+ p_port->tbl[port_index] = NULL;
+ }
+
+ CL_ASSERT( p_port->default_port_num < 0xFF );
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_port_t*
+osm_port_new(
+ IN const ib_node_info_t* p_ni,
+ IN const osm_node_t* const p_parent_node )
+{
+ osm_port_t* p_port;
+ uint32_t size;
+
+ /*
+ The port object already contains one physical port object pointer.
+ 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 pointer than they physically have since
+ we still reserve room for a "port 0".
+ */
+ size = p_ni->num_ports;
+
+ p_port = malloc( sizeof(*p_port) + sizeof(void *) * size );
+ if( p_port != NULL )
+ {
+ memset( p_port, 0, sizeof(*p_port) + sizeof(void *) * size );
+ osm_port_init( p_port, p_ni, p_parent_node );
+ }
+
+ return( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_get_lid_range_ho(
+ IN const osm_port_t* const p_port,
+ IN uint16_t* const p_min_lid,
+ IN uint16_t* const 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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_get_port_by_base_lid(
+ IN const osm_subn_t* const p_subn,
+ IN const ib_net16_t lid,
+ IN OUT const osm_port_t** const pp_port )
+{
+ ib_api_status_t status;
+ uint16_t base_lid;
+ uint8_t lmc;
+
+ *pp_port = NULL;
+
+ /* Loop on lmc from 0 up through max LMC possible */
+ for (lmc = 0; lmc <= IB_PORT_LMC_MAX; lmc++)
+ {
+ /* Calculate a base LID assuming this is the real LMC */
+ base_lid = cl_ntoh16(lid) & ~((1 << lmc) - 1);
+
+ /* Look for a match */
+ status = cl_ptr_vector_at( &p_subn->port_lid_tbl,
+ base_lid,
+ (void**)pp_port );
+ if ((status == CL_SUCCESS) && (*pp_port != NULL))
+ {
+ /* Determine if base LID "tested" is the real base LID */
+ /* This is true if the LMC "tested" is the port's actual LMC */
+ if (lmc == osm_port_get_lmc( *pp_port ) )
+ {
+ status = IB_SUCCESS;
+ goto Found;
+ }
+ }
+ }
+ *pp_port = NULL;
+ status = IB_NOT_FOUND;
+
+ Found:
+ return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_add_new_physp(
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num )
+{
+ osm_node_t *p_node;
+ osm_physp_t *p_physp;
+
+ CL_ASSERT( port_num < p_port->physp_tbl_size );
+
+ p_node = p_port->p_node;
+ CL_ASSERT( p_node );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ CL_ASSERT( osm_physp_get_port_guid( p_physp ) == p_port->guid );
+ p_port->tbl[port_num] = p_physp;
+
+ /*
+ For switches, we generally want to use Port 0, which is
+ the management port as the default Physical Port.
+ The LID value in the PortInfo for example, is only valid
+ for port 0 on switches.
+ */
+ if( !osm_physp_is_valid( p_port->tbl[p_port->default_port_num] ) )
+ {
+ p_port->default_port_num = port_num;
+ }
+ else
+ {
+ if( port_num < p_port->default_port_num )
+ {
+ p_port->default_port_num = port_num;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_port_add_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_mcm_info_t *p_mcm;
+
+ p_mcm = osm_mcm_info_new( mlid );
+ if( p_mcm )
+ cl_qlist_insert_tail( &p_port->mcm_list, (cl_list_item_t*)p_mcm );
+ else
+ status = IB_INSUFFICIENT_MEMORY;
+
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static cl_status_t
+__osm_port_mgrp_find_func(
+ IN const cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ if( *((ib_net16_t*)context) == ((osm_mcm_info_t*)p_list_item)->mlid )
+ return( CL_SUCCESS );
+ else
+ return( CL_NOT_FOUND );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_mgrp(
+ IN osm_port_t* const p_port,
+ IN const ib_net16_t mlid )
+{
+ cl_list_item_t *p_mcm;
+
+ p_mcm = cl_qlist_find_from_head( &p_port->mcm_list,
+ __osm_port_mgrp_find_func, &mlid );
+
+ if( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+ {
+ cl_qlist_remove_item( &p_port->mcm_list, p_mcm );
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_port_remove_all_mgrp(
+ IN osm_port_t* const p_port )
+{
+ cl_list_item_t *p_mcm;
+
+ p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+ while( p_mcm != cl_qlist_end( &p_port->mcm_list ) )
+ {
+ osm_mcm_info_delete( (osm_mcm_info_t*)p_mcm );
+ p_mcm = cl_qlist_remove_head( &p_port->mcm_list );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_physp_calc_link_mtu(
+ IN osm_log_t* p_log,
+ IN const osm_physp_t* p_physp )
+{
+ const ib_port_info_t* p_old_pi;
+ const ib_port_info_t* p_remote_pi;
+ const osm_physp_t* p_remote_physp;
+ uint8_t mtu;
+ uint8_t remote_mtu;
+
+ OSM_LOG_ENTER( p_log, osm_physp_calc_link_mtu );
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /* use the available MTU */
+ mtu = ib_port_info_get_mtu_cap( p_old_pi );
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+ remote_mtu = ib_port_info_get_mtu_cap( p_remote_pi );
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_mtu: "
+ "Remote port 0x%016" PRIx64 " port# = 0x%X : "
+ "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( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "osm_physp_calc_link_mtu: "
+ "MTU 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 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 );
+ }
+ }
+ }
+
+ if( mtu == 0 )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_mtu: 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 )
+{
+ const ib_port_info_t* p_old_pi;
+ const ib_port_info_t* p_remote_pi;
+ const osm_physp_t* p_remote_physp;
+ uint8_t op_vls;
+ uint8_t remote_op_vls;
+
+ OSM_LOG_ENTER( p_log, osm_physp_calc_link_op_vls );
+ p_old_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /* use the available VL CAP */
+ op_vls = ib_port_info_get_vl_cap(p_old_pi);
+
+ p_remote_physp = osm_physp_get_remote( p_physp );
+ if( p_remote_physp && osm_physp_is_valid( p_remote_physp ) )
+ {
+ p_remote_pi = osm_physp_get_port_info_ptr( p_remote_physp );
+ remote_op_vls = ib_port_info_get_vl_cap(p_remote_pi);
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_op_vls: "
+ "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( osm_log_is_active( p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "osm_physp_calc_link_op_vls: "
+ "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 );
+ }
+ }
+ }
+
+ /* support user limitation of max_op_vls */
+ if (op_vls > p_subn->opt.max_op_vls)
+ op_vls = p_subn->opt.max_op_vls;
+
+ if( op_vls == 0 )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_physp_calc_link_op_vls: ERR 4102: "
+ "Invalid OP_VLS = 0. Forcing correction to 1 (VL0)\n" );
+ op_vls = 1;
+ }
+
+ OSM_LOG_EXIT( p_log );
+ return(op_vls);
+}
+
+inline
+uint64_t
+__osm_ptr_to_key(void const *p)
+{
+ uint64_t k = 0;
+
+ memcpy(&k, p, sizeof(void *));
+ return k;
+}
+
+inline
+void *
+__osm_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).
+ **********************************************************************/
+cl_status_t
+__osm_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, __osm_physp_get_dr_physp_set );
+
+ /* 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,
+ "__osm_physp_get_dr_nodes_set: 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 = osm_port_get_parent_node(p_port);
+
+ /*
+ 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]);
+
+ /* we track the ports we go out along the path */
+ if (hop > 1)
+ cl_map_insert(p_physp_map, __osm_ptr_to_key(p_physp), NULL);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__osm_physp_get_dr_nodes_set: "
+ "Traversed through node: 0x%016" PRIx64
+ " port:%u\n",
+ cl_ntoh64(p_node->node_info.node_guid),
+ p_path->path[hop]);
+
+ /* make sure we got a valid port and it has a remote port */
+ if (!(p_physp && osm_physp_is_valid( p_physp )))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_physp_get_dr_nodes_set: ERR 4104: "
+ "DR Traversal stopped on invalid port at hop:%u\n",
+ hop);
+ status = CL_ERROR;
+ goto Exit;
+ }
+
+ if (! (p_physp = osm_physp_get_remote(p_physp)))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_physp_get_dr_nodes_set: 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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_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,
+ __osm_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,
+ __osm_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,
+ __osm_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, h_bind, 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;
+ cl_qmap_t const *p_port_tbl;
+ 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;
+
+ /*
+ 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 );
+ __osm_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
+ */
+ p_nextPortsList = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextPortsList );
+ cl_list_init( p_nextPortsList, 10 );
+
+ p_port_tbl = &p_subn->port_guid_tbl;
+ port_guid = p_subn->sm_port_guid;
+
+ CL_ASSERT( port_guid );
+
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_replace_dr_path_with_alternate_dr_path: 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 = osm_port_get_default_phys_ptr( p_port );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( 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));
+ 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. The port is a valid port
+ 3. This is not the port we came from
+ 4. The port is not in the physp_map
+ 5. This port haven't been visited before
+ */
+ if ( p_remote_physp &&
+ osm_physp_is_valid ( p_remote_physp ) &&
+ p_remote_physp != p_physp &&
+ cl_map_get( &physp_map, __osm_ptr_to_key(p_remote_physp)) == NULL &&
+ cl_map_get( &visited_map, __osm_ptr_to_key(p_remote_physp)) == NULL )
+ {
+ /* Insert the port into the visited_map, and save its source port */
+ cl_map_insert( &visited_map, __osm_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 */
+ __osm_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* const 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 && osm_physp_is_valid(p_remote_physp) )
+ 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* const p_physp,
+ IN ib_pkey_table_t *p_pkey_tbl,
+ IN uint16_t block_num )
+{
+ uint16_t max_blocks;
+
+ CL_ASSERT( p_pkey_tbl );
+ 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.
+ */
+ if (!p_physp->p_node->sw || p_physp->port_num == 0 )
+ {
+ /*
+ The maximum blocks is defined in the node info: partition cap for CA,
+ routers 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,
+ "osm_physp_set_pkey_tbl: ERR 4108: "
+ "Got illegal set for block number:%u "
+ "For GUID: %" PRIx64 " port number:0x%X\n",
+ block_num,
+ cl_ntoh64(p_physp->p_node->node_info.node_guid),
+ p_physp->port_num );
+ return;
+ }
+
+ osm_pkey_tbl_set( &p_physp->pkeys, block_num, p_pkey_tbl);
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pi_rcv_t.
+ * This object represents the PortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_port_info_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_set_sm(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp )
+{
+ osm_bind_handle_t h_bind;
+ osm_dr_path_t *p_dr_path;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_set_sm );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pi_rcv_set_sm: "
+ "Setting 'IS_SM' bit in port attributes\n" );
+ }
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+ /*
+ The 'IS_SM' bit isn't already set, so set it.
+ */
+ osm_vendor_set_sm( h_bind, TRUE );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_endport(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ ib_net64_t port_guid;
+ uint8_t rate, mtu;
+ cl_qmap_t* p_sm_tbl;
+ osm_remote_sm_t* p_sm;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_endport );
+
+ 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)
+ {
+ /* track the minimal endport MTU and rate */
+ mtu = ib_port_info_get_mtu_cap(p_pi);
+ if (mtu < p_rcv->p_subn->min_ca_mtu)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Setting endport minimal MTU to:%u defined by port:0x%"
+ PRIx64 "\n",
+ mtu,
+ cl_ntoh64( port_guid ) );
+ p_rcv->p_subn->min_ca_mtu = mtu;
+ }
+
+ rate = ib_port_info_compute_rate( p_pi );
+ if (rate < p_rcv->p_subn->min_ca_rate)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Setting endport minimal rate to:%u defined by port:0x%"
+ PRIx64 "\n",
+ rate,
+ cl_ntoh64( port_guid ) );
+ p_rcv->p_subn->min_ca_rate = rate;
+ }
+ }
+
+ if( port_guid == p_rcv->p_subn->sm_port_guid )
+ {
+ /*
+ We received the PortInfo for our own port.
+ */
+ if( !(p_pi->capability_mask & IB_PORT_CAP_IS_SM ) )
+ {
+ /*
+ Set the IS_SM bit to indicate our port hosts an SM.
+ */
+ __osm_pi_rcv_set_sm( p_rcv, p_physp );
+ }
+ }
+ else
+ {
+ /*
+ 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_tbl = &p_rcv->p_subn->sm_guid_tbl;
+ 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( p_pi->capability_mask & IB_PORT_CAP_IS_SM )
+ {
+ if( p_rcv->p_subn->opt.ignore_other_sm )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Ignoring SM on port 0x%" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_endport: "
+ "Detected another SM. Requesting SMInfo"
+ "\n\t\t\t\tPort 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;
+ status = osm_req_get( p_rcv->p_req,
+ osm_physp_get_dr_path_ptr( p_physp ),
+ IB_MAD_ATTR_SM_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_endport: ERR 0F05: "
+ "Failure requesting SMInfo (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_pi_rcv_process_switch_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_madw_context_t context;
+ osm_physp_t *p_remote_physp;
+ osm_node_t *p_remote_node;
+ ib_net16_t orig_lid;
+ uint8_t port_num;
+ uint8_t remote_port_num;
+ osm_dr_path_t path;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_switch_port );
+
+ /*
+ 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 in_sweep_hop_0 is TRUE, then this means the SM in on the switch,
+ and we got switchInfo of our local switch. Do not continue
+ probing through the switch. */
+ if( port_num != 0 && p_rcv->p_subn->in_sweep_hop_0 == FALSE)
+ {
+ 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 && osm_physp_is_valid( 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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_pi_rcv_process_switch_port: "
+ "Unlinking local node 0x%" PRIx64 ", port 0x%X"
+ "\n\t\t\t\tand remote node 0x%" PRIx64
+ ", port 0x%X\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 );
+
+ 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:
+ /*
+ 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 );
+
+ osm_dr_path_extend( &path, osm_physp_get_port_num( p_physp ) );
+
+ 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( p_rcv->p_req,
+ &path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_switch_port: ERR 0F02: "
+ "Failure initiating NodeInfo request (%s)\n",
+ ib_get_err_str(status) );
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pi_rcv_process_switch_port: "
+ "Skipping SMP responder port 0x%X\n",
+ p_pi->local_port_num );
+ }
+ }
+ break;
+
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_switch_port: ERR 0F03: "
+ "Unknown link state = %u, port = 0x%X\n",
+ ib_port_info_get_port_state( p_pi ),
+ p_pi->local_port_num );
+ break;
+ }
+ }
+
+ /*
+ Update the PortInfo attribute.
+ */
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ if (port_num == 0)
+ {
+ /* This is switch management port 0 */
+ if ( ( orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_switch_port: ERR 0F04: "
+ "Invalid base LID 0x%x corrected\n",
+ cl_ntoh16( orig_lid ) );
+ /* 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;
+ }
+ __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_ca_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ ib_net16_t orig_lid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_ca_port );
+
+ UNUSED_PARAM( p_node );
+
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_ca_port: ERR 0F08: "
+ "Invalid base LID 0x%x corrected\n",
+ cl_ntoh16 ( orig_lid ) );
+
+ __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_process_router_port(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp,
+ IN const ib_port_info_t* const p_pi )
+{
+ ib_net16_t orig_lid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_process_router_port );
+
+ UNUSED_PARAM( p_node );
+
+ /*
+ Update the PortInfo attribute.
+ */
+ osm_physp_set_port_info( p_physp, p_pi );
+
+ if ( (orig_lid = osm_physp_trim_base_lid_to_valid_range( p_physp ) ) )
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pi_rcv_process_router_port: ERR 0F09: "
+ "Invalid base LID 0x%x corrected\n",
+ cl_ntoh16 ( orig_lid) );
+
+ __osm_pi_rcv_process_endport(p_rcv, p_physp, p_pi);
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#define IBM_VENDOR_ID (0x5076)
+/**********************************************************************
+ **********************************************************************/
+void osm_pkey_get_tables(
+ IN osm_log_t *p_log,
+ IN osm_req_t *p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp ) {
+
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ osm_dr_path_t path;
+ uint8_t port_num;
+ uint16_t block_num, max_blocks;
+ uint32_t attr_mod_ho;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_get_tables );
+
+ 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 ;
+ }
+
+ for (block_num = 0 ; block_num < max_blocks ; block_num++)
+ {
+ if (osm_node_get_type( p_node ) != IB_NODE_TYPE_SWITCH)
+ attr_mod_ho = block_num;
+ else
+ attr_mod_ho = block_num | (port_num << 16);
+ status = osm_req_get( p_req,
+ &path,
+ IB_MAD_ATTR_P_KEY_TABLE,
+ cl_hton32(attr_mod_ho),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_physp_has_pkey: ERR 0F12: "
+ "Failure initiating PKeyTable request (%s)\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pi_rcv_get_pkey_slvl_vla_tables(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN osm_physp_t* const p_physp )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pi_rcv_get_pkey_slvl_vla_tables );
+
+ osm_pkey_get_tables( p_rcv->p_log, p_rcv->p_req, p_rcv->p_subn,
+ p_node, p_physp );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_construct(
+ IN osm_pi_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_destroy(
+ IN osm_pi_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_destroy );
+
+ CL_ASSERT( p_rcv );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_init(
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_pi_rcv_init );
+
+ osm_pi_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process_set(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_port_t* const p_port,
+ IN const uint8_t port_num,
+ IN osm_madw_t* const p_madw )
+{
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ 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( p_rcv->p_log, osm_pi_rcv_process_set );
+
+ p_context = osm_madw_get_pi_context_ptr( p_madw );
+
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_pi = (ib_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ /* check for error */
+ if (!p_context->ignore_errors && (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( p_rcv->p_log, OSM_LOG_INFO,
+ "osm_pi_rcv_process_set: "
+ "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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process_set: ERR 0F10: "
+ "Received error status for SetResp()\n");
+ }
+ osm_dump_port_info(
+ p_rcv->p_log,
+ osm_node_get_node_guid( p_node ),
+ port_guid,
+ port_num,
+ p_pi,
+ level);
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pi_rcv_process_set: "
+ "Received logical SetResp() for GUID 0x%" PRIx64
+ ", port num 0x%X"
+ "\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 );
+
+ /* We got a PortInfoSetResp - set the got_set_resp flag to TRUE */
+ p_physp->got_set_resp = TRUE;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_process(
+ IN const osm_pi_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ 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;
+ ib_net64_t node_guid;
+ uint8_t port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pi_rcv_process );
+
+ CL_ASSERT( p_rcv );
+ 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_port_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ CL_ASSERT( p_smp->attr_id == IB_MAD_ATTR_PORT_INFO );
+
+ /* On receipt of client reregister, clear the reregister bit so
+ reregistering won't be sent again and again */
+ if ( ib_port_info_get_client_rereg( p_pi ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pi_rcv_process: "
+ "Client reregister received on response\n");
+ ib_port_info_set_client_rereg( p_pi, 0 );
+ }
+
+ 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( p_rcv->p_log,
+ node_guid, port_guid, port_num, p_pi,
+ OSM_LOG_DEBUG );
+
+ /*
+ 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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "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 ) );
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ OSM_SIGNAL_CHANGE_DETECTED );
+ goto Exit;
+ }
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process: 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;
+ }
+
+ /*
+ 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 )
+ {
+ osm_pi_rcv_process_set( p_rcv, p_port, port_num, p_madw );
+ }
+ else
+ {
+ osm_port_discovery_count_inc( p_port );
+
+ /*
+ This PortInfo arrived because we did a Get() method,
+ most likely due to a subnet sweep in progress.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "Discovered port num 0x%X 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_node = osm_port_get_parent_node( p_port );
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_physp );
+
+ /*
+ Determine if we encountered a new Physical Port.
+ If so, initialize the new Physical Port then
+ continue processing as normal.
+ */
+ if( !osm_physp_is_valid( p_physp ) )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "Initializing port number 0x%X\n",
+ port_num );
+ }
+
+ osm_physp_init( p_physp,
+ port_guid,
+ port_num,
+ p_node,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count,
+ p_smp->initial_path );
+
+ osm_port_add_new_physp( p_port, port_num );
+ }
+ else
+ {
+ /*
+ 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,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count, p_smp->initial_path );
+ }
+
+ /*
+ Check if the update_sm_base_lid in the context is TRUE.
+ If it is - then update the master_sm_base_lid of the variable
+ in the subnet.
+ */
+ if (p_context->update_master_sm_base_lid == TRUE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pi_rcv_process: "
+ "update_master_sm is TRUE. "
+ "Updating master_sm_base_lid to:%u\n",
+ p_pi->master_sm_base_lid );
+
+ p_rcv->p_subn->master_sm_base_lid = p_pi->master_sm_base_lid;
+ }
+
+ switch( osm_node_get_type( p_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ __osm_pi_rcv_process_ca_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ __osm_pi_rcv_process_router_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ __osm_pi_rcv_process_switch_port( p_rcv,
+ p_node, p_physp, p_pi );
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_process: 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.
+ */
+ __osm_pi_rcv_get_pkey_slvl_vla_tables( p_rcv, p_node, p_physp );
+
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ Exit:
+ /*
+ Release the lock before jumping here!!
+ */
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_port_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pi_rcv_ctrl_t.
+ * This object represents the PortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_port_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pi_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pi_rcv_process( ((osm_pi_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_construct(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pi_rcv_ctrl_destroy(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pi_rcv_ctrl_init(
+ IN osm_pi_rcv_ctrl_t* const p_ctrl,
+ IN osm_pi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pi_rcv_ctrl_init );
+
+ osm_pi_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PORT_INFO,
+ __osm_pi_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pi_rcv_ctrl_init: ERR 1001: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_prtn_t.
+ * This object represents an IBA partition.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_multicast.h>
+
+extern int osm_prtn_config_parse_file(osm_log_t * const p_log,
+ osm_subn_t * const p_subn,
+ const char *file_name);
+
+static uint16_t global_pkey_counter;
+
+osm_prtn_t* osm_prtn_new(
+ IN const char *name,
+ IN const 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;
+ 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 OUT osm_prtn_t** const pp_prtn )
+{
+ 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);
+ 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)
+{
+ cl_qmap_t *p_port_tbl = &p_subn->port_guid_tbl;
+ 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_port_t *)cl_qmap_get(p_port_tbl, guid);
+ if (!p_port || p_port == (osm_port_t *)cl_qmap_end(p_port_tbl)) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "port 0x%" PRIx64 " not found\n",
+ cl_ntoh64(guid));
+ return status;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ if (!p_physp) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "no physical for port 0x%" PRIx64 "\n",
+ cl_ntoh64(guid));
+ return status;
+ }
+
+ if (cl_map_remove(&p->part_guid_tbl, guid) ||
+ cl_map_remove(&p->full_guid_tbl, guid)) {
+ osm_log(p_log, OSM_LOG_VERBOSE, "osm_prtn_add_port: "
+ "port 0x%" PRIx64 " already in "
+ "partition \'%s\' (0x%04x). Will overwrite\n",
+ cl_ntoh64(guid), p->name, cl_ntoh16(p->pkey));
+ }
+
+ p_tbl = (full == TRUE) ? &p->full_guid_tbl : &p->part_guid_tbl ;
+
+ 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, boolean_t full)
+{
+ 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);
+ status = osm_prtn_add_port(p_log, p_subn, p,
+ osm_port_get_guid(p_port), full);
+ if (status != IB_SUCCESS)
+ goto _err;
+ }
+
+ _err:
+ return status;
+}
+
+static const ib_gid_t osm_ipoib_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 */
+ },
+};
+
+/*
+ * HACK: Until TS resolves their noncompliant join compmask,
+ * we have to pre-define the MGID
+ */
+static const ib_gid_t osm_ts_ipoib_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 */
+ 0x00, 0x00, 0x00, 0x01, /* 32 bit IPv4 broadcast address */
+ },
+};
+
+ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p,
+ unsigned is_ipoib, uint8_t rate,
+ uint8_t mtu, uint8_t scope)
+{
+ ib_member_rec_t mc_rec;
+ ib_net64_t comp_mask;
+ ib_net16_t pkey;
+ osm_mgrp_t *p_mgrp = NULL;
+ osm_sa_t *p_sa = &p_subn->p_osm->sa;
+ ib_api_status_t status = IB_SUCCESS;
+ uint8_t ts_scope;
+
+ pkey = p->pkey | cl_hton16(0x8000);
+
+ memset(&mc_rec, 0, sizeof(mc_rec));
+
+ mc_rec.mgid = osm_ipoib_mgid; /* ipv4 broadcast group */
+ memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
+
+ mc_rec.qkey = CL_HTON32(0x0b1b);
+ mc_rec.mtu = (mtu ? mtu : OSM_DEFAULT_MGRP_MTU) | (2 << 6); /* 2048 Bytes */
+ mc_rec.tclass = 0;
+ mc_rec.pkey = pkey;
+ mc_rec.rate = (rate ? rate : OSM_DEFAULT_MGRP_RATE) | (2 << 6); /* 10Gb/sec */
+ mc_rec.pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;
+ mc_rec.sl_flow_hop = ib_member_set_sl_flow_hop(p->sl, 0, 0);
+ /* Scope in MCMemberRecord needs to be consistent with MGID */
+ mc_rec.scope_state = ib_member_set_scope_state(scope ? scope : OSM_DEFAULT_MGRP_SCOPE, MC_FULL_MEMBER);
+ ib_mgid_set_scope(&mc_rec.mgid, scope ? scope : OSM_DEFAULT_MGRP_SCOPE);
+
+ /* don't update rate, mtu, scope */
+ comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL
+ | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL
+ | IB_MCR_COMPMASK_SCOPE;
+ status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv,
+ comp_mask, &mc_rec, &p_mgrp);
+ if (!p_mgrp || status != IB_SUCCESS)
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_prtn_add_mcgroup: "
+ "Failed to create MC group with pkey 0x%04x\n",
+ cl_ntoh16(pkey));
+ if (p_mgrp)
+ p_mgrp->well_known = TRUE;
+
+ /* workaround for TS */
+ /* FIXME: remove this upon TS fixes */
+ mc_rec.mgid = osm_ts_ipoib_mgid;
+ memcpy(&mc_rec.mgid.raw[4], &pkey, sizeof(pkey));
+ /* Scope in MCMemberRecord needs to be consistent with MGID */
+ ts_scope = ib_mgid_get_scope(&osm_ts_ipoib_mgid); /* get scope from MGID */
+ mc_rec.scope_state = ib_member_set_scope_state(ts_scope, MC_FULL_MEMBER);
+ status = osm_mcmr_rcv_find_or_create_new_mgrp(&p_sa->mcmr_rcv,
+ comp_mask, &mc_rec, &p_mgrp);
+ if (p_mgrp)
+ p_mgrp->well_known = TRUE;
+
+ return status;
+}
+
+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;
+}
+
+static osm_prtn_t *find_prtn_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 = find_prtn_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,
+ "osm_prtn_make_new: 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,
+ "osm_prtn_make_new: Duplicated partition"
+ " definition: \'%s\' (0x%04x) prev name \'%s\'"
+ ". Will use it\n",
+ name, cl_ntoh16(pkey), p_check->name);
+ osm_prtn_delete(&p);
+ p = p_check;
+ }
+
+ return p;
+}
+
+static ib_api_status_t osm_prtn_make_default(osm_log_t * const p_log,
+ osm_subn_t * const 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, no_config);
+ 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);
+
+ if (no_config)
+ osm_prtn_add_mcgroup(p_log, p_subn, p, 1, 0, 0, 0);
+
+ _err:
+ return status;
+}
+
+ib_api_status_t osm_prtn_make_partitions(osm_log_t * const p_log,
+ osm_subn_t * const p_subn)
+{
+ struct stat statbuf;
+ const char *file_name;
+ boolean_t is_config = TRUE;
+ 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 :
+ "/etc/osm-partitions.conf";
+ if (stat(file_name, &statbuf))
+ is_config = FALSE;
+
+ /* 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 = osm_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,
+ "osm_prtn_make_partitions: Partition configuration "
+ "was not fully processed\n");
+ }
+
+ /* 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);
+ }
+ }
+
+ _err:
+ return status;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of opensm partition management configuration
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision$
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <opensm/osm_base.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_log.h>
+
+#if __WORDSIZE == 64
+#define STRTO_IB_NET64(str, end, base) strtoul(str, end, base)
+#else
+#define STRTO_IB_NET64(str, end, base) strtoull(str, end, base)
+#endif
+
+/*
+ */
+struct part_conf {
+ osm_log_t *p_log;
+ osm_subn_t *p_subn;
+ osm_prtn_t *p_prtn;
+ unsigned is_ipoib, mtu, rate, sl, scope;
+};
+
+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, boolean_t full);
+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);
+extern ib_api_status_t osm_prtn_add_mcgroup(osm_log_t *p_log,
+ osm_subn_t *p_subn, osm_prtn_t *p,
+ unsigned is_ipoib, uint8_t rate,
+ uint8_t mtu, uint8_t scope);
+
+static int partition_create(unsigned lineno, struct part_conf *conf,
+ char *name, char *id, char *flag, char *flag_val)
+{
+ uint16_t pkey;
+
+ if (!id && name && isdigit(*name)) {
+ id = name;
+ name = NULL;
+ }
+
+ if (id) {
+ char *end;
+
+ pkey = (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, cl_hton16(pkey));
+ if (!conf->p_prtn)
+ return -1;
+
+ if (conf->p_subn->opt.no_qos) {
+ if (conf->sl != OSM_DEFAULT_SL) {
+ osm_log(conf->p_log, OSM_LOG_ERROR,
+ "partition_create: Overriding SL %d to default SL %d on partition %s as QoS not enabled\n",
+ conf->sl, OSM_DEFAULT_SL, name);
+ conf->sl = OSM_DEFAULT_SL;
+ }
+ }
+ conf->p_prtn->sl = (uint8_t)conf->sl;
+
+ if (conf->is_ipoib)
+ osm_prtn_add_mcgroup(conf->p_log, conf->p_subn, conf->p_prtn,
+ conf->is_ipoib, (uint8_t)conf->rate,
+ (uint8_t)conf->mtu, (uint8_t)conf->scope);
+
+ return 0;
+}
+
+static int partition_add_flag(unsigned lineno, struct part_conf *conf,
+ char *flag, char *val)
+{
+ int len = strlen(flag);
+ if (!strncmp(flag, "ipoib", len)) {
+ conf->is_ipoib = 1;
+ } else if (!strncmp(flag, "mtu", len)) {
+ if (!val || (conf->mtu = strtoul(val, NULL, 0)) == 0)
+ osm_log(conf->p_log, OSM_LOG_VERBOSE,
+ "PARSE WARN: line %d: "
+ "flag \'mtu\' requires valid value"
+ " - skipped\n", lineno);
+ } else if (!strncmp(flag, "rate", len)) {
+ if (!val || (conf->rate = strtoul(val, NULL, 0)) == 0)
+ osm_log(conf->p_log, OSM_LOG_VERBOSE,
+ "PARSE WARN: line %d: "
+ "flag \'rate\' requires valid value"
+ " - skipped\n", lineno);
+ } else if (!strncmp(flag, "scope", len)) {
+ if (!val || (conf->scope = strtoul(val, NULL, 0)) == 0)
+ osm_log(conf->p_log, OSM_LOG_VERBOSE,
+ "PARSE WARN: line %d: "
+ "flag \'scope\' requires valid value"
+ " - skipped\n", lineno);
+ } else if (!strncmp(flag, "sl", len)) {
+ unsigned sl;
+ char *end;
+
+ if (!val || !*val || (sl = strtoul(val, &end, 0)) > 15 ||
+ (*end && !isspace(*end)))
+ osm_log(conf->p_log, OSM_LOG_VERBOSE,
+ "PARSE WARN: line %d: "
+ "flag \'sl\' requires valid value"
+ " - skipped\n", lineno);
+ else
+ conf->sl = sl;
+ } else {
+ osm_log(conf->p_log, OSM_LOG_VERBOSE,
+ "PARSE WARN: line %d: "
+ "unrecognized partition flag \'%s\'"
+ " - ignored\n", lineno, flag);
+ }
+ 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;
+ boolean_t full = FALSE;
+
+ if (!name || !*name || !strncmp(name, "NONE", strlen(name)))
+ return 0;
+
+ if (flag) {
+ if (!strncmp(flag, "full", strlen(flag)))
+ full = TRUE;
+ 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 osm_prtn_add_all(conf->p_log, conf->p_subn, p,
+ full) == IB_SUCCESS ? 0 : -1;
+ } else if (!strncmp(name, "SELF", strlen(name))) {
+ guid = cl_ntoh64(conf->p_subn->sm_port_guid);
+ } else {
+ char *end;
+ guid = STRTO_IB_NET64(name, &end, 0);
+ if (!guid || *end)
+ return -1;
+ }
+
+ if (osm_prtn_add_port(conf->p_log, conf->p_subn, p,
+ cl_hton64(guid), full) != 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 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->sl = OSM_DEFAULT_SL;
+ 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);
+ 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;
+ len += ret;
+ } while (q);
+
+ return len;
+}
+
+int osm_prtn_config_parse_file(osm_log_t *p_log, osm_subn_t *p_subn,
+ const char *file_name)
+{
+ char line[1024];
+ struct part_conf *conf = NULL;
+ FILE *file;
+ int lineno;
+
+ file = fopen(file_name, "r");
+ if (!file) {
+ osm_log(p_log, OSM_LOG_VERBOSE,
+ "osm_prtn_config_parse_file: "
+ "Cannot open config file \'%s\': %s\n",
+ file_name, strerror(errno));
+ return -1;
+ }
+
+ lineno = 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(conf->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);
+ break;
+ }
+
+ q = strchr(p, ';');
+ if (q)
+ *q = '\0';
+
+ len = parse_part_conf(conf, p, lineno);
+ if (len < 0) {
+ break;
+ }
+
+ p += len;
+
+ if (q) {
+ flush_part_conf(conf);
+ conf = NULL;
+ }
+ } while (q);
+ }
+
+ fclose(file);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of OpenSM QoS infrastructure primitives
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_subnet.h>
+
+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;
+};
+
+static void qos_build_config(struct qos_config * cfg,
+ osm_qos_options_t * opt, osm_qos_options_t * dflt);
+
+/*
+ * QoS primitives
+ */
+static ib_api_status_t vlarb_update_table_block(osm_req_t * p_req,
+ osm_physp_t * p,
+ uint8_t port_num,
+ const ib_vl_arb_table_t *table_block,
+ unsigned block_length,
+ unsigned block_num)
+{
+ ib_vl_arb_table_t block;
+ osm_madw_context_t context;
+ uint32_t attr_mod;
+ ib_port_info_t *p_pi;
+ unsigned vl_mask, i;
+
+ if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+ return IB_ERROR;
+
+ vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 1)) - 1;
+
+ memset(&block, 0, sizeof(block));
+ memcpy(&block, table_block,
+ block_length * sizeof(block.vl_entry[0]));
+ for (i = 0; i < block_length; i++)
+ block.vl_entry[i].vl &= vl_mask;
+
+ if (!memcmp(&p->vl_arb[block_num], &block,
+ block_length * sizeof(block.vl_entry[0])))
+ return IB_SUCCESS;
+
+ context.vla_context.node_guid =
+ osm_node_get_node_guid(osm_physp_get_node_ptr(p));
+ context.vla_context.port_guid = osm_physp_get_port_guid(p);
+ context.vla_context.set_method = TRUE;
+ attr_mod = ((block_num + 1) << 16) | port_num;
+
+ return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+ (uint8_t *) & block, sizeof(block),
+ IB_MAD_ATTR_VL_ARBITRATION,
+ cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t vlarb_update(osm_req_t * p_req,
+ osm_physp_t * p, uint8_t port_num,
+ const struct qos_config *qcfg)
+{
+ ib_api_status_t status = IB_SUCCESS;
+ ib_port_info_t *p_pi;
+ unsigned len;
+
+ if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+ return IB_ERROR;
+
+ 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(p_req, p, port_num,
+ &qcfg->vlarb_low[0],
+ len, 0)) != 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(p_req, p, port_num,
+ &qcfg->vlarb_low[1],
+ len, 1)) != 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(p_req, p, port_num,
+ &qcfg->vlarb_high[0],
+ len, 2)) != 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(p_req, p, port_num,
+ &qcfg->vlarb_high[1],
+ len, 3)) != IB_SUCCESS)
+ return status;
+ }
+
+ return status;
+}
+
+static ib_api_status_t sl2vl_update_table(osm_req_t * p_req,
+ osm_physp_t * p, uint8_t in_port,
+ uint8_t out_port,
+ const ib_slvl_table_t * sl2vl_table)
+{
+ osm_madw_context_t context;
+ ib_slvl_table_t tbl, *p_tbl;
+ osm_node_t *p_node = osm_physp_get_node_ptr(p);
+ uint32_t attr_mod;
+ ib_port_info_t *p_pi;
+ unsigned vl_mask;
+ uint8_t vl1, vl2;
+ int i;
+
+ if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+ return IB_ERROR;
+
+ vl_mask = (1 << (ib_port_info_get_op_vls(p_pi) - 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 (p_tbl && !memcmp(p_tbl, &tbl, sizeof(tbl)))
+ return IB_SUCCESS;
+
+ 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;
+ attr_mod = in_port << 8 | out_port;
+ return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+ (uint8_t *) & tbl, sizeof(tbl),
+ IB_MAD_ATTR_SLVL_TABLE,
+ cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t sl2vl_update(osm_req_t * p_req, osm_port_t * p_port,
+ osm_physp_t * p, uint8_t port_num,
+ const struct qos_config *qcfg)
+{
+ ib_api_status_t status;
+ uint8_t i, num_ports;
+ ib_port_info_t *p_pi = osm_physp_get_port_info_ptr(p);
+ osm_physp_t *p_physp;
+
+ if (!p_pi)
+ return IB_ERROR;
+
+ if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) {
+ if (ib_port_info_get_vl_cap(p_pi) == 1) {
+ /* Check port 0's capability mask */
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ p_pi = osm_physp_get_port_info_ptr(p_physp);
+ if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP))
+ return IB_SUCCESS;
+ }
+ num_ports = osm_node_get_num_physp(osm_physp_get_node_ptr(p));
+ } else {
+ if (!(p_pi->capability_mask & IB_PORT_CAP_HAS_SL_MAP))
+ return IB_SUCCESS;
+ num_ports = 1;
+ }
+
+ for (i = 0; i < num_ports; i++) {
+ status =
+ sl2vl_update_table(p_req, p, i, port_num, &qcfg->sl2vl);
+ if (status != IB_SUCCESS)
+ return status;
+ }
+
+ return IB_SUCCESS;
+}
+
+static ib_api_status_t vl_high_limit_update(osm_req_t * p_req,
+ osm_physp_t * p,
+ const struct qos_config *qcfg)
+{
+ uint8_t payload[IB_SMP_DATA_SIZE];
+ osm_madw_context_t context;
+ ib_port_info_t *p_pi;
+
+ if (!(p_pi = osm_physp_get_port_info_ptr(p)))
+ return IB_ERROR;
+
+ if (p_pi->vl_high_limit == qcfg->vl_high_limit)
+ return IB_SUCCESS;
+
+ memset(payload, 0, IB_SMP_DATA_SIZE);
+ memcpy(payload, p_pi, sizeof(ib_port_info_t));
+
+ p_pi = (ib_port_info_t *) payload;
+ ib_port_info_set_state_no_change(p_pi);
+
+ p_pi->vl_high_limit = qcfg->vl_high_limit;
+
+ context.pi_context.node_guid =
+ osm_node_get_node_guid(osm_physp_get_node_ptr(p));
+ context.pi_context.port_guid = osm_physp_get_port_guid(p);
+ context.pi_context.set_method = TRUE;
+ context.pi_context.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ return osm_req_set(p_req, osm_physp_get_dr_path_ptr(p),
+ payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
+ cl_hton32(osm_physp_get_port_num(p)),
+ CL_DISP_MSGID_NONE, &context);
+}
+
+static ib_api_status_t qos_physp_setup(osm_log_t * p_log, osm_req_t * p_req,
+ osm_port_t * p_port, osm_physp_t * p,
+ uint8_t port_num,
+ const struct qos_config *qcfg)
+{
+ ib_api_status_t status;
+
+ /* OpVLs should be ok at this moment - just use it */
+
+ /* setup VL high limit */
+ status = vl_high_limit_update(p_req, p, qcfg);
+ if (status != IB_SUCCESS) {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "qos_physp_setup: ERR 6201 : "
+ "failed to update VLHighLimit "
+ "for port %" PRIx64 " #%d\n",
+ cl_ntoh64(p->port_guid), port_num);
+ return status;
+ }
+
+ /* setup VLArbitration */
+ status = vlarb_update(p_req, p, port_num, qcfg);
+ if (status != IB_SUCCESS) {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "qos_physp_setup: ERR 6202 : "
+ "failed to update VLArbitration tables "
+ "for port %" PRIx64 " #%d\n",
+ cl_ntoh64(p->port_guid), port_num);
+ return status;
+ }
+
+ /* setup SL2VL tables */
+ status = sl2vl_update(p_req, p_port, p, port_num, qcfg);
+ if (status != IB_SUCCESS) {
+ osm_log(p_log, OSM_LOG_ERROR,
+ "qos_physp_setup: ERR 6203 : "
+ "failed to update SL2VLMapping tables "
+ "for port %" PRIx64 " #%d\n",
+ cl_ntoh64(p->port_guid), port_num);
+ return status;
+ }
+
+ return IB_SUCCESS;
+}
+
+osm_signal_t 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;
+ uint32_t num_physp;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ ib_api_status_t status;
+ uint8_t i;
+
+ if (p_osm->subn.opt.no_qos)
+ return OSM_SIGNAL_DONE;
+
+ OSM_LOG_ENTER(&p_osm->log, osm_qos_setup);
+
+ 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_plock_excl_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)) {
+ p_port = (osm_port_t *) p_next;
+ p_next = cl_qmap_next(p_next);
+
+ p_node = p_port->p_node;
+ if (p_node->sw) {
+ num_physp = osm_port_get_num_physp(p_port);
+ for (i = 1; i < num_physp; i++) {
+ p_physp = osm_port_get_phys_ptr(p_port, i);
+ if (!p_physp || !osm_physp_is_valid(p_physp))
+ continue;
+ status =
+ qos_physp_setup(&p_osm->log, &p_osm->sm.req,
+ p_port, p_physp, i, &swe_config);
+ }
+ /* skip base port 0 */
+ if (!ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
+ continue;
+
+ cfg = &sw0_config;
+ } else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER)
+ cfg = &rtr_config;
+ else
+ cfg = &ca_config;
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ if (!osm_physp_is_valid(p_physp))
+ continue;
+
+ status = qos_physp_setup(&p_osm->log, &p_osm->sm.req,
+ p_port, p_physp, 0, cfg);
+ }
+
+ cl_plock_release(&p_osm->lock);
+ OSM_LOG_EXIT(&p_osm->log);
+
+ return OSM_SIGNAL_DONE;
+}
+
+/*
+ * QoS config stuff
+ */
+static int parse_one_unsigned(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(char *str, ib_vl_arb_element_t * e)
+{
+ unsigned val;
+ 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(char *str, uint8_t * raw)
+{
+ unsigned val1, val2;
+ 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;
+ char *p;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ cfg->max_vls = opt->max_vls > 0 ? opt->max_vls : dflt->max_vls;
+ cfg->vl_high_limit = (uint8_t)opt->high_limit;
+
+ p = opt->vlarb_high ? opt->vlarb_high : dflt->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]);
+ }
+
+ p = opt->vlarb_low ? opt->vlarb_low : dflt->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;
+ for (i = 0; i < IB_MAX_NUM_VLS / 2; i++)
+ p += parse_sl2vl_entry(p, &cfg->sl2vl.raw_vl_by_sl[i]);
+
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_remote_sm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sm_t.
+ * This object represents the remote SM object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_remote_sm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_construct(
+ IN osm_remote_sm_t* const p_sm )
+{
+ memset( p_sm, 0, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_destroy(
+ IN osm_remote_sm_t* const p_sm )
+{
+ memset( p_sm, 0, sizeof(*p_sm) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_remote_sm_init(
+ IN osm_remote_sm_t* const p_sm,
+ IN const osm_port_t* const p_port,
+ IN const ib_sm_info_t* const p_smi )
+{
+ CL_ASSERT( p_sm );
+ CL_ASSERT( p_port );
+
+ osm_remote_sm_construct( p_sm );
+
+ p_sm->p_port = p_port;
+ p_sm->smi = *p_smi;
+ return;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_req.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_req_t.
+ * This object represents the generic attribute requester.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_construct(
+ IN osm_req_t* const p_req )
+{
+ CL_ASSERT( p_req );
+
+ memset( p_req, 0, sizeof(*p_req) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_destroy(
+ IN osm_req_t* const p_req )
+{
+ CL_ASSERT( p_req );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_init(
+ IN osm_req_t* const p_req,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN atomic32_t* const p_sm_trans_id )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_req_init );
+
+ osm_req_construct( p_req );
+ p_req->p_log = p_log;
+
+ p_req->p_pool = p_pool;
+ p_req->p_vl15 = p_vl15;
+ p_req->p_subn = p_subn;
+ p_req->p_sm_trans_id = p_sm_trans_id;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_get(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context )
+{
+ osm_madw_t *p_madw;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t tid;
+
+ CL_ASSERT( p_req );
+
+ OSM_LOG_ENTER( p_req->p_log, osm_req_get );
+
+ 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(
+ p_req->p_pool,
+ p_path->h_bind,
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_req->p_log, OSM_LOG_ERROR,
+ "osm_req_get: ERR 1101: "
+ "Unable to acquire MAD\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+ if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_req->p_log, OSM_LOG_DEBUG,
+ "osm_req_get: "
+ "Getting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n",
+ ib_get_sm_attr_str( attr_id ),
+ cl_ntoh16( attr_id ),
+ cl_ntoh32( attr_mod ),
+ cl_ntoh64( tid ) );
+ }
+
+ ib_smp_init_new(
+ osm_madw_get_smp_ptr( p_madw ),
+ IB_MAD_METHOD_GET,
+ tid,
+ attr_id,
+ attr_mod,
+ p_path->hop_count,
+ p_req->p_subn->opt.m_key,
+ 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( p_req->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_req->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ The plock MAY or MAY NOT be held before calling this function.
+**********************************************************************/
+ib_api_status_t
+osm_req_set(
+ IN const osm_req_t* const p_req,
+ IN const osm_dr_path_t* const p_path,
+ IN const uint8_t* const p_payload,
+ IN const size_t payload_size,
+ IN const uint16_t attr_id,
+ IN const uint32_t attr_mod,
+ IN const cl_disp_msgid_t err_msg,
+ IN const osm_madw_context_t* const p_context )
+{
+ osm_madw_t *p_madw;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t tid;
+
+ CL_ASSERT( p_req );
+
+ OSM_LOG_ENTER( p_req->p_log, osm_req_set );
+
+ 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(
+ p_req->p_pool,
+ p_path->h_bind,
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_req->p_log, OSM_LOG_ERROR,
+ "osm_req_set: ERR 1102: "
+ "Unable to acquire MAD\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ tid = cl_hton64( (uint64_t)cl_atomic_inc( p_req->p_sm_trans_id ) );
+
+ if( osm_log_is_active( p_req->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_req->p_log, OSM_LOG_DEBUG,
+ "osm_req_set: "
+ "Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64 "\n",
+ ib_get_sm_attr_str( attr_id ),
+ cl_ntoh16( attr_id ),
+ cl_ntoh32( attr_mod ),
+ cl_ntoh64( tid ) );
+ }
+
+ ib_smp_init_new(
+ osm_madw_get_smp_ptr( p_madw ),
+ IB_MAD_METHOD_SET,
+ tid,
+ attr_id,
+ attr_mod,
+ p_path->hop_count,
+ p_req->p_subn->opt.m_key,
+ 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 );
+
+ osm_vl15_post( p_req->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_req->p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_req_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_req_ctrl_t.
+ * This object represents the request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_req_ctrl.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_req_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_req_get( ((osm_req_ctrl_t*)context)->p_req,
+ (&((osm_attrib_req_t*)p_data)->path),
+ ((osm_attrib_req_t*)p_data)->attrib_id,
+ ((osm_attrib_req_t*)p_data)->attrib_mod,
+ ((osm_attrib_req_t*)p_data)->err_msg,
+ (&((osm_attrib_req_t*)p_data)->context) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_construct(
+ IN osm_req_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_req_ctrl_destroy(
+ IN osm_req_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_req_ctrl_init(
+ IN osm_req_ctrl_t* const p_ctrl,
+ IN osm_req_t* const p_req,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_req_ctrl_init );
+
+ osm_req_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_req = p_req;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_REQ,
+ __osm_req_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_req_ctrl_init: ERR 1202: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_resp.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_resp_t.
+ * This object represents the generic attribute responder.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_resp.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_attrib_req.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_construct(
+ IN osm_resp_t* const p_resp )
+{
+ memset( p_resp, 0, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_destroy(
+ IN osm_resp_t* const p_resp )
+{
+ CL_ASSERT( p_resp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_init(
+ IN osm_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_resp_init );
+
+ osm_resp_construct( p_resp );
+
+ p_resp->p_log = p_log;
+ p_resp->p_pool = p_pool;
+ p_resp->p_vl15 = p_vl15;
+ p_resp->p_subn = p_subn;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_resp_make_resp_smp(
+ IN const osm_resp_t* const p_resp,
+ IN const ib_smp_t* const p_src_smp,
+ IN const ib_net16_t status,
+ IN const uint8_t* const p_payload,
+ OUT ib_smp_t* const p_dest_smp )
+{
+ OSM_LOG_ENTER( p_resp->p_log, osm_resp_make_resp_smp );
+
+ 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( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_resp_make_resp_smp: 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( p_resp->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_resp_send(
+ IN const osm_resp_t* const p_resp,
+ IN const osm_madw_t* const p_req_madw,
+ IN const ib_net16_t mad_status,
+ IN const uint8_t* const 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( p_resp->p_log, osm_resp_send );
+
+ 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(
+ p_resp->p_pool,
+ osm_madw_get_bind_handle( p_req_madw ),
+ MAD_BLOCK_SIZE,
+ NULL );
+
+ if( p_madw == NULL )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_resp_send: 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 );
+ osm_resp_make_resp_smp( p_resp, 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;
+
+ if( osm_log_is_active( p_resp->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+ "osm_resp_send: "
+ "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( p_resp->p_vl15, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_resp->p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_router_t.
+ * This object represents an Infiniband router.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_router.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_construct(
+ IN osm_router_t* const p_rtr )
+{
+ CL_ASSERT( p_rtr );
+ memset( p_rtr, 0, sizeof(*p_rtr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_router_init(
+ IN osm_router_t* const p_rtr,
+ IN osm_port_t* const p_port )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ CL_ASSERT( p_rtr );
+ CL_ASSERT( p_port );
+
+ osm_router_construct( p_rtr );
+
+ p_rtr->p_port = p_port;
+
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_destroy(
+ IN osm_router_t* const p_rtr )
+{
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_router_delete(
+ IN OUT osm_router_t** const pp_rtr )
+{
+ osm_router_destroy( *pp_rtr );
+ free( *pp_rtr );
+ *pp_rtr = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_router_t*
+osm_router_new(
+ IN osm_port_t* const p_port )
+{
+ ib_api_status_t status;
+ osm_router_t *p_rtr;
+
+ p_rtr = (osm_router_t*)malloc( sizeof(*p_rtr) );
+ if( p_rtr )
+ {
+ memset( p_rtr, 0, sizeof(*p_rtr) );
+ status = osm_router_init( p_rtr, p_port );
+ if( status != IB_SUCCESS )
+ osm_router_delete( &p_rtr );
+ }
+
+ return( p_rtr );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_t.
+ * This object represents the Subnet Administration object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_service.h>
+
+#define OSM_SA_INITIAL_TID_VALUE 0xabc
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_construct(
+ IN osm_sa_t* const 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;
+
+ osm_sa_mad_ctrl_construct( &p_sa->mad_ctrl );
+ osm_sa_resp_construct( &p_sa->resp );
+
+ osm_nr_rcv_construct( &p_sa->nr_rcv);
+ osm_nr_rcv_ctrl_construct( &p_sa->nr_rcv_ctrl );
+
+ osm_pir_rcv_construct( &p_sa->pir_rcv );
+ osm_pir_rcv_ctrl_construct( &p_sa->pir_rcv_ctrl );
+
+ osm_gir_rcv_construct( &p_sa->gir_rcv );
+ osm_gir_rcv_ctrl_construct( &p_sa->gir_rcv_ctrl );
+
+ osm_lr_rcv_construct( &p_sa->lr_rcv );
+ osm_lr_rcv_ctrl_construct( &p_sa->lr_rcv_ctrl );
+
+ osm_pr_rcv_construct( &p_sa->pr_rcv );
+ osm_pr_rcv_ctrl_construct( &p_sa->pr_rcv_ctrl );
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+ osm_mpr_rcv_construct( &p_sa->mpr_rcv );
+ osm_mpr_rcv_ctrl_construct( &p_sa->mpr_rcv_ctrl );
+#endif
+
+ osm_smir_rcv_construct( &p_sa->smir_rcv );
+ osm_smir_ctrl_construct( &p_sa->smir_ctrl );
+
+ osm_mcmr_rcv_construct(&p_sa->mcmr_rcv );
+ osm_mcmr_rcv_ctrl_construct(&p_sa->mcmr_rcv_ctlr);
+
+ osm_sr_rcv_construct( &p_sa->sr_rcv );
+ osm_sr_rcv_ctrl_construct( &p_sa->sr_rcv_ctrl );
+
+ osm_infr_rcv_construct( &p_sa->infr_rcv );
+ osm_infr_rcv_ctrl_construct( &p_sa->infr_rcv_ctrl );
+
+ osm_vlarb_rec_rcv_construct( &p_sa->vlarb_rec_rcv );
+ osm_vlarb_rec_rcv_ctrl_construct( &p_sa->vlarb_rec_rcv_ctrl );
+
+ osm_slvl_rec_rcv_construct( &p_sa->slvl_rec_rcv );
+ osm_slvl_rec_rcv_ctrl_construct( &p_sa->slvl_rec_rcv_ctrl );
+
+ osm_pkey_rec_rcv_construct( &p_sa->pkey_rec_rcv );
+ osm_pkey_rec_rcv_ctrl_construct( &p_sa->pkey_rec_rcv_ctrl );
+
+ osm_lftr_rcv_construct( &p_sa->lftr_rcv );
+ osm_lftr_rcv_ctrl_construct( &p_sa->lftr_rcv_ctrl );
+
+ osm_sir_rcv_construct( &p_sa->sir_rcv );
+ osm_sir_rcv_ctrl_construct( &p_sa->sir_rcv_ctrl );
+
+ osm_mftr_rcv_construct( &p_sa->mftr_rcv );
+ osm_mftr_rcv_ctrl_construct( &p_sa->mftr_rcv_ctrl );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_shutdown(
+ IN osm_sa_t* const p_sa )
+{
+ ib_api_status_t status;
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_shutdown );
+
+ /* unbind from the mad service */
+ status = osm_sa_mad_ctrl_unbind( &p_sa->mad_ctrl );
+
+ /* remove any registered dispatcher message */
+ osm_nr_rcv_ctrl_destroy( &p_sa->nr_rcv_ctrl );
+ osm_pir_rcv_ctrl_destroy( &p_sa->pir_rcv_ctrl );
+ osm_gir_rcv_ctrl_destroy( &p_sa->gir_rcv_ctrl );
+ osm_lr_rcv_ctrl_destroy( &p_sa->lr_rcv_ctrl );
+ osm_pr_rcv_ctrl_destroy( &p_sa->pr_rcv_ctrl );
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+ osm_mpr_rcv_ctrl_destroy( &p_sa->mpr_rcv_ctrl );
+#endif
+ osm_smir_ctrl_destroy( &p_sa->smir_ctrl );
+ osm_mcmr_rcv_ctrl_destroy( &p_sa->mcmr_rcv_ctlr);
+ osm_sr_rcv_ctrl_destroy( &p_sa->sr_rcv_ctrl );
+ osm_infr_rcv_ctrl_destroy( &p_sa->infr_rcv_ctrl );
+ osm_vlarb_rec_rcv_ctrl_destroy( &p_sa->vlarb_rec_rcv_ctrl );
+ osm_slvl_rec_rcv_ctrl_destroy( &p_sa->slvl_rec_rcv_ctrl );
+ osm_pkey_rec_rcv_ctrl_destroy( &p_sa->pkey_rec_rcv_ctrl );
+ osm_lftr_rcv_ctrl_destroy( &p_sa->lftr_rcv_ctrl );
+ osm_sir_rcv_ctrl_destroy( &p_sa->sir_rcv_ctrl );
+ osm_mftr_rcv_ctrl_destroy( &p_sa->mftr_rcv_ctrl );
+ osm_sa_mad_ctrl_destroy( &p_sa->mad_ctrl );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_destroy(
+ IN osm_sa_t* const p_sa )
+{
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_destroy );
+
+ p_sa->state = OSM_SA_STATE_INIT;
+
+ osm_nr_rcv_destroy( &p_sa->nr_rcv );
+ osm_pir_rcv_destroy( &p_sa->pir_rcv );
+ osm_gir_rcv_destroy( &p_sa->gir_rcv );
+ osm_lr_rcv_destroy( &p_sa->lr_rcv );
+ osm_pr_rcv_destroy( &p_sa->pr_rcv );
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+ osm_mpr_rcv_destroy( &p_sa->mpr_rcv );
+#endif
+ osm_smir_rcv_destroy( &p_sa->smir_rcv );
+ osm_mcmr_rcv_destroy(&p_sa->mcmr_rcv);
+ osm_sr_rcv_destroy( &p_sa->sr_rcv );
+ osm_infr_rcv_destroy( &p_sa->infr_rcv );
+ osm_vlarb_rec_rcv_destroy( &p_sa->vlarb_rec_rcv );
+ osm_slvl_rec_rcv_destroy( &p_sa->slvl_rec_rcv );
+ osm_pkey_rec_rcv_destroy( &p_sa->pkey_rec_rcv );
+ osm_lftr_rcv_destroy( &p_sa->lftr_rcv );
+ osm_sir_rcv_destroy( &p_sa->sir_rcv );
+ osm_mftr_rcv_destroy( &p_sa->mftr_rcv );
+ osm_sa_resp_destroy( &p_sa->resp );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_init(
+ IN osm_sm_t* const p_sm,
+ IN osm_sa_t* const p_sa,
+ IN osm_subn_t* const p_subn,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_init );
+
+ 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_lock = p_lock;
+
+ p_sa->state = OSM_SA_STATE_READY;
+
+ status = osm_sa_resp_init(&p_sa->resp,
+ p_sa->p_mad_pool,
+ p_log);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sa_mad_ctrl_init(
+ &p_sa->mad_ctrl,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_sa->p_vendor,
+ p_subn,
+ p_log,
+ p_stats,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_cpi_rcv_init(
+ &p_sa->cpi_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_cpi_rcv_ctrl_init(
+ &p_sa->cpi_rcv_ctrl,
+ &p_sa->cpi_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nr_rcv_init(
+ &p_sa->nr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nr_rcv_ctrl_init(
+ &p_sa->nr_rcv_ctrl,
+ &p_sa->nr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pir_rcv_init(
+ &p_sa->pir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pir_rcv_ctrl_init(
+ &p_sa->pir_rcv_ctrl,
+ &p_sa->pir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_gir_rcv_init(
+ &p_sa->gir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_gir_rcv_ctrl_init(
+ &p_sa->gir_rcv_ctrl,
+ &p_sa->gir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lr_rcv_init(
+ &p_sa->lr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lr_rcv_ctrl_init(
+ &p_sa->lr_rcv_ctrl,
+ &p_sa->lr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pr_rcv_init(
+ &p_sa->pr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pr_rcv_ctrl_init(
+ &p_sa->pr_rcv_ctrl,
+ &p_sa->pr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+ status = osm_mpr_rcv_init(
+ &p_sa->mpr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mpr_rcv_ctrl_init(
+ &p_sa->mpr_rcv_ctrl,
+ &p_sa->mpr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+#endif
+
+ status = osm_smir_rcv_init(
+ &p_sa->smir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_stats,
+ p_log,
+ p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_smir_ctrl_init(
+ &p_sa->smir_ctrl,
+ &p_sa->smir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcmr_rcv_init(
+ p_sm,
+ &p_sa->mcmr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcmr_rcv_ctrl_init(
+ &p_sa->mcmr_rcv_ctlr,
+ &p_sa->mcmr_rcv,
+ p_log,
+ p_disp);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sr_rcv_init(
+ &p_sa->sr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sr_rcv_ctrl_init(
+ &p_sa->sr_rcv_ctrl,
+ &p_sa->sr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_infr_rcv_init(
+ &p_sa->infr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_infr_rcv_ctrl_init(
+ &p_sa->infr_rcv_ctrl,
+ &p_sa->infr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vlarb_rec_rcv_init(
+ &p_sa->vlarb_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vlarb_rec_rcv_ctrl_init(
+ &p_sa->vlarb_rec_rcv_ctrl,
+ &p_sa->vlarb_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rec_rcv_init(
+ &p_sa->slvl_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rec_rcv_ctrl_init(
+ &p_sa->slvl_rec_rcv_ctrl,
+ &p_sa->slvl_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rec_rcv_init(
+ &p_sa->pkey_rec_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rec_rcv_ctrl_init(
+ &p_sa->pkey_rec_rcv_ctrl,
+ &p_sa->pkey_rec_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lftr_rcv_init(
+ &p_sa->lftr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lftr_rcv_ctrl_init(
+ &p_sa->lftr_rcv_ctrl,
+ &p_sa->lftr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sir_rcv_init(
+ &p_sa->sir_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sir_rcv_ctrl_init(
+ &p_sa->sir_rcv_ctrl,
+ &p_sa->sir_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mftr_rcv_init(
+ &p_sa->mftr_rcv,
+ &p_sa->resp,
+ p_sa->p_mad_pool,
+ p_subn,
+ p_log,
+ p_lock);
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mftr_rcv_ctrl_init(
+ &p_sa->mftr_rcv_ctrl,
+ &p_sa->mftr_rcv,
+ p_log,
+ p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_bind(
+ IN osm_sa_t* const p_sa,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sa->p_log, osm_sa_bind );
+
+ status = osm_sa_mad_ctrl_bind(
+ &p_sa->mad_ctrl, port_guid );
+
+ OSM_LOG_EXIT( p_sa->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * 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];
+ 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,
+ "opensm_dump_to_file: ERR 0000: "
+ "cannot open file \'%s\': %s\n",
+ file_name, strerror(errno));
+ return -1;
+ }
+
+ chmod(path, S_IRUSR|S_IWUSR);
+
+ dump_func(p_osm, file);
+
+ fclose(file);
+ return 0;
+}
+
+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_port_t *p_mcm_port = (osm_mcm_port_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_port->port_gid.unicast.prefix),
+ cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id),
+ p_mcm_port->scope_state,
+ p_mcm_port->proxy_join);
+}
+
+static void
+sa_dump_one_mgrp(cl_map_item_t *p_map_item, 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;
+ osm_mgrp_t *p_mgrp = (osm_mgrp_t *)p_map_item;
+
+ 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_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=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_node_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),
+ cl_ntoh16(p_infr->report_addr.addr_type.gsi.pkey),
+ 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_all_sa(osm_opensm_t *p_osm, FILE *file)
+{
+ struct opensm_dump_context dump_context;
+
+ dump_context.p_osm = p_osm;
+ dump_context.file = file;
+ osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: Dump multicast:\n");
+ cl_plock_acquire(&p_osm->lock);
+ cl_qmap_apply_func(&p_osm->subn.mgrp_mlid_tbl,
+ sa_dump_one_mgrp, &dump_context);
+ osm_log(&p_osm->log, OSM_LOG_DEBUG, "sa_dump_all_sa: 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, "sa_dump_all_sa: Dump services:\n");
+ cl_qlist_apply_func(&p_osm->subn.sa_sr_list,
+ sa_dump_one_service, &dump_context);
+ cl_plock_release(&p_osm->lock);
+}
+
+int osm_sa_db_file_dump(osm_opensm_t *p_osm)
+{
+ return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa);
+}
+
+/*
+ * SA DB Loader
+ *
+ */
+
+osm_mgrp_t *load_mcgroup(osm_opensm_t *p_osm, ib_net16_t mlid,
+ ib_member_rec_t *p_mcm_rec, unsigned well_known)
+{
+ ib_net64_t comp_mask;
+ cl_map_item_t *p_next;
+ osm_mgrp_t *p_mgrp;
+
+ cl_plock_excl_acquire(&p_osm->lock);
+
+ if ((p_next = cl_qmap_get(&p_osm->subn.mgrp_mlid_tbl, mlid)) !=
+ cl_qmap_end(&p_osm->subn.mgrp_mlid_tbl)) {
+ p_mgrp = (osm_mgrp_t *)p_next;
+ if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid,
+ sizeof(ib_gid_t))) {
+ osm_log(&p_osm->log, OSM_LOG_DEBUG,
+ "load_mcgroup: mgrp %04x is already here.",
+ cl_ntoh16(mlid));
+ goto _out;
+ }
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "load_mcgroup: 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 (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa.mcmr_rcv,
+ comp_mask, p_mcm_rec,
+ &p_mgrp) != IB_SUCCESS ||
+ !p_mgrp || p_mgrp->mlid != mlid) {
+ osm_log(&p_osm->log, OSM_LOG_ERROR,
+ "load_mcgroup: 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;
+ }
+ else if (well_known)
+ p_mgrp->well_known = TRUE;
+
+ _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,
+ "load_svcr ServiceRecord already exists.\n");
+ goto _out;
+ }
+
+ if (!(p_svcr = osm_svcr_new(sr))) {
+ osm_log(&p_osm->log, OSM_LOG_ERROR,
+ "load_svcr: 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,
+ "load_svcr: 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_rcv.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.p_infr_rcv = &p_osm->sa.infr_rcv;
+ /* 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,
+ "load_infr: InformInfo Record already exists\n");
+ goto _out;
+ }
+
+ if (!(p_infr = osm_infr_new(&infr))) {
+ osm_log(&p_osm->log, OSM_LOG_ERROR,
+ "load_infr: cannot allocate new infr struct\n");
+ ret = -1;
+ goto _out;
+ }
+
+ osm_log(&p_osm->log, OSM_LOG_DEBUG,
+ "load_infr: 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;
+}
+
+
+#define UNPACK_FUNC(name,x) \
+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; \
+}
+
+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_mgrp = NULL;
+ unsigned rereg_clients = 0;
+ unsigned lineno;
+
+ file_name = p_osm->subn.opt.sa_db_file;
+ if (!file_name) {
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "osm_sa_db_file_load: 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,
+ "osm_sa_db_file_load: ERR 0000: "
+ "cannot open sa db file \'%s\'. "
+ "Skip restoring\n", file_name);
+ return -1;
+ }
+
+ 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;
+ unsigned well_known = 0;
+
+ p_mgrp = NULL;
+ memset(&mcm_rec, 0, sizeof(mcm_rec));
+
+ PARSE_AHEAD(p, net16, " 0x", &mlid);
+ if(strstr(p, "well known"))
+ well_known = 1;
+ 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_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec,
+ well_known);
+ if (!p_mgrp)
+ rereg_clients = 1;
+ }
+ else if (p_mgrp && !strncmp(p, "mcm_port", 8)) {
+ ib_gid_t port_gid;
+ ib_net64_t guid;
+ uint8_t scope_state;
+ boolean_t proxy_join;
+
+ PARSE_AHEAD(p, net64, " port_gid=0x",
+ &port_gid.unicast.prefix);
+ PARSE_AHEAD(p, net64, ":0x",
+ &port_gid.unicast.interface_id);
+ PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state);
+ PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
+ proxy_join = val;
+
+ guid = port_gid.unicast.interface_id;
+ if (cl_qmap_get(&p_mgrp->mcm_port_tbl,
+ port_gid.unicast.interface_id) ==
+ cl_qmap_end(&p_mgrp->mcm_port_tbl))
+ osm_mgrp_add_port(p_mgrp, &port_gid,
+ scope_state, proxy_join);
+ }
+ else if (!strncmp(p, "Service Record:", 15)) {
+ ib_service_record_t s_rec;
+ uint32_t modified_time, lease_period;
+
+ p_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;
+
+ p_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=0x",
+ &rep_addr.addr_type.gsi.pkey);
+ 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;
+ }
+ }
+
+ if (!rereg_clients)
+ p_osm->subn.opt.no_clients_rereg = TRUE;
+
+ _error:
+ fclose(file);
+ return ret;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_class_port_info.c 1931 2009-02-04 17:56:23Z stansmith $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_cpi_rcv_t.
+ * This object represents the ClassPortInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_class_port_info.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+
+#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) */
+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 };
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_construct(
+ IN osm_cpi_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_destroy(
+ IN osm_cpi_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_destroy );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_init(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_cpi_rcv_init );
+
+ osm_cpi_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_cpi_rcv_respond(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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_api_status_t status;
+ ib_gid_t zero_gid;
+ uint8_t rtv;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_cpi_rcv_respond );
+
+ 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( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ MAD_BLOCK_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_cpi_rcv_respond: 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 (p_rcv->p_subn->opt.transaction_timeout > __msecs_to_rtv_table[MAX_MSECS_TO_RTV])
+ rtv = MAX_MSECS_TO_RTV - 1;
+ else
+ {
+ for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) {
+ if (p_rcv->p_subn->opt.transaction_timeout <= __msecs_to_rtv_table[rtv])
+ break;
+ }
+ }
+ rtv += 8;
+ p_resp_cpi->cap_mask2_resp_time = 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 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
+ if (p_rcv->p_subn->opt.no_multicast_option != TRUE)
+ 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( p_rcv->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_cpi_rcv_respond: ERR 1409: "
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * This code actually handles the call
+ **********************************************************************/
+void
+osm_cpi_rcv_process(
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_path_rec_t* p_pr;
+ const ib_sa_mad_t* p_sa_mad;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_cpi_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_cpi_rcv_process: ERR 1403: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
+ goto Exit;
+ }
+
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );
+
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_CLASS_PORT_INFO );
+
+ /*
+ CLASS PORT INFO does not really look on the SMDB - no lock required.
+ */
+
+ __osm_cpi_rcv_respond( p_rcv, p_madw);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_class_port_info_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the ClassPortInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_class_port_info_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_cpi_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_cpi_rcv_process( ((osm_cpi_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_construct(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_cpi_rcv_ctrl_destroy(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_cpi_rcv_ctrl_init(
+ IN osm_cpi_rcv_ctrl_t* const p_ctrl,
+ IN osm_cpi_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_cpi_rcv_ctrl_init );
+
+ osm_cpi_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_CLASS_PORT_INFO,
+ __osm_cpi_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_cpi_rcv_ctrl_init: ERR 1501: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_guidinfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_gir_rcv_t.
+ * This object represents the GUIDInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_guidinfo_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_GIR_RCV_POOL_MIN_SIZE 32
+#define OSM_GIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_gir_item
+{
+ cl_pool_item_t pool_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_gir_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_gir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_construct(
+ IN osm_gir_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_destroy(
+ IN osm_gir_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_gir_rcv_init(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_gir_rcv_init );
+
+ osm_gir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_GIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_GIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_gir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_gir_rcv_new_gir(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const match_port_guid,
+ IN ib_net16_t const match_lid,
+ IN const osm_physp_t* const p_req_physp,
+ IN uint8_t const block_num )
+{
+ osm_gir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_gir_rcv_new_gir );
+
+ p_rec_item = (osm_gir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_gir_rcv_new_gir: ERR 5102: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_gir_rcv_new_gir: "
+ "New GUIDInfoRecord: lid 0x%X, block num %d\n",
+ cl_ntoh16( match_lid ), block_num );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = match_lid;
+ p_rec_item->rec.block_num = block_num;
+ if (!block_num)
+ p_rec_item->rec.guid_info.guid[0] = osm_physp_get_port_guid( p_req_physp );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_gir_create_gir(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const match_port_guid,
+ IN ib_net16_t const match_lid,
+ IN const osm_physp_t* const 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;
+ const ib_port_info_t* p_pi;
+ uint8_t block_num, start_block_num, end_block_num, num_blocks;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_gir_create_gir );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_gir_create_gir: "
+ "Looking for GUIDRecord with LID: 0x%X 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( !osm_physp_is_valid( 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( p_rcv->p_log, p_physp, p_req_physp ) )
+ continue;
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ if( match_port_guid && ( port_guid != match_port_guid ) )
+ continue;
+
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ /*
+ 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_pi->guid_cap == 0 )
+ continue;
+
+ num_blocks = p_pi->guid_cap / 8;
+ if ( p_pi->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.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_gir_create_gir: "
+ "Comparing LID: 0x%X <= 0x%X <= 0x%X\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++)
+ __osm_gir_rcv_new_gir( p_rcv, p_node, p_list,
+ port_guid, cl_ntoh16(base_lid_ho),
+ p_physp, block_num );
+
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_gir_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_gir_search_ctxt_t* const p_ctxt = (osm_gir_search_ctxt_t *)context;
+ const 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_gir_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ 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->p_rcv->p_log, __osm_sa_gir_by_comp_mask_cb);
+
+ 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;
+ }
+
+ __osm_sa_gir_create_gir( p_rcv, p_node, p_ctxt->p_list,
+ match_port_guid, match_lid, p_req_physp,
+ match_block_num );
+
+ Exit:
+ OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_process(
+ IN osm_gir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_guidinfo_record_t* p_rcvd_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_guidinfo_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_gir_search_ctxt_t context;
+ osm_gir_item_t* p_rec_item;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_gir_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ 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_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_GUIDINFO_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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_process: ERR 5105: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_process: ERR 5104: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_guidinfo_record( p_rcv->p_log, p_rcvd_rec, 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl,
+ __osm_sa_gir_by_comp_mask_cb,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_process: ERR 5103: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_gir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_guidinfo_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_gir_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_gir_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_guidinfo_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_process: ERR 5106: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_guidinfo_record_t) );
+
+ p_resp_rec = (ib_guidinfo_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_gir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_process: ERR 5107: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_guidinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_gir_rcv_ctrl_t.
+ * This object represents the GUIDInfoRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_guidinfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_gir_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_gir_rcv_process( ((osm_gir_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_ctrl_construct(
+ IN osm_gir_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_gir_rcv_ctrl_destroy(
+ IN osm_gir_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_gir_rcv_ctrl_init(
+ IN osm_gir_rcv_ctrl_t* const p_ctrl,
+ IN osm_gir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_gir_rcv_ctrl_init );
+
+ osm_gir_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_GUIDINFO_RECORD,
+ __osm_gir_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_gir_rcv_ctrl_init: ERR 5201: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_informinfo.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_infr_rcv_t.
+ * This object represents the InformInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_informinfo.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_IIR_RCV_POOL_MIN_SIZE 32
+#define OSM_IIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_iir_item
+{
+ cl_pool_item_t pool_item;
+ ib_inform_info_record_t rec;
+} osm_iir_item_t;
+
+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_infr_rcv_t* p_rcv;
+ osm_physp_t* p_req_physp;
+} osm_iir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_construct(
+ IN osm_infr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_destroy(
+ IN osm_infr_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_init(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_ERROR;
+
+ OSM_LOG_ENTER( p_log, osm_infr_rcv_init );
+
+ osm_infr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_IIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_IIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_iir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+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_infr_rcv_t* const p_rcv,
+ IN osm_infr_t* p_infr_rec )
+{
+ boolean_t valid = TRUE;
+ osm_physp_t* p_requester_physp;
+ osm_port_t* p_port;
+ osm_physp_t* p_physp;
+ ib_net64_t portguid;
+ ib_net16_t lid_range_begin;
+ ib_net16_t lid_range_end;
+ ib_net16_t lid;
+ const cl_ptr_vector_t* p_tbl;
+ ib_gid_t zero_gid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_ports_access_rights );
+
+ /* get the requester physp from the request address */
+ p_requester_physp = osm_get_physp_by_mad_addr( p_rcv->p_log,
+ p_rcv->p_subn,
+ &p_infr_rec->report_addr );
+
+ memset( &zero_gid, 0, sizeof(zero_gid) );
+ if ( memcmp (&(p_infr_rec->inform_record.inform_info.gid),
+ &zero_gid, sizeof(ib_gid_t) ) )
+ {
+ /* a gid is defined */
+ portguid = p_infr_rec->inform_record.inform_info.gid.unicast.interface_id;
+
+ p_port = osm_get_port_by_guid( p_rcv->p_subn, portguid );
+
+ if ( p_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_ports_access_rights: ERR 4301: "
+ "Invalid port guid: 0x%016" PRIx64 "\n",
+ cl_ntoh64(portguid) );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /* get the destination InformInfo physical port */
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+
+ /* make sure that the requester and destination port can access each other
+ according to the current partitioning. */
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_ports_access_rights: "
+ "port and requester don't share pkey\n" );
+ valid = FALSE;
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* 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);
+
+ /* 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;
+
+ /* 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_tbl = &p_rcv->p_subn->port_lid_tbl;
+ if ( cl_ptr_vector_get_size( p_tbl ) > lid )
+ {
+ p_port = cl_ptr_vector_get( p_tbl, lid );
+ }
+ else
+ {
+ /* lid requested is out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_ports_access_rights: ERR 4302: "
+ "Given LID (0x%X) is out of range:0x%X\n",
+ lid, cl_ptr_vector_get_size(p_tbl) );
+ valid = FALSE;
+ goto Exit;
+ }
+ if ( p_port == NULL )
+ continue;
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* make sure that the requester and destination port can access
+ each other according to the current partitioning. */
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_physp, p_requester_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_ports_access_rights: "
+ "port and requester don't share pkey\n" );
+ valid = FALSE;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static
+boolean_t
+__validate_infr(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_infr_t* p_infr_rec )
+{
+ boolean_t valid = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_infr );
+
+ valid = __validate_ports_access_rights( p_rcv, p_infr_rec );
+ if (!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_infr: "
+ "Invalid Access for InformInfo\n" );
+ valid = FALSE;
+ }
+
+ OSM_LOG_EXIT( p_rcv->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
+__osm_infr_rcv_respond(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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_inform_info_t* p_resp_infr;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_infr_rcv_respond );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_infr_rcv_respond: "
+ "Generating successful InformInfo response\n");
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ MAD_BLOCK_SIZE,
+ &p_madw->mad_addr );
+ if ( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_infr_rcv_respond: ERR 4303: "
+ "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 );
+
+ /* copy the request InformInfo */
+ memcpy( p_resp_sa_mad, p_sa_mad, MAD_BLOCK_SIZE );
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+ /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+ p_resp_sa_mad->sm_key = 0;
+
+ p_resp_infr = (ib_inform_info_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_infr_rcv_respond: ERR 4304: "
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_infr_t* const p_infr,
+ osm_iir_search_ctxt_t* const p_ctxt )
+{
+ const ib_inform_info_record_t* p_rcvd_rec = NULL;
+ 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_iir_item_t* p_rec_item;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_inform_info_rec_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID)
+ {
+ if (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)
+ {
+ if (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( p_rcv->p_subn, portguid );
+ if ( p_subscriber_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_inform_info_rec_by_comp_mask: ERR 430D: "
+ "Invalid subscriber port guid: 0x%016" PRIx64 "\n",
+ cl_ntoh64(portguid) );
+ goto Exit;
+ }
+
+ /* get the subscriber InformInfo physical port */
+ p_subscriber_physp = osm_port_get_default_phys_ptr(p_subscriber_port);
+ /* make sure that the requester and subscriber port can access each other
+ according to the current partitioning. */
+ if (! osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_subscriber_physp ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_inform_info_rec_by_comp_mask: "
+ "requester and subscriber ports don't share pkey\n" );
+ goto Exit;
+ }
+
+ p_rec_item = (osm_iir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_inform_info_rec_by_comp_mask: ERR 430E: "
+ "cl_qlock_pool_get failed\n" );
+ goto Exit;
+ }
+
+ memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record, sizeof(ib_inform_info_record_t));
+ cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_inform_info_rec_by_comp_mask_cb(
+ IN cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ const osm_infr_t* const p_infr = (osm_infr_t *)p_list_item;
+ osm_iir_search_ctxt_t* const p_ctxt = (osm_iir_search_ctxt_t *)context;
+
+ __osm_sa_inform_info_rec_by_comp_mask( p_ctxt->p_rcv, p_infr, p_ctxt );
+}
+
+/**********************************************************************
+Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_get_method(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t* p_rcvd_mad;
+ const ib_inform_info_record_t* p_rcvd_rec;
+ ib_inform_info_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i, j;
+ osm_iir_search_ctxt_t context;
+ osm_iir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process_get_method );
+
+ 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 );
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_get_method: ERR 4309: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_inform_info_record( p_rcv->p_log, p_rcvd_rec, 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_get_method: "
+ "Query Subscriber GID:0x%016" PRIx64 " : 0x%016" PRIx64 "(%02X) Enum:0x%X(%02X)\n",
+ cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.prefix),
+ cl_ntoh64(p_rcvd_rec->subscriber_gid.unicast.interface_id),
+ (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_plock_acquire( p_rcv->p_lock );
+
+ cl_qlist_apply_func( &p_rcv->p_subn->sa_infr_list,
+ __osm_sa_inform_info_rec_by_comp_mask_cb,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_get_method: ERR 430A: "
+ "More than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_iir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_inform_info_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_infr_rcv_process_get_method: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_get_method: "
+ "Returning %u records\n", num_rec );
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_inform_info_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_get_method: ERR 430B: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_inform_info_record_t) );
+
+ p_resp_rec = (ib_inform_info_record_t*)ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_iir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ /* clear reserved and pad fields in InformInfoRecord */
+ for (j = 0; j < 6; j++)
+ p_resp_rec->reserved[j] = 0;
+ for (j = 0; j < 4; j++)
+ p_resp_rec->pad[j] = 0;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_get_method: ERR 430C: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+Received a Set(InformInfo) MAD
+**********************************************************************/
+static void
+osm_infr_rcv_process_set_method(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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( p_rcv->p_log, osm_infr_rcv_process_set_method );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_inform_info( p_rcv->p_log, p_recvd_inform_info, OSM_LOG_DEBUG );
+#endif
+
+ /* Grab the lock */
+ cl_plock_excl_acquire( p_rcv->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.p_infr_rcv = p_rcv;
+
+ /* update the subscriber GID according to mad address */
+ res = osm_get_gid_by_mad_addr(
+ p_rcv->p_log,
+ p_rcv->p_subn,
+ &p_madw->mad_addr,
+ &inform_info_rec.inform_record.subscriber_gid );
+ if ( res != IB_SUCCESS )
+ {
+ cl_plock_release( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: ERR 4308 "
+ "Subscribe Request from unknown LID: 0x%04X\n",
+ cl_ntoh16(p_madw->mad_addr.dest_lid)
+ );
+ osm_sa_send_error( p_rcv->p_resp, 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( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: ERR 4308 "
+ "Invalid subscribe: %d\n",
+ p_recvd_inform_info->subscribe
+ );
+ osm_sa_send_error( p_rcv->p_resp, 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_set_method: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process_set_method: "
+ "UnSubscribe Request with QPN: 0x%06X\n",
+ cl_ntoh32(qpn)
+ );
+ }
+
+ /* If record exists with matching InformInfo */
+ p_infr = osm_infr_get_by_rec( p_rcv->p_subn, p_rcv->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( p_rcv, &inform_info_rec ) != TRUE )
+ {
+ cl_plock_release( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: 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( p_rcv->p_resp, 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( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: 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( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ /* Add this new osm_infr_t object to subnet object */
+ osm_infr_insert_to_db( p_rcv->p_subn, p_rcv->p_log, p_infr );
+ }
+ else
+ {
+ /* Update the old instance of the osm_infr_t object */
+ p_infr->inform_record = inform_info_rec.inform_record;
+ }
+ }
+ else
+ {
+ /* We got an UnSubscribe request */
+ if (p_infr == NULL)
+ {
+ cl_plock_release( p_rcv->p_lock );
+
+ /* No Such Item - So Error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_process_set_method: 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( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+ goto Exit;
+ }
+ else
+ {
+ /* Delete this object from the subnet list of informs */
+ osm_infr_remove_from_db( p_rcv->p_subn, p_rcv->p_log, p_infr );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ /* send the success response */
+ __osm_infr_rcv_respond( p_rcv, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+**********************************************************************/
+void
+osm_infr_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infr_rcv_process: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ osm_infr_rcv_process_set_method( p_rcv, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/*********************************************************************
+**********************************************************************/
+void
+osm_infir_rcv_process(
+ IN osm_infr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_infr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_infir_rcv_process: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ osm_infr_rcv_process_get_method( p_rcv, p_madw );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_informinfo_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_infr_rcv_ctrl_t.
+ * This object represents the InformInfo set request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_informinfo_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_infr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_infr_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_infir_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_infir_rcv_process( ((osm_infr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_construct(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+ p_ctrl->h_disp2 = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_infr_rcv_ctrl_destroy(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp2 );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_infr_rcv_ctrl_init(
+ IN osm_infr_rcv_ctrl_t* const p_ctrl,
+ IN osm_infr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_infr_rcv_ctrl_init );
+
+ osm_infr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_INFORM_INFO,
+ __osm_infr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_ctrl_init: ERR 1701: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ p_ctrl->h_disp2 = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_INFORM_INFO_RECORD,
+ __osm_infir_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp2 == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_infr_rcv_ctrl_init: ERR 1702: "
+ "Dispatcher registration failed\n" );
+ cl_disp_unregister( p_ctrl->h_disp );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_lft_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lftr_rcv_t.
+ * This object represents the LinearForwardingTable Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_lft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LFTR_RCV_POOL_MIN_SIZE 32
+#define OSM_LFTR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_lftr_item
+{
+ cl_pool_item_t pool_item;
+ ib_lft_record_t rec;
+} osm_lftr_item_t;
+
+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_lftr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_lftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_construct(
+ IN osm_lftr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_destroy(
+ IN osm_lftr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_init(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_lftr_rcv_init );
+
+ osm_lftr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_LFTR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_LFTR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_lftr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_lftr_rcv_new_lftr(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN const osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid,
+ IN ib_net16_t const block )
+{
+ osm_lftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lftr_rcv_new_lftr );
+
+ p_rec_item = (osm_lftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_new_lftr: ERR 4402: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_rcv_new_lftr: "
+ "New LinearForwardingTable: sw 0x%016" PRIx64
+ "\n\t\t\t\tblock 0x%02X lid 0x%02X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ),
+ cl_ntoh16( block ), cl_ntoh16( lid )
+ );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof(ib_lft_record_t) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.block_num = block;
+
+ /* copy the lft block */
+ osm_switch_get_fwd_tbl_block( p_sw, cl_ntoh16(block), p_rec_item->rec.lft );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_lftr_get_port_by_guid(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN uint64_t port_guid )
+{
+ osm_port_t* p_port;
+
+ CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ port_guid);
+ if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_get_port_by_guid ERR 4404: "
+ "Invalid port GUID 0x%016" PRIx64 "\n",
+ port_guid );
+ p_port = NULL;
+ }
+
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lftr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_lftr_search_ctxt_t* const p_ctxt =
+ (osm_lftr_search_ctxt_t *)context;
+ const osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ const ib_lft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ osm_lftr_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ 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_lftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+ if (! p_port)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_by_comp_mask: 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 = osm_port_get_default_phys_ptr( p_port );
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lftr_rcv_by_comp_mask: 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( p_rcv->p_log, p_req_physp, p_physp ))
+ 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lftr_rcv_by_comp_mask: "
+ "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\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 */
+ if( comp_mask & IB_LFTR_COMPMASK_BLOCK )
+ {
+ max_block = min_block = cl_ntoh16(p_rcvd_rec->block_num);
+ }
+ else
+ {
+ /* use as many blocks as "in use" */
+ min_block = 0;
+ max_block = osm_switch_get_max_block_id_in_use(p_sw);
+ }
+
+ /* so we can add these blocks one by one ... */
+ for (block = min_block; block <= max_block; block++)
+ __osm_lftr_rcv_new_lftr( p_rcv, p_sw, p_ctxt->p_list,
+ osm_port_get_base_lid(p_port),
+ cl_hton16(block) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_process(
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_lft_record_t* p_rcvd_rec;
+ ib_lft_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_lftr_search_ctxt_t context;
+ osm_lftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lftr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4408: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4407: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* Go over all switches */
+ cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+ __osm_lftr_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4409: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_lftr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_lft_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_lftr_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_lftr_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) &&
+ (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_lft_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4410: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_lft_record_t) );
+
+ p_resp_rec = (ib_lft_record_t*)ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_lftr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_process: ERR 4411: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_lft_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lftr_rcv_ctrl_t.
+ * This object represents the LinearForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_lft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lftr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lftr_rcv_process( ((osm_lftr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_construct(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lftr_rcv_ctrl_destroy(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lftr_rcv_ctrl_init(
+ IN osm_lftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lftr_rcv_ctrl_init );
+
+ osm_lftr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LFT_RECORD,
+ __osm_lftr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lftr_rcv_ctrl_init: ERR 4501: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_link_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lr_rcv_t.
+ * This object represents the LinkRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_link_record.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_LR_RCV_POOL_MIN_SIZE 64
+#define OSM_LR_RCV_POOL_GROW_SIZE 64
+
+typedef struct _osm_lr_item
+{
+ cl_pool_item_t pool_item;
+ ib_link_record_t link_rec;
+} osm_lr_item_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_construct(
+ IN osm_lr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->lr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_destroy(
+ IN osm_lr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->lr_pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_init(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lr_rcv_init );
+
+ osm_lr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->lr_pool,
+ OSM_LR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_LR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_lr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_build_physp_link(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_net16_t from_lid,
+ IN const ib_net16_t to_lid,
+ IN const uint8_t from_port,
+ IN const uint8_t to_port,
+ IN cl_qlist_t* p_list )
+{
+ osm_lr_item_t* p_lr_item;
+
+ p_lr_item = (osm_lr_item_t*)cl_qlock_pool_get( &p_rcv->lr_pool );
+ if( p_lr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_build_physp_link: ERR 1801: "
+ "Unable to acquire link record\n"
+ "\t\t\t\tFrom port 0x%u\n"
+ "\t\t\t\tTo port 0x%u\n"
+ "\t\t\t\tFrom lid 0x%X\n"
+ "\t\t\t\tTo lid 0x%X\n",
+ from_port, to_port,
+ cl_ntoh16(from_lid),
+ cl_ntoh16(to_lid) );
+ return;
+ }
+
+ p_lr_item->link_rec.from_port_num = from_port;
+ p_lr_item->link_rec.to_port_num = to_port;
+ p_lr_item->link_rec.to_lid = to_lid;
+ p_lr_item->link_rec.from_lid = from_lid;
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_lr_item->pool_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_base_lid(
+ IN const osm_physp_t* p_physp,
+ OUT uint16_t * p_base_lid )
+{
+ if(p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
+ {
+ *p_base_lid =
+ cl_ntoh16(
+ osm_physp_get_base_lid(
+ osm_node_get_physp_ptr(p_physp->p_node, 0))
+ );
+ }
+ else
+ {
+ *p_base_lid =
+ cl_ntoh16(osm_physp_get_base_lid(p_physp));
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_physp_link(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_link_record_t* const 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* const 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_ho;
+ ib_net16_t to_base_lid_ho;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_physp_link );
+
+ /*
+ If only one end of the link is specified, determine
+ the other side.
+ */
+ if( p_src_physp )
+ {
+ if( !osm_physp_is_valid( p_src_physp ) )
+ goto Exit;
+
+ if( p_dest_physp )
+ {
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+ /*
+ 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;
+
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+ }
+ }
+ else
+ {
+ if( p_dest_physp )
+ {
+ if( !osm_physp_is_valid( p_dest_physp ) )
+ goto Exit;
+
+ 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 */
+ }
+
+ CL_ASSERT( p_src_physp );
+ CL_ASSERT( p_dest_physp );
+ CL_ASSERT( osm_physp_is_valid( p_src_physp ) );
+ CL_ASSERT( osm_physp_is_valid( p_dest_physp ) );
+
+ /* 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(p_rcv->p_log, p_src_physp, p_dest_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Source and Dest PhysPorts do not share PKey\n");
+ goto Exit;
+ }
+ if (! osm_physp_share_pkey(p_rcv->p_log, p_src_physp, p_req_physp))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Source and Requester PhysPorts do not share PKey\n");
+ goto Exit;
+ }
+ if (! osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_dest_physp) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "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;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_get_physp_link: "
+ "Acquiring link record\n"
+ "\t\t\t\tsrc port 0x%" PRIx64 " (port 0x%X)"
+ ", dest port 0x%" PRIx64 " (port 0x%X)\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 );
+ }
+
+ __get_base_lid(p_src_physp, &from_base_lid_ho);
+ __get_base_lid(p_dest_physp, &to_base_lid_ho);
+
+ __osm_lr_rcv_build_physp_link(p_rcv, cl_ntoh16(from_base_lid_ho),
+ cl_ntoh16(to_base_lid_ho),
+ src_port_num, dest_port_num, p_list);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_get_port_links(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const ib_link_record_t* const 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* const 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_port_tbl;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint8_t dest_num_ports;
+ uint8_t dest_port_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_port_links );
+
+ 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_port_get_num_physp( p_src_port );
+ dest_num_ports = osm_port_get_num_physp( p_dest_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ for( dest_port_num = 1; dest_port_num < dest_num_ports;
+ dest_port_num++ )
+ {
+ p_dest_physp = osm_port_get_phys_ptr( p_dest_port,
+ dest_port_num );
+ /* both physical ports should be with data */
+ if (p_src_physp && p_dest_physp)
+ __osm_lr_rcv_get_physp_link( p_rcv, 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->physp_tbl_size)
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ if (p_src_physp)
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, p_src_physp,
+ NULL, comp_mask, p_list,
+ p_req_physp );
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_src_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_src_physp = osm_port_get_phys_ptr( p_src_port, port_num );
+ if (p_src_physp)
+ __osm_lr_rcv_get_physp_link( p_rcv, 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->physp_tbl_size )
+ {
+ p_dest_physp = osm_port_get_phys_ptr(
+ p_dest_port, port_num );
+ if (p_dest_physp)
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+ p_dest_physp, comp_mask,
+ p_list, p_req_physp );
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_dest_port );
+ for( port_num = 1; port_num < num_ports; port_num++ )
+ {
+ p_dest_physp = osm_port_get_phys_ptr(
+ p_dest_port, port_num );
+ if (p_dest_physp)
+ __osm_lr_rcv_get_physp_link( p_rcv, p_lr, NULL,
+ p_dest_physp, comp_mask,
+ p_list, p_req_physp );
+ }
+ }
+ }
+ else
+ {
+ /*
+ Process the world (recurse once back into this function).
+ */
+ p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+ p_src_port = (osm_port_t*)cl_qmap_head( p_port_tbl );
+
+ while( p_src_port != (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port,
+ NULL, comp_mask, p_list,
+ p_req_physp );
+
+ p_src_port = (osm_port_t*)cl_qmap_next(
+ &p_src_port->map_item );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Returns the SA status to return to the client.
+ **********************************************************************/
+static ib_net16_t
+__osm_lr_rcv_get_end_points(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ OUT const osm_port_t** const pp_src_port,
+ OUT const osm_port_t** const pp_dest_port )
+{
+ const ib_link_record_t* p_lr;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_net64_t comp_mask;
+ ib_api_status_t status;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_get_end_points );
+
+ /*
+ 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( p_sa_mad->comp_mask & IB_LR_COMPMASK_FROM_LID )
+ {
+ status = osm_get_port_by_base_lid( p_rcv->p_subn,
+ p_lr->from_lid,
+ pp_src_port );
+
+ if( (status != IB_SUCCESS) || (*pp_src_port == NULL) )
+ {
+ /*
+ 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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_get_end_points: "
+ "No source port with LID = 0x%X\n",
+ cl_ntoh16( p_lr->from_lid ) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+
+ if( p_sa_mad->comp_mask & IB_LR_COMPMASK_TO_LID )
+ {
+ status = osm_get_port_by_base_lid( p_rcv->p_subn,
+ p_lr->to_lid,
+ pp_dest_port );
+
+ if( (status != IB_SUCCESS) || (*pp_dest_port == NULL) )
+ {
+ /*
+ 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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_get_end_points: "
+ "No dest port with LID = 0x%X\n",
+ cl_ntoh16( p_lr->to_lid ) );
+
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( sa_status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_lr_rcv_respond(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ size_t num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+ size_t trim_num_rec;
+#endif
+ ib_link_record_t* p_resp_lr;
+ ib_api_status_t status;
+ osm_lr_item_t* p_lr_item;
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_lr_rcv_respond );
+
+ num_rec = cl_qlist_count( p_list );
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: ERR 1806: "
+ "Got more than one record for SubnAdmGet (%zu)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_link_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_lr_rcv_respond: "
+ "Number of records:%u trimmed to:%u to fit in one MAD\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_lr_rcv_respond: "
+ "Generating response with %zu records", num_rec );
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_link_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: ERR 1802: "
+ "Unable to allocate MAD\n" );
+ /* Release the quick pool items */
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ 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 );
+
+ /* Copy the header from the request to response */
+ memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_link_record_t) );
+ /* C15-0.1.5 - always return SM_Key = 0 (table table 185 p 884) */
+ p_resp_sa_mad->sm_key = 0;
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_lr = (ib_link_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+ memset( p_resp_lr, 0, sizeof(*p_resp_lr) );
+ }
+ else
+ {
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ /* we need to track the number of copied items so we can
+ * stop the copy - but clear them all
+ */
+ num_copied = 0;
+ while( p_lr_item != (osm_lr_item_t*)cl_qlist_end( p_list ) )
+ {
+ /* Copy the Link Records from the list into the MAD */
+ /* only if we did not go over the mad size (since we might trimmed it) */
+ if (num_copied < num_rec)
+ {
+ *p_resp_lr = p_lr_item->link_rec;
+ num_copied++;
+ }
+ cl_qlock_pool_put( &p_rcv->lr_pool, &p_lr_item->pool_item );
+ p_resp_lr++;
+ p_lr_item = (osm_lr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ }
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_lr_rcv_respond: ERR 1803: "
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_process(
+ IN osm_lr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ 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 sa_status;
+ osm_physp_t* p_req_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_lr_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ 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 );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_process: ERR 1804: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_process: ERR 1805: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_link_record( p_rcv->p_log, p_lr, 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.
+ */
+ cl_plock_acquire( p_rcv->p_lock );
+
+ sa_status = __osm_lr_rcv_get_end_points( p_rcv, p_madw,
+ &p_src_port, &p_dest_port );
+
+ if( sa_status == IB_SA_MAD_STATUS_SUCCESS )
+ {
+ __osm_lr_rcv_get_port_links( p_rcv, p_lr, p_src_port, p_dest_port,
+ p_sa_mad->comp_mask, &lr_list, p_req_physp );
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ if( (cl_qlist_count( &lr_list ) == 0) &&
+ (p_sa_mad->method == IB_MAD_METHOD_GET) )
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ __osm_lr_rcv_respond( p_rcv, p_madw, &lr_list );
+
+ Exit:
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_link_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_lr_rcv_ctrl_t.
+ * This object represents the link record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_link_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_lr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_lr_rcv_process( ((osm_lr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_construct(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_lr_rcv_ctrl_destroy(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_lr_rcv_ctrl_init(
+ IN osm_lr_rcv_ctrl_t* const p_ctrl,
+ IN osm_lr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_lr_rcv_ctrl_init );
+
+ osm_lr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_LINK_RECORD,
+ __osm_lr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_lr_rcv_ctrl_init: ERR 1901: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_mad_ctrl_t.
+ * This object is part of the SA object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa_response.h>
+
+/****f* opensm: SA/__osm_sa_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_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
+__osm_sa_mad_ctrl_disp_done_callback(
+ IN void* context,
+ IN void* p_data )
+{
+ osm_sa_mad_ctrl_t* const p_ctrl = (osm_sa_mad_ctrl_t*)context;
+ osm_madw_t* const p_madw = (osm_madw_t*)p_data;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_disp_done_callback );
+
+ 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/__osm_sa_mad_ctrl_process
+ * NAME
+ * __osm_sa_mad_ctrl_process
+ *
+ * DESCRIPTION
+ * This function handles known methods for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_process(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t *p_madw )
+{
+ ib_sa_mad_t* p_sa_mad;
+ 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, __osm_sa_mad_ctrl_process );
+
+ /*
+ 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.
+ */
+ cl_disp_get_queue_status(p_ctrl->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,
+ "__osm_sa_mad_ctrl_process: "
+ /* "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;
+ }
+
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );
+
+ /*
+ 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,
+ "__osm_sa_mad_ctrl_process: ERR 1A01: "
+ "Unsupported attribute = 0x%X\n",
+ cl_ntoh16( p_sa_mad->attr_id ) );
+ osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, 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,
+ "__osm_sa_mad_ctrl_process: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( msg_id ) );
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sa_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_process: ERR 1A02: "
+ "Dispatcher post message failed (%s) for attribute = 0x%X\n",
+ CL_STATUS_MSG( status ),
+ cl_ntoh16( 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.
+ */
+ 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/__osm_sa_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sa_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sa_mad_ctrl_rcv_callback(
+ IN osm_madw_t *p_madw,
+ IN void *bind_context,
+ IN osm_madw_t *p_req_madw )
+{
+ osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+ ib_sa_mad_t* p_sa_mad;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_rcv_callback );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ A MAD was received from the wire, possibly in response to a request.
+ */
+ cl_atomic_inc( &p_ctrl->p_stats->qp1_mads_rcvd );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "%u QP1 MADs received\n",
+ p_ctrl->p_stats->qp1_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 )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "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 )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "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( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_ctrl->p_log, p_sa_mad, 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.sm_key)) {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_rcv_callback: ERR 1A04: "
+ "Non-Zero SA MAD SM_Key: 0x%" PRIx64 " != SM_Key: 0x%" PRIx64
+ "; MAD ignored\n",
+ cl_ntoh64(p_sa_mad->sm_key),
+ cl_ntoh64(p_ctrl->p_subn->opt.sm_key)
+ );
+ 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,
+ "__osm_sa_mad_ctrl_rcv_callback: "
+ "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
+ case IB_MAD_METHOD_SET:
+ case IB_MAD_METHOD_DELETE:
+ __osm_sa_mad_ctrl_process( p_ctrl, p_madw );
+ break;
+
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_rcv_callback: 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/__osm_sa_mad_ctrl_send_err_callback
+ * NAME
+ * __osm_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
+ */
+void
+__osm_sa_mad_ctrl_send_err_callback(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ osm_sa_mad_ctrl_t* p_ctrl = (osm_sa_mad_ctrl_t*)bind_context;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sa_mad_ctrl_send_err_callback );
+
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_send_err_callback: ERR 1A06: "
+ "MAD transaction completed in error\n" );
+
+ /*
+ We should never be here since the SA never originates a request.
+ Unless we generated a Report(Notice)
+ */
+
+ CL_ASSERT( p_madw );
+
+ /*
+ An error occurred. No response was received to a request MAD.
+ Retire the original request MAD.
+ */
+
+ osm_dump_sa_mad(p_ctrl->p_log, osm_madw_get_sa_mad_ptr( p_madw ),
+ OSM_LOG_ERROR );
+
+ /* __osm_sm_mad_ctrl_update_wire_stats( p_ctrl ); */
+
+ if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+ {
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mad_ctrl_send_err_callback: "
+ "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,
+ __osm_sa_mad_ctrl_disp_done_callback,
+ p_ctrl );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sa_mad_ctrl_send_err_callback: 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* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_mad_ctrl_destroy(
+ IN osm_sa_mad_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_mad_ctrl_init(
+ IN osm_sa_mad_ctrl_t* const p_ctrl,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_mad_ctrl_init );
+
+ osm_sa_mad_ctrl_construct( p_ctrl );
+
+ 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_subn = p_subn;
+ p_ctrl->p_resp = p_resp;
+
+ 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,
+ "osm_sa_mad_ctrl_init: ERR 1A08: "
+ "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* const p_ctrl,
+ IN const 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, osm_sa_mad_ctrl_bind );
+
+ if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_bind: 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;
+
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "osm_sa_mad_ctrl_bind: "
+ "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,
+ __osm_sa_mad_ctrl_rcv_callback,
+ __osm_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,
+ "osm_sa_mad_ctrl_bind: 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* const p_ctrl)
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, osm_sa_mad_ctrl_unbind );
+
+ if( p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sa_mad_ctrl_unbind: 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 );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mcmember_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcmr_recv_t.
+ * This object represents the MCMemberRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.15 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_inform.h>
+
+#define OSM_MCMR_RCV_POOL_MIN_SIZE 32
+#define OSM_MCMR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_mcmr_item
+{
+ cl_pool_item_t pool_item;
+ ib_member_rec_t rec;
+} osm_mcmr_item_t;
+
+typedef struct osm_sa_mcmr_search_ctxt {
+ const ib_member_rec_t *p_mcmember_rec;
+ osm_mgrp_t *p_mgrp;
+ osm_mcmr_recv_t *p_rcv;
+ cl_qlist_t *p_list; /* hold results */
+ ib_net64_t comp_mask;
+ const osm_physp_t* p_req_physp;
+ boolean_t trusted_req;
+} osm_sa_mcmr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_construct(
+ IN osm_mcmr_recv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_destroy(
+ IN osm_mcmr_recv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_destroy );
+
+ cl_qlock_pool_destroy( &p_rcv->pool );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mcmr_rcv_init );
+
+ osm_mcmr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_sm = p_sm;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+ p_rcv->mlid_ho = 0xC000;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_MCMR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_MCMR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_mcmr_item_t),
+ NULL, NULL, NULL );
+ if (status != CL_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_init: ERR 1B02: "
+ "qlock pool init failed (%d)\n",
+ status );
+ }
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ A search function that compares the given mgrp with the search context
+ if there is a match by mgid the p_mgrp is copied to the search context
+ p_mgrp component
+
+ Inputs:
+ p_map_item - which is part of a mgrp object
+ context - points to the osm_sa_mcmr_search_ctxt_t including the mgid
+ looked for and the result p_mgrp
+**********************************************************************/
+static void
+__search_mgrp_by_mgid(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item;
+ osm_sa_mcmr_search_ctxt_t *p_ctxt = (osm_sa_mcmr_search_ctxt_t *) context;
+ const ib_member_rec_t *p_recvd_mcmember_rec;
+ osm_mcmr_recv_t *p_rcv;
+
+ p_recvd_mcmember_rec = p_ctxt->p_mcmember_rec;
+ p_rcv = p_ctxt->p_rcv;
+
+ /* ignore groups marked for deletion */
+ if (p_mgrp->to_be_deleted)
+ return;
+
+ /* compare entire MGID so different scope will not sneak in for
+ the same MGID */
+ if (memcmp(&p_mgrp->mcmember_rec.mgid,
+ &p_recvd_mcmember_rec->mgid,
+ sizeof(ib_gid_t)))
+ return;
+
+ if (p_ctxt->p_mgrp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__search_mgrp_by_mgid: ERR 1B03: "
+ "Multiple MC groups for same MGID\n" );
+ return;
+ }
+
+ p_ctxt->p_mgrp = p_mgrp;
+
+}
+
+/**********************************************************************
+ Look for a MGRP in the mgrp_mlid_tbl by mlid
+**********************************************************************/
+static osm_mgrp_t *
+__get_mgrp_by_mlid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net16_t const mlid)
+{
+ cl_map_item_t *map_item;
+
+ map_item = cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid);
+ if (map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+ {
+ return NULL;
+ }
+ return (osm_mgrp_t *)map_item;
+
+}
+
+/**********************************************************************
+Look for a MGRP in the mgrp_mlid_tbl by mgid
+***********************************************************************/
+static ib_api_status_t
+__get_mgrp_by_mgid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_member_rec_t* p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ osm_sa_mcmr_search_ctxt_t mcmr_search_context;
+
+ mcmr_search_context.p_mcmember_rec = p_recvd_mcmember_rec;
+ mcmr_search_context.p_rcv = p_rcv;
+ mcmr_search_context.p_mgrp = NULL;
+
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+ __search_mgrp_by_mgid,
+ &mcmr_search_context);
+
+ if (mcmr_search_context.p_mgrp == NULL)
+ {
+ return IB_NOT_FOUND;
+ }
+
+ *pp_mgrp = mcmr_search_context.p_mgrp;
+ return IB_SUCCESS;
+}
+
+/*********************************************************************
+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 inline void
+__copy_from_create_mc_rec(
+ IN ib_member_rec_t * const dest,
+ IN const ib_member_rec_t *const 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->mtu = src->mtu;
+ dest->rate = src->rate;
+ dest->pkt_life = src->pkt_life;
+}
+
+/*********************************************************************
+Return an mlid to the pool of free mlids.
+But this implementation is not a pool - it is simply scanning through
+the MGRP database for unused mlids...
+*********************************************************************/
+static void
+__free_mlid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN uint16_t mlid)
+{
+ UNUSED_PARAM(p_rcv);
+ UNUSED_PARAM(mlid);
+}
+
+/*********************************************************************
+Get a new unused mlid by scanning all the used ones in the subnet.
+TODO: Implement a more scalable - O(1) solution based on pool of
+available mlids.
+**********************************************************************/
+static ib_net16_t
+__get_new_mlid(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net16_t requested_mlid)
+{
+ osm_subn_t *p_subn = p_rcv->p_subn;
+ osm_mgrp_t *p_mgrp;
+ uint8_t *used_mlids_array;
+ uint16_t idx;
+ uint16_t mlid; /* the result */
+ uint16_t max_num_mlids;
+
+ OSM_LOG_ENTER(p_rcv->p_log, __get_new_mlid);
+
+ if (requested_mlid && cl_ntoh16(requested_mlid) >= IB_LID_MCAST_START_HO &&
+ cl_ntoh16(requested_mlid) < p_subn->max_multicast_lid_ho &&
+ cl_qmap_get(&p_subn->mgrp_mlid_tbl, requested_mlid) ==
+ cl_qmap_end(&p_subn->mgrp_mlid_tbl) ) {
+ mlid = cl_ntoh16(requested_mlid);
+ goto Exit;
+ }
+
+ /* If MCGroups table empty, first return the min mlid */
+ p_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+ if (p_mgrp == (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ))
+ {
+ mlid = IB_LID_MCAST_START_HO;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_new_mlid: "
+ "No multicast groups found using minimal mlid:0x%04X\n",
+ mlid );
+ goto Exit;
+ }
+
+ max_num_mlids =
+ p_rcv->p_subn->max_multicast_lid_ho - IB_LID_MCAST_START_HO;
+
+ /* track all used mlids in the array (by mlid index) */
+ used_mlids_array =
+ (uint8_t *)malloc(sizeof(uint8_t)*max_num_mlids);
+ if (used_mlids_array)
+ memset(used_mlids_array, 0, sizeof(uint8_t)*max_num_mlids);
+ if (!used_mlids_array)
+ return 0;
+
+ /* scan all available multicast groups in the DB and fill in the table */
+ while( p_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+ {
+ /* ignore mgrps marked for deletion */
+ if (p_mgrp->to_be_deleted == FALSE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__get_new_mlid: "
+ "Found mgrp with lid:0x%X MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh16( p_mgrp->mlid),
+ cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.prefix ),
+ cl_ntoh64( p_mgrp->mcmember_rec.mgid.unicast.interface_id ) );
+
+ /* Map in table */
+ if (cl_ntoh16(p_mgrp->mlid) > p_rcv->p_subn->max_multicast_lid_ho)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_new_mlid: ERR 1B27: "
+ "Found mgrp with mlid:0x%04X > max allowed mlid:0x%04X\n",
+ cl_ntoh16(p_mgrp->mlid),
+ max_num_mlids + IB_LID_MCAST_START_HO );
+ }
+ else
+ {
+ used_mlids_array[cl_ntoh16(p_mgrp->mlid) - IB_LID_MCAST_START_HO] = 1;
+ }
+ }
+ p_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ /* Find "mlid holes" in the mgrp table */
+ for (idx = 0;
+ (idx < max_num_mlids) && (used_mlids_array[idx] == 1);
+ idx++);
+
+ /* did it go above the maximal mlid allowed */
+ if ( idx < max_num_mlids )
+ {
+ mlid = idx + IB_LID_MCAST_START_HO;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_new_mlid: "
+ "Found available mlid:0x%04X at idx:%u\n",
+ mlid, idx );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_new_mlid: ERR 1B23: "
+ "All available:%u mlids are taken\n",
+ max_num_mlids );
+ mlid = 0;
+ }
+
+ free(used_mlids_array);
+
+ Exit:
+ OSM_LOG_EXIT(p_rcv->p_log);
+ return cl_hton16(mlid);
+}
+
+/*********************************************************************
+This procedure is only invoked to cleanup an INTERMEDIATE mgrp.
+If there is only one port on the mgrp it means that the current
+request was the only member and the group is not really needed. So we
+silently drop it. Since it was an intermediate group no need to
+re-route it.
+**********************************************************************/
+static void
+__cleanup_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net16_t const mlid)
+{
+ osm_mgrp_t *p_mgrp;
+
+ p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+ if(p_mgrp)
+ {
+ /* Remove MGRP only if osm_mcm_port_t count is 0 and
+ * Not a well known group
+ */
+ if(cl_is_qmap_empty(&p_mgrp->mcm_port_tbl) &&
+ (p_mgrp->well_known == FALSE))
+ {
+ cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_mgrp );
+ osm_mgrp_destroy(p_mgrp);
+ }
+ }
+}
+
+/*********************************************************************
+Add a port to the group. Calculating its PROXY_JOIN by the Port and
+requester gids.
+**********************************************************************/
+static ib_api_status_t
+__add_new_mgrp_port(
+ IN osm_mcmr_recv_t *p_rcv,
+ IN osm_mgrp_t *p_mgrp,
+ IN ib_member_rec_t *p_recvd_mcmember_rec,
+ IN osm_mad_addr_t *p_mad_addr,
+ OUT osm_mcm_port_t **pp_mcmr_port)
+{
+ boolean_t proxy_join;
+ ib_gid_t requester_gid;
+ ib_api_status_t res;
+
+ /* set the proxy_join if the requester gid is not identical to the
+ joined gid */
+ res = osm_get_gid_by_mad_addr( p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr, &requester_gid );
+ if ( res != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__add_new_mgrp_port: ERR 1B29: "
+ "Could not find GID for requester\n" );
+
+ return IB_INVALID_PARAMETER;
+ }
+
+ if (!memcmp(&p_recvd_mcmember_rec->port_gid, &requester_gid,
+ sizeof(ib_gid_t)))
+ {
+ proxy_join = FALSE;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__add_new_mgrp_port: "
+ "Create new port with proxy_join FALSE\n" );
+ }
+ else
+ {
+ /* The port is not the one specified in PortGID.
+ The check that the requester is in the same partition as
+ the PortGID is done before - just need to update the proxy_join. */
+ proxy_join = TRUE;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__add_new_mgrp_port: "
+ "Create new port with proxy_join TRUE\n" );
+ }
+
+ *pp_mcmr_port = osm_mgrp_add_port( p_mgrp,
+ &p_recvd_mcmember_rec->port_gid,
+ p_recvd_mcmember_rec->scope_state,
+ proxy_join );
+ if(*pp_mcmr_port == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__add_new_mgrp_port: ERR 1B06: "
+ "osm_mgrp_add_port failed\n" );
+
+ return IB_INSUFFICIENT_MEMORY;
+ }
+
+ return IB_SUCCESS;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 inline 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
+__osm_mcmr_rcv_respond(
+ IN const osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN ib_member_rec_t *p_mcmember_rec )
+{
+ osm_madw_t *p_resp_madw;
+ ib_sa_mad_t *p_sa_mad, *p_resp_sa_mad;
+ ib_member_rec_t *p_resp_mcmember_rec;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_respond );
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get(p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ sizeof(ib_member_rec_t)+IB_SA_MAD_HDR_SIZE,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if ( !p_resp_madw )
+ {
+ goto Exit;
+ }
+
+ p_resp_sa_mad = (ib_sa_mad_t*)p_resp_madw->p_mad;
+ p_sa_mad = (ib_sa_mad_t*)p_madw->p_mad;
+ /* Copy the MAD header back into the response mad */
+ memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE);
+ /* based on the current method decide about the response: */
+ if ((p_resp_sa_mad->method == IB_MAD_METHOD_GET) ||
+ (p_resp_sa_mad->method == IB_MAD_METHOD_SET)) {
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET_RESP;
+ }
+ else if (p_resp_sa_mad->method == IB_MAD_METHOD_DELETE) {
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
+ }
+ else
+ {
+ CL_ASSERT( p_resp_sa_mad->method == 0);
+ }
+
+ /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
+ p_resp_sa_mad->sm_key = 0;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_member_rec_t) );
+ p_resp_mcmember_rec = (ib_member_rec_t*)&p_resp_sa_mad->data;
+
+ *p_resp_mcmember_rec = *p_mcmember_rec;
+
+ /* Fill in the mtu, rate, and packet lifetime selectors */
+ p_resp_mcmember_rec->mtu &= 0x3f;
+ p_resp_mcmember_rec->mtu |= 2<<6; /* exactly */
+ p_resp_mcmember_rec->rate &= 0x3f;
+ p_resp_mcmember_rec->rate |= 2<<6; /* exactly */
+ p_resp_mcmember_rec->pkt_life &= 0x3f;
+ p_resp_mcmember_rec->pkt_life |= 2<<6; /* exactly */
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_respond: ERR 1B07: "
+ "Unable to send MAD (%s) for TID <0x%"PRIx64">\n",
+ ib_get_err_str( status ),
+ p_resp_sa_mad->trans_id );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/*********************************************************************
+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_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x 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_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x 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_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested MTU %x 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(rate_mgrp <= rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x is not greater than %x\n",
+ rate_mgrp, rate_required );
+ return FALSE;
+ }
+ break;
+ case 1: /* Less than RATE specified */
+ if(rate_mgrp >= rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x is not less than %x\n",
+ rate_mgrp, rate_required );
+ return FALSE;
+ }
+ break;
+ case 2: /* Exactly RATE specified */
+ if(rate_mgrp != rate_required)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_more_comp_fields: "
+ "Requested RATE %x 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 * const p_log,
+ const osm_mgrp_t *p_mgrp,
+ const osm_physp_t *p_physp)
+{
+ ib_port_info_t *p_pi;
+ uint8_t mtu_required;
+ uint8_t mtu_mgrp;
+ uint8_t rate_required;
+ uint8_t rate_mgrp;
+
+ p_pi = osm_physp_get_port_info_ptr(p_physp);
+ if (!p_pi)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_port_caps: "
+ "Cannot get Port's 0x%016" PRIx64 " PortInfo\n",
+ cl_ntoh64( osm_physp_get_port_guid(p_physp) ) );
+ return FALSE;
+ }
+
+ mtu_required = ib_port_info_get_mtu_cap(p_pi);
+ mtu_mgrp = (uint8_t)(p_mgrp->mcmember_rec.mtu & 0x3F);
+ if (mtu_required < mtu_mgrp)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_port_caps: "
+ "Port's MTU %x is less than %x\n",
+ mtu_required, mtu_mgrp );
+ return FALSE;
+ }
+
+ rate_required = ib_port_info_compute_rate(p_pi);
+ rate_mgrp = (uint8_t)(p_mgrp->mcmember_rec.rate & 0x3F);
+ if (rate_required < rate_mgrp)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__validate_port_caps: "
+ "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_mcmr_recv_t* const p_rcv,
+ 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_port_t **pp_mcm_port)
+{
+ 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_port = NULL;
+
+ /* o15-0.2.1: If this is a new port being added - nothing to check */
+ if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "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_port)->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(p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr,
+ &request_gid);
+
+ if ( res != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "Could not find port for requested address\n"
+ );
+ return FALSE;
+ }
+
+ if (memcmp(&((*pp_mcm_port)->port_gid), &request_gid, sizeof(ib_gid_t)))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "No ProxyJoin but different ports: stored:0x%016"PRIx64
+ " request:0x%016"PRIx64"\n",
+ cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+ cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+ );
+ 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(p_rcv->p_log,
+ p_rcv->p_subn,
+ p_mad_addr);
+ if (p_request_physp == NULL)
+ return FALSE;
+
+ if (!osm_physp_has_pkey(p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+ p_request_physp))
+ {
+ /* the request port is not part of the partition for this mgrp */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_modify: "
+ "ProxyJoin but port not in partition. stored:0x%016"PRIx64
+ " request:0x%016"PRIx64"\n",
+ cl_ntoh64((*pp_mcm_port)->port_gid.unicast.interface_id),
+ cl_ntoh64(p_mad_addr->addr_type.gsi.grh_info.src_gid.unicast.interface_id)
+ );
+ 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_mcmr_recv_t* const p_rcv,
+ 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_port_t **pp_mcm_port)
+{
+ ib_net64_t portguid;
+
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ *pp_mcm_port = NULL;
+
+ /* 1 */
+ if (!osm_mgrp_is_port_present(p_mgrp, portguid, pp_mcm_port))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "Failed to find the port in the MC group\n" );
+ return FALSE;
+ }
+
+ /* 2 */
+ if (!(p_recvd_mcmember_rec->scope_state & 0x0F &
+ (*pp_mcm_port)->scope_state))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "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_port)->scope_state)) !=
+ (0x0F & (*pp_mcm_port)->scope_state))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "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_port)->scope_state)
+ );
+ return FALSE;
+ }
+
+ /* 4 */
+ /* Validate according the the proxy_join (o15-0.1.2) */
+ if ( __validate_modify( p_rcv, p_mgrp, p_mad_addr, p_recvd_mcmember_rec,
+ pp_mcm_port ) == FALSE )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_delete: "
+ "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><Sc>,<Si>,<Si>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<P>,<Id>,<Id>,<Id>,<Id>
+ * 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 Pkey ?)
+ *
+ * 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)
+ */
+ib_api_status_t
+__validate_requested_mgid(IN osm_mcmr_recv_t* const p_rcv,
+ IN const ib_member_rec_t* p_mcm_rec)
+{
+ uint16_t signature;
+ boolean_t valid = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_requested_mgid );
+
+ /* 14-a: mcast GID must start with 0xFF */
+ if (p_mcm_rec->mgid.multicast.header[0] != 0xFF)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B01: "
+ "Wrong MGID Prefix 0x%02X 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_requested_mgid: "
+ "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|<IPoIB signature>|< P_Key >|00.......0|<all 1's>|
+ * +--------+----+----+-----------------+---------+----------+---------+
+ *
+ * For IPv6 over IB, the signature will be "0x601B".
+ *
+ * | 8 | 4 | 4 | 16 bits | 16 bits | 80 bits |
+ * +--------+----+----+-----------------+---------+--------------------+
+ * |11111111|0001|scop|<IPoIB signature>|< P_Key >|000.............0001|
+ * +--------+----+----+-----------------+---------+--------------------+
+ *
+ */
+ if (signature == 0x401B || signature == 0x601B)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_requested_mgid: "
+ "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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B28: "
+ "MGID 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) == MC_SCOPE_LINK_LOCAL) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__validate_requested_mgid: ERR 1B24: "
+ "MGID 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 Unique MGID 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( p_rcv->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.
+**********************************************************************/
+boolean_t
+__mgrp_request_is_realizable(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN ib_member_rec_t * p_mcm_rec,
+ IN const osm_physp_t* const 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;
+ osm_log_t *p_log = p_rcv->p_log;
+ ib_port_info_t *p_pi = NULL;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __mgrp_request_is_realizable );
+
+ if (p_physp != NULL)
+ p_pi = osm_physp_get_port_info_ptr(p_physp);
+
+ /*
+ * 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.
+ */
+
+ port_mtu = p_pi ? 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 : p_rcv->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_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "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 < p_rcv->p_subn->min_ca_mtu)
+ mtu = p_rcv->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 be in the range */
+ if (mtu < IB_MIN_MTU || mtu > IB_MAX_MTU)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Calculated MTU %x is out of range\n",
+ mtu );
+ return FALSE;
+ }
+ }
+ p_mcm_rec->mtu = (mtu_sel<<6) | mtu;
+
+ port_rate = p_pi ? ib_port_info_compute_rate(p_pi) : 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 : p_rcv->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 (port_rate && rate_required >= port_rate)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "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 (rate_required < p_rcv->p_subn->min_ca_rate)
+ rate = p_rcv->p_subn->min_ca_rate;
+ else
+ 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 (port_rate && rate_required > port_rate)
+ rate = port_rate;
+ else
+ 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_DEBUG,
+ "__mgrp_request_is_realizable: "
+ "Calculated RATE %x is out of range\n",
+ rate );
+ return FALSE;
+ }
+ }
+ p_mcm_rec->rate = (rate_sel<<6) | rate;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return TRUE;
+}
+
+/**********************************************************************
+ Call this function to find or create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_find_or_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN ib_member_rec_t* const p_recvd_mcmember_rec,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ ib_api_status_t status;
+
+ status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, pp_mgrp);
+ if (status == IB_SUCCESS)
+ return status;
+ return osm_mcmr_rcv_create_new_mgrp(p_rcv, comp_mask,
+ p_recvd_mcmember_rec, NULL, pp_mgrp);
+}
+
+/**********************************************************************
+ Call this function to create a new mgrp.
+**********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_create_new_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN ib_net64_t comp_mask,
+ IN const ib_member_rec_t* const p_recvd_mcmember_rec,
+ IN const osm_physp_t* const p_physp,
+ OUT osm_mgrp_t **pp_mgrp)
+{
+ ib_net16_t mlid;
+ uint8_t zero_mgid, valid;
+ uint8_t scope, i;
+ ib_gid_t *p_mgid;
+ osm_mgrp_t *p_prev_mgrp;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_member_rec_t mcm_rec = *p_recvd_mcmember_rec; /* copy for modifications */
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_create_new_mgrp );
+
+ /* but what if the given MGID was not 0 ? */
+ zero_mgid = 1;
+ for ( i = 0 ; i < sizeof(p_recvd_mcmember_rec->mgid); i++ )
+ {
+ if (p_recvd_mcmember_rec->mgid.raw[i] != 0)
+ {
+ zero_mgid = 0;
+ break;
+ }
+ }
+
+ /*
+ we allocate a new mlid number before we might use it
+ for MGID ...
+ */
+ mlid = __get_new_mlid(p_rcv, mcm_rec.mlid);
+ if ( mlid == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B19: "
+ "__get_new_mlid failed\n" );
+ status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ goto Exit;
+ }
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Obtained new mlid 0x%X\n", cl_ntoh16(mlid) );
+
+ /* we need to create the new MGID if it was not defined */
+ if (zero_mgid)
+ {
+ /* create a new MGID */
+
+ /* use the given scope state only if requested! */
+ if (comp_mask & IB_MCR_COMPMASK_SCOPE)
+ {
+ ib_member_get_scope_state(
+ p_recvd_mcmember_rec->scope_state, &scope, NULL);
+ }
+ else
+ {
+ /* to guarantee no collision with other subnets use local scope! */
+ scope = MC_SCOPE_LINK_LOCAL;
+ }
+
+ p_mgid = &(mcm_rec.mgid);
+ p_mgid->raw[0] = 0xFF;
+ p_mgid->raw[1] = 0x10 | scope;
+ p_mgid->raw[2] = 0xA0;
+ p_mgid->raw[3] = 0x1B;
+
+ /* HACK: use the SA port gid to make it globally unique */
+ memcpy((&p_mgid->raw[4]),
+ &p_rcv->p_subn->opt.subnet_prefix, sizeof(uint64_t));
+
+ /* HACK: how do we get a unique number - use the mlid twice */
+ memcpy(&p_mgid->raw[10], &mlid, sizeof(uint16_t));
+ memcpy(&p_mgid->raw[12], &mlid, sizeof(uint16_t));
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Allocated new MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64(p_mgid->unicast.prefix),
+ cl_ntoh64(p_mgid->unicast.interface_id) );
+ }
+ else
+ {
+ /* a specific MGID was requested so validate the resulting MGID */
+ valid = __validate_requested_mgid(p_rcv, &mcm_rec);
+ if (!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B22: "
+ "Invalid requested MGID\n" );
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_REQ_INVALID;
+ goto Exit;
+ }
+ }
+
+ /* check the requested parameters are realizable */
+ if (__mgrp_request_is_realizable(p_rcv, comp_mask, &mcm_rec, p_physp) == FALSE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B26: "
+ "Requested MGRP parameters are not realizable\n" );
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_REQ_INVALID;
+ goto Exit;
+ }
+
+ /* create a new MC Group */
+ *pp_mgrp = osm_mgrp_new(mlid);
+ if (*pp_mgrp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_create_new_mgrp: ERR 1B08: "
+ "osm_mgrp_new failed\n" );
+ __free_mlid(p_rcv, mlid);
+ status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ goto Exit;
+ }
+
+ /* Initialize the mgrp */
+ (*pp_mgrp)->mcmember_rec = mcm_rec;
+ (*pp_mgrp)->mcmember_rec.mlid = mlid;
+
+ /* 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 |= 2<<6; /* exactly */
+ (*pp_mgrp)->mcmember_rec.rate &= 0x3f;
+ (*pp_mgrp)->mcmember_rec.rate |= 2<<6; /* exactly */
+ (*pp_mgrp)->mcmember_rec.pkt_life &= 0x3f;
+ (*pp_mgrp)->mcmember_rec.pkt_life |= 2<<6; /* exactly */
+
+ /* Insert the new group in the data base */
+
+ /* since we might have an old group by that mlid
+ one whose deletion was delayed for an idle time
+ we need to deallocate it first */
+ p_prev_mgrp = (osm_mgrp_t *)cl_qmap_get(&p_rcv->p_subn->mgrp_mlid_tbl, mlid);
+ if (p_prev_mgrp != (osm_mgrp_t *)cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mcmr_rcv_create_new_mgrp: "
+ "Found previous group for mlid:0x%04x - Need to destroy it\n",
+ cl_ntoh16(mlid) );
+ cl_qmap_remove_item(&p_rcv->p_subn->mgrp_mlid_tbl,
+ (cl_map_item_t *)p_prev_mgrp );
+ osm_mgrp_destroy( p_prev_mgrp );
+ }
+
+ cl_qmap_insert(&p_rcv->p_subn->mgrp_mlid_tbl,
+ mlid,
+ &(*pp_mgrp)->map_item);
+
+ /* Send a Report to any InformInfo registerd for
+ Trap 66: MCGroup create */
+ osm_mgrp_send_create_notice(p_rcv->p_subn, p_rcv->p_log, *pp_mgrp);
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return status;
+
+}
+
+/*********************************************************************
+Process a request for leaving the group
+**********************************************************************/
+static void
+__osm_mcmr_rcv_leave_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ boolean_t valid;
+ osm_mgrp_t *p_mgrp;
+ 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;
+ ib_net16_t mlid;
+ ib_net16_t sa_status;
+ ib_net64_t portguid;
+ osm_mcm_port_t *p_mcm_port;
+ uint8_t port_join_state;
+ uint8_t new_join_state;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_leave_mgrp );
+
+ p_mgrp = NULL;
+ 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;
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_leave_mgrp: Dump of record\n" );
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+ status = __get_mgrp_by_mgid(p_rcv,p_recvd_mcmember_rec, &p_mgrp);
+ if (status == IB_SUCCESS)
+ {
+ mlid = p_mgrp->mlid;
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ /* check validity of the delete request o15-0.1.14 */
+ valid = __validate_delete(p_rcv,
+ p_mgrp,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ p_recvd_mcmember_rec,
+ &p_mcm_port);
+
+ if (valid)
+ {
+ /*
+ * 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 = p_mcm_port->scope_state & 0x0F;
+ new_join_state =
+ port_join_state & ~(p_recvd_mcmember_rec->scope_state & 0x0F);
+ if (new_join_state)
+ {
+ /* Just update the result JoinState */
+ p_mcm_port->scope_state =
+ new_join_state | (p_mcm_port->scope_state & 0xf0);
+
+ mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_leave_mgrp: "
+ "After update JoinState != 0. Updating from 0x%X to 0x%X\n",
+ port_join_state,
+ new_join_state
+ );
+ }
+ else
+ {
+ /* we need to return the stored scope state */
+ mcmember_rec.scope_state = p_mcm_port->scope_state;
+
+ /* OK we can leave */
+ /* note: osm_sm_mcgrp_leave() will release p_rcv->p_lock */
+
+ status = osm_sm_mcgrp_leave(p_rcv->p_sm, mlid, portguid);
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_leave_mgrp: ERR 1B09: "
+ "osm_sm_mcgrp_leave failed\n" );
+ }
+ }
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_leave_mgrp: ERR 1B25: "
+ "Received an invalid delete request for "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " for "
+ "PortGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_leave_mgrp: "
+ "Failed since multicast group not present\n" );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /* Send an SA response */
+ __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ Handle a join (or create) request
+**********************************************************************/
+static void
+__osm_mcmr_rcv_join_mgrp(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ boolean_t valid;
+ 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;
+ ib_net16_t sa_status;
+ ib_net16_t mlid;
+ osm_mcm_port_t *p_mcmr_port;
+ 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 */
+ osm_mcast_req_type_t req_type;
+ uint8_t join_state;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_join_mgrp );
+
+ p_mgrp = NULL;
+ 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 );
+
+ portguid = p_recvd_mcmember_rec->port_gid.unicast.interface_id;
+
+ mcmember_rec = *p_recvd_mcmember_rec;
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_join_mgrp: "
+ "Dump of incoming record\n" );
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+ /* make sure the requested port guid is known to the SM */
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ portguid);
+
+ if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_join_mgrp: "
+ "Unknown port GUID 0x%016" PRIx64 "\n",
+ portguid );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* Check that the p_physp and the requester physp are in the same
+ partition. */
+ p_request_physp =
+ osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_request_physp == NULL)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ if (!osm_physp_share_pkey( p_rcv->p_log, p_physp, p_request_physp))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_rcv_join_mgrp: "
+ "Port and requester don't share pkey\n" );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ ib_member_get_scope_state(
+ p_recvd_mcmember_rec->scope_state, NULL, &join_state);
+
+ /* do we need to create a new group? */
+ status = __get_mgrp_by_mgid(p_rcv, p_recvd_mcmember_rec, &p_mgrp);
+ if ((status == IB_NOT_FOUND) || p_mgrp->to_be_deleted)
+ {
+ /* check for JoinState.FullMember = 1 o15.0.1.9 */
+ if ((join_state & 0x01) != 0x01)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_join_mgrp: ERR 1B10: "
+ "Provided Join State != FullMember - required for create, "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ) );
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /* check for the comp_mask */
+ valid = __check_create_comp_mask(p_sa_mad->comp_mask,
+ p_recvd_mcmember_rec);
+ if (valid)
+ {
+ status = osm_mcmr_rcv_create_new_mgrp(p_rcv,
+ p_sa_mad->comp_mask,
+ p_recvd_mcmember_rec,
+ p_physp,
+ &p_mgrp);
+ if (status != IB_SUCCESS)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = status;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ /* copy the MGID to the result */
+ mcmember_rec.mgid = p_mgrp->mcmember_rec.mgid;
+ }
+ else
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_join_mgrp: ERR 1B11: "
+ "method = %s, "
+ "scope_state = 0x%x, "
+ "component mask = 0x%016" PRIx64 ", "
+ "expected comp mask = 0x%016" PRIx64 ", "
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " from port 0x%016" PRIx64 "\n",
+ ib_get_sa_method_str(p_sa_mad->method),
+ p_recvd_mcmember_rec->scope_state,
+ cl_ntoh64(p_sa_mad->comp_mask),
+ CL_NTOH64(REQUIRED_MC_CREATE_COMP_MASK),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+ cl_ntoh64( portguid ) );
+
+ sa_status = IB_SA_MAD_STATUS_INSUF_COMPS;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ is_new_group = 1;
+ req_type = OSM_MCAST_REQ_TYPE_CREATE;
+ }
+ else
+ {
+ /* no need for a new group */
+ is_new_group = 0;
+ req_type = OSM_MCAST_REQ_TYPE_JOIN;
+ }
+
+ CL_ASSERT(p_mgrp);
+ mlid = p_mgrp->mlid;
+
+ /*
+ * 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:
+ */
+ valid = __validate_more_comp_fields(
+ p_rcv->p_log,
+ p_mgrp,
+ p_recvd_mcmember_rec,
+ p_sa_mad->comp_mask) && __validate_port_caps(
+ p_rcv->p_log,
+ p_mgrp,
+ p_physp) && (join_state != 0);
+
+ if (!valid)
+ {
+ /* since we might have created the new group we need to cleanup */
+ __cleanup_mgrp(p_rcv, mlid);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_join_mgrp: ERR 1B12: "
+ "__validate_more_comp_fields, __validate_port_caps, "
+ "or JoinState = 0 failed from port 0x%016" PRIx64 ", "
+ "sending IB_SA_MAD_STATUS_REQ_INVALID\n",
+ cl_ntoh64( portguid ) );
+
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /*
+ * Do some validation of the modification
+ */
+ if (!is_new_group)
+ {
+ /*
+ * o15-0.2.1 requires validation of the requesting port
+ * in the case of modification:
+ */
+ valid = __validate_modify(p_rcv,
+ p_mgrp,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ p_recvd_mcmember_rec,
+ &p_mcmr_port);
+ if (!valid)
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_join_mgrp: ERR 1B13: "
+ "__validate_modify failed, "
+ "sending IB_SA_MAD_STATUS_REQ_INVALID\n" );
+
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ }
+
+ /* create or update existing port (join-state will be updated) */
+ status = __add_new_mgrp_port(
+ p_rcv,
+ p_mgrp,
+ p_recvd_mcmember_rec,
+ osm_madw_get_mad_addr_ptr(p_madw),
+ &p_mcmr_port);
+
+ if (status != IB_SUCCESS)
+ {
+ /* we fail to add the port so we might need to delete the group */
+ __cleanup_mgrp(p_rcv, mlid);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ if (status == IB_INVALID_PARAMETER)
+ sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ else
+ sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /* o15.0.1.11: copy the join state */
+ mcmember_rec.scope_state = p_mcmr_port->scope_state;
+
+ /* copy qkey mlid tclass pkey sl_flow_hop mtu rate pkt_life sl_flow_hop */
+ __copy_from_create_mc_rec(&mcmember_rec, &p_mgrp->mcmember_rec);
+
+ /* Release the lock as we don't need it. */
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /* do the actual routing (actually schedule the update) */
+ status =
+ osm_sm_mcgrp_join(p_rcv->p_sm,
+ mlid,
+ p_recvd_mcmember_rec->port_gid.unicast.interface_id,
+ req_type);
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_join_mgrp: ERR 1B14: "
+ "osm_sm_mcgrp_join failed, "
+ "sending IB_SA_MAD_STATUS_NO_RESOURCES\n" );
+
+ CL_PLOCK_EXCL_ACQUIRE(p_rcv->p_lock);
+
+ /* the request for routing failed so we need to remove the port */
+ p_mgrp = __get_mgrp_by_mlid(p_rcv, mlid);
+ if (p_mgrp != NULL)
+ {
+ osm_mgrp_remove_port(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_mgrp,
+ p_recvd_mcmember_rec->port_gid.unicast.interface_id);
+ __cleanup_mgrp(p_rcv, mlid);
+ }
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ sa_status = IB_SA_MAD_STATUS_NO_RESOURCES;
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+
+ } /* failed to route */
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_mc_record( p_rcv->p_log, &mcmember_rec, OSM_LOG_DEBUG );
+
+ __osm_mcmr_rcv_respond( p_rcv, p_madw, &mcmember_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ Add a patched multicast group to the results list
+**********************************************************************/
+static ib_api_status_t
+__osm_mcmr_rcv_new_mcmr(
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN const ib_member_rec_t* p_rcvd_rec,
+ IN cl_qlist_t* const p_list )
+{
+ osm_mcmr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_rcv_new_mcmr );
+
+ p_rec_item = (osm_mcmr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_rcv_new_mcmr: ERR 1B15: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+ /* HACK: Not trusted requesters should result with 0 Join
+ State, Port Guid, and Proxy */
+ p_rec_item->rec = *p_rcvd_rec;
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ Match the given mgrp to the requested mcmr
+**********************************************************************/
+void
+__osm_sa_mcm_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_mgrp_t * const p_mgrp = (osm_mgrp_t *)p_map_item;
+ osm_sa_mcmr_search_ctxt_t* const p_ctxt =
+ (osm_sa_mcmr_search_ctxt_t *)context;
+ osm_mcmr_recv_t* const p_rcv = p_ctxt->p_rcv;
+ const ib_member_rec_t* p_rcvd_rec = p_ctxt->p_mcmember_rec;
+ const osm_physp_t* p_req_physp = p_ctxt->p_req_physp;
+
+ /* since we might change scope_state */
+ ib_member_rec_t match_rec;
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ osm_mcm_port_t* p_mcm_port;
+ 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;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_mcm_by_comp_mask_cb );
+
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "Checking mlid:0x%X\n",
+ cl_ntoh16(p_mgrp->mlid));
+
+ /* the group might be marked for deletion */
+ if (p_mgrp->to_be_deleted)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "Group mlid:0x%X is marked to be deleted\n",
+ cl_ntoh16(p_mgrp->mlid));
+ goto Exit;
+ }
+
+ /* 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( p_rcv->p_log, p_mgrp->mcmember_rec.pkey,
+ p_req_physp ))
+ goto Exit;
+
+ /* now do the rest of the match */
+ if ((IB_MCR_COMPMASK_QKEY & comp_mask) &&
+ (p_rcvd_rec->qkey != p_mgrp->mcmember_rec.qkey))
+ goto Exit;
+
+ if ((IB_MCR_COMPMASK_PKEY & comp_mask) &&
+ (p_rcvd_rec->pkey != p_mgrp->mcmember_rec.pkey))
+ goto Exit;
+
+ if ((IB_MCR_COMPMASK_TCLASS & comp_mask) &&
+ (p_rcvd_rec->tclass != p_mgrp->mcmember_rec.tclass))
+ goto Exit;
+
+ /* check SL, Flow, and Hop limit */
+ {
+ uint8_t mgrp_sl, query_sl;
+ uint32_t mgrp_flow, query_flow;
+ uint8_t mgrp_hop, query_hop;
+
+ ib_member_get_sl_flow_hop(p_rcvd_rec->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 )
+ if (query_sl != mgrp_sl)
+ goto Exit;
+
+ if (IB_MCR_COMPMASK_FLOW & comp_mask)
+ if (query_flow != mgrp_flow)
+ goto Exit;
+
+ if (IB_MCR_COMPMASK_HOP & comp_mask)
+ if (query_hop != mgrp_hop)
+ goto Exit;
+ }
+
+ if ((IB_MCR_COMPMASK_PROXY & comp_mask) &&
+ (p_rcvd_rec->proxy_join != p_mgrp->mcmember_rec.proxy_join))
+ goto Exit;
+
+ 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;
+
+ /* need to validate mtu, rate, and pkt_lifetime fields. */
+ if (__validate_more_comp_fields( p_rcv->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 */
+ if (osm_mgrp_is_port_present(p_mgrp, portguid, &p_mcm_port))
+ {
+ scope_state = p_mcm_port->scope_state;
+ memcpy(&port_gid, &(p_mcm_port->port_gid), sizeof(ib_gid_t));
+ proxy_join = p_mcm_port->proxy_join;
+ }
+ else
+ {
+ /* port not in group */
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* point to the group information */
+ scope_state = p_mgrp->mcmember_rec.scope_state;
+ }
+
+ /* Many MC records returned */
+ if ( (p_ctxt->trusted_req == TRUE) && !(IB_MCR_COMPMASK_PORT_GID & comp_mask) )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "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_port_tbl));
+ while( p_item != cl_qmap_end(&(p_mgrp->mcm_port_tbl)) )
+ {
+ p_mcm_port=(osm_mcm_port_t *)p_item;
+
+ if ((scope_state_mask & p_rcvd_rec->scope_state) ==
+ (scope_state_mask & p_mcm_port->scope_state))
+ {
+ /* add to the list */
+ match_rec = p_mgrp->mcmember_rec;
+ match_rec.scope_state = p_mcm_port->scope_state;
+ memcpy( &(match_rec.port_gid), &(p_mcm_port->port_gid),
+ sizeof(ib_gid_t));
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_mcm_by_comp_mask_cb: "
+ "Record of port_gid: 0x%016" PRIx64 "0x%016" PRIx64
+ " in multicast_lid: 0x%X is returned\n",
+ cl_ntoh64(match_rec.port_gid.unicast.prefix),
+ cl_ntoh64(match_rec.port_gid.unicast.interface_id),
+ cl_ntoh16(p_mgrp->mlid)
+ );
+
+ match_rec.proxy_join = (uint8_t)(p_mcm_port->proxy_join);
+
+ __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+ }
+ p_item = cl_qmap_next(p_item);
+ }
+ }
+ /* One MC record returned */
+ else
+ {
+ 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;
+
+ __osm_mcmr_rcv_new_mcmr(p_rcv, &match_rec, p_ctxt->p_list);
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ Handle a query request
+**********************************************************************/
+static void
+__osm_mcmr_query_mgrp(IN osm_mcmr_recv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw)
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_member_rec_t* p_rcvd_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_member_rec_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_sa_mcmr_search_ctxt_t context;
+ osm_mcmr_item_t* p_rec_item;
+ ib_api_status_t status;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+ boolean_t trusted_req;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mcmr_query_mgrp );
+
+ 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);
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_query_mgrp: ERR 1B04: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ cl_qlist_init( &rec_list );
+
+ context.p_mcmember_rec = p_rcvd_rec;
+ context.p_list = &rec_list;
+ context.comp_mask = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+ context.trusted_req = trusted_req;
+
+ CL_PLOCK_ACQUIRE( p_rcv->p_lock );
+
+ /* simply go over all MCGs and match */
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,
+ __osm_sa_mcm_by_comp_mask_cb,
+ &context);
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_query_mgrp: ERR 1B05: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_mcmr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_member_rec_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_mcmr_query_mgrp: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mcmr_query_mgrp: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_member_rec_t) + IB_SA_MAD_HDR_SIZE,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_query_mgrp: ERR 1B16: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_member_rec_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ /*
+ 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.
+ */
+
+ for ( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_mcmr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ if (trusted_req == FALSE)
+ {
+ memset(&p_resp_rec->port_gid, 0, sizeof(ib_gid_t));
+ ib_member_set_join_state(p_resp_rec, 0);
+ p_resp_rec->proxy_join = 0;
+ }
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mcmr_query_mgrp: ERR 1B17: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_process(
+ IN osm_mcmr_recv_t* const p_rcv,
+ const IN osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t *p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ ib_member_rec_t *p_recvd_mcmember_rec;
+ boolean_t valid;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mcmr_rcv_process );
+
+ 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:
+ valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: ERR 1B18: "
+ "component mask = 0x%016" PRIx64 ", "
+ "expected comp mask = 0x%016" PRIx64 " ,"
+ "MGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " for "
+ "PortGID: 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sa_mad->comp_mask),
+ CL_NTOH64(JOIN_MC_COMP_MASK),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->mgid.unicast.interface_id ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.prefix ),
+ cl_ntoh64( p_recvd_mcmember_rec->port_gid.unicast.interface_id ) );
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /*
+ * Join or Create Multicast Group
+ */
+ __osm_mcmr_rcv_join_mgrp(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_DELETE:
+ valid = __check_join_comp_mask(p_sa_mad->comp_mask);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: 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( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /*
+ * Leave Multicast Group
+ */
+ __osm_mcmr_rcv_leave_mgrp(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_GET:
+ case IB_MAD_METHOD_GETTABLE:
+ /*
+ * Querying a Multicast Group
+ */
+ __osm_mcmr_query_mgrp(p_rcv, p_madw);
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_process: ERR 1B21: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ break;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_mcmember_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mcmr_rcv_ctrl_t.
+ * This object represents the Multicast member record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sa_mcmember_record_ctrl.h>
+#include <opensm/osm_sa_mcmember_record.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mcmr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mcmr_rcv_process( ((osm_mcmr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_construct(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mcmr_rcv_ctrl_destroy(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mcmr_rcv_ctrl_init(
+ IN osm_mcmr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mcmr_recv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mcmr_rcv_ctrl_init );
+
+ osm_mcmr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MCMEMBER_RECORD,
+ __osm_mcmr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mcmr_rcv_ctrl_init: ERR 1C01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mftr_rcv_t.
+ * This object represents the MulticastForwardingTable Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_mft_record.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_MFTR_RCV_POOL_MIN_SIZE 32
+#define OSM_MFTR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_mftr_item
+{
+ cl_pool_item_t pool_item;
+ ib_mft_record_t rec;
+} osm_mftr_item_t;
+
+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_mftr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_mftr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_construct(
+ IN osm_mftr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_destroy(
+ IN osm_mftr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_init(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mftr_rcv_init );
+
+ osm_mftr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_MFTR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_MFTR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_mftr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_mftr_rcv_new_mftr(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid,
+ IN uint16_t const block,
+ IN uint8_t const position )
+{
+ osm_mftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ uint16_t position_block_num;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mftr_rcv_new_mftr );
+
+ p_rec_item = (osm_mftr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mftr_rcv_new_mftr: ERR 4A02: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mftr_rcv_new_mftr: "
+ "New MulticastForwardingTable: sw 0x%016" PRIx64
+ "\n\t\t\t\tblock %u position %u lid 0x%02X\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->rec, 0, sizeof(ib_mft_record_t) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->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->rec.mft );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_mftr_get_port_by_guid(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN uint64_t port_guid )
+{
+ osm_port_t* p_port;
+
+ CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ port_guid);
+ if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mftr_get_port_by_guid ERR 4A04: "
+ "Invalid port GUID 0x%016" PRIx64 "\n",
+ port_guid );
+ p_port = NULL;
+ }
+
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mftr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_mftr_search_ctxt_t* const p_ctxt =
+ (osm_mftr_search_ctxt_t *)context;
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ const ib_mft_record_t* const p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ osm_mftr_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ 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_mftr_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+ if (! p_port)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mftr_rcv_by_comp_mask: 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 = osm_port_get_default_phys_ptr( p_port );
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mftr_rcv_by_comp_mask: 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( p_rcv->p_log, p_req_physp, p_physp ))
+ 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mftr_rcv_by_comp_mask: "
+ "Comparing lid:0x%02X to port lid range: 0x%02X .. 0x%02X\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++)
+ __osm_mftr_rcv_new_mftr( p_rcv, p_sw, p_ctxt->p_list,
+ osm_port_get_base_lid(p_port),
+ block, position );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_process(
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_mft_record_t* p_rcvd_rec;
+ ib_mft_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_mftr_search_ctxt_t context;
+ osm_mftr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mftr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A08: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A07: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* Go over all switches */
+ cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+ __osm_mftr_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A09: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_mftr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_mft_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_mftr_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_mftr_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method != IB_MAD_METHOD_GETTABLE) &&
+ (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_mft_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A10: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_mft_record_t) );
+
+ p_resp_rec = (ib_mft_record_t*)ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_mftr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_process: ERR 4A11: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mftr_rcv_ctrl_t.
+ * This object represents the MulticastForwardingTable request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_mft_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_mftr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mftr_rcv_process( ((osm_mftr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_construct(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mftr_rcv_ctrl_destroy(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mftr_rcv_ctrl_init(
+ IN osm_mftr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mftr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mftr_rcv_ctrl_init );
+
+ osm_mftr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MFT_RECORD,
+ __osm_mftr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mftr_rcv_ctrl_init: ERR 4A01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_multipath_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_partition.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+
+#define OSM_MPR_RCV_POOL_MIN_SIZE 64
+#define OSM_MPR_RCV_POOL_GROW_SIZE 64
+
+#define OSM_SA_MPR_MAX_NUM_PATH 127
+
+typedef struct _osm_mpr_item
+{
+ cl_pool_item_t pool_item;
+ const osm_port_t *p_src_port;
+ const osm_port_t *p_dest_port;
+ int hops;
+ ib_path_rec_t path_rec;
+} osm_mpr_item_t;
+
+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;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_construct(
+ IN osm_mpr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pr_pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_destroy(
+ IN osm_mpr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pr_pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mpr_rcv_init(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_mpr_rcv_init );
+
+ osm_mpr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pr_pool,
+ OSM_MPR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_MPR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_mpr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline boolean_t
+__osm_sa_multipath_rec_is_tavor_port(
+ IN const osm_port_t* const p_port)
+{
+ osm_node_t const* p_node;
+ ib_net32_t vend_id;
+
+ p_node = osm_port_get_parent_node( p_port );
+ 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))) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+ __osm_sa_multipath_rec_apply_tavor_mtu_limit(
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const 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 (! __osm_sa_multipath_rec_is_tavor_port(p_src_port) &&
+ ! __osm_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_PR_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
+__osm_mpr_rcv_get_path_parms(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const uint16_t dest_lid_ho,
+ IN const ib_net64_t comp_mask,
+ OUT osm_path_parms_t* const p_parms )
+{
+ const osm_node_t* p_node;
+ const osm_physp_t* p_physp;
+ const osm_physp_t* p_dest_physp;
+ const osm_prtn_t* p_prtn;
+ const ib_port_info_t* p_pi;
+ ib_slvl_table_t* p_slvl_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+ uint8_t mtu;
+ uint8_t rate;
+ uint8_t pkt_life;
+ uint8_t required_mtu;
+ uint8_t required_rate;
+ uint16_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 vl;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_path_parms );
+
+ dest_lid = cl_hton16( dest_lid_ho );
+
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+ p_physp = osm_port_get_default_phys_ptr( p_src_port );
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ rate = ib_port_info_compute_rate( p_pi );
+
+ /*
+ 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 ( p_rcv->p_subn->opt.enable_quirks &&
+ __osm_sa_multipath_rec_apply_tavor_mtu_limit(
+ p_mpr, p_src_port, p_dest_port, comp_mask) )
+ if (mtu > IB_MTU_LEN_1024)
+ {
+ mtu = IB_MTU_LEN_1024;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "Optimized Path MTU to 1K for Mellanox Tavor device\n");
+ }
+
+ if ( comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
+ cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) )
+ required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );
+ else if ( comp_mask & IB_MPR_COMPMASK_PKEY ) {
+ required_pkey = p_mpr->pkey;
+ if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, required_pkey ) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4518: "
+ "Ports do not share specified PKey 0x%04x\n"
+ "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n",
+ cl_ntoh16( required_pkey ),
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+ } else {
+ required_pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );
+ if ( !required_pkey ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4519: "
+ "Ports do not have any shared PKeys\n"
+ "\t\tsrc %" PRIx64 " dst %" PRIx64 "\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh64( osm_physp_get_port_guid( p_dest_physp ) ) );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ required_sl = OSM_DEFAULT_SL;
+
+ if (required_pkey) {
+ p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl,
+ required_pkey & cl_ntoh16((uint16_t)~0x8000));
+ if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) )
+ {
+ /* this may be possible when pkey tables are created somehow in
+ previous runs or things are going wrong here */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 451A: "
+ "No partition found for PKey 0x%04x - using default SL %d\n", cl_ntoh16(required_pkey), required_sl );
+ }
+ else
+ required_sl = p_prtn->sl;
+
+ /* reset pkey when raw traffic */
+ if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&
+ cl_ntoh32( p_mpr->hop_flow_raw ) & ( 1<<31 ) )
+ required_pkey = 0;
+ }
+
+ if ( ( comp_mask & IB_MPR_COMPMASK_SL ) && ib_multipath_rec_sl( p_mpr ) != required_sl )
+ {
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+
+ /*
+ 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 )
+ {
+
+ /*
+ * If the dest_lid_ho is equal to the lid of the switch pointed by
+ * p_sw then p_physp will be the physical port of the switch port zero.
+ */
+ p_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );
+ if ( p_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4514: "
+ "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ }
+
+ /*
+ * Same as above
+ */
+ p_node = osm_physp_get_node_ptr( p_dest_physp );
+
+ if ( p_node->sw )
+ {
+
+ p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );
+
+ if ( p_dest_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4515: "
+ "Can't find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ }
+
+ while ( p_physp != p_dest_physp )
+ {
+ p_physp = osm_physp_get_remote( p_physp );
+
+ if ( p_physp == 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4505: "
+ "Can't find remote phys port when routing to LID 0x%X from node GUID 0x%016" PRIx64 "\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ hops++;
+
+ /*
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4503: "
+ "Internal error, bad path\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /*
+ Check parameters for the ingress port in this switch.
+ */
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64
+ " port num 0x%X\n",
+ mtu,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ if ( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+ rate = ib_port_info_compute_rate( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest rate = %u at intervening port 0x%016" PRIx64
+ " port num 0x%X\n",
+ rate,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ /*
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_path_parms: ERR 4516: "
+ "Dead end on path to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",
+ dest_lid_ho,
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ if ( comp_mask & IB_MPR_COMPMASK_SL ) {
+ in_port_num = osm_physp_get_port_num( p_physp );
+ p_slvl_tbl = osm_physp_get_slvl_tbl( p_physp, in_port_num );
+ vl = ib_slvl_table_get( p_slvl_tbl, required_sl );
+ if (vl == IB_DROP_VL) { /* discard packet */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_mpr_rcv_get_path_parms: Path not found for SL %d\n"
+ "\t\tin_port_num %d port_guid %" PRIx64 "\n",
+ required_sl, in_port_num,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64
+ " port num 0x%X\n",
+ mtu,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ if ( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+ rate = ib_port_info_compute_rate( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest rate = %u at intervening port 0x%016" PRIx64
+ " port num 0x%X\n",
+ rate,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ osm_physp_get_port_num( p_physp ) );
+ }
+ }
+
+ }
+
+ /*
+ p_physp now points to the destination
+ */
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ if ( mtu > ib_port_info_get_mtu_cap( p_pi ) )
+ {
+ mtu = ib_port_info_get_mtu_cap( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n",
+ mtu,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ }
+
+ if ( rate > ib_port_info_compute_rate( p_pi ) )
+ {
+ rate = ib_port_info_compute_rate( p_pi );
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "New smallest rate = %u at destination port 0x%016" PRIx64 "\n",
+ rate,
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ }
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_path_parms: "
+ "Path min MTU = %u, min rate = %u\n", mtu, rate );
+ }
+
+ /*
+ 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;
+ }
+ }
+
+ /* we silently ignore cases where only the Rate selector is defined */
+ if ( ( comp_mask & IB_MPR_COMPMASK_RATESELEC ) &&
+ ( comp_mask & IB_PR_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 ( rate <= required_rate )
+ status = IB_NOT_FOUND;
+ break;
+
+ case 1: /* must be less than */
+ if ( rate >= required_rate )
+ {
+ /* adjust the rate to use the highest rate
+ lower then the required one */
+ if ( required_rate > 2 )
+ rate = required_rate - 1;
+ else
+ status = IB_NOT_FOUND;
+ }
+ break;
+
+ case 2: /* exact match */
+ if ( 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;
+ }
+ }
+
+ /* 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_port == p_dest_port )
+ pkt_life = 0; /* loopback */
+ else
+ pkt_life = OSM_DEFAULT_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;
+
+ 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;
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_build_pr(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ 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* const p_parms,
+ OUT ib_path_rec_t* const p_pr )
+{
+ const osm_physp_t* p_src_physp;
+ const osm_physp_t* p_dest_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_build_pr );
+
+ p_src_physp = osm_port_get_default_phys_ptr( p_src_port );
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );
+
+ p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix( p_dest_physp );
+ p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid( p_dest_physp );
+
+ p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix( p_src_physp );
+ p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid( p_src_physp );
+
+ 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;
+ p_pr->sl = cl_hton16( 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_port == p_dest_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( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t*
+__osm_mpr_rcv_get_lid_pair_path(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ 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_mpr_item_t *p_pr_item;
+ ib_api_status_t status, rev_path_status;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_lid_pair_path );
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_lid_pair_path: "
+ "Src LID 0x%X, Dest LID 0x%X\n",
+ src_lid_ho, dest_lid_ho );
+ }
+
+ p_pr_item = (osm_mpr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );
+ if ( p_pr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_lid_pair_path: ERR 4501: "
+ "Unable to allocate path record\n" );
+ goto Exit;
+ }
+
+ status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_src_port,
+ p_dest_port, dest_lid_ho,
+ comp_mask, &path_parms );
+
+ if ( status != IB_SUCCESS )
+ {
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_pr_item = NULL;
+ goto Exit;
+ }
+
+ /* now try the reversible path */
+ rev_path_status = __osm_mpr_rcv_get_path_parms( p_rcv, p_mpr, p_dest_port,
+ p_src_port, 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_lid_pair_path: "
+ "Requested reversible path but failed to get one\n");
+
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );
+ p_pr_item = NULL;
+ goto Exit;
+ }
+ }
+
+ p_pr_item->p_src_port = p_src_port;
+ p_pr_item->p_dest_port = p_dest_port;
+ p_pr_item->hops = path_parms.hops;
+
+ __osm_mpr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho,
+ dest_lid_ho, preference, &path_parms,
+ &p_pr_item->path_rec );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( p_pr_item );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static uint32_t
+__osm_mpr_rcv_get_port_pair_paths(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_req_port,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN const uint32_t rem_paths,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ osm_mpr_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;
+ uintn_t src_offset;
+ uintn_t dest_offset;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_port_pair_paths );
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_port_pair_paths: "
+ "Src port 0x%016" PRIx64 ", "
+ "Dst port 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_port_get_guid( p_src_port ) ),
+ cl_ntoh64( osm_port_get_guid( p_dest_port ) ) );
+ }
+
+ /* 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(p_rcv->p_log, p_req_port, p_src_port ) == FALSE ||
+ osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port ) == FALSE ||
+ osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port ) == 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_port, &src_lid_min_ho, &src_lid_max_ho );
+ osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho, &dest_lid_max_ho );
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_port_pair_paths: "
+ "Src LID [0x%X-0x%X], "
+ "Dest LID [0x%X-0x%X]\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 = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+ p_src_port, p_dest_port,
+ src_lid_ho, dest_lid_ho,
+ comp_mask, preference );
+
+ if ( p_pr_item )
+ {
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&p_pr_item->pool_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 = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+ p_src_port, p_dest_port,
+ src_lid_ho, dest_lid_ho,
+ comp_mask, preference );
+
+ if ( p_pr_item )
+ {
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&p_pr_item->pool_item );
+ ++path_num;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return path_num;
+}
+
+#undef min
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+/**********************************************************************
+ **********************************************************************/
+static osm_mpr_item_t*
+__osm_mpr_rcv_get_apm_port_pair_paths(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_src_port,
+ IN const osm_port_t* const p_dest_port,
+ IN int base_offs,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ osm_mpr_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;
+ uintn_t iterations;
+ int src_lids, dest_lids;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_port_pair_paths );
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_apm_port_pair_paths: "
+ "Src port 0x%016" PRIx64 ", "
+ "Dst port 0x%016" PRIx64 ", base offs %d\n",
+ cl_ntoh64( osm_port_get_guid( p_src_port ) ),
+ cl_ntoh64( osm_port_get_guid( p_dest_port ) ),
+ base_offs );
+ }
+
+ osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho, &src_lid_max_ho );
+ osm_port_get_lid_range_ho( p_dest_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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_apm_port_pair_paths: "
+ "Src LIDs [0x%X-0x%X] hashed %d, "
+ "Dest LIDs [0x%X-0x%X] hashed %d\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 = __osm_mpr_rcv_get_lid_pair_path( p_rcv, p_mpr,
+ p_src_port, p_dest_port,
+ src_lid_ho, dest_lid_ho,
+ comp_mask, 0 );
+
+ if ( p_pr_item )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_get_apm_port_pair_paths: "
+ "Found matching path from Src LID 0x%X to Dest LID 0x%X with %d hops\n",
+ src_lid_ho, dest_lid_ho, p_pr_item->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( p_rcv->p_log );
+ return p_pr_item;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_gids(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_gid_t * gids,
+ IN int ngids,
+ IN int is_sgid,
+ OUT osm_port_t** pp_port )
+{
+ osm_port_t *p_port;
+ ib_net16_t ib_status = IB_SUCCESS;
+ int i;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_gids );
+
+ 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 ) != p_rcv->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( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_mpr_rcv_get_gids: ERR 451B: "
+ "Non local %sGID subnet prefix 0x%016" PRIx64 "\n",
+ is_sgid ? "S" : "D",
+ cl_ntoh64( gids->unicast.prefix ) );
+
+ ib_status = IB_SA_MAD_STATUS_INVALID_GID;
+ goto Exit;
+ }
+ }
+
+ p_port = (osm_port_t *)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl,
+ gids->unicast.interface_id );
+ if ( !p_port ||
+ p_port == (osm_port_t *)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ) ) {
+ /*
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_get_gids: 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_port[i] = p_port;
+ }
+
+ Exit:
+ OSM_LOG_EXIT(p_rcv->p_log);
+
+ return ib_status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_net16_t
+__osm_mpr_rcv_get_end_points(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ OUT osm_port_t ** pp_ports,
+ 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( p_rcv->p_log, __osm_mpr_rcv_get_end_points );
+
+ /*
+ 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 = __osm_mpr_rcv_get_gids( p_rcv, gids, *nsrc, 1, pp_ports );
+ 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 = __osm_mpr_rcv_get_gids( p_rcv, gids + *nsrc, *ndest, 0,
+ pp_ports + *nsrc );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( sa_status );
+}
+
+#define __hash_lids(a, b, lmc) \
+ (((((a) >> (lmc)) << 4) | ((b) >> (lmc))) % 103)
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_get_apm_paths(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN const osm_port_t* const p_req_port,
+ IN osm_port_t ** _pp_ports,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ osm_port_t *pp_ports[4];
+ osm_mpr_item_t *matrix[2][2];
+ int base_offs, src_lid_ho, dest_lid_ho;
+ int sumA, sumB, minA, minB;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_get_apm_paths );
+
+ /*
+ * 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 __osm_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 indepentent, 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_ports[0]->guid < _pp_ports[1]->guid ) {
+ pp_ports[0] = _pp_ports[0];
+ pp_ports[1] = _pp_ports[1];
+ }
+ else
+ {
+ pp_ports[0] = _pp_ports[1];
+ pp_ports[1] = _pp_ports[0];
+ }
+ if ( _pp_ports[2]->guid < _pp_ports[3]->guid ) {
+ pp_ports[2] = _pp_ports[2];
+ pp_ports[3] = _pp_ports[3];
+ }
+ else
+ {
+ pp_ports[2] = _pp_ports[3];
+ pp_ports[3] = _pp_ports[2];
+ }
+
+ src_lid_ho = osm_port_get_base_lid( pp_ports[0] );
+ dest_lid_ho = osm_port_get_base_lid( pp_ports[2] );
+
+ base_offs = src_lid_ho < dest_lid_ho ?
+ __hash_lids( src_lid_ho, dest_lid_ho, p_rcv->p_subn->opt.lmc ) :
+ __hash_lids( dest_lid_ho, src_lid_ho, p_rcv->p_subn->opt.lmc );
+
+ matrix[0][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0],
+ pp_ports[2], base_offs, comp_mask , p_list );
+ matrix[0][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[0],
+ pp_ports[3], base_offs, comp_mask, p_list );
+ matrix[1][0] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1],
+ pp_ports[2], base_offs+1, comp_mask, p_list );
+ matrix[1][1] = __osm_mpr_rcv_get_apm_port_pair_paths( p_rcv, p_mpr, pp_ports[1],
+ pp_ports[3], base_offs+1, comp_mask, p_list );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+ "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]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops,
+ matrix[0][1]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops,
+ matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops,
+ matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops );
+
+ /* check diagonal A {(0,0), (1,1)} */
+ sumA = matrix[0][0]->hops + matrix[1][1]->hops;
+ minA = min( matrix[0][0]->hops, matrix[1][1]->hops );
+
+ /* check diagonal B {(0,1), (1,0)} */
+ sumB = matrix[0][1]->hops + matrix[1][0]->hops;
+ minB = min( matrix[0][1]->hops, matrix[1][0]->hops );
+
+ /* and the winner is... */
+ if ( minA <= minB || ( minA == minB && sumA < sumB ) ) {
+ /* Diag A */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+ "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]->path_rec.slid, matrix[0][0]->path_rec.dlid, matrix[0][0]->hops,
+ matrix[1][1]->path_rec.slid, matrix[1][1]->path_rec.dlid, matrix[1][1]->hops );
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&matrix[0][0]->pool_item );
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&matrix[1][1]->pool_item );
+ cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][1]->pool_item );
+ cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][0]->pool_item );
+ }
+ else
+ {
+ /* Diag B */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG, "__osm_mpr_rcv_get_apm_paths: "
+ "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]->path_rec.slid, matrix[0][1]->path_rec.dlid, matrix[0][1]->hops,
+ matrix[1][0]->path_rec.slid, matrix[1][0]->path_rec.dlid, matrix[1][0]->hops );
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&matrix[0][1]->pool_item );
+ cl_qlist_insert_tail( p_list,
+ (cl_list_item_t*)&matrix[1][0]->pool_item );
+ cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[0][0]->pool_item );
+ cl_qlock_pool_put( &p_rcv->pr_pool, &matrix[1][1]->pool_item );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_process_pairs(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const ib_multipath_rec_t* const p_mpr,
+ IN osm_port_t* const p_req_port,
+ IN osm_port_t ** pp_ports,
+ IN const int nsrc,
+ IN const int ndest,
+ IN const ib_net64_t comp_mask,
+ IN cl_qlist_t* const p_list )
+{
+ osm_port_t **pp_src_port, **pp_es;
+ osm_port_t **pp_dest_port, **pp_ed;
+ uint32_t max_paths, num_paths, total_paths = 0;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_process_pairs );
+
+ 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_port = pp_ports, pp_es = pp_ports + nsrc; pp_src_port < pp_es; pp_src_port++ )
+ {
+ for ( pp_dest_port = pp_es, pp_ed = pp_es + ndest; pp_dest_port < pp_ed; pp_dest_port++ )
+ {
+ num_paths = __osm_mpr_rcv_get_port_pair_paths( p_rcv, p_mpr, p_req_port,
+ *pp_src_port, *pp_dest_port,
+ max_paths - total_paths,
+ comp_mask, p_list );
+ total_paths += num_paths;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_process_pairs: "
+ "%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( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_respond(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ size_t num_rec;
+ size_t mad_size;
+ ib_path_rec_t* p_resp_pr;
+ ib_multipath_rec_t* p_mpr;
+ ib_api_status_t status;
+ osm_mpr_item_t* p_mpr_item;
+ uint32_t i;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_mpr_rcv_respond );
+
+ 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 );
+
+ num_rec = cl_qlist_count( p_list );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_mpr_rcv_respond: "
+ "Generating response with %zu records\n", num_rec );
+
+ mad_size = IB_SA_MAD_HDR_SIZE + num_rec * sizeof(ib_path_rec_t);
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, p_madw->h_bind,
+ mad_size, &p_madw->mad_addr );
+
+ if ( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_respond: "
+ "ERR 4502: Unable to allocate MAD\n" );
+
+ for ( i = 0; i < num_rec; i++ )
+ {
+ p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list );
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ 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;
+
+ /*
+ 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_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;
+ p_resp_sa_mad->attr_offset = ib_get_attr_offset( sizeof(ib_path_rec_t) );
+
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+
+ p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ for ( i = 0; i < num_rec; i++ )
+ {
+ p_mpr_item = (osm_mpr_item_t*)cl_qlist_remove_head( p_list );
+
+ /* Copy the Path Records from the list into the MAD */
+ *p_resp_pr = p_mpr_item->path_rec;
+
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_mpr_item->pool_item );
+ p_resp_pr++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( p_list ) );
+
+ osm_dump_sa_mad( p_rcv->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_mpr_rcv_respond: ERR 4507: "
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_process(
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ const ib_multipath_rec_t* p_mpr;
+ const ib_sa_mad_t* p_sa_mad;
+ osm_port_t* requester_port;
+ osm_port_t* pp_ports[IB_MULTIPATH_MAX_GIDS];
+ cl_qlist_t pr_list;
+ ib_net16_t sa_status;
+ int nsrc, ndest;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_mpr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mpr_rcv_process: ERR 4510: "
+ "Invalid request since RMPP_FLAG_ACTIVE is not set\n" );
+ osm_sa_send_error( p_rcv->p_resp, 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mpr_rcv_process: ERR 4513: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ requester_port = osm_get_port_by_mad_addr( p_rcv->p_log, p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr( p_madw ) );
+ if ( requester_port == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mpr_rcv_process: ERR 4517: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_multipath_record( p_rcv->p_log, p_mpr, OSM_LOG_DEBUG );
+
+ 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( p_rcv->p_lock );
+
+ sa_status = __osm_mpr_rcv_get_end_points( p_rcv, p_madw, pp_ports,
+ &nsrc, &ndest );
+
+ if ( sa_status != IB_SA_MAD_STATUS_SUCCESS || !nsrc || !ndest )
+ {
+ if ( sa_status == IB_SA_MAD_STATUS_SUCCESS && ( !nsrc || !ndest ) )
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_mpr_rcv_process_cb: ERR 4512: "
+ "__osm_mpr_rcv_get_end_points failed, not enough GIDs "
+ "(nsrc %d ndest %d)\n",
+ nsrc, ndest);
+ cl_plock_release( p_rcv->p_lock );
+ if ( sa_status == IB_SA_MAD_STATUS_SUCCESS )
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+ else
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /* APM request */
+ if ( nsrc == 2 && ndest == 2 && ( p_mpr->num_path & 0x7F ) == 2 )
+ __osm_mpr_rcv_get_apm_paths( p_rcv, p_mpr, requester_port, pp_ports,
+ p_sa_mad->comp_mask, &pr_list );
+ else
+ __osm_mpr_rcv_process_pairs( p_rcv, p_mpr, requester_port, pp_ports,
+ nsrc, ndest,
+ p_sa_mad->comp_mask, &pr_list );
+
+ cl_plock_release( p_rcv->p_lock );
+ __osm_mpr_rcv_respond( p_rcv, p_madw, &pr_list );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_mpr_rcv_ctrl_t.
+ * This object represents the MultiPathRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_multipath_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_mpr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_mpr_rcv_process( ((osm_mpr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_ctrl_construct(
+ IN osm_mpr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_mpr_rcv_ctrl_destroy(
+ IN osm_mpr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_mpr_rcv_ctrl_init(
+ IN osm_mpr_rcv_ctrl_t* const p_ctrl,
+ IN osm_mpr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_mpr_rcv_ctrl_init );
+
+ osm_mpr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_MULTIPATH_RECORD,
+ __osm_mpr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_mpr_rcv_ctrl_init: ERR 4B01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+#endif
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_node_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nr_rcv_t.
+ * This object represents the NodeInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.8 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_node_record.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_NR_RCV_POOL_MIN_SIZE 32
+#define OSM_NR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_nr_item
+{
+ cl_pool_item_t pool_item;
+ ib_node_record_t rec;
+} osm_nr_item_t;
+
+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_nr_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_nr_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_construct(
+ IN osm_nr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_destroy(
+ IN osm_nr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_init(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_nr_rcv_init );
+
+ osm_nr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_NR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_NR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_nr_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_nr_rcv_new_nr(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const port_guid,
+ IN ib_net16_t const lid )
+{
+ osm_nr_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_nr_rcv_new_nr );
+
+ p_rec_item = (osm_nr_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_nr_rcv_new_nr: ERR 1D02: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_nr_rcv_new_nr: "
+ "New NodeRecord: node 0x%016" PRIx64
+ "\n\t\t\t\tport 0x%016" PRIx64 ", lid 0x%X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ cl_ntoh64( port_guid ), cl_ntoh16( lid )
+ );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof(ib_node_record_t) );
+
+ p_rec_item->rec.lid = lid;
+
+ p_rec_item->rec.node_info = p_node->node_info;
+ p_rec_item->rec.node_info.port_guid = port_guid;
+ memcpy(&(p_rec_item->rec.node_desc), &(p_node->node_desc),
+ IB_NODE_DESCRIPTION_SIZE);
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_create_nr(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_node_t* const p_node,
+ IN cl_qlist_t* const p_list,
+ IN ib_net64_t const match_port_guid,
+ IN ib_net16_t const match_lid,
+ IN const osm_physp_t* const p_req_physp )
+{
+ 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( p_rcv->p_log, __osm_nr_rcv_create_nr );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_nr_rcv_create_nr: "
+ "Looking for NodeRecord with LID: 0x%X 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( !osm_physp_is_valid( 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( p_rcv->p_log, p_physp, p_req_physp ) )
+ continue;
+
+ port_guid = osm_physp_get_port_guid( p_physp );
+
+ if( match_port_guid && ( port_guid != match_port_guid ) )
+ continue;
+
+ base_lid = osm_physp_get_base_lid( p_physp );
+ 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 );
+
+ if( match_lid_ho )
+ {
+ /*
+ We validate that the lid belongs to this node.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_nr_rcv_create_nr: "
+ "Comparing LID: 0x%X <= 0x%X <= 0x%X\n",
+ base_lid_ho, match_lid_ho, max_lid_ho
+ );
+ }
+
+ if ( match_lid_ho < base_lid_ho || match_lid_ho > max_lid_ho )
+ continue;
+ }
+
+ __osm_nr_rcv_new_nr( p_rcv, p_node, p_list, port_guid, base_lid );
+
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_nr_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_nr_search_ctxt_t* const p_ctxt = (osm_nr_search_ctxt_t *)context;
+ const osm_node_t* const 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_nr_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ ib_net64_t const comp_mask = p_ctxt->comp_mask;
+ ib_net64_t match_port_guid = 0;
+ ib_net16_t match_lid = 0;
+
+ OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_nr_rcv_by_comp_mask );
+
+ osm_dump_node_info(
+ p_ctxt->p_rcv->p_log,
+ &p_node->node_info,
+ OSM_LOG_VERBOSE );
+
+ if( comp_mask & IB_NR_COMPMASK_LID )
+ match_lid = p_rcvd_rec->lid;
+
+ if( comp_mask & IB_NR_COMPMASK_NODEGUID)
+ {
+ /*
+ DEBUG TOP
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_nr_rcv_by_comp_mask: "
+ "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 ) )
+ );
+ }
+ /*
+ DEBUG BOTTOM
+ */
+ 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 )
+ {
+ if( (p_node->node_info.sys_guid != p_rcvd_rec->node_info.sys_guid) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_BASEVERSION )
+ {
+ if( (p_node->node_info.base_version != p_rcvd_rec->node_info.base_version) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_CLASSVERSION )
+ {
+ if( (p_node->node_info.class_version != p_rcvd_rec->node_info.class_version) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_NODETYPE )
+ {
+ if( (p_node->node_info.node_type != p_rcvd_rec->node_info.node_type) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_NUMPORTS )
+ {
+ if( (p_node->node_info.num_ports != p_rcvd_rec->node_info.num_ports) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_PARTCAP )
+ {
+ if( (p_node->node_info.partition_cap != p_rcvd_rec->node_info.partition_cap) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_DEVID )
+ {
+ if( (p_node->node_info.device_id != p_rcvd_rec->node_info.device_id) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_REV )
+ {
+ if( (p_node->node_info.revision != p_rcvd_rec->node_info.revision) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_PORTNUM )
+ {
+ if( ib_node_info_get_local_port_num(&p_node->node_info) !=
+ ib_node_info_get_local_port_num(&p_rcvd_rec->node_info) )
+ goto Exit;
+ }
+ if( comp_mask & IB_NR_COMPMASK_VENDID )
+ {
+ if( 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 )
+ {
+ if( strncmp((char*) &p_node->node_desc,
+ (char*) &p_rcvd_rec->node_desc, sizeof(ib_node_desc_t)) )
+ goto Exit;
+ }
+
+ __osm_nr_rcv_create_nr( p_rcv, p_node, p_ctxt->p_list,
+ match_port_guid, match_lid, p_req_physp );
+
+ Exit:
+ OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_process(
+ IN osm_nr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_node_record_t* p_rcvd_rec;
+ ib_node_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_nr_search_ctxt_t context;
+ osm_nr_item_t* p_rec_item;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_nr_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D05: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D04: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_node_record( p_rcv->p_log, p_rcvd_rec, 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ cl_qmap_apply_func( &p_rcv->p_subn->node_guid_tbl,
+ __osm_nr_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D03: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_nr_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_node_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_nr_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_nr_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_node_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D06: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_node_record_t) );
+
+ p_resp_rec = (ib_node_record_t*)ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_nr_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_process: ERR 1D07: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_node_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_nr_rcv_ctrl_t.
+ * This object represents the Node Record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_node_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_nr_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_nr_rcv_process( ((osm_nr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_construct(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_nr_rcv_ctrl_destroy(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_nr_rcv_ctrl_init(
+ IN osm_nr_rcv_ctrl_t* const p_ctrl,
+ IN osm_nr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_nr_rcv_ctrl_init );
+
+ osm_nr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NODE_RECORD,
+ __osm_nr_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_nr_rcv_ctrl_init: ERR 1E01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osm_sa_path_record.c 1929 2009-02-04 15:24:59Z tzachid $\r
+ */\r
+\r
+\r
+/*\r
+ * Abstract:\r
+ * Implementation of osm_pr_rcv_t.\r
+ * This object represents the PathRecord Receiver object.\r
+ * This object is part of the opensm family of objects.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.10 $\r
+ */\r
+\r
+#if HAVE_CONFIG_H\r
+# include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <string.h>\r
+#include <iba/ib_types.h>\r
+#include <complib/cl_qmap.h>\r
+#include <complib/cl_passivelock.h>\r
+#include <complib/cl_debug.h>\r
+#include <complib/cl_qlist.h>\r
+#include <opensm/osm_base.h>\r
+#include <opensm/osm_sa_path_record.h>\r
+#include <opensm/osm_port.h>\r
+#include <opensm/osm_node.h>\r
+#include <opensm/osm_switch.h>\r
+#include <vendor/osm_vendor.h>\r
+#include <vendor/osm_vendor_api.h>\r
+#include <opensm/osm_helper.h>\r
+#include <opensm/osm_pkey.h>\r
+#include <opensm/osm_multicast.h>\r
+#include <opensm/osm_partition.h>\r
+\r
+#define OSM_PR_RCV_POOL_MIN_SIZE 64\r
+#define OSM_PR_RCV_POOL_GROW_SIZE 64\r
+\r
+typedef struct _osm_pr_item\r
+{\r
+ cl_pool_item_t pool_item;\r
+ ib_path_rec_t path_rec;\r
+} osm_pr_item_t;\r
+\r
+typedef struct _osm_path_parms\r
+{\r
+ ib_net16_t pkey;\r
+ uint8_t mtu;\r
+ uint8_t rate;\r
+ uint8_t sl;\r
+ uint8_t pkt_life;\r
+ boolean_t reversible;\r
+} osm_path_parms_t;\r
+\r
+typedef struct osm_sa_pr_mcmr_search_ctxt {\r
+ ib_gid_t *p_mgid;\r
+ osm_mgrp_t *p_mgrp;\r
+ osm_pr_rcv_t *p_rcv;\r
+} osm_sa_pr_mcmr_search_ctxt_t;\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_construct(\r
+ IN osm_pr_rcv_t* const p_rcv )\r
+{\r
+ memset( p_rcv, 0, sizeof(*p_rcv) );\r
+ cl_qlock_pool_construct( &p_rcv->pr_pool );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_destroy(\r
+ IN osm_pr_rcv_t* const p_rcv )\r
+{\r
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_destroy );\r
+ cl_qlock_pool_destroy( &p_rcv->pr_pool );\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osm_pr_rcv_init(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN osm_sa_resp_t* const p_resp,\r
+ IN osm_mad_pool_t* const p_mad_pool,\r
+ IN osm_subn_t* const p_subn,\r
+ IN osm_log_t* const p_log,\r
+ IN cl_plock_t* const p_lock )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_log, osm_pr_rcv_init );\r
+\r
+ osm_pr_rcv_construct( p_rcv );\r
+\r
+ p_rcv->p_log = p_log;\r
+ p_rcv->p_subn = p_subn;\r
+ p_rcv->p_lock = p_lock;\r
+ p_rcv->p_resp = p_resp;\r
+ p_rcv->p_mad_pool = p_mad_pool;\r
+\r
+ status = cl_qlock_pool_init( &p_rcv->pr_pool,\r
+ OSM_PR_RCV_POOL_MIN_SIZE,\r
+ 0,\r
+ OSM_PR_RCV_POOL_GROW_SIZE,\r
+ sizeof(osm_pr_item_t),\r
+ NULL, NULL, NULL );\r
+\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static inline boolean_t\r
+__osm_sa_path_rec_is_tavor_port(\r
+ IN const osm_port_t* const p_port)\r
+{\r
+ osm_node_t const* p_node;\r
+ ib_net32_t vend_id;\r
+\r
+ p_node = osm_port_get_parent_node( p_port );\r
+ vend_id = ib_node_info_get_vendor_id( &p_node->node_info );\r
+ \r
+ return( (p_node->node_info.device_id == CL_HTON16(23108)) &&\r
+ ((vend_id == CL_HTON32(OSM_VENDOR_ID_MELLANOX)) || \r
+ (vend_id == CL_HTON32(OSM_VENDOR_ID_TOPSPIN)) || \r
+ (vend_id == CL_HTON32(OSM_VENDOR_ID_SILVERSTORM)) || \r
+ (vend_id == CL_HTON32(OSM_VENDOR_ID_VOLTAIRE))) );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static boolean_t\r
+ __osm_sa_path_rec_apply_tavor_mtu_limit(\r
+ IN const ib_path_rec_t* const p_pr,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const ib_net64_t comp_mask)\r
+{\r
+ uint8_t required_mtu;\r
+ \r
+ /* only if at least one of the ports is a Tavor device */\r
+ if (! __osm_sa_path_rec_is_tavor_port(p_src_port) && \r
+ ! __osm_sa_path_rec_is_tavor_port(p_dest_port) )\r
+ return( FALSE );\r
+\r
+ /*\r
+ we can apply the patch if either:\r
+ 1. No MTU required\r
+ 2. Required MTU < \r
+ 3. Required MTU = 1K or 512 or 256\r
+ 4. Required MTU > 256 or 512\r
+ */\r
+ required_mtu = ib_path_rec_mtu( p_pr );\r
+ if ( ( comp_mask & IB_PR_COMPMASK_MTUSELEC ) &&\r
+ ( comp_mask & IB_PR_COMPMASK_MTU ) )\r
+ {\r
+ switch( ib_path_rec_mtu_sel( p_pr ) )\r
+ {\r
+ case 0: /* must be greater than */\r
+ case 2: /* exact match */\r
+ if( IB_MTU_LEN_1024 < required_mtu )\r
+ return(FALSE);\r
+ break;\r
+\r
+ case 1: /* must be less than */\r
+ /* can't be disqualified by this one */\r
+ break;\r
+\r
+ case 3: /* largest available */\r
+ /* the ULP intentionally requested */\r
+ /* the largest MTU possible */\r
+ return(FALSE);\r
+ break;\r
+ \r
+ default:\r
+ /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+ CL_ASSERT( FALSE );\r
+ break;\r
+ }\r
+ }\r
+\r
+ return(TRUE);\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_pr_rcv_get_path_parms(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const ib_path_rec_t* const p_pr,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const uint16_t dest_lid_ho,\r
+ IN const ib_net64_t comp_mask,\r
+ OUT osm_path_parms_t* const p_parms )\r
+{\r
+ const osm_node_t* p_node;\r
+ const osm_physp_t* p_physp;\r
+ const osm_physp_t* p_dest_physp;\r
+ const osm_prtn_t* p_prtn;\r
+ const ib_port_info_t* p_pi;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ ib_net16_t pkey;\r
+ uint8_t mtu;\r
+ uint8_t rate;\r
+ uint8_t pkt_life;\r
+ uint8_t required_mtu;\r
+ uint8_t required_rate;\r
+ uint8_t required_pkt_life;\r
+ uint8_t sl;\r
+ ib_net16_t dest_lid;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_path_parms );\r
+\r
+ dest_lid = cl_hton16( dest_lid_ho );\r
+\r
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );\r
+ p_physp = osm_port_get_default_phys_ptr( p_src_port );\r
+ p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+ mtu = ib_port_info_get_mtu_cap( p_pi );\r
+ rate = ib_port_info_compute_rate( p_pi );\r
+\r
+ /* \r
+ Mellanox Tavor device performance is better using 1K MTU.\r
+ If required MTU and MTU selector are such that 1K is OK \r
+ and at least one end of the path is Tavor we override the\r
+ port MTU with 1K.\r
+ */\r
+ if ( p_rcv->p_subn->opt.enable_quirks &&\r
+ __osm_sa_path_rec_apply_tavor_mtu_limit(\r
+ p_pr, p_src_port, p_dest_port, comp_mask) )\r
+ if (mtu > IB_MTU_LEN_1024) \r
+ {\r
+ mtu = IB_MTU_LEN_1024;\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "Optimized Path MTU to 1K for Mellanox Tavor device\n");\r
+ }\r
+\r
+ /*\r
+ Walk the subnet object from source to destination,\r
+ tracking the most restrictive rate and mtu values along the way...\r
+\r
+ If source port node is a switch, then p_physp should\r
+ point to the port that routes the destination lid\r
+ */\r
+\r
+ p_node = osm_physp_get_node_ptr( p_physp );\r
+\r
+ if( p_node->sw )\r
+ {\r
+ /*\r
+ * If the dest_lid_ho is equal to the lid of the switch pointed by\r
+ * p_sw then p_physp will be the physical port of the switch port zero.\r
+ */\r
+ p_physp = osm_switch_get_route_by_lid(p_node->sw, cl_ntoh16( dest_lid_ho ) );\r
+ if ( p_physp == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F02: "\r
+ "Cannot find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+ dest_lid_ho,\r
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Same as above\r
+ */\r
+ p_node = osm_physp_get_node_ptr( p_dest_physp );\r
+\r
+ if( p_node->sw )\r
+ {\r
+ p_dest_physp = osm_switch_get_route_by_lid( p_node->sw, cl_ntoh16( dest_lid_ho ) );\r
+\r
+ if ( p_dest_physp == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F03: "\r
+ "Cannot find routing to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+ dest_lid_ho,\r
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ }\r
+\r
+ while( p_physp != p_dest_physp )\r
+ {\r
+ p_physp = osm_physp_get_remote( p_physp );\r
+\r
+ if ( p_physp == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F05: "\r
+ "Cannot find remote phys port when routing to LID 0x%X from node GUID 0x%016" PRIx64 "\n",\r
+ dest_lid_ho,\r
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ This is point to point case (no switch in between)\r
+ */\r
+ if( p_physp == p_dest_physp )\r
+ break;\r
+\r
+ p_node = osm_physp_get_node_ptr( p_physp );\r
+\r
+ if( !p_node->sw )\r
+ {\r
+ /*\r
+ There is some sort of problem in the subnet object!\r
+ If this isn't a switch, we should have reached\r
+ the destination by now!\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F06: "\r
+ "Internal error, bad path\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ Check parameters for the ingress port in this switch.\r
+ */\r
+ p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+ {\r
+ mtu = ib_port_info_get_mtu_cap( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64\r
+ " port num 0x%X\n",\r
+ mtu,\r
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+ osm_physp_get_port_num( p_physp ) );\r
+ }\r
+ }\r
+\r
+ if( rate > ib_port_info_compute_rate( p_pi ) )\r
+ {\r
+ rate = ib_port_info_compute_rate( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest rate = %u at intervening port 0x%016" PRIx64\r
+ " port num 0x%X\n",\r
+ rate,\r
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+ osm_physp_get_port_num( p_physp ) );\r
+ }\r
+ }\r
+\r
+ /*\r
+ Continue with the egress port on this switch.\r
+ */\r
+ p_physp = osm_switch_get_route_by_lid( p_node->sw, dest_lid );\r
+\r
+ if ( p_physp == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F07: "\r
+ "Dead end on path to LID 0x%X from switch for GUID 0x%016" PRIx64 "\n",\r
+ dest_lid_ho,\r
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ CL_ASSERT( p_physp );\r
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );\r
+\r
+ p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+ {\r
+ mtu = ib_port_info_get_mtu_cap( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest MTU = %u at intervening port 0x%016" PRIx64\r
+ " port num 0x%X\n",\r
+ mtu,\r
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+ osm_physp_get_port_num( p_physp ) );\r
+ }\r
+ }\r
+\r
+ if( rate > ib_port_info_compute_rate( p_pi ) )\r
+ {\r
+ rate = ib_port_info_compute_rate( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest rate = %u at intervening port 0x%016" PRIx64\r
+ " port num 0x%X\n",\r
+ rate,\r
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),\r
+ osm_physp_get_port_num( p_physp ) );\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ /*\r
+ p_physp now points to the destination\r
+ */\r
+ p_pi = osm_physp_get_port_info_ptr( p_physp );\r
+\r
+ if( mtu > ib_port_info_get_mtu_cap( p_pi ) )\r
+ {\r
+ mtu = ib_port_info_get_mtu_cap( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest MTU = %u at destination port 0x%016" PRIx64 "\n",\r
+ mtu,\r
+ cl_ntoh64(osm_physp_get_port_guid( p_physp )) );\r
+ }\r
+ }\r
+\r
+ if( rate > ib_port_info_compute_rate( p_pi ) )\r
+ {\r
+ rate = ib_port_info_compute_rate( p_pi );\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "New smallest rate = %u at destination port 0x%016" PRIx64 "\n",\r
+ rate,\r
+ cl_ntoh64(osm_physp_get_port_guid( p_physp )) );\r
+ }\r
+ }\r
+\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_path_parms: "\r
+ "Path min MTU = %u, min rate = %u\n", mtu, rate );\r
+ }\r
+\r
+ /*\r
+ Determine if these values meet the user criteria\r
+ and adjust appropriately\r
+ */\r
+\r
+ /* we silently ignore cases where only the MTU selector is defined */\r
+ if ( ( comp_mask & IB_PR_COMPMASK_MTUSELEC ) &&\r
+ ( comp_mask & IB_PR_COMPMASK_MTU ) )\r
+ {\r
+ required_mtu = ib_path_rec_mtu( p_pr );\r
+ switch( ib_path_rec_mtu_sel( p_pr ) )\r
+ {\r
+ case 0: /* must be greater than */\r
+ if( mtu <= required_mtu )\r
+ status = IB_NOT_FOUND;\r
+ break;\r
+\r
+ case 1: /* must be less than */\r
+ if( mtu >= required_mtu )\r
+ {\r
+ /* adjust to use the highest mtu\r
+ lower then the required one */\r
+ if( required_mtu > 1 )\r
+ mtu = required_mtu - 1;\r
+ else\r
+ status = IB_NOT_FOUND;\r
+ }\r
+ break;\r
+\r
+ case 2: /* exact match */\r
+ if( mtu < required_mtu )\r
+ status = IB_NOT_FOUND;\r
+ else\r
+ mtu = required_mtu;\r
+ break;\r
+\r
+ case 3: /* largest available */\r
+ /* can't be disqualified by this one */\r
+ break;\r
+\r
+ default:\r
+ /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+ CL_ASSERT( FALSE );\r
+ status = IB_ERROR;\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* we silently ignore cases where only the Rate selector is defined */\r
+ if ( ( comp_mask & IB_PR_COMPMASK_RATESELEC ) &&\r
+ ( comp_mask & IB_PR_COMPMASK_RATE ) )\r
+ {\r
+ required_rate = ib_path_rec_rate( p_pr );\r
+ switch( ib_path_rec_rate_sel( p_pr ) )\r
+ {\r
+ case 0: /* must be greater than */\r
+ if( rate <= required_rate )\r
+ status = IB_NOT_FOUND;\r
+ break;\r
+\r
+ case 1: /* must be less than */\r
+ if( rate >= required_rate )\r
+ {\r
+ /* adjust the rate to use the highest rate\r
+ lower then the required one */\r
+ if( required_rate > 2 )\r
+ rate = required_rate - 1;\r
+ else\r
+ status = IB_NOT_FOUND;\r
+ }\r
+ break;\r
+\r
+ case 2: /* exact match */\r
+ if( rate < required_rate )\r
+ status = IB_NOT_FOUND;\r
+ else\r
+ rate = required_rate;\r
+ break;\r
+\r
+ case 3: /* largest available */\r
+ /* can't be disqualified by this one */\r
+ break;\r
+\r
+ default:\r
+ /* if we're here, there's a bug in ib_path_rec_mtu_sel() */\r
+ CL_ASSERT( FALSE );\r
+ status = IB_ERROR;\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* Verify the pkt_life_time */\r
+ /* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,\r
+ for loopback paths, packetLifeTime shall be zero. */\r
+ if ( p_src_port == p_dest_port )\r
+ pkt_life = 0; /* loopback */\r
+ else\r
+ pkt_life = OSM_DEFAULT_SUBNET_TIMEOUT;\r
+\r
+ /* we silently ignore cases where only the PktLife selector is defined */\r
+ if ( ( comp_mask & IB_PR_COMPMASK_PKTLIFETIMESELEC ) &&\r
+ ( comp_mask & IB_PR_COMPMASK_PKTLIFETIME ) )\r
+ {\r
+ required_pkt_life = ib_path_rec_pkt_life( p_pr );\r
+ switch( ib_path_rec_pkt_life_sel( p_pr ) )\r
+ {\r
+ case 0: /* must be greater than */\r
+ if( pkt_life <= required_pkt_life )\r
+ status = IB_NOT_FOUND;\r
+ break;\r
+\r
+ case 1: /* must be less than */\r
+ if( pkt_life >= required_pkt_life )\r
+ {\r
+ /* adjust the lifetime to use the highest possible\r
+ lower then the required one */\r
+ if( required_pkt_life > 1 )\r
+ pkt_life = required_pkt_life - 1;\r
+ else\r
+ status = IB_NOT_FOUND;\r
+ }\r
+ break;\r
+\r
+ case 2: /* exact match */\r
+ if( pkt_life < required_pkt_life )\r
+ status = IB_NOT_FOUND;\r
+ else\r
+ pkt_life = required_pkt_life;\r
+ break;\r
+\r
+ case 3: /* smallest available */\r
+ /* can't be disqualified by this one */\r
+ break;\r
+\r
+ default:\r
+ /* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */\r
+ CL_ASSERT( FALSE );\r
+ status = IB_ERROR;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (status != IB_SUCCESS)\r
+ goto Exit;\r
+\r
+ p_parms->mtu = mtu;\r
+ p_parms->rate = rate;\r
+ p_parms->pkt_life = pkt_life;\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&\r
+ cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) )\r
+ pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );\r
+ else if( comp_mask & IB_PR_COMPMASK_PKEY )\r
+ {\r
+ pkey = p_pr->pkey;\r
+ if( !osm_physp_share_this_pkey( p_physp, p_dest_physp, pkey ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F1A: "\r
+ "Ports do not share specified PKey 0x%04x\n", cl_ntoh16(pkey));\r
+ status = IB_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ pkey = osm_physp_find_common_pkey( p_physp, p_dest_physp );\r
+ if ( !pkey )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F1B: "\r
+ "Ports do not have any shared PKeys\n");\r
+ status = IB_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ sl = OSM_DEFAULT_SL;\r
+\r
+ if (pkey) {\r
+ p_prtn = (osm_prtn_t *)cl_qmap_get(&p_rcv->p_subn->prtn_pkey_tbl,\r
+ pkey & cl_ntoh16((uint16_t)~0x8000));\r
+ if ( p_prtn == (osm_prtn_t *)cl_qmap_end(&p_rcv->p_subn->prtn_pkey_tbl) )\r
+ {\r
+ /* this may be possible when pkey tables are created somehow in\r
+ previous runs or things are going wrong here */\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_path_parms: ERR 1F1C: "\r
+ "No partition found for PKey 0x%04x - using default SL %d\n",\r
+ cl_ntoh16(pkey), sl );\r
+ }\r
+ else\r
+ sl = p_prtn->sl;\r
+\r
+ /* reset pkey when raw traffic */\r
+ if( comp_mask & IB_PR_COMPMASK_RAWTRAFFIC &&\r
+ cl_ntoh32( p_pr->hop_flow_raw ) & ( 1<<31 ) )\r
+ pkey = 0;\r
+ }\r
+\r
+ if ( ( comp_mask & IB_PR_COMPMASK_SL ) && ib_path_rec_sl( p_pr ) != sl )\r
+ {\r
+ status = IB_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+\r
+ p_parms->pkey = pkey;\r
+ p_parms->sl = sl;\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_build_pr(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const uint16_t src_lid_ho,\r
+ IN const uint16_t dest_lid_ho,\r
+ IN const uint8_t preference,\r
+ IN const osm_path_parms_t* const p_parms,\r
+ OUT ib_path_rec_t* const p_pr )\r
+{\r
+ const osm_physp_t* p_src_physp;\r
+ const osm_physp_t* p_dest_physp;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_build_pr );\r
+\r
+ p_src_physp = osm_port_get_default_phys_ptr( p_src_port );\r
+ p_dest_physp = osm_port_get_default_phys_ptr( p_dest_port );\r
+\r
+ p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix( p_dest_physp );\r
+ p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid( p_dest_physp );\r
+\r
+ p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix( p_src_physp );\r
+ p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid( p_src_physp );\r
+\r
+ p_pr->dlid = cl_hton16( dest_lid_ho );\r
+ p_pr->slid = cl_hton16( src_lid_ho );\r
+\r
+ p_pr->hop_flow_raw &= cl_hton32(1<<31);\r
+\r
+ p_pr->pkey = p_parms->pkey;\r
+ p_pr->qos_class_sl = cl_hton16(p_parms->sl);\r
+ p_pr->mtu = (uint8_t)(p_parms->mtu | 0x80);\r
+ p_pr->rate = (uint8_t)(p_parms->rate | 0x80);\r
+\r
+ /* According to 1.2 spec definition Table 205 PacketLifeTime description,\r
+ for loopback paths, packetLifeTime shall be zero. */\r
+ if ( p_src_port == p_dest_port )\r
+ p_pr->pkt_life = 0x80; /* loopback */\r
+ else\r
+ p_pr->pkt_life = (uint8_t)(p_parms->pkt_life | 0x80);\r
+\r
+ p_pr->preference = preference;\r
+\r
+ /* always return num_path = 0 so this is only the reversible component */\r
+ if (p_parms->reversible)\r
+ p_pr->num_path = 0x80;\r
+\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static osm_pr_item_t*\r
+__osm_pr_rcv_get_lid_pair_path(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const ib_path_rec_t* const p_pr,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const uint16_t src_lid_ho,\r
+ IN const uint16_t dest_lid_ho,\r
+ IN const ib_net64_t comp_mask,\r
+ IN const uint8_t preference )\r
+{\r
+ osm_path_parms_t path_parms;\r
+ osm_path_parms_t rev_path_parms;\r
+ osm_pr_item_t *p_pr_item;\r
+ ib_api_status_t status, rev_path_status;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_lid_pair_path );\r
+\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_lid_pair_path: "\r
+ "Src LID 0x%X, Dest LID 0x%X\n",\r
+ src_lid_ho, dest_lid_ho );\r
+ }\r
+\r
+ p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );\r
+ if( p_pr_item == NULL )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_lid_pair_path: ERR 1F01: "\r
+ "Unable to allocate path record\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, p_src_port,\r
+ p_dest_port, dest_lid_ho,\r
+ comp_mask, &path_parms );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+ p_pr_item = NULL;\r
+ goto Exit;\r
+ }\r
+\r
+ /* now try the reversible path */\r
+ rev_path_status = __osm_pr_rcv_get_path_parms( p_rcv, p_pr, p_dest_port,\r
+ p_src_port, src_lid_ho,\r
+ comp_mask, &rev_path_parms );\r
+ path_parms.reversible = ( rev_path_status == IB_SUCCESS );\r
+\r
+ /* did we get a Reversible Path compmask ? */\r
+ /* \r
+ NOTE that if the reversible component = 0, it is a don't care\r
+ rather then requiring non-reversible paths ... \r
+ see Vol1 Ver1.2 p900 l16\r
+ */\r
+ if( comp_mask & IB_PR_COMPMASK_REVERSIBLE )\r
+ {\r
+ if( (! path_parms.reversible && ( p_pr->num_path & 0x80 ) ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_lid_pair_path: "\r
+ "Requested reversible path but failed to get one\n");\r
+\r
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+ p_pr_item = NULL;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ __osm_pr_rcv_build_pr( p_rcv, p_src_port, p_dest_port, src_lid_ho,\r
+ dest_lid_ho, preference, &path_parms,\r
+ &p_pr_item->path_rec );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( p_pr_item );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_get_port_pair_paths(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN const osm_port_t* const p_req_port,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const ib_net64_t comp_mask,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ const ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ osm_pr_item_t* p_pr_item;\r
+ uint16_t src_lid_min_ho;\r
+ uint16_t src_lid_max_ho;\r
+ uint16_t dest_lid_min_ho;\r
+ uint16_t dest_lid_max_ho;\r
+ uint16_t src_lid_ho;\r
+ uint16_t dest_lid_ho;\r
+ uint32_t path_num;\r
+ uint8_t preference;\r
+ uintn_t iterations;\r
+ uintn_t src_offset;\r
+ uintn_t dest_offset;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_port_pair_paths );\r
+\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_port_pair_paths: "\r
+ "Src port 0x%016" PRIx64 ", "\r
+ "Dst port 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( osm_port_get_guid( p_src_port ) ),\r
+ cl_ntoh64( osm_port_get_guid( p_dest_port ) ) );\r
+ }\r
+\r
+ /* Check that the req_port, src_port and dest_port all share a\r
+ pkey. The check is done on the default physical port of the ports. */\r
+ if (osm_port_share_pkey(p_rcv->p_log, p_req_port, p_src_port) == FALSE ||\r
+ osm_port_share_pkey(p_rcv->p_log, p_req_port, p_dest_port) == FALSE ||\r
+ osm_port_share_pkey(p_rcv->p_log, p_src_port, p_dest_port) == FALSE )\r
+ {\r
+ /* One of the pairs doesn't share a pkey so the path is disqualified. */\r
+ goto Exit;\r
+ }\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ /*\r
+ We shouldn't be here if the paths are disqualified in some way...\r
+ Thus, we assume every possible connection is valid.\r
+\r
+ We desire to return high-quality paths first.\r
+ In OpenSM, higher quality means least overlap with other paths.\r
+ This is acheived in practice by returning paths with\r
+ different LID value on each end, which means these\r
+ paths are more redundant that paths with the same LID repeated\r
+ on one side. For example, in OpenSM the paths between two\r
+ endpoints with LMC = 1 might be as follows:\r
+\r
+ Port A, LID 1 <-> Port B, LID 3\r
+ Port A, LID 1 <-> Port B, LID 4\r
+ Port A, LID 2 <-> Port B, LID 3\r
+ Port A, LID 2 <-> Port B, LID 4\r
+\r
+ The OpenSM unicast routing algorithms attempt to disperse each path\r
+ to as varied a physical path as is reasonable. 1<->3 and 1<->4 have\r
+ more physical overlap (hence less redundancy) than 1<->3 and 2<->4.\r
+\r
+ OpenSM ranks paths in three preference groups:\r
+\r
+ Preference Value Description\r
+ ---------------- -------------------------------------------\r
+ 0 Redundant in both directions with other\r
+ pref value = 0 paths\r
+\r
+ 1 Redundant in one direction with other\r
+ pref value = 0 and pref value = 1 paths\r
+\r
+ 2 Not redundant in either direction with\r
+ other paths\r
+\r
+ 3-FF Unused\r
+\r
+\r
+ SA clients don't need to know these details, only that the lower\r
+ preference paths are preferred, as stated in the spec. The paths\r
+ may not actually be physically redundant depending on the topology\r
+ of the subnet, but the point of LMC > 0 is to offer redundancy,\r
+ so it is assumed that the subnet is physically appropriate for the\r
+ specified LMC value. A more advanced implementation would inspect for \r
+ physical redundancy, but I'm not going to bother with that now.\r
+ */\r
+\r
+ /*\r
+ Refine our search if the client specified end-point LIDs\r
+ */\r
+ if( comp_mask & IB_PR_COMPMASK_DLID )\r
+ {\r
+ dest_lid_min_ho = cl_ntoh16( p_pr->dlid );\r
+ dest_lid_max_ho = cl_ntoh16( p_pr->dlid );\r
+ }\r
+ else\r
+ {\r
+ osm_port_get_lid_range_ho( p_dest_port, &dest_lid_min_ho,\r
+ &dest_lid_max_ho );\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_SLID )\r
+ {\r
+ src_lid_min_ho = cl_ntoh16( p_pr->slid );\r
+ src_lid_max_ho = cl_ntoh16( p_pr->slid );\r
+ }\r
+ else\r
+ {\r
+ osm_port_get_lid_range_ho( p_src_port, &src_lid_min_ho,\r
+ &src_lid_max_ho );\r
+ }\r
+\r
+ if ( src_lid_min_ho == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_port_pair_paths: ERR 1F20:"\r
+ "Obtained source LID of 0. No such LID possible\n");\r
+ goto Exit;\r
+ }\r
+\r
+ if ( dest_lid_min_ho == 0 )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_get_port_pair_paths: ERR 1F21:"\r
+ "Obtained destination LID of 0. No such LID possible\n");\r
+ goto Exit;\r
+ }\r
+\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_get_port_pair_paths: "\r
+ "Src LIDs [0x%X-0x%X], "\r
+ "Dest LIDs [0x%X-0x%X]\n",\r
+ src_lid_min_ho, src_lid_max_ho,\r
+ dest_lid_min_ho, dest_lid_max_ho );\r
+ }\r
+\r
+ src_lid_ho = src_lid_min_ho;\r
+ dest_lid_ho = dest_lid_min_ho;\r
+\r
+ /*\r
+ Preferred paths come first in OpenSM\r
+ */\r
+ preference = 0;\r
+ path_num = 0;\r
+\r
+ /* If SubnAdmGet, assume NumbPaths 1 (1.2 erratum) */\r
+ if( p_sa_mad->method != IB_MAD_METHOD_GET )\r
+ if( comp_mask & IB_PR_COMPMASK_NUMBPATH )\r
+ iterations = ib_path_rec_num_path( p_pr );\r
+ else\r
+ iterations = (uintn_t)(-1);\r
+ else\r
+ iterations = 1;\r
+\r
+ while( path_num < iterations )\r
+ {\r
+ /*\r
+ These paths are "fully redundant"\r
+ */\r
+\r
+ p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,\r
+ p_src_port, p_dest_port,\r
+ src_lid_ho, dest_lid_ho,\r
+ comp_mask, preference );\r
+\r
+ if( p_pr_item )\r
+ {\r
+ cl_qlist_insert_tail( p_list,\r
+ (cl_list_item_t*)&p_pr_item->pool_item );\r
+ ++path_num;\r
+ }\r
+\r
+ if( ++src_lid_ho > src_lid_max_ho )\r
+ break;\r
+\r
+ if( ++dest_lid_ho > dest_lid_max_ho )\r
+ break;\r
+ }\r
+\r
+ /*\r
+ Check if we've accumulated all the paths that the user cares to see\r
+ */\r
+ if( path_num == iterations )\r
+ goto Exit;\r
+\r
+ /*\r
+ Don't bother reporting preference 1 paths for now.\r
+ It's more trouble than it's worth and can only occur\r
+ if ports have different LMC values, which isn't supported\r
+ by OpenSM right now anyway.\r
+ */\r
+ preference = 2;\r
+ src_lid_ho = src_lid_min_ho;\r
+ dest_lid_ho = dest_lid_min_ho;\r
+ src_offset = 0;\r
+ dest_offset = 0;\r
+\r
+ /*\r
+ Iterate over the remaining paths\r
+ */\r
+ while( path_num < iterations )\r
+ {\r
+ dest_offset++;\r
+ dest_lid_ho++;\r
+\r
+ if( dest_lid_ho > dest_lid_max_ho )\r
+ {\r
+ src_offset++;\r
+ src_lid_ho++;\r
+\r
+ if( src_lid_ho > src_lid_max_ho )\r
+ break; /* done */\r
+\r
+ dest_offset = 0;\r
+ dest_lid_ho = dest_lid_min_ho;\r
+ }\r
+\r
+ /*\r
+ These paths are "fully non-redundant" with paths already\r
+ identified above and consequently not of much value.\r
+\r
+ Don't return paths we already identified above, as indicated\r
+ by the offset values being equal.\r
+ */\r
+ if( src_offset == dest_offset )\r
+ continue; /* already reported */\r
+\r
+ p_pr_item = __osm_pr_rcv_get_lid_pair_path( p_rcv, p_pr,\r
+ p_src_port, p_dest_port,\r
+ src_lid_ho, dest_lid_ho,\r
+ comp_mask, preference );\r
+\r
+ if( p_pr_item )\r
+ {\r
+ cl_qlist_insert_tail( p_list,\r
+ (cl_list_item_t*)&p_pr_item->pool_item );\r
+ ++path_num;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_net16_t\r
+__osm_pr_rcv_get_end_points(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ OUT const osm_port_t** const pp_src_port,\r
+ OUT const osm_port_t** const pp_dest_port )\r
+{\r
+ const ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ ib_net64_t comp_mask;\r
+ ib_api_status_t status;\r
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_get_end_points );\r
+\r
+ /*\r
+ Determine what fields are valid and then get a pointer\r
+ to the source and destination port objects, if possible.\r
+ */\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ comp_mask = p_sa_mad->comp_mask;\r
+\r
+ /*\r
+ Check a few easy disqualifying cases up front before getting\r
+ into the endpoints.\r
+ */\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_SGID )\r
+ {\r
+ if ( ! ib_gid_is_link_local ( &p_pr->sgid ) )\r
+ {\r
+ if ( ib_gid_get_subnet_prefix ( &p_pr->sgid ) != p_rcv->p_subn->opt.subnet_prefix )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad gid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "Non local SGID subnet prefix 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pr->sgid.unicast.prefix ) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ *pp_src_port = (osm_port_t*)cl_qmap_get(\r
+ &p_rcv->p_subn->port_guid_tbl,\r
+ p_pr->sgid.unicast.interface_id );\r
+\r
+ if( *pp_src_port == (osm_port_t*)cl_qmap_end(\r
+ &p_rcv->p_subn->port_guid_tbl ) )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad gid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "No source port with GUID 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pr->sgid.unicast.interface_id) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *pp_src_port = 0;\r
+ if( comp_mask & IB_PR_COMPMASK_SLID )\r
+ {\r
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,\r
+ cl_ntoh16(p_pr->slid), (void**)pp_src_port );\r
+\r
+ if( (status != CL_SUCCESS) || (*pp_src_port == NULL) )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad lid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "No source port with LID = 0x%X\n",\r
+ cl_ntoh16( p_pr->slid) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;\r
+ goto Exit;\r
+ }\r
+ }\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_DGID )\r
+ {\r
+ if ( ! ib_gid_is_link_local ( &p_pr->dgid ) )\r
+ {\r
+ if ( ! ib_gid_is_multicast ( &p_pr->dgid ) &&\r
+ ib_gid_get_subnet_prefix ( &p_pr->dgid ) != p_rcv->p_subn->opt.subnet_prefix )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad gid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "Non local DGID subnet prefix 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pr->dgid.unicast.prefix ) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ *pp_dest_port = (osm_port_t*)cl_qmap_get(\r
+ &p_rcv->p_subn->port_guid_tbl,\r
+ p_pr->dgid.unicast.interface_id );\r
+\r
+ if( *pp_dest_port == (osm_port_t*)cl_qmap_end(\r
+ &p_rcv->p_subn->port_guid_tbl ) )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad gid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "No dest port with GUID 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pr->dgid.unicast.interface_id) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_INVALID_GID;\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *pp_dest_port = 0;\r
+ if( comp_mask & IB_PR_COMPMASK_DLID )\r
+ {\r
+ status = cl_ptr_vector_at( &p_rcv->p_subn->port_lid_tbl,\r
+ cl_ntoh16(p_pr->dlid), (void**)pp_dest_port );\r
+\r
+ if( (status != CL_SUCCESS) || (*pp_dest_port == NULL) )\r
+ {\r
+ /*\r
+ This 'error' is the client's fault (bad lid) so\r
+ don't enter it as an error in our own log.\r
+ Return an error response to the client.\r
+ */\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_get_end_points: "\r
+ "No dest port with LID = 0x%X\n",\r
+ cl_ntoh16( p_pr->dlid) );\r
+\r
+ sa_status = IB_SA_MAD_STATUS_NO_RECORDS;\r
+ goto Exit;\r
+ }\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( sa_status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_world(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN const osm_port_t* const requester_port,\r
+ IN const ib_net64_t comp_mask,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ const cl_qmap_t* p_tbl;\r
+ const osm_port_t* p_dest_port;\r
+ const osm_port_t* p_src_port;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_world );\r
+\r
+ /*\r
+ Iterate the entire port space over itself.\r
+ A path record from a port to itself is legit, so no\r
+ need for a special case there.\r
+\r
+ We compute both A -> B and B -> A, since we don't have\r
+ any check to determine the reversability of the paths.\r
+ */\r
+ p_tbl = &p_rcv->p_subn->port_guid_tbl;\r
+\r
+ p_dest_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+ while( p_dest_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+ {\r
+ p_src_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+ while( p_src_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+ {\r
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_src_port,\r
+ p_dest_port, comp_mask, p_list );\r
+\r
+ p_src_port = (osm_port_t*)cl_qmap_next( &p_src_port->map_item );\r
+ }\r
+\r
+ p_dest_port = (osm_port_t*)cl_qmap_next( &p_dest_port->map_item );\r
+ }\r
+\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_half(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN const osm_port_t* const requester_port,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const ib_net64_t comp_mask,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ const cl_qmap_t* p_tbl;\r
+ const osm_port_t* p_port;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_half );\r
+\r
+ /*\r
+ Iterate over every port, looking for matches...\r
+ A path record from a port to itself is legit, so no\r
+ need to special case that one.\r
+ */\r
+ p_tbl = &p_rcv->p_subn->port_guid_tbl;\r
+\r
+ if( p_src_port )\r
+ {\r
+ /*\r
+ The src port if fixed, so iterate over destination ports.\r
+ */\r
+ p_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+ while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+ {\r
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw , requester_port, p_src_port,\r
+ p_port, comp_mask, p_list );\r
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ The dest port if fixed, so iterate over source ports.\r
+ */\r
+ p_port = (osm_port_t*)cl_qmap_head( p_tbl );\r
+ while( p_port != (osm_port_t*)cl_qmap_end( p_tbl ) )\r
+ {\r
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_port,\r
+ p_dest_port, comp_mask, p_list );\r
+ p_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );\r
+ }\r
+ }\r
+\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_process_pair(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN const osm_port_t* const requester_port,\r
+ IN const osm_port_t* const p_src_port,\r
+ IN const osm_port_t* const p_dest_port,\r
+ IN const ib_net64_t comp_mask,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_process_pair );\r
+\r
+ __osm_pr_rcv_get_port_pair_paths( p_rcv, p_madw, requester_port, p_src_port,\r
+ p_dest_port, comp_mask, p_list );\r
+\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ *********************************************************************/\r
+static void\r
+__search_mgrp_by_mgid(\r
+ IN cl_map_item_t* const p_map_item,\r
+ IN void* context )\r
+{\r
+ osm_mgrp_t* p_mgrp = (osm_mgrp_t*)p_map_item;\r
+ osm_sa_pr_mcmr_search_ctxt_t *p_ctxt = (osm_sa_pr_mcmr_search_ctxt_t *) context;\r
+ const ib_gid_t *p_recvd_mgid;\r
+ osm_pr_rcv_t *p_rcv;\r
+ /* uint32_t i; */\r
+\r
+ p_recvd_mgid = p_ctxt->p_mgid;\r
+ p_rcv = p_ctxt->p_rcv;\r
+\r
+ /* ignore groups marked for deletion */\r
+ if ( p_mgrp->to_be_deleted )\r
+ return;\r
+\r
+ /* compare entire MGID so different scope will not sneak in for\r
+ the same MGID */\r
+ if ( memcmp( &p_mgrp->mcmember_rec.mgid,\r
+ p_recvd_mgid,\r
+ sizeof(ib_gid_t) ) )\r
+ return;\r
+\r
+#if 0\r
+ for ( i = 0 ; i < sizeof(p_mgrp->mcmember_rec.mgid.multicast.raw_group_id); i++)\r
+ {\r
+ if ( p_mgrp->mcmember_rec.mgid.multicast.raw_group_id[i] !=\r
+ p_recvd_mgid->mgid.multicast.raw_group_id[i] )\r
+ return;\r
+ }\r
+#endif\r
+\r
+ if( p_ctxt->p_mgrp )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__search_mgrp_by_mgid: ERR 1F08: "\r
+ "Multiple MC groups for same MGID\n" );\r
+ return;\r
+ }\r
+ p_ctxt->p_mgrp = p_mgrp;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__get_mgrp_by_mgid(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN ib_path_rec_t* p_recvd_path_rec,\r
+ OUT osm_mgrp_t ** pp_mgrp )\r
+{\r
+ osm_sa_pr_mcmr_search_ctxt_t mcmr_search_context;\r
+\r
+ mcmr_search_context.p_mgid = &p_recvd_path_rec->dgid;\r
+ mcmr_search_context.p_rcv = p_rcv;\r
+ mcmr_search_context.p_mgrp = NULL;\r
+\r
+ cl_qmap_apply_func( &p_rcv->p_subn->mgrp_mlid_tbl,\r
+ __search_mgrp_by_mgid,\r
+ &mcmr_search_context);\r
+\r
+ if( mcmr_search_context.p_mgrp == NULL )\r
+ {\r
+ return IB_NOT_FOUND;\r
+ }\r
+\r
+ *pp_mgrp = mcmr_search_context.p_mgrp;\r
+ return IB_SUCCESS;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static osm_mgrp_t *\r
+__get_mgrp_by_mlid(\r
+ IN const osm_pr_rcv_t* const p_rcv,\r
+ IN ib_net16_t const mlid )\r
+{\r
+ cl_map_item_t * map_item;\r
+\r
+ map_item = cl_qmap_get( &p_rcv->p_subn->mgrp_mlid_tbl, mlid );\r
+\r
+ if( map_item == cl_qmap_end(&p_rcv->p_subn->mgrp_mlid_tbl) )\r
+ {\r
+ return NULL;\r
+ }\r
+\r
+ return (osm_mgrp_t *)map_item;\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_get_mgrp(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ OUT osm_mgrp_t **pp_mgrp )\r
+{\r
+ ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ ib_net64_t comp_mask;\r
+ ib_api_status_t status;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_get_mgrp );\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ comp_mask = p_sa_mad->comp_mask;\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_DGID )\r
+ {\r
+ status = __get_mgrp_by_mgid( p_rcv, p_pr, pp_mgrp );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_get_mgrp: ERR 1F09: "\r
+ "No MC group found for PathRecord destination GID\n" );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_DLID )\r
+ {\r
+ if( *pp_mgrp)\r
+ {\r
+ /* check that the MLID in the MC group is */\r
+ /* the same as the DLID in the PathRecord */\r
+ if( (*pp_mgrp)->mlid != p_pr->dlid )\r
+ {\r
+ /* Note: perhaps this might be better indicated as an invalid request */\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_get_mgrp: ERR 1F10: "\r
+ "MC group MLID does not match PathRecord destination LID\n" );\r
+ *pp_mgrp = NULL;\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ *pp_mgrp = __get_mgrp_by_mlid( p_rcv, p_pr->dlid );\r
+ if( *pp_mgrp == NULL)\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_get_mgrp: ERR 1F11: "\r
+ "No MC group found for PathRecord destination LID\n" );\r
+ }\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+__osm_pr_match_mgrp_attributes(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN const osm_mgrp_t* const p_mgrp )\r
+{\r
+ const ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ ib_net64_t comp_mask;\r
+ ib_api_status_t status = IB_ERROR;\r
+ uint32_t flow_label;\r
+ uint8_t sl;\r
+ uint8_t hop_limit;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_match_mgrp_attributes );\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ comp_mask = p_sa_mad->comp_mask;\r
+\r
+ /* If SGID and/or SLID specified, should validate as member of MC group */\r
+ /* Also, MTU, rate, packet lifetime, and raw traffic requested are not currently checked */\r
+ if( comp_mask & IB_PR_COMPMASK_PKEY )\r
+ {\r
+ if( p_pr->pkey != p_mgrp->mcmember_rec.pkey )\r
+ goto Exit;\r
+ }\r
+\r
+ ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,\r
+ &sl, &flow_label, &hop_limit );\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_SL )\r
+ {\r
+ if( ib_path_rec_sl( p_pr ) != sl )\r
+ goto Exit;\r
+ }\r
+\r
+ /* If SubnAdmGet, assume NumbPaths of 1 (1.2 erratum) */\r
+ if( ( comp_mask & IB_PR_COMPMASK_NUMBPATH ) &&\r
+ ( p_sa_mad->method != IB_MAD_METHOD_GET ) )\r
+ {\r
+ if( ib_path_rec_num_path( p_pr ) == 0 )\r
+ goto Exit;\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_FLOWLABEL )\r
+ {\r
+ if( ib_path_rec_flow_lbl( p_pr ) != flow_label )\r
+ goto Exit;\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_HOPLIMIT )\r
+ {\r
+ if( ib_path_rec_hop_limit( p_pr ) != hop_limit )\r
+ goto Exit;\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_TCLASS )\r
+ {\r
+ if( p_pr->tclass != p_mgrp->mcmember_rec.tclass )\r
+ goto Exit;\r
+ }\r
+\r
+ status = IB_SUCCESS;\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static int\r
+__osm_pr_rcv_check_mcast_dest(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw )\r
+{\r
+ const ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ ib_net64_t comp_mask;\r
+ int is_multicast = 0;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_check_mcast_dest );\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ comp_mask = p_sa_mad->comp_mask;\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_DGID )\r
+ {\r
+ is_multicast = ib_gid_is_multicast( &p_pr->dgid );\r
+ if( !is_multicast )\r
+ goto Exit;\r
+ }\r
+\r
+ if( comp_mask & IB_PR_COMPMASK_DLID )\r
+ {\r
+ if( cl_ntoh16( p_pr->dlid ) >= IB_LID_MCAST_START_HO &&\r
+ cl_ntoh16( p_pr->dlid ) <= IB_LID_MCAST_END_HO )\r
+ is_multicast = 1;\r
+ else if( is_multicast )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_check_mcast_dest: ERR 1F12: "\r
+ "PathRecord request indicates MGID but not MLID\n" );\r
+ is_multicast = -1;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+ return( is_multicast );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+__osm_pr_rcv_respond(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw,\r
+ IN cl_qlist_t* const p_list )\r
+{\r
+ osm_madw_t* p_resp_madw;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ ib_sa_mad_t* p_resp_sa_mad;\r
+ size_t num_rec, pre_trim_num_rec;\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+ size_t trim_num_rec;\r
+#endif\r
+ ib_path_rec_t* p_resp_pr;\r
+ ib_api_status_t status;\r
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ osm_pr_item_t* p_pr_item;\r
+ uint32_t i;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pr_rcv_respond );\r
+\r
+ num_rec = cl_qlist_count( p_list );\r
+\r
+ /*\r
+ * C15-0.1.30:\r
+ * If we do a SubnAdmGet and got more than one record it is an error !\r
+ */\r
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)\r
+ {\r
+ if (num_rec == 0)\r
+ {\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );\r
+ goto Exit;\r
+ }\r
+ if (num_rec > 1)\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_respond: ERR 1F13: "\r
+ "Got more than one record for SubnAdmGet (%zu)\n",\r
+ num_rec );\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw,\r
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );\r
+ /* need to set the mem free ... */\r
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+ while( p_pr_item != (osm_pr_item_t*)cl_qlist_end( p_list ) )\r
+ {\r
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+ }\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ pre_trim_num_rec = num_rec;\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_path_rec_t);\r
+ if (trim_num_rec < num_rec)\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,\r
+ "__osm_pr_rcv_respond: "\r
+ "Number of records:%u trimmed to:%u to fit in one MAD\n",\r
+ num_rec,trim_num_rec );\r
+ num_rec = trim_num_rec;\r
+ }\r
+#endif\r
+\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "__osm_pr_rcv_respond: "\r
+ "Generating response with %zu records\n", num_rec );\r
+\r
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))\r
+ {\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper\r
+ */\r
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool, p_madw->h_bind,\r
+ num_rec * sizeof(ib_path_rec_t) + IB_SA_MAD_HDR_SIZE,\r
+ &p_madw->mad_addr );\r
+ if( !p_resp_madw )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_respond: ERR 1F14: "\r
+ "Unable to allocate MAD\n" );\r
+\r
+ for( i = 0; i < num_rec; i++ )\r
+ {\r
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+ }\r
+\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );\r
+ goto Exit;\r
+ }\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_resp_madw );\r
+\r
+ memcpy( p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE );\r
+ p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;\r
+ /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */\r
+ p_resp_sa_mad->sm_key = 0;\r
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */\r
+ p_resp_sa_mad->attr_offset = ib_get_attr_offset( sizeof(ib_path_rec_t) );\r
+\r
+ p_resp_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );\r
+\r
+#ifndef VENDOR_RMPP_SUPPORT\r
+ /* we support only one packet RMPP - so we will set the first and\r
+ last flags for gettable */\r
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)\r
+ {\r
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;\r
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | IB_RMPP_FLAG_ACTIVE;\r
+ }\r
+#else\r
+ /* forcefully define the packet as RMPP one */\r
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)\r
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;\r
+#endif\r
+\r
+ for ( i = 0; i < pre_trim_num_rec; i++ )\r
+ {\r
+ p_pr_item = (osm_pr_item_t*)cl_qlist_remove_head( p_list );\r
+ /* copy only if not trimmed */\r
+ if (i < num_rec)\r
+ *p_resp_pr = p_pr_item->path_rec;\r
+\r
+ cl_qlock_pool_put( &p_rcv->pr_pool, &p_pr_item->pool_item );\r
+ p_resp_pr++;\r
+ }\r
+\r
+ CL_ASSERT( cl_is_qlist_empty( p_list ) );\r
+\r
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "__osm_pr_rcv_respond: ERR 1F15: "\r
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );\r
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osm_pr_rcv_process(\r
+ IN osm_pr_rcv_t* const p_rcv,\r
+ IN const osm_madw_t* const p_madw )\r
+{\r
+ const ib_path_rec_t* p_pr;\r
+ const ib_sa_mad_t* p_sa_mad;\r
+ const osm_port_t* p_src_port;\r
+ const osm_port_t* p_dest_port;\r
+ cl_qlist_t pr_list;\r
+ ib_net16_t sa_status;\r
+ osm_port_t* requester_port;\r
+ int ret;\r
+\r
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pr_rcv_process );\r
+\r
+ CL_ASSERT( p_madw );\r
+\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+\r
+ CL_ASSERT( p_sa_mad->attr_id == IB_MAD_ATTR_PATH_RECORD );\r
+\r
+ /* we only support SubnAdmGet and SubnAdmGetTable methods */\r
+ if ((p_sa_mad->method != IB_MAD_METHOD_GET) &&\r
+ (p_sa_mad->method != IB_MAD_METHOD_GETTABLE)) {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "osm_pr_rcv_process: ERR 1F17: " \r
+ "Unsupported Method (%s)\n",\r
+ ib_get_sa_method_str( p_sa_mad->method ) );\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );\r
+ goto Exit;\r
+ }\r
+\r
+ /* update the requester physical port. */\r
+ requester_port = osm_get_port_by_mad_addr( p_rcv->p_log, p_rcv->p_subn,\r
+ osm_madw_get_mad_addr_ptr( p_madw ) );\r
+ if( requester_port == NULL )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "osm_pr_rcv_process: ERR 1F16: "\r
+ "Cannot find requester physical port\n" );\r
+ goto Exit;\r
+ }\r
+\r
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )\r
+ osm_dump_path_record( p_rcv->p_log, p_pr, OSM_LOG_DEBUG );\r
+\r
+ cl_qlist_init( &pr_list );\r
+\r
+ /*\r
+ Most SA functions (including this one) are read-only on the\r
+ subnet object, so we grab the lock non-exclusively.\r
+ */\r
+ cl_plock_acquire( p_rcv->p_lock );\r
+\r
+ /* Handle multicast destinations separately */\r
+ if( (ret = __osm_pr_rcv_check_mcast_dest( p_rcv, p_madw )) < 0 )\r
+ {\r
+ /* Multicast DGID with unicast DLID */\r
+ cl_plock_release( p_rcv->p_lock );\r
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_INVALID_FIELD );\r
+ goto Exit;\r
+ }\r
+\r
+ if(ret > 0)\r
+ goto McastDest;\r
+\r
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "osm_pr_rcv_process: "\r
+ "Unicast destination requested\n" );\r
+\r
+ sa_status = __osm_pr_rcv_get_end_points( p_rcv, p_madw,\r
+ &p_src_port, &p_dest_port );\r
+\r
+ if( sa_status == IB_SA_MAD_STATUS_SUCCESS )\r
+ {\r
+ /*\r
+ What happens next depends on the type of endpoint information\r
+ that was specified....\r
+ */\r
+ if( p_src_port )\r
+ {\r
+ if( p_dest_port )\r
+ __osm_pr_rcv_process_pair( p_rcv, p_madw, requester_port,\r
+ p_src_port, p_dest_port,\r
+ p_sa_mad->comp_mask, &pr_list );\r
+ else\r
+ __osm_pr_rcv_process_half( p_rcv, p_madw, requester_port,\r
+ p_src_port, NULL,\r
+ p_sa_mad->comp_mask, &pr_list );\r
+ }\r
+ else\r
+ {\r
+ if( p_dest_port )\r
+ __osm_pr_rcv_process_half( p_rcv, p_madw, requester_port,\r
+ NULL, p_dest_port,\r
+ p_sa_mad->comp_mask, &pr_list );\r
+ else\r
+ /*\r
+ Katie, bar the door!\r
+ */\r
+ __osm_pr_rcv_process_world( p_rcv, p_madw, requester_port,\r
+ p_sa_mad->comp_mask, &pr_list );\r
+ }\r
+ }\r
+ goto Unlock;\r
+\r
+ McastDest:\r
+ osm_log(p_rcv->p_log, OSM_LOG_DEBUG,\r
+ "osm_pr_rcv_process: "\r
+ "Multicast destination requested\n" );\r
+ {\r
+ osm_mgrp_t *p_mgrp = NULL;\r
+ ib_api_status_t status;\r
+ osm_pr_item_t* p_pr_item;\r
+ uint32_t flow_label;\r
+ uint8_t sl;\r
+ uint8_t hop_limit;\r
+\r
+ /* First, get the MC info */\r
+ __osm_pr_get_mgrp( p_rcv, p_madw, &p_mgrp );\r
+\r
+ if ( p_mgrp )\r
+ {\r
+ /* Make sure the rest of the PathRecord matches the MC group attributes */\r
+ status = __osm_pr_match_mgrp_attributes( p_rcv, p_madw, p_mgrp );\r
+ if ( status == IB_SUCCESS )\r
+ {\r
+ p_pr_item = (osm_pr_item_t*)cl_qlock_pool_get( &p_rcv->pr_pool );\r
+ if( p_pr_item == NULL )\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "osm_pr_rcv_process: ERR 1F18: "\r
+ "Unable to allocate path record for MC group\n" );\r
+ }\r
+ else\r
+ {\r
+ /* Copy PathRecord request into response */\r
+ p_sa_mad = osm_madw_get_sa_mad_ptr( p_madw );\r
+ p_pr = (ib_path_rec_t*)ib_sa_mad_get_payload_ptr( p_sa_mad );\r
+ p_pr_item->path_rec = *p_pr;\r
+\r
+ /* Now, use the MC info to cruft up the PathRecord response */ \r
+ p_pr_item->path_rec.dgid = p_mgrp->mcmember_rec.mgid;\r
+ p_pr_item->path_rec.dlid = p_mgrp->mcmember_rec.mlid;\r
+ p_pr_item->path_rec.tclass = p_mgrp->mcmember_rec.tclass;\r
+ p_pr_item->path_rec.num_path = 1;\r
+ p_pr_item->path_rec.pkey = p_mgrp->mcmember_rec.pkey;\r
+\r
+ /* MTU, rate, and packet lifetime should be exactly */\r
+ p_pr_item->path_rec.mtu = (2<<6) | p_mgrp->mcmember_rec.mtu;\r
+ p_pr_item->path_rec.rate = (2<<6) | p_mgrp->mcmember_rec.rate;\r
+ p_pr_item->path_rec.pkt_life = (2<<6) | p_mgrp->mcmember_rec.pkt_life;\r
+\r
+ /* SL, Hop Limit, and Flow Label */\r
+ ib_member_get_sl_flow_hop( p_mgrp->mcmember_rec.sl_flow_hop,\r
+ &sl, &flow_label, &hop_limit );\r
+ p_pr_item->path_rec.qos_class_sl = cl_hton16( sl );\r
+ p_pr_item->path_rec.hop_flow_raw = (uint32_t)(hop_limit) |\r
+ (flow_label << 8);\r
+\r
+ cl_qlist_insert_tail( &pr_list,\r
+ (cl_list_item_t*)&p_pr_item->pool_item );\r
+\r
+ }\r
+ }\r
+ else\r
+ {\r
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,\r
+ "osm_pr_rcv_process: ERR 1F19: "\r
+ "MC group attributes don't match PathRecord request\n" );\r
+ }\r
+ }\r
+ }\r
+\r
+ Unlock:\r
+ cl_plock_release( p_rcv->p_lock );\r
+\r
+ /* Now, (finally) respond to the PathRecord request */\r
+ __osm_pr_rcv_respond( p_rcv, p_madw, &pr_list );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( p_rcv->p_log );\r
+}\r
+\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_path_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pr_rcv_ctrl_t.
+ * This object represents the PathRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_path_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_pr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pr_rcv_process( ((osm_pr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_construct(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pr_rcv_ctrl_destroy(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pr_rcv_ctrl_init(
+ IN osm_pr_rcv_ctrl_t* const p_ctrl,
+ IN osm_pr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pr_rcv_ctrl_init );
+
+ osm_pr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PATH_RECORD,
+ __osm_pr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pr_rcv_ctrl_init: ERR 2001: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_pkey_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_pkey_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PKEY_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_PKEY_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_pkey_item
+{
+ cl_pool_item_t pool_item;
+ ib_pkey_table_record_t rec;
+} osm_pkey_item_t;
+
+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_pkey_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_pkey_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_construct(
+ IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_destroy(
+ IN osm_pkey_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_init(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_init );
+
+ osm_pkey_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_PKEY_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_PKEY_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_pkey_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_create(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN osm_pkey_search_ctxt_t* const p_ctxt,
+ IN uint16_t block )
+{
+ osm_pkey_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_create );
+
+ p_rec_item = (osm_pkey_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_pkey_create: ERR 4602: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_pkey_create: "
+ "New P_Key table for: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X 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->rec, 0, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.block_num = block;
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.pkey_tbl =
+ *(osm_pkey_tbl_block_get(osm_physp_get_pkey_tbl(p_physp), block));
+
+ cl_qlist_insert_tail( p_ctxt->p_list,
+ (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pkey_check_physp(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ osm_pkey_search_ctxt_t* const p_ctxt )
+{
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ uint16_t block, num_blocks;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pkey_check_physp );
+
+ /* we got here with the phys port - all is left is to get the right block */
+ if ( comp_mask & IB_PKEY_COMPMASK_BLOCK )
+ {
+ __osm_sa_pkey_create( p_rcv, 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++) {
+ __osm_sa_pkey_create( p_rcv, p_physp, p_ctxt, block );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_by_comp_mask(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_pkey_search_ctxt_t* const 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( p_rcv->p_log, __osm_sa_pkey_by_comp_mask );
+
+ 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->default_port_num;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_pkey_by_comp_mask: "
+ "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_port_get_num_physp( p_port ))
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, 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_is_valid( p_physp ) &&
+ (osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp)) )
+ __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_pkey_by_comp_mask: ERR 4603: "
+ "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+ port_num, osm_port_get_num_physp( p_port ));
+ goto Exit;
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requester and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+ continue;
+
+ __osm_sa_pkey_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pkey_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_pkey_search_ctxt_t* const p_ctxt = (osm_pkey_search_ctxt_t *)context;
+
+ __osm_sa_pkey_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_process(
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_pkey_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_pkey_table_t* p_pkey;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_pkey_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_pkey_search_ctxt_t context;
+ osm_pkey_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pkey_rec_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4605: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, 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 != p_rcv->p_subn->opt.sm_key )
+ {
+ /* This is not a trusted requester! */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process ERR 4608: "
+ "Request from non-trusted requester: "
+ "Given SM_Key:0x%016" PRIx64 "\n",
+ cl_ntoh64(p_rcvd_mad->sm_key) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_REQ_INVALID );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4604: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ p_pkey = (ib_pkey_table_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.p_rcv = p_rcv;
+ context.block_num = p_rcvd_rec->block_num;
+ context.p_req_physp = p_req_physp;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pkey_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%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,
+ p_rcvd_rec->block_num, (comp_mask & IB_PKEY_COMPMASK_BLOCK) != 0 );
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /*
+ 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_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+ if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 460B: "
+ "No port found with LID 0x%x\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 */
+ __osm_sa_pkey_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_pkey_by_comp_mask_cb,
+ &context );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 460A: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_pkey_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_pkey_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pkey_rec_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pkey_rec_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_pkey_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4606: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_pkey_table_record_t) );
+
+ p_resp_rec = (ib_pkey_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_pkey_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_process: ERR 4607: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_pkey_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_pkey_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pkey_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pkey_rec_rcv_process( ((osm_pkey_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_construct(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pkey_rec_rcv_ctrl_destroy(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pkey_rec_rcv_ctrl_init(
+ IN osm_pkey_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_pkey_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pkey_rec_rcv_ctrl_init );
+
+ osm_pkey_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PKEY_TBL_RECORD,
+ __osm_pkey_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pkey_rec_rcv_ctrl_init: ERR 4701: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_portinfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pir_rcv_t.
+ * This object represents the PortInfoRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.10 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_portinfo_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_PIR_RCV_POOL_MIN_SIZE 32
+#define OSM_PIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_pir_item
+{
+ cl_pool_item_t pool_item;
+ ib_portinfo_record_t rec;
+} osm_pir_item_t;
+
+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_pir_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+ boolean_t is_enhanced_comp_mask;
+} osm_pir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_construct(
+ IN osm_pir_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_destroy(
+ IN osm_pir_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_init(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_pir_rcv_init );
+
+ osm_pir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_PIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_PIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_pir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_pir_rcv_new_pir(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid )
+{
+ osm_pir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_pir_rcv_new_pir );
+
+ p_rec_item = (osm_pir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_pir_rcv_new_pir: ERR 2102: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_pir_rcv_new_pir: "
+ "New PortInfoRecord: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X\n",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ),
+ cl_ntoh16( lid ), osm_physp_get_port_num( p_physp ) );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.port_info = *osm_physp_get_port_info_ptr( p_physp );
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_create(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN osm_pir_search_ctxt_t* const 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( p_rcv->p_log, __osm_sa_pir_create );
+
+ 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, p_rcv->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.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_pir_create: "
+ "Comparing LID: 0x%X <= 0x%X <= 0x%X\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;
+ }
+
+ __osm_pir_rcv_new_pir( p_rcv, p_physp, p_ctxt->p_list,
+ cl_hton16( base_lid_ho ) );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_pir_check_physp(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ osm_pir_search_ctxt_t* const 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;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_pir_check_physp );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ p_comp_pi = &p_rcvd_rec->port_info;
+ p_pi = osm_physp_get_port_info_ptr( p_physp );
+
+ osm_dump_port_info(
+ p_rcv->p_log,
+ osm_node_get_node_guid( p_physp->p_node ),
+ p_physp->port_guid,
+ p_physp->port_num,
+ &p_physp->port_info,
+ 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;
+ }
+
+ __osm_sa_pir_create( p_rcv, p_physp, p_ctxt );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_pir_search_ctxt_t* const 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( p_rcv->p_log, __osm_sa_pir_by_comp_mask );
+
+ 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_port_get_num_physp( p_port );
+
+ if( comp_mask & IB_PIR_COMPMASK_PORTNUM )
+ {
+ if (p_rcvd_rec->port_num < num_ports)
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, 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_is_valid( p_physp ) &&
+ osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+ __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ else
+ {
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requester and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp ) )
+ continue;
+
+ __osm_sa_pir_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_pir_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_pir_search_ctxt_t* const p_ctxt = (osm_pir_search_ctxt_t *)context;
+
+ __osm_sa_pir_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_process(
+ IN osm_pir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_portinfo_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_port_info_t* p_pi;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_portinfo_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_pir_search_ctxt_t context;
+ osm_pir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+ boolean_t trusted_req = TRUE;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_pir_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2105: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2104: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_portinfo_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+ p_pi = &p_rcvd_rec->port_info;
+
+ 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+ context.is_enhanced_comp_mask = cl_ntoh32(p_rcvd_mad->attr_mod) & (1 << 31);
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ /*
+ 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 )
+ {
+ status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+ if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2109: "
+ "No port found with LID 0x%x\n",
+ cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ }
+ else
+ {
+ if( comp_mask & IB_PIR_COMPMASK_BASELID )
+ {
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > cl_ntoh16(p_pi->base_lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_pi->base_lid) );
+ }
+ else
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2103: "
+ "Given LID (0x%X) is out of range:0x%X\n",
+ cl_ntoh16(p_pi->base_lid), cl_ptr_vector_get_size(p_tbl));
+ }
+ }
+ }
+
+ if ( status == IB_SUCCESS )
+ {
+ if( p_port )
+ __osm_sa_pir_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_pir_by_comp_mask_cb,
+ &context );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2108: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_pir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_portinfo_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_pir_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_pir_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_portinfo_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2106: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_portinfo_record_t) );
+
+ p_resp_rec = (ib_portinfo_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ /*
+ 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 == 0)
+ trusted_req = FALSE;
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_pir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ if (trusted_req == FALSE)
+ p_resp_rec->port_info.m_key = 0;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_process: ERR 2107: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_portinfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_pir_rcv_ctrl_t.
+ * This object represents the PortInfoRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_portinfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_pir_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_pir_rcv_process( ((osm_pir_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_construct(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_pir_rcv_ctrl_destroy(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_pir_rcv_ctrl_init(
+ IN osm_pir_rcv_ctrl_t* const p_ctrl,
+ IN osm_pir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_pir_rcv_ctrl_init );
+
+ osm_pir_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_PORTINFO_RECORD,
+ __osm_pir_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_pir_rcv_ctrl_init: ERR 2201: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_response.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sa_resp_t.
+ * This object represents the SA query responder.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_construct(
+ IN osm_sa_resp_t* const p_resp )
+{
+ memset( p_resp, 0, sizeof(*p_resp) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_resp_destroy(
+ IN osm_sa_resp_t* const p_resp )
+{
+ CL_ASSERT( p_resp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sa_resp_init(
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_pool,
+ IN osm_log_t* const p_log )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sa_resp_init );
+
+ osm_sa_resp_construct( p_resp );
+
+ p_resp->p_log = p_log;
+ p_resp->p_pool = p_pool;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sa_send_error(
+ IN osm_sa_resp_t* const p_resp,
+ IN const osm_madw_t* const p_madw,
+ IN const 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;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_resp->p_log, osm_sa_send_error );
+
+ /* avoid races - if we are exiting - exit */
+ if (osm_exit_flag)
+ {
+ osm_log( p_resp->p_log, OSM_LOG_DEBUG,
+ "osm_sa_send_error: "
+ "Ignoring requested send after exit\n" );
+ goto Exit;
+ }
+
+ p_resp_madw = osm_mad_pool_get( p_resp->p_pool,
+ p_madw->h_bind, MAD_BLOCK_SIZE, &p_madw->mad_addr );
+
+ if( p_resp_madw == NULL )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_sa_send_error: ERR 2301: "
+ "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;
+
+ 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( p_resp->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_sa_mad( p_resp->p_log, p_resp_sa_mad, OSM_LOG_FRAMES );
+
+ status = osm_vendor_send( osm_madw_get_bind_handle( p_resp_madw ),
+ p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_resp->p_log, OSM_LOG_ERROR,
+ "osm_sa_send_error: ERR 2302: "
+ "Error sending MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_resp->p_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_resp->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_service_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sr_rcv_t.
+ * This object represents the ServiceRecord Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_service_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_sa.h>
+#include <opensm/osm_service.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SR_RCV_POOL_MIN_SIZE 64
+#define OSM_SR_RCV_POOL_GROW_SIZE 64
+
+typedef struct _osm_sr_item
+{
+ cl_pool_item_t pool_item;
+ ib_service_record_t service_rec;
+} osm_sr_item_t;
+
+typedef struct osm_sr_match_item {
+ cl_qlist_t sr_list;
+ ib_service_record_t* p_service_rec;
+ ib_net64_t comp_mask;
+ osm_sr_rcv_t* p_rcv;
+
+} 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;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_construct(
+ IN osm_sr_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->sr_pool );
+ cl_timer_construct(&p_rcv->sr_timer );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_destroy(
+ IN osm_sr_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->sr_pool );
+ cl_timer_trim(&p_rcv->sr_timer, 1);
+ cl_timer_destroy(&p_rcv->sr_timer );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_init(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_ERROR;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_log, osm_sr_rcv_init );
+
+ osm_sr_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ cl_status = cl_qlock_pool_init( &p_rcv->sr_pool,
+ OSM_SR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_sr_item_t),
+ NULL, NULL, NULL );
+ if(cl_status != CL_SUCCESS)
+ goto Exit;
+
+ status = cl_timer_init(&p_rcv->sr_timer,
+ osm_sr_rcv_lease_cb,
+ p_rcv );
+ if(cl_status != CL_SUCCESS)
+ goto Exit;
+
+ status = IB_SUCCESS;
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static boolean_t
+__match_service_pkey_with_ports_pkey(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ ib_service_record_t * const 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(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw));
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__match_service_pkey_with_ports_pkey: ERR 2404: "
+ "Cannot find requester physical port\n" );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ 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(p_rcv->p_log, p_service_rec->service_pkey, p_req_physp))
+ {
+ valid = FALSE;
+ goto Exit;
+ }
+
+ /* Make sure it matches the port of the ServiceGid */
+ if((comp_mask & IB_SR_COMPMASK_SGID) == IB_SR_COMPMASK_SGID)
+ {
+ service_guid = p_service_rec->service_gid.unicast.interface_id;
+ service_port = (osm_port_t*)cl_qmap_get( &p_rcv->p_subn->port_guid_tbl, service_guid );
+ if (service_port == (osm_port_t*)cl_qmap_end( &p_rcv->p_subn->port_guid_tbl ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__match_service_pkey_with_ports_pkey: 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( p_rcv->p_log,
+ p_service_rec->service_pkey,
+ osm_port_get_default_phys_ptr(service_port) ) )
+ {
+ valid = FALSE;
+ goto Exit;
+ }
+ }
+ }
+
+ Exit:
+ return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+__match_name_to_key_association(
+ IN osm_sr_rcv_t* const p_rcv,
+ ib_service_record_t* p_service_rec,
+ ib_net64_t comp_mask )
+{
+ UNUSED_PARAM( p_service_rec );
+ UNUSED_PARAM( p_rcv );
+
+ 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_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ boolean_t valid = TRUE;
+ ib_sa_mad_t * p_sa_mad;
+ ib_service_record_t* p_recvd_service_rec;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __validate_sr );
+
+ 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(
+ p_rcv,
+ p_madw,
+ p_recvd_service_rec,
+ p_sa_mad->comp_mask );
+
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_sr: "
+ "No Match for Service Pkey\n" );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ valid = __match_name_to_key_association(
+ p_rcv,
+ p_recvd_service_rec,
+ p_sa_mad->comp_mask );
+
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__validate_sr: "
+ "Service Record Name to key matching failed\n" );
+ valid = FALSE;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return valid;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_respond(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw,
+ IN cl_qlist_t* const p_list )
+{
+ osm_madw_t* p_resp_madw;
+ const ib_sa_mad_t* p_sa_mad;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, num_copied;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ ib_service_record_t* p_resp_sr;
+ ib_api_status_t status;
+ osm_sr_item_t* p_sr_item;
+ const ib_sa_mad_t* p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ boolean_t trusted_req = TRUE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sr_rcv_respond );
+
+ num_rec = cl_qlist_count( p_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) &&
+ (num_rec > 1)) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2406: "
+ "Got more than one record for SubnAdmGet (%u).\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ goto Exit;
+ }
+
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_service_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sr_rcv_respond: "
+ "Number of records:%u trimmed to:%u to fit in one MAD\n",
+ num_rec, trim_num_rec );
+ num_rec = trim_num_rec;
+ }
+#endif
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sr_rcv_respond: "
+ "Generating response with %u records\n", num_rec );
+ }
+
+ /*
+ Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_service_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2402: "
+ "Unable to allocate MAD\n" );
+ /* Release the quick pool items */
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+
+ 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 );
+
+ /* but what if it was a SET ? setting the response bit is not enough */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_SET)
+ {
+ p_resp_sa_mad->method = IB_MAD_METHOD_GET;
+ }
+ 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;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_service_record_t) );
+
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we support only one packet RMPP - so we will set the first and
+ last flags for gettable */
+ if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ p_resp_sr = (ib_service_record_t*)ib_sa_mad_get_payload_ptr( p_resp_sa_mad );
+
+ if( (p_resp_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) &&
+ (num_rec == 0))
+ {
+ p_resp_sa_mad->status = IB_SA_MAD_STATUS_NO_RECORDS;
+ memset( p_resp_sr, 0, sizeof(*p_resp_sr) );
+ }
+ else
+ {
+ /*
+ 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 (p_sa_mad->sm_key == 0)
+ trusted_req = FALSE;
+
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+
+ /* we need to track the number of copied items so we can
+ * stop the copy - but clear them all
+ */
+ num_copied = 0;
+ while( p_sr_item != (osm_sr_item_t*)cl_qlist_end( p_list ) )
+ {
+ /* Copy the Link Records from the list into the MAD */
+ if (num_copied < num_rec)
+ {
+ *p_resp_sr = p_sr_item->service_rec;
+ if (trusted_req == FALSE)
+ memset(p_resp_sr->service_key, 0, sizeof(p_resp_sr->service_key));
+
+ num_copied++;
+ }
+ cl_qlock_pool_put( &p_rcv->sr_pool, &p_sr_item->pool_item );
+ p_resp_sr++;
+ p_sr_item = (osm_sr_item_t*)cl_qlist_remove_head( p_list );
+ }
+ }
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sr_rcv_respond: ERR 2407: "
+ "Unable to send MAD (%s)\n", ib_get_err_str( status ) );
+ /* osm_mad_pool_put( p_rcv->p_mad_pool, p_resp_madw ); */
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__get_matching_sr(
+ IN cl_list_item_t* const p_list_item,
+ IN void* context )
+{
+ osm_sr_search_ctxt_t* const p_ctxt = (osm_sr_search_ctxt_t*)context;
+ osm_svcr_t * p_svcr = (osm_svcr_t*)p_list_item;
+ osm_sr_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) == 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) == 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) == 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) == 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) == 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) == 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) == 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) == 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) == 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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)== 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->p_rcv->p_log,
+ p_svcr->service_record.service_pkey,
+ p_req_physp ) )
+ {
+ osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__get_matching_sr: "
+ "requester port doesn't have the service_pkey: 0x%X\n",
+ cl_ntoh16(p_svcr->service_record.service_pkey) );
+ return;
+ }
+ }
+
+ p_sr_pool_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_sr_item->p_rcv->sr_pool );
+
+ if( p_sr_pool_item == NULL )
+ {
+ osm_log( p_sr_item->p_rcv->p_log, OSM_LOG_ERROR,
+ "__get_matching_sr: ERR 2408: "
+ "Unable to acquire Service Record from pool\n" );
+ goto Exit;
+ }
+
+ p_sr_pool_item->service_rec = p_svcr->service_record;
+
+ cl_qlist_insert_tail( &p_sr_item->sr_list,
+ (cl_list_item_t*)&p_sr_pool_item->pool_item );
+
+ Exit:
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_get_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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( p_rcv->p_log, osm_sr_rcv_process_get_method );
+
+ CL_ASSERT( p_madw );
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_get_method: 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( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_service_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ 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.p_rcv = p_rcv;
+
+ context.p_sr_item = &sr_match_item;
+ context.p_req_physp = p_req_physp;
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ cl_qlist_apply_func(&p_rcv->p_subn->sa_sr_list,
+ __get_matching_sr,
+ &context);
+
+ cl_plock_release(p_rcv->p_lock);
+
+ if ((p_sa_mad->method == IB_MAD_METHOD_GET) &&
+ (cl_qlist_count( &sr_match_item.sr_list ) == 0))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_get_method: "
+ "No records matched the Service Record query\n");
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_match_item.sr_list );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_set_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t * p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ ib_service_record_t* p_recvd_service_rec;
+ ib_net64_t comp_mask;
+ osm_svcr_t* p_svcr;
+ osm_sr_item_t* p_sr_item;
+ cl_qlist_t sr_list;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_set_method );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_service_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ OSM_LOG_DEBUG );
+ }
+
+ if( (comp_mask & ( IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID )) !=
+ (IB_SR_COMPMASK_SID | IB_SR_COMPMASK_SGID ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_sr_rcv_process_set_method: "
+ "Component Mask RID check failed for METHOD_SET\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+
+ /* if we were not provided with a service lease make it
+ infinite */
+ if( (comp_mask & IB_SR_COMPMASK_SLEASE) != IB_SR_COMPMASK_SLEASE)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_set_method: "
+ "ServiceLease Component Mask not set - using infinite lease\n");
+ p_recvd_service_rec->service_lease = 0xFFFFFFFF;
+ }
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ /* If Record exists with matching RID */
+ p_svcr = osm_svcr_get_by_rid(
+ p_rcv->p_subn,
+ p_rcv->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(p_rcv->p_lock);
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_set_method: ERR 2411: "
+ "osm_svcr_get_by_rid failed\n" );
+
+ osm_sa_send_error( p_rcv->p_resp, 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(
+ p_rcv->p_subn,
+ p_rcv->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(p_rcv->p_lock);
+
+ if( p_recvd_service_rec->service_lease != 0xFFFFFFFF )
+ {
+#if 0
+ cl_timer_trim(&p_rcv->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(&p_rcv->sr_timer, 1000);
+ p_svcr->modified_time = cl_get_time_stamp_sec();
+ }
+
+ p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+ if( p_sr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_set_method: ERR 2412: "
+ "Unable to acquire Service record\n" );
+ osm_sa_send_error( p_rcv->p_resp, 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->service_rec = *p_recvd_service_rec;
+ cl_qlist_init(&sr_list);
+
+ cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+osm_sr_rcv_process_delete_method(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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_sr_item_t* p_sr_item;
+ cl_qlist_t sr_list;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process_delete_method );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_dump_service_record( p_rcv->p_log,
+ p_recvd_service_rec,
+ OSM_LOG_DEBUG );
+ }
+
+ /* Grab the lock */
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ /* If Record exists with matching RID */
+ p_svcr = osm_svcr_get_by_rid(
+ p_rcv->p_subn,
+ p_rcv->p_log,
+ p_recvd_service_rec );
+
+ if(p_svcr == NULL)
+ {
+ cl_plock_release(p_rcv->p_lock);
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process_delete_method: "
+ "No records matched the RID\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ else
+ {
+ osm_svcr_remove_from_db(p_rcv->p_subn,
+ p_rcv->p_log,
+ p_svcr );
+ }
+
+ cl_plock_release(p_rcv->p_lock);
+
+ p_sr_item = (osm_sr_item_t*)cl_qlock_pool_get( &p_rcv->sr_pool );
+ if( p_sr_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_process_delete_method: ERR 2413: "
+ "Unable to acquire Service record\n");
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ /* provide back the copy of the record */
+ p_sr_item->service_rec = p_svcr->service_record;
+ cl_qlist_init(&sr_list);
+
+ cl_qlist_insert_tail( &sr_list, (cl_list_item_t*)&p_sr_item->pool_item );
+
+ if(p_svcr)
+ osm_svcr_destroy(p_svcr);
+
+ __osm_sr_rcv_respond( p_rcv, p_madw, &sr_list );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_process(
+ IN osm_sr_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_sa_mad_t * p_sa_mad;
+ ib_net16_t sa_status = IB_SA_MAD_STATUS_REQ_INVALID;
+ boolean_t valid;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sr_rcv_process );
+
+ 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:
+ valid = __validate_sr(p_rcv, p_madw);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_sr_rcv_process: "
+ "Component Mask check failed for set request\n" );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ osm_sr_rcv_process_set_method(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_DELETE:
+ valid = __validate_sr(p_rcv, p_madw);
+ if(!valid)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process: "
+ "Component Mask check failed for delete request\n" );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, sa_status );
+ goto Exit;
+ }
+ osm_sr_rcv_process_delete_method(p_rcv, p_madw);
+ break;
+ case IB_MAD_METHOD_GET:
+ case IB_MAD_METHOD_GETTABLE:
+ osm_sr_rcv_process_get_method(p_rcv, p_madw);
+ break;
+ default:
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_process: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_sa_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ break;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_lease_cb(
+ IN void* context )
+{
+ osm_sr_rcv_t* p_rcv = (osm_sr_rcv_t*)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( p_rcv->p_log, osm_sr_rcv_lease_cb );
+
+ cl_plock_excl_acquire(p_rcv->p_lock);
+
+ p_list_item = cl_qlist_head(&p_rcv->p_subn->sa_sr_list);
+
+ while( p_list_item != cl_qlist_end(&p_rcv->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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sr_rcv_lease_cb: "
+ "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(p_rcv->p_subn,
+ p_rcv->p_log,
+ p_svcr);
+
+ osm_svcr_destroy(p_svcr);
+
+ p_list_item = p_next_list_item;
+ continue;
+ }
+ }
+
+ /* Release the Lock */
+ cl_plock_release(p_rcv->p_lock);
+
+ if(trim_time != 0xFFFFFFFF)
+ {
+ cl_timer_trim(&p_rcv->sr_timer,
+ trim_time * 1000); /* Convert to milli seconds */
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_service_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sr_rcv_ctrl_t.
+ * This object represents the ServiceRecord request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_service_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sr_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_sr_rcv_process( ((osm_sr_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_construct(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sr_rcv_ctrl_destroy(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sr_rcv_ctrl_init(
+ IN osm_sr_rcv_ctrl_t* const p_ctrl,
+ IN osm_sr_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sr_rcv_ctrl_init );
+
+ osm_sr_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SERVICE_RECORD,
+ __osm_sr_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sr_rcv_ctrl_init: ERR 2501: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_slvl_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_slvl_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SLVL_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_SLVL_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_slvl_item
+{
+ cl_pool_item_t pool_item;
+ ib_slvl_table_record_t rec;
+} osm_slvl_item_t;
+
+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_slvl_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_slvl_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_construct(
+ IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_destroy(
+ IN osm_slvl_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_init(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_init );
+
+ osm_slvl_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_SLVL_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SLVL_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_slvl_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_create(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_physp_t* const p_physp,
+ IN osm_slvl_search_ctxt_t* const p_ctxt,
+ IN uint8_t in_port_idx )
+{
+ osm_slvl_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_slvl_create );
+
+ p_rec_item = (osm_slvl_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_slvl_create: ERR 2602: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_slvl_create: "
+ "New SLtoVL Map for: OUT port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X 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->rec, 0, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.out_port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.in_port_num = in_port_idx;
+ p_rec_item->rec.slvl_tbl = *(osm_physp_get_slvl_tbl(p_physp,in_port_idx));
+
+ cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_slvl_search_ctxt_t* const 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( p_rcv->p_log, __osm_sa_slvl_by_comp_mask );
+
+ p_rcvd_rec = p_ctxt->p_rcvd_rec;
+ comp_mask = p_ctxt->comp_mask;
+ num_ports = osm_port_get_num_physp( p_port );
+ in_port_start = 0;
+ in_port_end = num_ports;
+ out_port_start = 0;
+ out_port_end = num_ports;
+ p_req_physp = p_ctxt->p_req_physp;
+
+ if ( p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_slvl_by_comp_mask: "
+ "Using Physical Default Port Number: 0x%X (for End Node)\n",
+ p_port->default_port_num );
+ p_out_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num );
+ /* check that the p_out_physp and the p_req_physp share a pkey */
+ if (osm_physp_share_pkey( p_rcv->p_log, p_req_physp, p_out_physp ))
+ __osm_sa_slvl_create( p_rcv, 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_port_get_phys_ptr( p_port, out_port_num );
+ if( p_out_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( 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_port_get_phys_ptr( p_port, in_port_num );
+ if( p_in_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_in_physp ) )
+ continue;
+
+ /* if the requester and the p_out_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_out_physp ) )
+ continue;
+
+ __osm_sa_slvl_create(p_rcv, p_out_physp, p_ctxt, in_port_num);
+ }
+ }
+ }
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_slvl_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_slvl_search_ctxt_t* const p_ctxt = (osm_slvl_search_ctxt_t *)context;
+
+ __osm_sa_slvl_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_process(
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_slvl_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_slvl_table_t* p_slvl_tbl;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_slvl_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_slvl_search_ctxt_t context;
+ osm_slvl_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rec_rcv_process );
+
+ 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2604: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2603: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ p_slvl_tbl = (ib_slvl_table_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.p_rcv = p_rcv;
+ context.in_port_num = p_rcvd_rec->in_port_num;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_slvl_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%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_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+ if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2608: "
+ "No port found with LID 0x%x\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 */
+ __osm_sa_slvl_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_slvl_by_comp_mask_cb,
+ &context );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2607: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_slvl_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_slvl_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_slvl_rec_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_slvl_rec_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_slvl_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2605: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_slvl_table_record_t) );
+
+ p_resp_rec = (ib_slvl_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_slvl_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE);
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_process: ERR 2606: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_slvl_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rec_rcv_ctrl_t.
+ * This object represents the SLtoVL Map Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_slvl_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_slvl_rec_rcv_process( ((osm_slvl_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_construct(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rec_rcv_ctrl_destroy(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rec_rcv_ctrl_init(
+ IN osm_slvl_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rec_rcv_ctrl_init );
+
+ osm_slvl_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SLVL_TBL_RECORD,
+ __osm_slvl_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_slvl_rec_rcv_ctrl_init: ERR 2701: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_sminfo_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_smir_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_sminfo_record.h>
+#include <opensm/osm_sa_response.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <vendor/osm_vendor.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey.h>
+#include <opensm/osm_remote_sm.h>
+
+#define OSM_SMIR_RCV_POOL_MIN_SIZE 32
+#define OSM_SMIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_smir_item
+{
+ cl_pool_item_t pool_item;
+ ib_sminfo_record_t rec;
+} osm_smir_item_t;
+
+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_smir_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_smir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_construct(
+ IN osm_smir_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_destroy(
+ IN osm_smir_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_rcv_init(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_smir_rcv_init );
+
+ osm_smir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_SMIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SMIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_smir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+static ib_api_status_t
+__osm_smir_rcv_new_smir(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ IN cl_qlist_t* const 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* const p_req_physp )
+{
+ osm_smir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_smir_rcv_new_smir );
+
+ p_rec_item = (osm_smir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_smir_rcv_new_smir: ERR 2801: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_smir_rcv_new_smir: "
+ "New SMInfo: GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64( guid )
+ );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof(ib_sminfo_record_t) );
+
+ p_rec_item->rec.lid = osm_port_get_base_lid( p_port );
+ p_rec_item->rec.sm_info.guid = guid;
+ p_rec_item->rec.sm_info.act_count = act_count;
+ p_rec_item->rec.sm_info.pri_state = pri_state;
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_smir_by_comp_mask(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN const osm_remote_sm_t* const p_rem_sm,
+ osm_smir_search_ctxt_t* const 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_LOG_ENTER( p_rcv->p_log, __osm_sa_smir_by_comp_mask );
+
+ 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 */
+
+ __osm_smir_rcv_new_smir( p_rcv, p_rem_sm->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( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sa_smir_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_remote_sm_t* const p_rem_sm = (osm_remote_sm_t*)p_map_item;
+ osm_smir_search_ctxt_t* const p_ctxt = (osm_smir_search_ctxt_t *)context;
+
+ __osm_sa_smir_by_comp_mask( p_ctxt->p_rcv, p_rem_sm, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_rcv_process(
+ IN osm_smir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_sminfo_record_t* p_rcvd_rec;
+ const cl_qmap_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_sm_info_t* p_smi;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_sminfo_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_smir_search_ctxt_t context;
+ osm_smir_item_t* p_rec_item;
+ 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_smir_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_sminfo_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_SMINFO_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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2804: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2803: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_sm_info_record( p_rcv->p_log, p_rcvd_rec, OSM_LOG_DEBUG );
+
+ p_tbl = &p_rcv->p_subn->sm_guid_tbl;
+ 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 = p_rcvd_mad->comp_mask;
+ context.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /*
+ 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 )
+ {
+ status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+ if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2806: "
+ "No port found with LID 0x%x\n",
+ cl_ntoh16(p_rcvd_rec->lid) );
+ }
+ }
+
+ if ( status == IB_SUCCESS )
+ {
+ /* Handle our own SM first */
+ local_port = osm_get_port_by_guid( p_rcv->p_subn, p_rcv->p_subn->sm_port_guid );
+ if ( !local_port )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2809: "
+ "No port found with GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64(p_rcv->p_subn->sm_port_guid ) );
+ goto Exit;
+ }
+
+ if ( !p_port || local_port == p_port )
+ {
+ if (FALSE ==
+ osm_physp_share_pkey( p_rcv->p_log, p_req_physp,
+ osm_port_get_default_phys_ptr( local_port ) ) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: 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 )
+ {
+ if ( p_rcv->p_subn->sm_port_guid != p_smi->guid )
+ goto Remotes;
+ }
+ if ( comp_mask & IB_SMIR_COMPMASK_PRIORITY )
+ {
+ if ( p_rcv->p_subn->opt.sm_priority != ib_sminfo_get_priority( p_smi ) )
+ goto Remotes;
+ }
+ if ( comp_mask & IB_SMIR_COMPMASK_SMSTATE )
+ {
+ if ( p_rcv->p_subn->sm_state != ib_sminfo_get_state( p_smi ) )
+ goto Remotes;
+ }
+
+ /* Now, add local SMInfo to list */
+ pri_state = p_rcv->p_subn->sm_state & 0x0F;
+ pri_state |= (p_rcv->p_subn->opt.sm_priority & 0x0F) << 4;
+ __osm_smir_rcv_new_smir( p_rcv, local_port, context.p_list,
+ p_rcv->p_subn->sm_port_guid,
+ cl_ntoh32( p_rcv->p_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 = &p_rcv->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 ) )
+ __osm_sa_smir_by_comp_mask( p_rcv, p_rem_sm, &context );
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 280A: "
+ "No remote SM for GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ }
+ }
+ else
+ {
+ /* Go over all other known (remote) SMs */
+ cl_qmap_apply_func( &p_rcv->p_subn->sm_guid_tbl,
+ __osm_sa_smir_by_comp_mask_cb,
+ &context );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2808: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_smir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_sminfo_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_smir_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_smir_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_sminfo_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2807: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_NO_RESOURCES );
+
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_sminfo_record_t) );
+
+ p_resp_rec = (ib_sminfo_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_smir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ p_resp_rec->sm_info.sm_key = 0;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if( status != IB_SUCCESS )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_smir_rcv_process: ERR 2802: "
+ "Error sending MAD (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_sminfo_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_smir_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_sminfo_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_smir_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_smir_rcv_process( ((osm_smir_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_construct(
+ IN osm_smir_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_smir_ctrl_destroy(
+ IN osm_smir_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_smir_ctrl_init(
+ IN osm_smir_ctrl_t* const p_ctrl,
+ IN osm_smir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_smir_ctrl_init );
+
+ osm_smir_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SMINFO_RECORD,
+ __osm_smir_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_smir_ctrl_init: ERR 2901: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sir_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_sw_info_record.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_SIR_RCV_POOL_MIN_SIZE 32
+#define OSM_SIR_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_sir_item
+{
+ cl_pool_item_t pool_item;
+ ib_switch_info_record_t rec;
+} osm_sir_item_t;
+
+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_sir_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_sir_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_construct(
+ IN osm_sir_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_destroy(
+ IN osm_sir_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sir_rcv_init(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_sir_rcv_init );
+
+ osm_sir_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_SIR_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_SIR_RCV_POOL_GROW_SIZE,
+ sizeof(osm_sir_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sir_rcv_new_sir(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN const osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const lid )
+{
+ osm_sir_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sir_rcv_new_sir );
+
+ p_rec_item = (osm_sir_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sir_rcv_new_sir: ERR 5308: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sir_rcv_new_sir: "
+ "New SwitchInfoRecord: lid 0x%X\n",
+ cl_ntoh16( lid )
+ );
+ }
+
+ memset( &p_rec_item->rec, 0, sizeof(ib_switch_info_record_t) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.switch_info = p_sw->switch_info;
+
+ cl_qlist_insert_tail( p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_port_t*
+__osm_sir_get_port_by_guid(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN uint64_t port_guid )
+{
+ osm_port_t* p_port;
+
+ CL_PLOCK_ACQUIRE(p_rcv->p_lock);
+
+ p_port = (osm_port_t *)cl_qmap_get(&p_rcv->p_subn->port_guid_tbl,
+ port_guid);
+ if (p_port == (osm_port_t *)cl_qmap_end(&p_rcv->p_subn->port_guid_tbl))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sir_get_port_by_guid ERR 5309: "
+ "Invalid port GUID 0x%016" PRIx64 "\n",
+ port_guid );
+ p_port = NULL;
+ }
+
+ CL_PLOCK_RELEASE(p_rcv->p_lock);
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sir_rcv_create_sir(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN const osm_switch_t* const p_sw,
+ IN cl_qlist_t* const p_list,
+ IN ib_net16_t const match_lid,
+ IN const osm_physp_t* const 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( p_rcv->p_log, __osm_sir_rcv_create_sir );
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sir_rcv_create_sir: "
+ "Looking for SwitchInfoRecord with LID: 0x%X\n",
+ cl_ntoh16( match_lid )
+ );
+ }
+
+ /* In switches, the port guid is the node guid. */
+ p_port =
+ __osm_sir_get_port_by_guid( p_rcv, p_sw->p_node->node_info.port_guid );
+ if (! p_port)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sir_rcv_create_sir: 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 = osm_port_get_default_phys_ptr( p_port );
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sir_rcv_create_sir: 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( p_rcv->p_log, p_req_physp, p_physp ))
+ 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.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sir_rcv_create_sir: "
+ "Comparing LID: 0x%X <= 0x%X <= 0x%X\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;
+
+ }
+
+ __osm_sir_rcv_new_sir( p_rcv, p_sw, p_list, osm_port_get_base_lid(p_port) );
+
+Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sir_rcv_by_comp_mask(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_sir_search_ctxt_t* const p_ctxt = (osm_sir_search_ctxt_t *)context;
+ const osm_switch_t* const 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_sir_rcv_t* const p_rcv = p_ctxt->p_rcv;
+ ib_net64_t const comp_mask = p_ctxt->comp_mask;
+ ib_net16_t match_lid = 0;
+
+ OSM_LOG_ENTER( p_ctxt->p_rcv->p_log, __osm_sir_rcv_by_comp_mask );
+
+ osm_dump_switch_info(
+ p_ctxt->p_rcv->p_log,
+ &p_sw->switch_info,
+ OSM_LOG_VERBOSE );
+
+ if( comp_mask & IB_SWIR_COMPMASK_LID )
+ {
+ match_lid = p_rcvd_rec->lid;
+ if (!match_lid)
+ goto Exit;
+ }
+
+ __osm_sir_rcv_create_sir( p_rcv, p_sw, p_ctxt->p_list,
+ match_lid, p_req_physp );
+
+Exit:
+ OSM_LOG_EXIT( p_ctxt->p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_process(
+ IN osm_sir_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_switch_info_record_t* p_rcvd_rec;
+ ib_switch_info_record_t* p_resp_rec;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_sir_search_ctxt_t context;
+ osm_sir_item_t* p_rec_item;
+ ib_api_status_t status;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sir_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_rcvd_mad );
+
+ CL_ASSERT( p_rcvd_mad->attr_id == IB_MAD_ATTR_SWITCH_INFO_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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_process: ERR 5305: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_process: ERR 5304: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ if ( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ osm_dump_switch_info_record( p_rcv->p_log, p_rcvd_rec, 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.p_rcv = p_rcv;
+ context.p_req_physp = p_req_physp;
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /* Go over all switches */
+ cl_qmap_apply_func( &p_rcv->p_subn->sw_guid_tbl,
+ __osm_sir_rcv_by_comp_mask,
+ &context );
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if ( (p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec > 1) ) {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_process: ERR 5303: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_sir_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ /* we limit the number of records to a single packet */
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_switch_info_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_sir_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_sir_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_switch_info_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_process: ERR 5306: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_switch_info_record_t) );
+
+ p_resp_rec = (ib_switch_info_record_t*)ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_sir_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if (status != IB_SUCCESS)
+ {
+ osm_log(p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_process: ERR 5307: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status));
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sir_rcv_ctrl_t.
+ * This object represents the SwitchInfo Record controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_sw_info_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sir_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_sir_rcv_process( ((osm_sir_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_ctrl_construct(
+ IN osm_sir_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sir_rcv_ctrl_destroy(
+ IN osm_sir_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sir_rcv_ctrl_init(
+ IN osm_sir_rcv_ctrl_t* const p_ctrl,
+ IN osm_sir_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sir_rcv_ctrl_init );
+
+ osm_sir_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SWITCH_INFO_RECORD,
+ __osm_sir_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sir_rcv_ctrl_init: ERR 5301: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_vlarb_record.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qlist.h>
+#include <opensm/osm_sa_vlarb_record.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_node.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_pkey.h>
+
+#define OSM_VLARB_REC_RCV_POOL_MIN_SIZE 32
+#define OSM_VLARB_REC_RCV_POOL_GROW_SIZE 32
+
+typedef struct _osm_vl_arb_item
+{
+ cl_pool_item_t pool_item;
+ ib_vl_arb_table_record_t rec;
+} osm_vl_arb_item_t;
+
+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_vlarb_rec_rcv_t* p_rcv;
+ const osm_physp_t* p_req_physp;
+} osm_vl_arb_search_ctxt_t;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_construct(
+ IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_qlock_pool_construct( &p_rcv->pool );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_destroy(
+ IN osm_vlarb_rec_rcv_t* const p_rcv )
+{
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_destroy );
+ cl_qlock_pool_destroy( &p_rcv->pool );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_init(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_sa_resp_t* const p_resp,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN const osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_init );
+
+ osm_vlarb_rec_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_mad_pool = p_mad_pool;
+
+ /* used for matching records collection */
+ status = cl_qlock_pool_init( &p_rcv->pool,
+ OSM_VLARB_REC_RCV_POOL_MIN_SIZE,
+ 0,
+ OSM_VLARB_REC_RCV_POOL_GROW_SIZE,
+ sizeof(osm_vl_arb_item_t),
+ NULL, NULL, NULL );
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_create(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ IN osm_vl_arb_search_ctxt_t* const p_ctxt,
+ IN uint8_t block )
+{
+ osm_vl_arb_item_t* p_rec_item;
+ uint16_t lid;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_create );
+
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlock_pool_get( &p_rcv->pool );
+ if( p_rec_item == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_vl_arb_create: ERR 2A02: "
+ "cl_qlock_pool_get failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ if (p_physp->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH)
+ {
+ lid = osm_physp_get_port_info_ptr( p_physp )->base_lid;
+ }
+ else
+ {
+ lid = osm_node_get_base_lid( p_physp->p_node, 0 );
+ }
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_vl_arb_create: "
+ "New VLArbitration for: port 0x%016" PRIx64
+ ", lid 0x%X, port# 0x%X 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->rec, 0, sizeof( p_rec_item->rec ) );
+
+ p_rec_item->rec.lid = lid;
+ p_rec_item->rec.port_num = osm_physp_get_port_num( p_physp );
+ p_rec_item->rec.block_num = block;
+ p_rec_item->rec.vl_arb_tbl = *(osm_physp_get_vla_tbl(p_physp, block));
+
+ cl_qlist_insert_tail( p_ctxt->p_list, (cl_list_item_t*)&p_rec_item->pool_item );
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_check_physp(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_physp_t* const p_physp,
+ osm_vl_arb_search_ctxt_t* const p_ctxt )
+{
+ ib_net64_t comp_mask = p_ctxt->comp_mask;
+ uint8_t block;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sa_vl_arb_check_physp );
+
+ /* 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)
+ {
+ __osm_sa_vl_arb_create( p_rcv, p_physp, p_ctxt, block );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_port_t* const p_port,
+ osm_vl_arb_search_ctxt_t* const 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( p_rcv->p_log, __osm_sa_vl_arb_by_comp_mask );
+
+ 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->default_port_num;
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sa_vl_arb_by_comp_mask: "
+ "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_port_get_num_physp( p_port ))
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, 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_is_valid( p_physp ) &&
+ osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp) )
+ __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sa_vl_arb_by_comp_mask: ERR 2A03: "
+ "Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
+ port_num, osm_port_get_num_physp( p_port ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( p_physp == NULL )
+ continue;
+
+ if( !osm_physp_is_valid( p_physp ) )
+ continue;
+
+ /* if the requester and the p_physp don't share a pkey -
+ continue */
+ if (!osm_physp_share_pkey(p_rcv->p_log, p_req_physp, p_physp))
+ continue;
+
+ __osm_sa_vl_arb_check_physp( p_rcv, p_physp, p_ctxt );
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sa_vl_arb_by_comp_mask_cb(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ const osm_port_t* const p_port = (osm_port_t*)p_map_item;
+ osm_vl_arb_search_ctxt_t* const p_ctxt = (osm_vl_arb_search_ctxt_t *)context;
+
+ __osm_sa_vl_arb_by_comp_mask( p_ctxt->p_rcv, p_port, p_ctxt );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_process(
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_sa_mad_t* p_rcvd_mad;
+ const ib_vl_arb_table_record_t* p_rcvd_rec;
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const ib_vl_arb_table_t* p_vl_arb;
+ cl_qlist_t rec_list;
+ osm_madw_t* p_resp_madw;
+ ib_sa_mad_t* p_resp_sa_mad;
+ ib_vl_arb_table_record_t* p_resp_rec;
+ uint32_t num_rec, pre_trim_num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ uint32_t trim_num_rec;
+#endif
+ uint32_t i;
+ osm_vl_arb_search_ctxt_t context;
+ osm_vl_arb_item_t* p_rec_item;
+ ib_api_status_t status = IB_SUCCESS;
+ ib_net64_t comp_mask;
+ osm_physp_t* p_req_physp;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vlarb_rec_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_rcvd_mad = osm_madw_get_sa_mad_ptr( p_madw );
+ p_rcvd_rec = (ib_vl_arb_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_VLARB_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( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A05: "
+ "Unsupported Method (%s)\n",
+ ib_get_sa_method_str( p_rcvd_mad->method ) );
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR );
+ goto Exit;
+ }
+
+ /* update the requester physical port. */
+ p_req_physp = osm_get_physp_by_mad_addr(p_rcv->p_log,
+ p_rcv->p_subn,
+ osm_madw_get_mad_addr_ptr(p_madw) );
+ if (p_req_physp == NULL)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A04: "
+ "Cannot find requester physical port\n" );
+ goto Exit;
+ }
+
+ p_vl_arb = (ib_vl_arb_table_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.p_rcv = p_rcv;
+ context.block_num = p_rcvd_rec->block_num;
+ context.p_req_physp = p_req_physp;
+
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_vlarb_rec_rcv_process: "
+ "Got Query Lid:0x%04X(%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 );
+
+ cl_plock_acquire( p_rcv->p_lock );
+
+ /*
+ 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_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ status = osm_get_port_by_base_lid( p_rcv->p_subn, p_rcvd_rec->lid, &p_port );
+ if ( ( status != IB_SUCCESS ) || ( p_port == NULL ) )
+ {
+ status = IB_NOT_FOUND;
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A09: "
+ "No port found with LID 0x%x\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 */
+ __osm_sa_vl_arb_by_comp_mask( p_rcv, p_port, &context );
+ else
+ {
+ cl_qmap_apply_func( &p_rcv->p_subn->port_guid_tbl,
+ __osm_sa_vl_arb_by_comp_mask_cb,
+ &context );
+ }
+ }
+
+ cl_plock_release( p_rcv->p_lock );
+
+ num_rec = cl_qlist_count( &rec_list );
+
+ /*
+ * C15-0.1.30:
+ * If we do a SubnAdmGet and got more than one record it is an error !
+ */
+ if (p_rcvd_mad->method == IB_MAD_METHOD_GET)
+ {
+ if (num_rec == 0)
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+ if (num_rec > 1)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A08: "
+ "Got more than one record for SubnAdmGet (%u)\n",
+ num_rec );
+ osm_sa_send_error( p_rcv->p_resp, p_madw,
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS );
+
+ /* need to set the mem free ... */
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ while( p_rec_item != (osm_vl_arb_item_t*)cl_qlist_end( &rec_list ) )
+ {
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ }
+
+ goto Exit;
+ }
+ }
+
+ pre_trim_num_rec = num_rec;
+#ifndef VENDOR_RMPP_SUPPORT
+ trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / sizeof(ib_vl_arb_table_record_t);
+ if (trim_num_rec < num_rec)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_vlarb_rec_rcv_process: "
+ "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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_vlarb_rec_rcv_process: "
+ "Returning %u records\n", num_rec );
+
+ if ((p_rcvd_mad->method == IB_MAD_METHOD_GET) && (num_rec == 0))
+ {
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RECORDS );
+ goto Exit;
+ }
+
+ /*
+ * Get a MAD to reply. Address of Mad is in the received mad_wrapper
+ */
+ p_resp_madw = osm_mad_pool_get( p_rcv->p_mad_pool,
+ p_madw->h_bind,
+ num_rec * sizeof(ib_vl_arb_table_record_t) + IB_SA_MAD_HDR_SIZE,
+ &p_madw->mad_addr );
+
+ if( !p_resp_madw )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A06: "
+ "osm_mad_pool_get failed\n" );
+
+ for( i = 0; i < num_rec; i++ )
+ {
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ }
+
+ osm_sa_send_error( p_rcv->p_resp, p_madw, IB_SA_MAD_STATUS_NO_RESOURCES );
+ goto Exit;
+ }
+
+ p_resp_sa_mad = osm_madw_get_sa_mad_ptr( p_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( p_resp_sa_mad, p_rcvd_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;
+
+ /* Fill in the offset (paylen will be done by the rmpp SAR) */
+ p_resp_sa_mad->attr_offset =
+ ib_get_attr_offset( sizeof(ib_vl_arb_table_record_t) );
+
+ p_resp_rec = (ib_vl_arb_table_record_t*)
+ ib_sa_mad_get_payload_ptr( p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ {
+ p_resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
+ p_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 (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
+ p_resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
+#endif
+
+ for( i = 0; i < pre_trim_num_rec; i++ )
+ {
+ p_rec_item = (osm_vl_arb_item_t*)cl_qlist_remove_head( &rec_list );
+ /* copy only if not trimmed */
+ if (i < num_rec)
+ {
+ *p_resp_rec = p_rec_item->rec;
+ }
+ cl_qlock_pool_put( &p_rcv->pool, &p_rec_item->pool_item );
+ p_resp_rec++;
+ }
+
+ CL_ASSERT( cl_is_qlist_empty( &rec_list ) );
+
+ status = osm_vendor_send( p_resp_madw->h_bind, p_resp_madw, FALSE );
+ if(status != IB_SUCCESS)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_process: ERR 2A07: "
+ "osm_vendor_send status = %s\n",
+ ib_get_err_str(status) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sa_vlarb_record_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vlarb_rec_rcv_ctrl_t.
+ * This object represents the VL Arbitration Record SA request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sa_vlarb_record_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vlarb_rec_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_vlarb_rec_rcv_process( ((osm_vlarb_rec_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_construct(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vlarb_rec_rcv_ctrl_destroy(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vlarb_rec_rcv_ctrl_init(
+ IN osm_vlarb_rec_rcv_ctrl_t* const p_ctrl,
+ IN osm_vlarb_rec_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vlarb_rec_rcv_ctrl_init );
+
+ osm_vlarb_rec_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_VL_ARB_RECORD,
+ __osm_vlarb_rec_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_vlarb_rec_rcv_ctrl_init: ERR 2B01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_service.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of service record functions.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_timer.h>
+#include <opensm/osm_service.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_construct(
+ IN osm_svcr_t* const p_svcr )
+{
+ memset( p_svcr, 0, sizeof(*p_svcr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_destroy(
+ IN osm_svcr_t* const p_svcr )
+{
+ free( p_svcr);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_svcr_init(
+ IN osm_svcr_t* const 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 )
+ {
+ osm_svcr_construct( 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* const 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;
+ int32_t count;
+
+ count = 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) );
+
+ if(count == 0)
+ return CL_SUCCESS;
+ else
+ return CL_NOT_FOUND;
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+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* const p_svc_rec )
+{
+ cl_list_item_t* p_list_item;
+
+ OSM_LOG_ENTER( p_log, osm_svcr_get_by_rid );
+
+ 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_svcr_insert_to_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_svcr_insert_to_db: "
+ "Inserting new Service Record into Database\n");
+
+ cl_qlist_insert_head(&p_subn->sa_sr_list,
+ &p_svcr->list_item);
+
+ 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_svcr_remove_from_db );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_svcr_remove_from_db: "
+ "Removing Service Record Name:%s ID:0x%016" PRIx64" from Database\n",
+ p_svcr->service_record.service_name, p_svcr->service_record.service_id
+ );
+
+ cl_qlist_remove_item(&p_subn->sa_sr_list,
+ &p_svcr->list_item);
+
+ OSM_LOG_EXIT( p_log );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_slvl_map_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rcv_t.
+ * This object represents the SLtoVL Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_slvl_map_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_construct(
+ IN osm_slvl_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_destroy(
+ IN osm_slvl_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_init(
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rcv_init );
+
+ osm_slvl_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE A GET or SET responses
+ */
+void
+osm_slvl_rcv_process(
+ IN const osm_slvl_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ 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;
+ uint8_t out_port_num, in_port_num;
+
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_slvl_rcv_process );
+
+ 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_slvl_table_t*)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 );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_process: 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 = osm_port_get_parent_node( p_port );
+ 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)
+ {
+ out_port_num = (uint8_t)cl_ntoh32( p_smp->attr_mod & 0xFF000000);
+ in_port_num = (uint8_t)cl_ntoh32( (p_smp->attr_mod & 0x00FF0000) << 8);
+ p_physp = osm_node_get_physp_ptr( p_node, out_port_num );
+ }
+ else
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ out_port_num = p_port->default_port_num;
+ in_port_num = 0;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to update
+ the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_slvl_rcv_process: "
+ "Got SLtoVL get response in_port_num %u out_port_num %u with GUID 0x%" PRIx64
+ " for parent node GUID 0x%" PRIx64
+ ", TID 0x%" PRIx64 "\n",
+ in_port_num, out_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( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_process: "
+ "Got invalid port number 0x%X\n",
+ out_port_num );
+ goto Exit;
+ }
+
+ osm_dump_slvl_map_table( p_rcv->p_log,
+ port_guid, in_port_num,
+ out_port_num, p_slvl_tbl,
+ OSM_LOG_DEBUG );
+
+ osm_physp_set_slvl_tbl( p_physp, p_slvl_tbl, in_port_num);
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_slvl_map_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_slvl_rcv_ctrl_t.
+ * This object represents the SLtoVL request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_slvl_map_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_slvl_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_slvl_rcv_process( ((osm_slvl_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_construct(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_slvl_rcv_ctrl_destroy(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_slvl_rcv_ctrl_init(
+ IN osm_slvl_rcv_ctrl_t* const p_ctrl,
+ IN osm_slvl_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_slvl_rcv_ctrl_init );
+
+ osm_slvl_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SLVL,
+ __osm_slvl_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_slvl_rcv_ctrl_init: ERR 2D01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sm_t.
+ * This object represents the SM Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sm.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_mcast_mgr.h>
+#include <opensm/osm_mcm_info.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+#define OSM_SM_INITIAL_TID_VALUE 0x1233
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_sweeper(
+ IN void *p_ptr )
+{
+ ib_api_status_t status;
+ osm_sm_t *const p_sm = ( osm_sm_t * ) p_ptr;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_sweeper );
+
+ if( p_sm->thread_state == OSM_THREAD_STATE_INIT )
+ {
+ p_sm->thread_state = OSM_THREAD_STATE_RUN;
+ }
+
+ /* If the sweep interval was updated before - then run only if
+ * it is not zero. */
+ while( p_sm->thread_state == OSM_THREAD_STATE_RUN &&
+ p_sm->p_subn->opt.sweep_interval != 0 )
+ {
+ /* do the sweep only if we are in MASTER state */
+ if( p_sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER ||
+ p_sm->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+ osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+
+ /*
+ * 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,
+ p_sm->p_subn->opt.sweep_interval * 1000000,
+ TRUE );
+
+ if( status == CL_SUCCESS )
+ {
+ if( osm_log_is_active( p_sm->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_sweeper: " "Off schedule sweep signalled\n" );
+ }
+ }
+ else
+ {
+ if( status != CL_TIMEOUT )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "__osm_sm_sweeper: ERR 2E01: "
+ "Event wait failed (%s)\n", CL_STATUS_MSG( status ) );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_construct(
+ IN osm_sm_t * const 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_event_construct( &p_sm->signal );
+ cl_event_construct( &p_sm->subnet_up_event );
+ cl_thread_construct( &p_sm->sweeper );
+ osm_req_construct( &p_sm->req );
+ osm_req_ctrl_construct( &p_sm->req_ctrl );
+ osm_resp_construct( &p_sm->resp );
+ osm_ni_rcv_construct( &p_sm->ni_rcv );
+ osm_ni_rcv_ctrl_construct( &p_sm->ni_rcv_ctrl );
+ osm_pi_rcv_construct( &p_sm->pi_rcv );
+ osm_pi_rcv_ctrl_construct( &p_sm->pi_rcv_ctrl );
+ osm_nd_rcv_construct( &p_sm->nd_rcv );
+ osm_nd_rcv_ctrl_construct( &p_sm->nd_rcv_ctrl );
+ osm_sm_mad_ctrl_construct( &p_sm->mad_ctrl );
+ osm_si_rcv_construct( &p_sm->si_rcv );
+ osm_si_rcv_ctrl_construct( &p_sm->si_rcv_ctrl );
+ osm_lid_mgr_construct( &p_sm->lid_mgr );
+ osm_ucast_mgr_construct( &p_sm->ucast_mgr );
+ osm_link_mgr_construct( &p_sm->link_mgr );
+ osm_state_mgr_construct( &p_sm->state_mgr );
+ osm_state_mgr_ctrl_construct( &p_sm->state_mgr_ctrl );
+ osm_drop_mgr_construct( &p_sm->drop_mgr );
+ osm_lft_rcv_construct( &p_sm->lft_rcv );
+ osm_lft_rcv_ctrl_construct( &p_sm->lft_rcv_ctrl );
+ osm_mft_rcv_construct( &p_sm->mft_rcv );
+ osm_mft_rcv_ctrl_construct( &p_sm->mft_rcv_ctrl );
+ osm_sweep_fail_ctrl_construct( &p_sm->sweep_fail_ctrl );
+ osm_sminfo_rcv_construct( &p_sm->sm_info_rcv );
+ osm_sminfo_rcv_ctrl_construct( &p_sm->sm_info_rcv_ctrl );
+ osm_trap_rcv_construct( &p_sm->trap_rcv );
+ osm_trap_rcv_ctrl_construct( &p_sm->trap_rcv_ctrl );
+ osm_sm_state_mgr_construct( &p_sm->sm_state_mgr );
+ osm_slvl_rcv_construct( &p_sm->slvl_rcv );
+ osm_slvl_rcv_ctrl_construct( &p_sm->slvl_rcv_ctrl );
+ osm_vla_rcv_construct( &p_sm->vla_rcv );
+ osm_vla_rcv_ctrl_construct( &p_sm->vla_rcv_ctrl );
+ osm_pkey_rcv_construct( &p_sm->pkey_rcv );
+ osm_pkey_rcv_ctrl_construct( &p_sm->pkey_rcv_ctrl );
+ osm_mcast_mgr_construct( &p_sm->mcast_mgr );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_shutdown(
+ IN osm_sm_t * const p_sm )
+{
+ boolean_t signal_event = FALSE;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_shutdown );
+
+ /*
+ * 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 );
+
+ 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 );
+ osm_trap_rcv_ctrl_destroy( &p_sm->trap_rcv_ctrl );
+ osm_sminfo_rcv_ctrl_destroy( &p_sm->sm_info_rcv_ctrl );
+ osm_req_ctrl_destroy( &p_sm->req_ctrl );
+ osm_ni_rcv_ctrl_destroy( &p_sm->ni_rcv_ctrl );
+ osm_pi_rcv_ctrl_destroy( &p_sm->pi_rcv_ctrl );
+ osm_si_rcv_ctrl_destroy( &p_sm->si_rcv_ctrl );
+ osm_nd_rcv_ctrl_destroy( &p_sm->nd_rcv_ctrl );
+ osm_lft_rcv_ctrl_destroy( &p_sm->lft_rcv_ctrl );
+ osm_mft_rcv_ctrl_destroy( &p_sm->mft_rcv_ctrl );
+ osm_slvl_rcv_ctrl_destroy( &p_sm->slvl_rcv_ctrl );
+ osm_vla_rcv_ctrl_destroy( &p_sm->vla_rcv_ctrl );
+ osm_pkey_rcv_ctrl_destroy( &p_sm->pkey_rcv_ctrl );
+ osm_sweep_fail_ctrl_destroy( &p_sm->sweep_fail_ctrl );
+ osm_state_mgr_ctrl_destroy( &p_sm->state_mgr_ctrl );
+
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_destroy(
+ IN osm_sm_t * const p_sm )
+{
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_destroy );
+ osm_trap_rcv_destroy( &p_sm->trap_rcv );
+ osm_sminfo_rcv_destroy( &p_sm->sm_info_rcv );
+ osm_req_destroy( &p_sm->req );
+ osm_resp_destroy( &p_sm->resp );
+ osm_ni_rcv_destroy( &p_sm->ni_rcv );
+ osm_pi_rcv_destroy( &p_sm->pi_rcv );
+ osm_si_rcv_destroy( &p_sm->si_rcv );
+ osm_nd_rcv_destroy( &p_sm->nd_rcv );
+ osm_lid_mgr_destroy( &p_sm->lid_mgr );
+ osm_ucast_mgr_destroy( &p_sm->ucast_mgr );
+ osm_link_mgr_destroy( &p_sm->link_mgr );
+ osm_drop_mgr_destroy( &p_sm->drop_mgr );
+ osm_lft_rcv_destroy( &p_sm->lft_rcv );
+ osm_mft_rcv_destroy( &p_sm->mft_rcv );
+ osm_slvl_rcv_destroy( &p_sm->slvl_rcv );
+ osm_vla_rcv_destroy( &p_sm->vla_rcv );
+ osm_pkey_rcv_destroy( &p_sm->pkey_rcv );
+ osm_state_mgr_destroy( &p_sm->state_mgr );
+ osm_sm_state_mgr_destroy( &p_sm->sm_state_mgr );
+ osm_mcast_mgr_destroy( &p_sm->mcast_mgr );
+ cl_event_destroy( &p_sm->signal );
+ cl_event_destroy( &p_sm->subnet_up_event );
+
+ osm_log( p_sm->p_log, OSM_LOG_SYS, "Exiting SM\n" ); /* Format Waived */
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_init(
+ IN osm_sm_t * const p_sm,
+ IN osm_subn_t * const p_subn,
+ IN osm_db_t * const p_db,
+ IN osm_vendor_t * const p_vendor,
+ IN osm_mad_pool_t * const p_mad_pool,
+ IN osm_vl15_t * const p_vl15,
+ IN osm_log_t * const p_log,
+ IN osm_stats_t * const p_stats,
+ IN cl_dispatcher_t * const p_disp,
+ IN cl_plock_t * const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sm_init );
+
+ 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_event_init( &p_sm->signal, FALSE );
+ if( status != CL_SUCCESS )
+ goto Exit;
+
+ status = cl_event_init( &p_sm->subnet_up_event, FALSE );
+ if( status != CL_SUCCESS )
+ goto Exit;
+
+ 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 = osm_req_init( &p_sm->req,
+ p_mad_pool,
+ p_vl15, p_subn, p_log, &p_sm->sm_trans_id );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_req_ctrl_init( &p_sm->req_ctrl, &p_sm->req, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_resp_init( &p_sm->resp, p_mad_pool, p_vl15, p_subn, p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ni_rcv_init( &p_sm->ni_rcv,
+ &p_sm->req,
+ p_subn, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ni_rcv_ctrl_init( &p_sm->ni_rcv_ctrl,
+ &p_sm->ni_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pi_rcv_init( &p_sm->pi_rcv,
+ &p_sm->req,
+ p_subn, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pi_rcv_ctrl_init( &p_sm->pi_rcv_ctrl,
+ &p_sm->pi_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_si_rcv_init( &p_sm->si_rcv,
+ p_sm->p_subn,
+ p_sm->p_log,
+ &p_sm->req, &p_sm->state_mgr, p_sm->p_lock );
+
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_si_rcv_ctrl_init( &p_sm->si_rcv_ctrl,
+ &p_sm->si_rcv, p_sm->p_log, p_sm->p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nd_rcv_init( &p_sm->nd_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_nd_rcv_ctrl_init( &p_sm->nd_rcv_ctrl,
+ &p_sm->nd_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lid_mgr_init( &p_sm->lid_mgr,
+ &p_sm->req,
+ p_sm->p_subn,
+ p_sm->p_db, p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_ucast_mgr_init( &p_sm->ucast_mgr,
+ &p_sm->req,
+ p_sm->p_subn,
+ p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_link_mgr_init( &p_sm->link_mgr,
+ &p_sm->req,
+ p_sm->p_subn, p_sm->p_log, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_state_mgr_init( &p_sm->state_mgr,
+ p_sm->p_subn,
+ &p_sm->lid_mgr,
+ &p_sm->ucast_mgr,
+ &p_sm->mcast_mgr,
+ &p_sm->link_mgr,
+ &p_sm->drop_mgr,
+ &p_sm->req,
+ p_stats,
+ &p_sm->sm_state_mgr,
+ &p_sm->mad_ctrl,
+ p_sm->p_lock,
+ &p_sm->subnet_up_event,
+ p_sm->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_state_mgr_ctrl_init( &p_sm->state_mgr_ctrl,
+ &p_sm->state_mgr,
+ p_sm->p_log, p_sm->p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_drop_mgr_init( &p_sm->drop_mgr,
+ p_sm->p_subn,
+ p_sm->p_log, &p_sm->req, p_sm->p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lft_rcv_init( &p_sm->lft_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_lft_rcv_ctrl_init( &p_sm->lft_rcv_ctrl,
+ &p_sm->lft_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mft_rcv_init( &p_sm->mft_rcv, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mft_rcv_ctrl_init( &p_sm->mft_rcv_ctrl,
+ &p_sm->mft_rcv, p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sweep_fail_ctrl_init( &p_sm->sweep_fail_ctrl,
+ p_log, &p_sm->state_mgr, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sminfo_rcv_init( &p_sm->sm_info_rcv,
+ p_subn,
+ p_stats,
+ &p_sm->resp,
+ p_log,
+ &p_sm->state_mgr,
+ &p_sm->sm_state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sminfo_rcv_ctrl_init( &p_sm->sm_info_rcv_ctrl,
+ &p_sm->sm_info_rcv,
+ p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_trap_rcv_init( &p_sm->trap_rcv,
+ p_subn,
+ p_stats,
+ &p_sm->resp, p_log, &p_sm->state_mgr, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_trap_rcv_ctrl_init( &p_sm->trap_rcv_ctrl,
+ &p_sm->trap_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_sm_state_mgr_init( &p_sm->sm_state_mgr,
+ &p_sm->state_mgr,
+ p_sm->p_subn, &p_sm->req, p_sm->p_log );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_mcast_mgr_init( &p_sm->mcast_mgr,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rcv_init( &p_sm->slvl_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_slvl_rcv_ctrl_init( &p_sm->slvl_rcv_ctrl,
+ &p_sm->slvl_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vla_rcv_init( &p_sm->vla_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_vla_rcv_ctrl_init( &p_sm->vla_rcv_ctrl,
+ &p_sm->vla_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rcv_init( &p_sm->pkey_rcv,
+ &p_sm->req, p_subn, p_log, p_lock );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_pkey_rcv_ctrl_init( &p_sm->pkey_rcv_ctrl,
+ &p_sm->pkey_rcv, p_sm->p_log, p_disp );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ /*
+ * Now that the component objects are initialized, start
+ * the sweeper thread if the user wants sweeping.
+ */
+ if( p_sm->p_subn->opt.sweep_interval )
+ {
+ p_sm->thread_state = OSM_THREAD_STATE_INIT;
+ status = cl_thread_init( &p_sm->sweeper, __osm_sm_sweeper, p_sm,
+ "opensm sweeper" );
+ if( status != IB_SUCCESS )
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_sweep(
+ IN osm_sm_t * const p_sm )
+{
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_sweep );
+ osm_state_mgr_process( &p_sm->state_mgr, OSM_SIGNAL_SWEEP );
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_bind(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_bind );
+
+ 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,
+ "osm_sm_bind: 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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static ib_api_status_t
+__osm_sm_mgrp_connect(
+ IN osm_sm_t * const p_sm,
+ IN osm_mgrp_t * const p_mgrp,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type )
+{
+ ib_api_status_t status;
+ osm_mcast_mgr_ctxt_t *ctx2;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_connect );
+
+ /*
+ * 'Schedule' all the QP0 traffic for when the state manager
+ * isn't busy trying to do something else.
+ */
+ ctx2 =
+ ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+ memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+ ctx2->req_type = req_type;
+ ctx2->port_guid = port_guid;
+
+ status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+ osm_mcast_mgr_process_mgrp_cb,
+ NULL, &p_sm->mcast_mgr,
+ ( void * )ctx2 );
+
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_mgrp_disconnect(
+ IN osm_sm_t * const p_sm,
+ IN osm_mgrp_t * const p_mgrp,
+ IN const ib_net64_t port_guid )
+{
+ ib_api_status_t status;
+ osm_mcast_mgr_ctxt_t *ctx2;
+
+ OSM_LOG_ENTER( p_sm->p_log, __osm_sm_mgrp_disconnect );
+
+ /*
+ * 'Schedule' all the QP0 traffic for when the state manager
+ * isn't busy trying to do something else.
+ */
+ ctx2 =
+ ( osm_mcast_mgr_ctxt_t * ) malloc( sizeof( osm_mcast_mgr_ctxt_t ) );
+ memcpy( &ctx2->mlid, &p_mgrp->mlid, sizeof( p_mgrp->mlid ) );
+ ctx2->req_type = OSM_MCAST_REQ_TYPE_LEAVE;
+ ctx2->port_guid = port_guid;
+
+ status = osm_state_mgr_process_idle( &p_sm->state_mgr,
+ osm_mcast_mgr_process_mgrp_cb,
+ NULL, &p_sm->mcast_mgr, ctx2 );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mgrp_disconnect: ERR 2E11: "
+ "Failure processing multicast group (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ OSM_LOG_EXIT( p_sm->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_join(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid,
+ IN osm_mcast_req_type_t req_type )
+{
+ osm_mgrp_t *p_mgrp;
+ osm_port_t *p_port;
+ cl_qmap_t *p_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+ osm_mcm_info_t *p_mcm;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_join );
+
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_join: "
+ "Port 0x%016" PRIx64 " joining MLID 0x%X\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+ /*
+ * Acquire the port object for the port joining this group.
+ */
+ CL_PLOCK_EXCL_ACQUIRE( p_sm->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E05: "
+ "No port object for port 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * If this multicast group does not already exist, create it.
+ */
+ p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+ p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+ if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_join: "
+ "Creating group, MLID 0x%X\n", cl_ntoh16( mlid ) );
+
+ p_mgrp = osm_mgrp_new( mlid );
+ if( p_mgrp == NULL )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E06: "
+ "Unable to allocate multicast group object\n" );
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ cl_qmap_insert( p_tbl, mlid, &p_mgrp->map_item );
+ }
+ else
+ {
+ /*
+ * The group already exists. If the port is not a
+ * member of the group, then fail immediately.
+ * This can happen since the spinlock is released briefly
+ * before the SA calls this function.
+ */
+ if( !osm_mgrp_is_guid( p_mgrp, port_guid ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E12: "
+ "Port 0x%016" PRIx64 " not in mcast group 0x%X\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+ }
+
+ /*
+ * Check if the object (according to mlid) already exists on this port.
+ * If it does - then no need to update it again, and no need to
+ * create the mc tree again. Just goto Exit.
+ */
+ p_mcm = ( osm_mcm_info_t * ) cl_qlist_head( &p_port->mcm_list );
+ while( p_mcm != ( osm_mcm_info_t * ) cl_qlist_end( &p_port->mcm_list ) )
+ {
+ if( p_mcm->mlid == mlid )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_DEBUG,
+ "osm_sm_mcgrp_join: "
+ "Found mlid object for Port:"
+ "0x%016" PRIx64 " lid:0x%X\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+ goto Exit;
+ }
+ p_mcm = ( osm_mcm_info_t * ) cl_qlist_next( &p_mcm->list_item );
+ }
+
+ status = osm_port_add_mgrp( p_port, mlid );
+ if( status != IB_SUCCESS )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_join: ERR 2E03: "
+ "Unable to associate port 0x%" PRIx64 " to mlid 0x%X\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ cl_ntoh16( osm_mgrp_get_mlid( p_mgrp ) ) );
+ goto Exit;
+ }
+
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ status = __osm_sm_mgrp_connect( p_sm, p_mgrp, port_guid, req_type );
+
+ Exit:
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_mcgrp_leave(
+ IN osm_sm_t * const p_sm,
+ IN const ib_net16_t mlid,
+ IN const ib_net64_t port_guid )
+{
+ osm_mgrp_t *p_mgrp;
+ osm_port_t *p_port;
+ cl_qmap_t *p_tbl;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_sm->p_log, osm_sm_mcgrp_leave );
+
+ osm_log( p_sm->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mcgrp_leave: "
+ "Port 0x%" PRIx64 " leaving MLID 0x%X\n",
+ cl_ntoh64( port_guid ), cl_ntoh16( mlid ) );
+
+ /*
+ * Acquire the port object for the port leaving this group.
+ */
+ /* note: p_sm->p_lock is locked by caller, but will be released later
+ this function */
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm->p_subn->port_guid_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_leave: ERR 2E04: "
+ "No port object for port 0x%" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * Get the multicast group object for this group.
+ */
+ p_tbl = &p_sm->p_subn->mgrp_mlid_tbl;
+ p_mgrp = ( osm_mgrp_t * ) cl_qmap_get( p_tbl, mlid );
+ if( p_mgrp == ( osm_mgrp_t * ) cl_qmap_end( p_tbl ) )
+ {
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+ osm_log( p_sm->p_log, OSM_LOG_ERROR,
+ "osm_sm_mcgrp_leave: ERR 2E08: "
+ "No multicast group for MLID 0x%X\n", cl_ntoh16( mlid ) );
+ status = IB_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ /*
+ * Walk the list of ports in the group, and remove the appropriate one.
+ */
+ osm_mgrp_remove_port( p_sm->p_subn, p_sm->p_log, p_mgrp, port_guid );
+
+ osm_port_remove_mgrp( p_port, mlid );
+
+ CL_PLOCK_RELEASE( p_sm->p_lock );
+
+ __osm_sm_mgrp_disconnect( p_sm, p_mgrp, port_guid );
+
+ Exit:
+ OSM_LOG_EXIT( p_sm->p_log );
+ return ( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm_mad_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_sm_mad_ctrl.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad
+ * NAME
+ * __osm_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
+__osm_sm_mad_ctrl_retire_trans_mad(
+ IN osm_sm_mad_ctrl_t* const p_ctrl,
+ IN osm_madw_t* const p_madw )
+{
+ uint32_t outstanding;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_retire_trans_mad );
+
+ CL_ASSERT( p_madw );
+ /*
+ Return the MAD & wrapper to the pool.
+ */
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "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 = cl_atomic_dec( &p_ctrl->p_stats->qp0_mads_outstanding );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "%u QP0 MADs outstanding\n",
+ p_ctrl->p_stats->qp0_mads_outstanding );
+ }
+
+ if( outstanding == 0 )
+ {
+ /*
+ The wire is clean.
+ Signal the state manager.
+ */
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_retire_trans_mad: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS,
+ NULL,
+ NULL );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_retire_trans_mad: ERR 3101: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+/************/
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback
+ * NAME
+ * __osm_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
+__osm_sm_mad_ctrl_disp_done_callback(
+ IN void* context,
+ IN void* p_data )
+{
+ osm_sm_mad_ctrl_t* const p_ctrl = (osm_sm_mad_ctrl_t*)context;
+ osm_madw_t* const p_madw = (osm_madw_t*)p_data;
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_disp_done_callback );
+
+ /*
+ 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 );
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ }
+ else
+ {
+ if( p_madw->resp_expected == TRUE )
+ __osm_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/__osm_sm_mad_ctrl_update_wire_stats
+ * NAME
+ * __osm_sm_mad_ctrl_update_wire_stats
+ *
+ * DESCRIPTION
+ * Updates wire stats for outstanding MADs and calls the VL15 poller.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_update_wire_stats(
+ IN osm_sm_mad_ctrl_t* const p_ctrl )
+{
+ uint32_t mads_on_wire;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_update_wire_stats );
+
+ mads_on_wire = cl_atomic_dec(
+ &p_ctrl->p_stats->qp0_mads_outstanding_on_wire );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_update_wire_stats: "
+ "%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/__osm_sm_mad_ctrl_process_get_resp
+ * NAME
+ * __osm_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
+__osm_sm_mad_ctrl_process_get_resp(
+ IN osm_sm_mad_ctrl_t* const 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, __osm_sm_mad_ctrl_process_get_resp );
+
+ 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 )
+ {
+ if( !ib_smp_is_d( p_smp ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3102: "
+ "'D' bit not set in returned SMP\n" );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ }
+ }
+
+ p_old_madw = (osm_madw_t*)transaction_context;
+
+ __osm_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_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_GUID_INFO:
+ case IB_MAD_ATTR_CLASS_PORT_INFO:
+ case IB_MAD_ATTR_NOTICE:
+ case IB_MAD_ATTR_INFORM_INFO:
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3103: "
+ "Unsupported attribute = 0x%X\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ goto Exit;
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_get_resp: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get_resp: ERR 3104: "
+ "Dispatcher post message failed (%s) for attribute = 0x%X\n",
+ CL_STATUS_MSG( status ),
+ cl_ntoh16( p_smp->attr_id ) );
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/****f* opensm: SM/__osm_sm_mad_ctrl_process_get
+ * NAME
+ * __osm_sm_mad_ctrl_process_get
+ *
+ * DESCRIPTION
+ * This function handles method Get() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_get(
+ IN osm_sm_mad_ctrl_t* const 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, __osm_sm_mad_ctrl_process_get );
+
+ 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:
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_mad_ctrl_process_get: "
+ "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ break;
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_get: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_get: ERR 3106: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is an unknown MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ 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: SM/__osm_sm_mad_ctrl_process_set
+ * NAME
+ * __osm_sm_mad_ctrl_process_set
+ *
+ * DESCRIPTION
+ * This function handles method Set() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_set(
+ IN osm_sm_mad_ctrl_t* const 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, __osm_sm_mad_ctrl_process_set );
+
+ 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:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_set: ERR 3107: "
+ "Unsupported attribute = 0x%X\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ break;
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_set: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_set: ERR 3108: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is an unknown MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ 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: SM/__osm_sm_mad_ctrl_process_trap
+ * NAME
+ * __osm_sm_mad_ctrl_process_trap
+ *
+ * DESCRIPTION
+ * This function handles method Trap() for received MADs.
+ *
+ * SYNOPSIS
+ */
+static void
+__osm_sm_mad_ctrl_process_trap(
+ IN osm_sm_mad_ctrl_t* const 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, __osm_sm_mad_ctrl_process_trap );
+
+ 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,
+ "__osm_sm_mad_ctrl_process_trap: "
+ "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:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_trap: ERR 3109: "
+ "Unsupported attribute = 0x%X\n",
+ cl_ntoh16( p_smp->attr_id ) );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ break;
+ }
+
+ if( msg_id != CL_DISP_MSGID_NONE )
+ {
+ /*
+ Post this MAD to the dispatcher for asynchronous
+ processing by the appropriate controller.
+ */
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_process_trap: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( msg_id ) );
+ }
+
+ status = cl_disp_post( p_ctrl->h_disp,
+ msg_id,
+ p_madw,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_process_trap: ERR 3110: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /*
+ There is an unknown MAD attribute type for which there is
+ no recipient. Simply retire the MAD here.
+ */
+ 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: SM/__osm_sm_mad_ctrl_rcv_callback
+ * NAME
+ * __osm_sm_mad_ctrl_rcv_callback
+ *
+ * DESCRIPTION
+ * This is the callback from the transport layer for received MADs.
+ *
+ * SYNOPSIS
+ */
+void
+__osm_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 = (osm_sm_mad_ctrl_t*)bind_context;
+ ib_smp_t* p_smp;
+ ib_net16_t status;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_rcv_callback );
+
+ 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 );
+
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_rcv_callback: "
+ "%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,
+ "__osm_sm_mad_ctrl_rcv_callback: "
+ "Ignoring received mad - since we are exiting\n");
+
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_DEBUG );
+
+ /* retire the mad or put it back */
+ if( ib_smp_is_response( p_smp ) ||
+ (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS))
+ {
+ CL_ASSERT( p_madw->resp_expected == FALSE );
+ __osm_sm_mad_ctrl_retire_trans_mad( p_ctrl, p_madw );
+ }
+ else
+ {
+ if( p_madw->resp_expected == TRUE )
+ __osm_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( p_ctrl->p_log, OSM_LOG_FRAMES ) )
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, 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 )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_rcv_callback: ERR 3111: "
+ "Error status = 0x%X\n", status );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, OSM_LOG_ERROR );
+ }
+
+ switch( p_smp->method )
+ {
+ case IB_MAD_METHOD_GET_RESP:
+ CL_ASSERT( p_req_madw != NULL );
+ __osm_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 );
+ __osm_sm_mad_ctrl_process_get( p_ctrl, p_madw );
+ break;
+
+ case IB_MAD_METHOD_TRAP:
+ CL_ASSERT( p_req_madw == NULL );
+ __osm_sm_mad_ctrl_process_trap( p_ctrl, p_madw );
+ break;
+
+ case IB_MAD_METHOD_SET:
+ CL_ASSERT( p_req_madw == NULL );
+ __osm_sm_mad_ctrl_process_set( p_ctrl, p_madw );
+ break;
+
+ case IB_MAD_METHOD_SEND:
+ case IB_MAD_METHOD_REPORT:
+ case IB_MAD_METHOD_REPORT_RESP:
+ case IB_MAD_METHOD_TRAP_REPRESS:
+ default:
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_rcv_callback: ERR 3112: "
+ "Unsupported method = 0x%X\n", p_smp->method );
+ osm_dump_dr_smp( p_ctrl->p_log, p_smp, 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/__osm_sm_mad_ctrl_send_err_cb
+ * NAME
+ * __osm_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
+ */
+void
+__osm_sm_mad_ctrl_send_err_cb(
+ IN void *bind_context,
+ IN osm_madw_t *p_madw )
+{
+ osm_sm_mad_ctrl_t* p_ctrl = (osm_sm_mad_ctrl_t*)bind_context;
+#if 0
+ osm_physp_t* p_physp;
+#endif
+ ib_api_status_t status;
+ ib_smp_t* p_smp;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sm_mad_ctrl_send_err_cb );
+
+ CL_ASSERT( p_madw );
+
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3113: "
+ "MAD completed in error (%s)\n",
+ ib_get_err_str( p_madw->status ) );
+
+ /*
+ 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.
+ */
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ if (p_smp->method == IB_MAD_METHOD_SET &&
+ ( p_smp->attr_id == IB_MAD_ATTR_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 ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3119: "
+ "Set method failed\n" );
+ p_ctrl->p_subn->subnet_initialization_error = TRUE;
+ }
+
+ /*
+ 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 )
+ {
+ 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,
+ "__osm_sm_mad_ctrl_send_err_cb: 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.
+ */
+
+ osm_dump_dr_smp( p_ctrl->p_log, osm_madw_get_smp_ptr( p_madw ),
+ OSM_LOG_ERROR );
+
+ __osm_sm_mad_ctrl_update_wire_stats( p_ctrl );
+
+ if( osm_madw_get_err_msg( p_madw ) != CL_DISP_MSGID_NONE )
+ {
+ if( osm_log_is_active( p_ctrl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_mad_ctrl_send_err_cb: "
+ "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,
+ __osm_sm_mad_ctrl_disp_done_callback,
+ p_ctrl );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "__osm_sm_mad_ctrl_send_err_cb: ERR 3115: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+ else
+ {
+ /*
+ No error message was provided, just retire the MAD.
+ */
+ __osm_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* const 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* const 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* const p_ctrl,
+ IN osm_subn_t* const p_subn,
+ IN osm_mad_pool_t* const p_mad_pool,
+ IN osm_vl15_t* const p_vl15,
+ IN osm_vendor_t* const p_vendor,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN cl_plock_t* const p_lock,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sm_mad_ctrl_init );
+
+ 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,
+ "osm_sm_mad_ctrl_init: 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* const p_ctrl,
+ IN const 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, osm_sm_mad_ctrl_bind );
+
+ if( p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_ctrl->p_log, OSM_LOG_ERROR,
+ "osm_sm_mad_ctrl_bind: 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;
+
+ osm_log( p_ctrl->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_mad_ctrl_bind: "
+ "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,
+ __osm_sm_mad_ctrl_rcv_callback,
+ __osm_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,
+ "osm_sm_mad_ctrl_bind: ERR 3118: "
+ "Vendor specific bind failed\n" );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_ctrl->p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_t.
+ * This file implements the SM State Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.7 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <time.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_standby_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering STANDBY state\n" ); /* Format Waived */
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_standby_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM STANDBY"
+ " STATE *******************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_master_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_log( p_sm_mgr->p_log, OSM_LOG_SYS, "Entering MASTER state\n" ); /* Format Waived */
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_master_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM MASTER"
+ " STATE ********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_discovering_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_discovering_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM DISCOVERING"
+ " STATE ***************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_notactive_msg(
+ IN const osm_sm_state_mgr_t * p_sm_mgr )
+{
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_notactive_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING SM NOT-ACTIVE"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+#if 0
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_send_local_port_info_req(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_madw_context_t context;
+ osm_port_t *p_port;
+ ib_net64_t port_guid = p_sm_mgr->p_subn->sm_port_guid;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log,
+ __osm_sm_state_mgr_send_local_port_info_req );
+ /*
+ * Send a query of SubnGet(PortInfo) to our own port, in order to
+ * update the master_sm_base_lid of the subnet.
+ */
+ memset( &context, 0, sizeof( context ) );
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+ port_guid );
+ if( p_port ==
+ ( osm_port_t * ) cl_qmap_end( &p_sm_mgr->p_subn->port_guid_tbl ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_local_port_info_req: ERR 3205: "
+ "No port object for port 0x%016" PRIx64 "\n",
+ cl_ntoh64( port_guid ) );
+ goto Exit;
+ }
+
+ context.pi_context.port_guid = port_guid;
+ context.pi_context.node_guid = p_port->p_node->node_info.node_guid;
+ context.pi_context.set_method = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ /* mark the update_master_sm_base_lid with TRUE - we want to update it */
+ /* with the new master lid value. */
+ context.pi_context.update_master_sm_base_lid = TRUE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ status = osm_req_get( p_sm_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ),
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( p_port->default_port_num ),
+ CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_local_port_info_req: ERR 3202: "
+ "Failure requesting PortInfo (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+#endif
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_send_master_sm_info_req(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ osm_madw_context_t context;
+ const osm_port_t *p_port;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log,
+ __osm_sm_state_mgr_send_master_sm_info_req );
+
+ memset( &context, 0, sizeof( context ) );
+ if( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY )
+ {
+ /*
+ * We are in STANDBY state - this means we need to poll on the master
+ * SM (according to master_guid)
+ * Send a query of SubnGet(SMInfo) to the subn master_sm_base_lid object.
+ */
+ p_port = ( osm_port_t * ) cl_qmap_get( &p_sm_mgr->p_subn->port_guid_tbl,
+ p_sm_mgr->master_guid );
+ }
+ else
+ {
+ /*
+ * We are not in STANDBY - this means we are in MASTER state - so we need
+ * to poll on the SM that is saved in p_polling_sm under p_sm_mgr.
+ * Send a query of SubnGet(SMInfo) to that SM.
+ */
+ p_port = p_sm_mgr->p_polling_sm->p_port;
+ }
+ if( p_port == NULL )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3203: "
+ "No port object for GUID 0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sm_mgr->master_guid) );
+ goto Exit;
+ }
+
+ context.smi_context.port_guid = p_port->guid;
+ context.smi_context.set_method = FALSE;
+
+ status = osm_req_get( p_sm_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ),
+ IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_send_master_sm_info_req: ERR 3204: "
+ "Failure rquesting SMInfo (%s)\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_start_polling(
+ IN osm_sm_state_mgr_t * p_sm_mgr )
+{
+ uint32_t sminfo_polling_timeout =
+ p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_start_polling );
+
+ /*
+ * Init the retry_nubmer back to zero - need to restart counting
+ */
+ p_sm_mgr->retry_number = 0;
+
+ /*
+ * Send a SubnGet(SMInfo) query to the current (or new) master found.
+ */
+ __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+ /*
+ * 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( &p_sm_mgr->polling_timer,
+ sminfo_polling_timeout );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_start_polling : ERR 3210: "
+ "Failed to start timer\n" );
+ }
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sm_state_mgr_polling_callback(
+ IN void *context )
+{
+ osm_sm_state_mgr_t *p_sm_mgr = ( osm_sm_state_mgr_t * ) context;
+ uint32_t sminfo_polling_timeout =
+ p_sm_mgr->p_subn->opt.sminfo_polling_timeout;
+ cl_status_t cl_status;
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, __osm_sm_state_mgr_polling_callback );
+
+ /*
+ * 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( !( ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER &&
+ p_sm_mgr->p_polling_sm != NULL ) ||
+ ( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY ) ) )
+ {
+ goto Exit;
+ }
+
+ /*
+ * If we are a STANDBY sm and the osm_exit_flag is 1, 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( p_sm_mgr->p_subn->sm_state == IB_SMINFO_STATE_STANDBY &&
+ osm_exit_flag == 1 )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Signalling subnet_up_event\n" );
+ cl_event_signal( p_sm_mgr->p_state_mgr->p_subnet_up_event );
+ goto Exit;
+ }
+
+ /*
+ * Incr the retry number.
+ * If it reached the max_retry_number in the subnet opt - call
+ * osm_sm_state_mgr_process with signal OSM_SM_SIGNAL_POLLING_TIMEOUT
+ */
+ p_sm_mgr->retry_number++;
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Retry number:%d\n", p_sm_mgr->retry_number );
+
+ if( p_sm_mgr->retry_number >= p_sm_mgr->p_subn->opt.polling_retry_number )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_sm_state_mgr_polling_callback : "
+ "Reached polling_retry_number value in retry_number. "
+ "Go to DISCOVERY state\n" );
+ osm_sm_state_mgr_process( p_sm_mgr, OSM_SM_SIGNAL_POLLING_TIMEOUT );
+ goto Exit;
+ }
+
+ /* Send a SubnGet(SMInfo) request to the remote sm (depends on our state) */
+ __osm_sm_state_mgr_send_master_sm_info_req( p_sm_mgr );
+
+ /* restart the timer */
+ cl_status = cl_timer_start( &p_sm_mgr->polling_timer,
+ sminfo_polling_timeout );
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_polling_callback : ERR 3211: "
+ "Failed to restart timer\n" );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_construct(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ memset( p_sm_mgr, 0, sizeof( *p_sm_mgr ) );
+ cl_spinlock_construct( &p_sm_mgr->state_lock );
+ cl_timer_construct( &p_sm_mgr->polling_timer );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_destroy(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ CL_ASSERT( p_sm_mgr );
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_destroy );
+
+ cl_spinlock_destroy( &p_sm_mgr->state_lock );
+ cl_timer_destroy( &p_sm_mgr->polling_timer );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_init(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_state_mgr_t * const p_state_mgr,
+ IN osm_subn_t * const p_subn,
+ IN osm_req_t * const p_req,
+ IN osm_log_t * const p_log )
+{
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_sm_state_mgr_init );
+
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_state_mgr );
+ CL_ASSERT( p_req );
+
+ osm_sm_state_mgr_construct( p_sm_mgr );
+
+ p_sm_mgr->p_log = p_log;
+ p_sm_mgr->p_req = p_req;
+ p_sm_mgr->p_subn = p_subn;
+ p_sm_mgr->p_state_mgr = p_state_mgr;
+
+ /* init the state of the SM to idle */
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_INIT;
+
+ status = cl_spinlock_init( &p_sm_mgr->state_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_init: ERR 3201: "
+ "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+ }
+
+ status = cl_timer_init( &p_sm_mgr->polling_timer,
+ __osm_sm_state_mgr_polling_callback, p_sm_mgr );
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_init: ERR 3206: "
+ "Timer init failed (%s)\n", CL_STATUS_MSG( status ) );
+ }
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sm_state_mgr_signal_error(
+ IN const osm_sm_state_mgr_t * const p_sm_mgr,
+ IN const osm_sm_signal_t signal )
+{
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_sm_state_mgr_signal_error: ERR 3207: "
+ "Invalid signal %s in state %s\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sm_state_mgr_signal_master_is_alive(
+ IN osm_sm_state_mgr_t * const p_sm_mgr )
+{
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_signal_master_is_alive );
+ p_sm_mgr->retry_number = 0;
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_process(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_sm_signal_t signal )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ CL_ASSERT( p_sm_mgr );
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_process );
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process.
+ */
+ cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_sm_state_mgr_process: "
+ "Received signal %s in state %s\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ }
+
+ switch ( p_sm_mgr->p_subn->sm_state )
+ {
+ case IB_SMINFO_STATE_INIT:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_INIT:
+ /*
+ * Update the state of the SM to DISCOVERING
+ */
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ break;
+
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_DISCOVERING:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_DISCOVERY_COMPLETED:
+ /*
+ * Update the state of the SM to MASTER
+ */
+ __osm_sm_state_mgr_master_msg( p_sm_mgr );
+ /* Turn on the moved_to_master_state flag */
+ p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+ /* Turn on the first_time_master_sweep flag */
+ if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+ p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+ /*
+ * Make sure to set the subnet master_sm_base_lid
+ * to the sm_base_lid value
+ */
+ p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+ break;
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ /*
+ * Stop the discovering
+ */
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr,
+ OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED );
+ break;
+ case OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+ /*
+ * Finished all discovery actions - move to STANDBY
+ * start the polling
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ /*
+ * Since another SM is doing the LFT config - we should not
+ * ignore the results of it
+ */
+ p_sm_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ case OSM_SM_SIGNAL_HANDOVER:
+ /*
+ * Do nothing. We will discover it later on. 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).
+ */
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, 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
+ * no longer alive.
+ * case 2: Got a signal to move to DISCOVERING
+ * Move to DISCOVERING state, and start sweeping
+ */
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+ break;
+ case OSM_SM_SIGNAL_DISABLE:
+ /*
+ * Update the state to NOT_ACTIVE
+ */
+ __osm_sm_state_mgr_notactive_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_NOTACTIVE;
+ break;
+ case OSM_SM_SIGNAL_HANDOVER:
+ /*
+ * Update state to MASTER, and start sweeping
+ * OPTIONAL: send ACKNOWLEDGE
+ */
+ __osm_sm_state_mgr_master_msg( p_sm_mgr );
+ /* Turn on the moved_to_master_state flag */
+ p_sm_mgr->p_subn->moved_to_master_state = TRUE;
+ /* Turn on the first_time_master_sweep flag */
+ if( p_sm_mgr->p_subn->first_time_master_sweep == FALSE )
+ p_sm_mgr->p_subn->first_time_master_sweep = TRUE;
+ /* Turn on the force_immediate_heavy_sweep - we want a
+ * heavy sweep to occur on the first sweep of this SM. */
+ p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_MASTER;
+ /*
+ * Make sure to set the subnet master_sm_base_lid
+ * to the sm_base_lid value
+ */
+ p_sm_mgr->p_subn->master_sm_base_lid = p_sm_mgr->p_subn->sm_base_lid;
+ p_sm_mgr->p_subn->coming_out_of_standby = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_EXIT_STBY );
+ break;
+ case OSM_SM_SIGNAL_ACKNOWLEDGE:
+ /*
+ * Do nothing - already moved to STANDBY
+ */
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, 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
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, 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 p_polling_sm object - 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 p_polling_sm object - since we are
+ * done polling on that remote sm - we got a handover from it.
+ */
+ osm_log( p_sm_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_sm_state_mgr_process: "
+ "Forcing immediate heavy sweep. "
+ "Received OSM_SM_SIGNAL_HANDOVER or OSM_SM_SIGNAL_POLLING_TIMEOUT\n" );
+ p_sm_mgr->p_polling_sm = NULL;
+ p_sm_mgr->p_subn->force_immediate_heavy_sweep = TRUE;
+ osm_state_mgr_process( p_sm_mgr->p_state_mgr, OSM_SIGNAL_SWEEP );
+ break;
+ case OSM_SM_SIGNAL_HANDOVER_SENT:
+ /*
+ * Just sent a HANDOVER signal - move to STANDBY
+ * start the polling
+ */
+ __osm_sm_state_mgr_standby_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_STANDBY;
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ 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
+ * on 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.
+ */
+ __osm_sm_state_mgr_start_polling( p_sm_mgr );
+ break;
+ case OSM_SM_SIGNAL_DISCOVER:
+ __osm_sm_state_mgr_discovering_msg( p_sm_mgr );
+ p_sm_mgr->p_subn->sm_state = IB_SMINFO_STATE_DISCOVERING;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ default:
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_process: ERR 3208: "
+ "Invalid state %s\n",
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+
+ }
+
+ cl_spinlock_release( &p_sm_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sm_state_mgr_check_legality(
+ IN osm_sm_state_mgr_t * const p_sm_mgr,
+ IN osm_sm_signal_t signal )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ CL_ASSERT( p_sm_mgr );
+
+ OSM_LOG_ENTER( p_sm_mgr->p_log, osm_sm_state_mgr_check_legality );
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process.
+ */
+ cl_spinlock_acquire( &p_sm_mgr->state_lock );
+
+ if( osm_log_is_active( p_sm_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_sm_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_sm_state_mgr_check_legality: "
+ "Received signal %s in state %s\n",
+ osm_get_sm_mgr_signal_str( signal ),
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ }
+
+ switch ( p_sm_mgr->p_subn->sm_state )
+ {
+ case IB_SMINFO_STATE_INIT:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_INIT:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ 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_MASTER_OR_HIGHER_SM_DETECTED_DONE:
+ case OSM_SM_SIGNAL_HANDOVER:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, 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:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ case IB_SMINFO_STATE_NOTACTIVE:
+ switch ( signal )
+ {
+ case OSM_SM_SIGNAL_STANDBY:
+ status = IB_SUCCESS;
+ break;
+ default:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, 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:
+ __osm_sm_state_mgr_signal_error( p_sm_mgr, signal );
+ status = IB_INVALID_PARAMETER;
+ break;
+ }
+ break;
+
+ default:
+ osm_log( p_sm_mgr->p_log, OSM_LOG_ERROR,
+ "osm_sm_state_mgr_check_legality: ERR 3209: "
+ "Invalid state %s\n",
+ osm_get_sm_mgr_state_str( p_sm_mgr->p_subn->sm_state ) );
+ status = IB_INVALID_PARAMETER;
+
+ }
+
+ cl_spinlock_release( &p_sm_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_sm_mgr->p_log );
+ return ( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sminfo_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sminfo_rcv_t.
+ * This object represents the SMInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sminfo_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_construct(
+ IN osm_sminfo_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_destroy(
+ IN osm_sminfo_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_init(
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN osm_sm_state_mgr_t* const p_sm_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sminfo_rcv_init );
+
+ osm_sminfo_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_state_mgr = p_state_mgr;
+ p_rcv->p_sm_state_mgr = p_sm_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ 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 inline boolean_t
+__osm_sminfo_rcv_remote_sm_is_higher(
+ IN const osm_sminfo_rcv_t* p_rcv,
+ IN const ib_sm_info_t* p_remote_sm )
+{
+
+ return( osm_sm_is_greater_than( ib_sminfo_get_priority( p_remote_sm ),
+ p_remote_sm->guid,
+ p_rcv->p_subn->opt.sm_priority,
+ p_rcv->p_subn->sm_port_guid) );
+
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_request(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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_api_status_t status;
+ ib_sm_info_t* p_remote_smi;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_request );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ No real need to grab the lock for this function.
+ */
+ memset( payload, 0, sizeof( payload ) );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( p_smp->method == IB_MAD_METHOD_GET );
+
+ p_smi->guid = p_rcv->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+ p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+ p_rcv->p_subn->opt.sm_priority << 4);
+ /*
+ p.750 row 11 - 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_get_request: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requester is not authenticated as master - set sm_key to zero. */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_get_request: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_request: ERR 2F02: "
+ "Error sending response (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * Check if the p_smp received is legal.
+ * Current checks:
+ * MADHeader:AttributeModifiers 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 is matching.
+ **********************************************************************/
+static ib_api_status_t
+__osm_sminfo_rcv_check_set_req_legality(
+ IN const ib_smp_t* const 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
+__osm_sminfo_rcv_process_set_request(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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* p_rcv_smi;
+ ib_api_status_t status;
+ osm_sm_signal_t sm_signal;
+ ib_sm_info_t* p_remote_smi;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_request );
+
+ CL_ASSERT( p_madw );
+
+ /*
+ No real need to grab the lock for this function.
+ */
+ memset( payload, 0, sizeof( payload ) );
+
+ /* get the lock */
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_rcv_smi = ib_smp_get_payload_ptr( p_smp );
+
+ if( p_smp->method != IB_MAD_METHOD_SET )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F03: "
+ "Unsupported method 0x%X\n",
+ p_smp->method );
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ p_smi->guid = p_rcv->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_rcv->p_stats->qp0_mads_sent );
+ p_smi->pri_state = (uint8_t)(p_rcv->p_subn->sm_state |
+ p_rcv->p_subn->opt.sm_priority << 4);
+ /*
+ p.750 row 11 - 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_rcv->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requester is not authenticated as master - set sm_key to zero. */
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ /* Check the legality of the packet */
+ status = __osm_sminfo_rcv_check_set_req_legality( p_smp );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: 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( p_rcv_smi ) ) );
+ /* send a response with error code */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F05: "
+ "Error sending response (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ CL_PLOCK_RELEASE( p_rcv->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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F06: "
+ "THIS CODE SHOULD NOT BE REACHED!!\n");
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ /* check legality of the needed transition in the SM state machine */
+ status = osm_sm_state_mgr_check_legality( p_rcv->p_sm_state_mgr,
+ sm_signal );
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F07: "
+ "Check legality of SM needed transition. AttributeModifier:0x%X RemoteState:%s\n",
+ p_smp->attr_mod,
+ osm_get_sm_mgr_state_str(ib_sminfo_get_state( p_rcv_smi ) ) );
+ /* send a response with error code */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 7, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F08: "
+ "Error sending response (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ goto Exit;
+ }
+
+ /* the SubnSet(SMInfo) command is ok. Send a response. */
+ status = osm_resp_send( p_rcv->p_resp, p_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F09: "
+ "Error sending 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 */
+ /* p_sm_state_mgr in the master_guid variable - the guid of the */
+ /* current master. */
+ if ( p_smp->attr_mod == IB_SMINFO_ATTR_MOD_STANDBY )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_set_request: "
+ "Received a STANDBY signal. Updating "
+ "sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
+ cl_ntoh64(p_rcv_smi->guid) );
+ p_rcv->p_sm_state_mgr->master_guid = p_rcv_smi->guid;
+ }
+
+ /* call osm_sm_state_mgr_process with the received signal. */
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ status = osm_sm_state_mgr_process( p_rcv->p_sm_state_mgr,
+ sm_signal );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_request: ERR 2F10: "
+ "Error in SM state transition (%s)\n",
+ ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ * Return a signal with which to call the osm_state_mgr_process.
+ * This is done since we are locked by p_rcv->p_lock in this function,
+ * and thus cannot call osm_state_mgr_process (that locks the state_lock).
+ * If return OSM_SIGNAL_NONE - do not call osm_state_mgr_process.
+ **********************************************************************/
+static osm_signal_t
+__osm_sminfo_rcv_process_get_sm(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_remote_sm_t* const p_sm )
+{
+ const ib_sm_info_t* p_smi;
+ osm_signal_t ret_val = OSM_SIGNAL_NONE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_sm );
+
+ p_smi = &p_sm->smi;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Detected SM 0x%016" PRIx64 " in state %u\n",
+ cl_ntoh64( p_smi->guid ), ib_sminfo_get_state( p_smi ) );
+ }
+
+ /*
+ Check the state of this SM vs. our own.
+ */
+ switch( p_rcv->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:
+ ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+ /* save on the p_sm_state_mgr the guid of the current master. */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Found master SM. Updating sm_state_mgr master_guid: 0x%016" PRIx64 "\n",
+ cl_ntoh64( p_sm->p_port->guid ) );
+ p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->guid;
+ break;
+ case IB_SMINFO_STATE_DISCOVERING:
+ case IB_SMINFO_STATE_STANDBY:
+ if ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+ {
+ /* the remote is a higher sm - need to stop sweeping */
+ ret_val = OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED;
+ /* save on the p_sm_state_mgr the guid of the higher SM we found - */
+ /* we will poll it - as long as it lives - we should be in Standby. */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_sminfo_rcv_process_get_sm: "
+ "Found higher SM. Updating sm_state_mgr master_guid:"
+ " 0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sm->p_port->guid) );
+ p_rcv->p_sm_state_mgr->master_guid = p_sm->p_port->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( p_rcv->p_sm_state_mgr );
+ 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 (p_rcv->p_sm_state_mgr->master_guid == p_sm->p_port->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 ( __osm_sminfo_rcv_remote_sm_is_higher(p_rcv, p_smi) == TRUE )
+ osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+ }
+ 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 ( p_rcv->p_sm_state_mgr->p_polling_sm != NULL )
+ {
+ osm_sm_state_mgr_signal_master_is_alive( p_rcv->p_sm_state_mgr );
+ }
+ else
+ {
+ /* This is a response we got while sweeping the subnet.
+ We will handle a case of handover needed later on, when the sweep
+ is done and all SMs are recongnized. */
+ }
+ break;
+ default:
+ /* any other state - do nothing */
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return ret_val;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_get_response(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_smp_t* p_smp;
+ const ib_sm_info_t* p_smi;
+ cl_qmap_t* p_sm_tbl;
+ cl_qmap_t* p_port_tbl;
+ osm_port_t* p_port;
+ ib_net64_t port_guid;
+ osm_remote_sm_t* p_sm;
+ osm_signal_t process_get_sm_ret_val = OSM_SIGNAL_NONE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_get_response );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F11: "
+ "Unsupported method 0x%X\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ p_smi = ib_smp_get_payload_ptr( p_smp );
+ p_sm_tbl = &p_rcv->p_subn->sm_guid_tbl;
+ p_port_tbl = &p_rcv->p_subn->port_guid_tbl;
+ port_guid = p_smi->guid;
+
+ osm_dump_sm_info( p_rcv->p_log, p_smi, 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 != p_rcv->p_subn->opt.sm_key )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F18: "
+ "Got SM with sm_key that doesn't match our "
+ "local key. Exiting\n" );
+ osm_log( p_rcv->p_log, OSM_LOG_SYS,
+ "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( p_rcv->p_lock );
+
+ p_port = (osm_port_t*)cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == (osm_port_t*)cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F12: "
+ "No port object for this SM\n" );
+ goto Exit;
+ }
+
+ if( osm_port_get_guid( p_port ) != p_smi->guid )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F13: "
+ "Bogus SM port GUID"
+ "\n\t\t\t\tExpected 0x%016" PRIx64
+ ", Received 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ cl_ntoh64( p_smi->guid ) );
+ goto 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_get_response: ERR 2F14: "
+ "Unable to allocate SM object\n" );
+ goto Exit;
+ }
+
+ osm_remote_sm_init( p_sm, p_port, 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;
+ }
+
+ process_get_sm_ret_val = __osm_sminfo_rcv_process_get_sm( p_rcv, p_sm );
+
+ Exit:
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+
+ /* If process_get_sm_ret_val != OSM_SIGNAL_NONE then we have to signal
+ * to the state_mgr with that signal. */
+ if (process_get_sm_ret_val != OSM_SIGNAL_NONE)
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ process_get_sm_ret_val );
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_sminfo_rcv_process_set_response(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+ const ib_smp_t* p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_sminfo_rcv_process_set_response );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ if( p_smp->method != IB_MAD_METHOD_GET_RESP )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_response: ERR 2F16: "
+ "Unsupported method 0x%X\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ /* Check the AttributeModifier */
+ if ( p_smp->attr_mod != IB_SMINFO_ATTR_MOD_HANDOVER )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_sminfo_rcv_process_set_response: ERR 2F17: "
+ "Unsupported attribute modifier 0x%X\n",
+ p_smp->attr_mod );
+ goto Exit;
+ }
+
+ /*
+ This is a response on a HANDOVER request -
+ Nothing to do.
+ */
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_process(
+ IN const osm_sminfo_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ ib_smp_t *p_smp;
+ osm_smi_context_t *p_smi_context;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_sminfo_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ 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 ) )
+ {
+ /* 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 );
+ if ( p_smi_context->set_method == FALSE )
+ {
+ /* this is a response to a Get method */
+ __osm_sminfo_rcv_process_get_response( p_rcv, p_madw );
+ }
+ else
+ {
+ /* this is a response to a Set method */
+ __osm_sminfo_rcv_process_set_response( p_rcv, p_madw );
+ }
+ }
+ else
+ {
+ /* This is a request */
+ if ( p_smp->method == IB_MAD_METHOD_GET )
+ {
+ /* This is a SubnGet request */
+ __osm_sminfo_rcv_process_get_request( p_rcv, p_madw );
+ }
+ else
+ {
+ /* This is a SubnSet request */
+ __osm_sminfo_rcv_process_set_request( p_rcv, p_madw );
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sminfo_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sminfo_rcv_ctrl_t.
+ * This object represents the SMInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sminfo_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sminfo_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_sminfo_rcv_process( ((osm_sminfo_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_construct(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sminfo_rcv_ctrl_destroy(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sminfo_rcv_ctrl_init(
+ IN osm_sminfo_rcv_ctrl_t* const p_ctrl,
+ IN osm_sminfo_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sminfo_rcv_ctrl_init );
+
+ osm_sminfo_rcv_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SM_INFO,
+ __osm_sminfo_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sminfo_rcv_ctrl_init: ERR 3001: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_state_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_t.
+ * This file implements the State Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_state_mgr.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_pkey_mgr.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_sm_state_mgr.h>
+#include <opensm/osm_opensm.h>
+
+#define SUBNET_LIST_FILENAME "/osm-subnet.lst"
+
+osm_signal_t osm_qos_setup(IN osm_opensm_t * p_osm);
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_construct(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ memset( p_mgr, 0, sizeof( *p_mgr ) );
+ cl_spinlock_construct( &p_mgr->state_lock );
+ cl_spinlock_construct( &p_mgr->idle_lock );
+ p_mgr->state = OSM_SM_STATE_INIT;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_destroy(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_destroy );
+
+ /* destroy the locks */
+ cl_spinlock_destroy( &p_mgr->state_lock );
+ cl_spinlock_destroy( &p_mgr->idle_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_init(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_subn_t * const p_subn,
+ IN osm_lid_mgr_t * const p_lid_mgr,
+ IN osm_ucast_mgr_t * const p_ucast_mgr,
+ IN osm_mcast_mgr_t * const p_mcast_mgr,
+ IN osm_link_mgr_t * const p_link_mgr,
+ IN osm_drop_mgr_t * const p_drop_mgr,
+ IN osm_req_t * const p_req,
+ IN osm_stats_t * const p_stats,
+ IN osm_sm_state_mgr_t * const p_sm_state_mgr,
+ IN const osm_sm_mad_ctrl_t * const p_mad_ctrl,
+ IN cl_plock_t * const p_lock,
+ IN cl_event_t * const p_subnet_up_event,
+ IN osm_log_t * const p_log )
+{
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_log, osm_state_mgr_init );
+
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lid_mgr );
+ CL_ASSERT( p_ucast_mgr );
+ CL_ASSERT( p_mcast_mgr );
+ CL_ASSERT( p_link_mgr );
+ CL_ASSERT( p_drop_mgr );
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_stats );
+ CL_ASSERT( p_sm_state_mgr );
+ CL_ASSERT( p_mad_ctrl );
+ CL_ASSERT( p_lock );
+
+ osm_state_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lid_mgr = p_lid_mgr;
+ p_mgr->p_ucast_mgr = p_ucast_mgr;
+ p_mgr->p_mcast_mgr = p_mcast_mgr;
+ p_mgr->p_link_mgr = p_link_mgr;
+ p_mgr->p_drop_mgr = p_drop_mgr;
+ p_mgr->p_mad_ctrl = p_mad_ctrl;
+ p_mgr->p_req = p_req;
+ p_mgr->p_stats = p_stats;
+ p_mgr->p_sm_state_mgr = p_sm_state_mgr;
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_subnet_up_event = p_subnet_up_event;
+ p_mgr->state_step_mode = OSM_STATE_STEP_CONTINUOUS;
+ p_mgr->next_stage_signal = OSM_SIGNAL_NONE;
+
+ status = cl_spinlock_init( &p_mgr->state_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_init: ERR 3301: "
+ "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+ }
+
+ cl_qlist_init( &p_mgr->idle_time_list );
+
+ status = cl_spinlock_init( &p_mgr->idle_lock );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_init: ERR 3302: "
+ "Spinlock init failed (%s)\n", CL_STATUS_MSG( status ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_up_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ /*
+ * This message should be written only once - when the
+ * SM moves to Master state and the subnet is up for
+ * the first time. The change of state is marked with
+ * the subnet flag moved_to_master_state
+ */
+ if( p_mgr->p_subn->moved_to_master_state == TRUE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "SUBNET UP\n" ); /* Format Waived */
+ /* clear the signal */
+ p_mgr->p_subn->moved_to_master_state = FALSE;
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_INFO, "SUBNET UP\n" ); /* Format Waived */
+ }
+
+ if( p_mgr->p_subn->opt.sweep_interval )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_up_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "**************************** SUBNET UP "
+ "***************************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_up_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************* SUBNET UP "
+ "(sweep disabled) *******************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_init_errors_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "Errors during initialization\n" ); /* Format Waived */
+
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_init_errors_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "****************** ERRORS DURING INITI"
+ "ALIZATION ******************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_light_sweep_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_light_sweep_done_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "********************** LIGHT SWEEP "
+ "COMPLETE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_standby_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_standby_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "******************** ENTERING STANDBY"
+ " STATE **********************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sm_port_down_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_SYS, "SM port is down\n" ); /* Format Waived */
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sm_port_down_msg: "
+ "\n\n\n********************************"
+ "**********************************\n"
+ "************************** SM PORT DOWN "
+ "**************************\n"
+ "**************************************"
+ "****************************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_lid_assign_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_lid_assign_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "***** LID ASSIGNMENT COMPLETE - STARTING SWITC"
+ "H TABLE CONFIG *****\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_set_sm_lid_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_set_sm_lid_done_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "**** SM LID ASSIGNMENT COMPLETE - STARTING SUBN"
+ "ET LID CONFIG *****\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_switch_config_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_switch_config_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "***************** SWITCHES CONFIGURED FOR UNICAST "
+ "****************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_multicast_config_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_multicast_config_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "**************** SWITCHES CONFIGURED FOR MULTICAST "
+ "***************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_ports_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_links_ports_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******* LINKS PORTS CONFIGURED - SET LINKS TO ARMED "
+ "STATE ********\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_links_armed_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_links_armed_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "************* LINKS ARMED - SET LINKS TO ACTIVE "
+ "STATE ************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_heavy_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******************** INITIATING HEAVY SWEEP "
+ "**********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_heavy_done_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_heavy_done_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "********************* HEAVY SWEEP COMPLETE "
+ "***********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_sweep_light_msg(
+ IN const osm_state_mgr_t * p_mgr )
+{
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_sweep_light_msg: "
+ "\n\n\n**************************************"
+ "****************************\n"
+ "******************** INITIATING LIGHT SWEEP "
+ "**********************\n"
+ "*********************************************"
+ "*********************\n\n\n" );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_signal_warning(
+ IN const osm_state_mgr_t * const p_mgr,
+ IN const osm_signal_t signal )
+{
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_signal_warning: "
+ "Invalid signal %s(%lu) in state %s\n",
+ osm_get_sm_signal_str( signal ),
+ signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_signal_error(
+ IN const osm_state_mgr_t * const p_mgr,
+ IN const osm_signal_t signal )
+{
+ /* the Request for IDLE processing can come async to the state so it
+ * really is just verbose ... */
+ if( signal == OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST )
+ __osm_state_mgr_signal_warning( p_mgr, signal );
+ else
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_signal_error: ERR 3303: "
+ "Invalid signal %s(%lu) in state %s\n",
+ osm_get_sm_signal_str( signal ),
+ signal, osm_get_sm_state_str( p_mgr->state ) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_node_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_node_t *p_node = ( osm_node_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_node_count: "
+ "Resetting discovery count for node 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ }
+
+ osm_node_discovery_count_reset( p_node );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_port_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_port_t *p_port = ( osm_port_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_port_count: "
+ "Resetting discovery count for port 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ }
+
+ osm_port_discovery_count_reset( p_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_reset_switch_count(
+ IN cl_map_item_t * const p_map_item,
+ IN void *context )
+{
+ osm_switch_t *p_sw = ( osm_switch_t * ) p_map_item;
+ osm_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_reset_switch_count: "
+ "Resetting discovery count for switch 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_sw->p_node ) ) );
+ }
+
+ osm_switch_discovery_count_reset( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_get_sw_info(
+ IN cl_map_item_t * const p_object,
+ IN void *context )
+{
+ osm_node_t *p_node;
+ 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_state_mgr_t *const p_mgr = ( osm_state_mgr_t * ) context;
+ ib_api_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_sw_info );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_dr_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ memset( &context, 0, sizeof( 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;
+
+ status = osm_req_get( p_mgr->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0, OSM_MSG_LIGHT_SWEEP_FAIL, &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_get_sw_info: ERR 3304: "
+ "Request SwitchInfo failed\n" );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ Initiate a remote port info request for the given physical port
+ **********************************************************************/
+static void
+__osm_state_mgr_get_remote_port_info(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_physp_t * const 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( p_mgr->p_log, __osm_state_mgr_get_remote_port_info );
+
+ /* 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 ) );
+ osm_dr_path_extend( &rem_node_dr_path, osm_physp_get_port_num( p_physp ) );
+
+ 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 =
+ cl_hton64( osm_physp_get_port_num( p_physp ) );
+ mad_context.pi_context.set_method = FALSE;
+ mad_context.pi_context.light_sweep = TRUE;
+ mad_context.pi_context.ignore_errors = FALSE;
+ mad_context.pi_context.update_master_sm_base_lid = FALSE;
+ mad_context.pi_context.active_transition = 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( p_mgr->p_req,
+ &rem_node_dr_path,
+ IB_MAD_ATTR_PORT_INFO,
+ 0, CL_DISP_MSGID_NONE, &mad_context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_get_remote_port_info: ERR 332E: "
+ "Request for PortInfo failed\n" );
+ }
+
+ OSM_LOG_EXIT( p_mgr->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
+__osm_state_mgr_sweep_hop_0(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status;
+ osm_dr_path_t dr_path;
+ osm_bind_handle_t h_bind;
+ osm_ni_context_t ni_context;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_0 );
+
+ memset( path_array, 0, sizeof( path_array ) );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ __osm_state_mgr_sweep_heavy_msg( p_mgr );
+
+ /*
+ * Start the sweep by clearing the port counts, then
+ * get our own NodeInfo at 0 hops.
+ */
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->node_guid_tbl,
+ __osm_state_mgr_reset_node_count, p_mgr );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->port_guid_tbl,
+ __osm_state_mgr_reset_port_count, p_mgr );
+
+ cl_qmap_apply_func( &p_mgr->p_subn->sw_guid_tbl,
+ __osm_state_mgr_reset_switch_count, p_mgr );
+
+ /* 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. */
+ p_mgr->p_subn->in_sweep_hop_0 = TRUE;
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ memset( &ni_context, 0, sizeof( ni_context ) );
+ osm_dr_path_init( &dr_path, h_bind, 0, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &dr_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, NULL );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_0: ERR 3305: "
+ "Request NodeInfo failed\n" );
+ }
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_sweep_hop_0: "
+ "No bound ports. Deferring sweep...\n" );
+ status = IB_INVALID_STATE;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ Clear out all existing port lid assignments
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_clean_known_lids(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ cl_ptr_vector_t *p_vec = &( p_mgr->p_subn->port_lid_tbl );
+ uint32_t i;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_clean_known_lids );
+
+ /* we need a lock here! */
+ CL_PLOCK_ACQUIRE( p_mgr->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( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->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
+__osm_state_mgr_notify_lid_change(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status;
+ osm_bind_handle_t h_bind;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_notify_lid_change );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind == OSM_BIND_INVALID_HANDLE )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_notify_lid_change: 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_notify_lid_change: ERR 3307: "
+ "Vendor LID update failed (%s)\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->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
+__osm_state_mgr_is_sm_port_down(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_net64_t port_guid;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ cl_qmap_t *p_tbl;
+ uint8_t state;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_is_sm_port_down );
+
+ port_guid = p_mgr->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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_is_sm_port_down: ERR 3308: "
+ "SM port GUID unknown\n" );
+ state = IB_LINK_DOWN;
+ goto Exit;
+ }
+
+ p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ CL_ASSERT( port_guid );
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_get( p_tbl, port_guid );
+ if( p_port == ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_is_sm_port_down: ERR 3309: "
+ "SM port with GUID:%016" PRIx64 " is unknown\n",
+ cl_ntoh64( port_guid ) );
+ state = IB_LINK_DOWN;
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ goto Exit;
+ }
+
+ p_physp = osm_port_get_default_phys_ptr( p_port );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ state = osm_physp_get_port_state( p_physp );
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->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
+__osm_state_mgr_sweep_hop_1(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_bind_handle_t h_bind;
+ osm_madw_context_t context;
+ osm_node_t *p_node;
+ osm_port_t *p_port;
+ osm_physp_t *p_physp;
+ osm_dr_path_t *p_dr_path;
+ osm_dr_path_t hop_1_path;
+ ib_net64_t port_guid;
+ uint8_t port_num;
+ cl_qmap_t *p_port_tbl;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+ uint8_t num_ports;
+ osm_physp_t *p_ext_physp;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_sweep_hop_1 );
+
+ /*
+ * First, get our own port and node objects.
+ */
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+ port_guid = p_mgr->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. */
+ p_mgr->p_subn->in_sweep_hop_0 = FALSE;
+
+ p_port = ( osm_port_t * ) cl_qmap_get( p_port_tbl, port_guid );
+ if( p_port == ( osm_port_t * ) cl_qmap_end( p_port_tbl ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3310: "
+ "No SM port object\n" );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ CL_ASSERT( p_node );
+
+ port_num = ib_node_info_get_local_port_num( &p_node->node_info );
+
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_sweep_hop_1: "
+ "Probing hop 1 on local port %u\n", port_num );
+
+ p_physp = osm_node_get_physp_ptr( p_node, port_num );
+
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
+ h_bind = osm_dr_path_get_bind_handle( p_dr_path );
+
+ CL_ASSERT( h_bind != OSM_BIND_INVALID_HANDLE );
+
+ 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:
+ 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, h_bind, 1, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &hop_1_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3311: "
+ "Request 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 );
+ /* Make sure the physp object exists */
+ if( !p_ext_physp )
+ continue;
+ if( ib_port_info_get_port_state( &( p_ext_physp->port_info ) ) >
+ IB_LINK_DOWN )
+ {
+ 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, h_bind, 1, path_array );
+ status = osm_req_get( p_mgr->p_req,
+ &hop_1_path,
+ IB_MAD_ATTR_NODE_INFO,
+ 0, CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3312: "
+ "Request NodeInfo failed\n" );
+ }
+ }
+ }
+ break;
+
+ default:
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_sweep_hop_1: ERR 3313: Unknown node type %d\n",
+ osm_node_get_type( p_node ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ Initiates a lightweight sweep of the subnet.
+ Used during normal sweeps after the subnet is up.
+**********************************************************************/
+static ib_api_status_t
+__osm_state_mgr_light_sweep_start(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ osm_bind_handle_t h_bind;
+ cl_qmap_t *p_sw_tbl;
+ cl_list_t *p_no_rem_port_list;
+ cl_list_iterator_t list_iter;
+ uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_light_sweep_start );
+
+ p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
+
+ memset( path_array, 0, sizeof( path_array ) );
+
+ /*
+ * First, get the bind handle.
+ */
+ h_bind = osm_sm_mad_ctrl_get_bind_handle( p_mgr->p_mad_ctrl );
+ if( h_bind != OSM_BIND_INVALID_HANDLE )
+ {
+ __osm_state_mgr_sweep_light_msg( p_mgr );
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ cl_qmap_apply_func( p_sw_tbl, __osm_state_mgr_get_sw_info, p_mgr );
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ /* now scan the list of physical ports that were not down but have no remote port */
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_no_rem_port_list = &p_mgr->p_subn->light_sweep_physp_list;
+ list_iter = cl_list_head( p_no_rem_port_list );
+ while( list_iter != cl_list_end( p_no_rem_port_list ) )
+ {
+ __osm_state_mgr_get_remote_port_info( p_mgr,
+ ( osm_physp_t * )
+ cl_list_obj( list_iter ) );
+ list_iter = cl_list_next( list_iter );
+ }
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_light_sweep_start: "
+ "No bound ports. Deferring sweep...\n" );
+ status = IB_INVALID_STATE;
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_topology_file_create(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ const osm_node_t *p_node;
+ char *file_name;
+ FILE *rc;
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_topology_file_create );
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+
+ file_name =
+ ( char * )malloc( strlen( p_mgr->p_subn->opt.dump_files_dir )
+ + strlen(SUBNET_LIST_FILENAME) + 1 );
+
+ CL_ASSERT( file_name );
+
+ strcpy( file_name, p_mgr->p_subn->opt.dump_files_dir );
+ strcat( file_name, SUBNET_LIST_FILENAME );
+
+ if( ( rc = fopen( file_name, "w" ) ) == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_topology_file_create: "
+ "fopen failed for file:%s\n", file_name );
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ goto Exit;
+ }
+
+ p_node = ( osm_node_t * ) cl_qmap_head( &p_mgr->p_subn->node_guid_tbl );
+ while( p_node !=
+ ( osm_node_t * ) cl_qmap_end( &p_mgr->p_subn->node_guid_tbl ) )
+ {
+ if( p_node->node_info.num_ports )
+ {
+ uint32_t cPort;
+ osm_node_t *p_nbnode;
+ osm_physp_t *p_physp;
+ osm_physp_t *p_default_physp;
+ osm_physp_t *p_rphysp;
+ uint8_t link_speed_act;
+
+ 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 == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+ continue;
+
+ p_rphysp = p_physp->p_remote_physp;
+
+ if( ( p_rphysp == NULL ) || ( !osm_physp_is_valid( 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;
+ }
+
+ memcpy(desc, p_node->node_desc.description,
+ IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+ fprintf( rc, "{ %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 ),
+ 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;
+ }
+
+ memcpy(desc, p_nbnode->node_desc.description,
+ IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+ fprintf( rc, "{ %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 ),
+ 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 );
+
+ fprintf( rc, "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 == 8 ) ? "12x" :
+ "??",
+ ( ( port_state == IB_LINK_ACTIVE ) ? "ACT" :
+ ( port_state == IB_LINK_ARMED ) ? "ARM" :
+ ( port_state == IB_LINK_INIT ) ? "INI" : "DWN" ),
+ ( link_speed_act == 1 ) ? "2.5" :
+ ( link_speed_act == 2 ) ? "5" :
+ ( link_speed_act == 4 ) ? "10" : "??" );
+ }
+ }
+ p_node = ( osm_node_t * ) cl_qmap_next( &p_node->map_item );
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ fclose( rc );
+
+ Exit:
+ free( file_name );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_state_mgr_report(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ const cl_qmap_t *p_tbl;
+ const osm_port_t *p_port;
+ const osm_node_t *p_node;
+ const osm_physp_t *p_physp;
+ const osm_physp_t *p_remote_physp;
+ const ib_port_info_t *p_pi;
+ uint8_t port_num;
+ uint8_t start_port;
+ uint32_t num_ports;
+ uint8_t node_type;
+
+ if( !osm_log_is_active( p_mgr->p_log, OSM_LOG_VERBOSE ) )
+ return;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report );
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "\n==================================================="
+ "===================================================="
+ "\nVendor : Ty "
+ ": # : Sta : LID : LMC : MTU : LWA : LSA : Port GUID "
+ " : Neighbor Port (Port #)\n" );
+
+ p_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ * Hold lock non-exclusively while we perform these read-only operations.
+ */
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_port = ( osm_port_t * ) cl_qmap_head( p_tbl );
+ while( p_port != ( osm_port_t * ) cl_qmap_end( p_tbl ) )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_report: "
+ "Processing port 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ }
+
+ p_node = osm_port_get_parent_node( p_port );
+ node_type = osm_node_get_type( p_node );
+ if( node_type == IB_NODE_TYPE_SWITCH )
+ start_port = 0;
+ else
+ start_port = 1;
+
+ num_ports = osm_port_get_num_physp( p_port );
+ for( port_num = start_port; port_num < num_ports; port_num++ )
+ {
+ p_physp = osm_port_get_phys_ptr( p_port, port_num );
+ if( ( p_physp == NULL ) || ( !osm_physp_is_valid( p_physp ) ) )
+ continue;
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "%s : %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 = osm_physp_get_port_info_ptr( p_physp );
+
+ /*
+ * Port state is not defined for switch port 0
+ */
+ if( port_num == 0 )
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " :" );
+ else
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %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 ) )
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %04X : %01X :",
+ cl_ntoh16( p_pi->base_lid ),
+ ib_port_info_get_lmc( p_pi ) );
+ else
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " : :" );
+
+ if( port_num != 0 )
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " %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 ) ) );
+ else
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " : : " );
+
+ if( osm_physp_get_port_guid( p_physp ) ==
+ p_mgr->p_subn->sm_port_guid )
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "* %016" PRIx64 " *",
+ cl_ntoh64( osm_physp_get_port_guid( p_physp ) ) );
+ else
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, ": %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 && osm_physp_is_valid( p_remote_physp ) )
+ {
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+ " %016" PRIx64 " (%02X)",
+ cl_ntoh64( osm_physp_get_port_guid
+ ( p_remote_physp ) ),
+ osm_physp_get_port_num( p_remote_physp ) );
+ }
+ else
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, " UNKNOWN" );
+ }
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE, "\n" );
+ }
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "------------------------------------------------------"
+ "------------------------------------------------\n" );
+ p_port = ( osm_port_t * ) cl_qmap_next( &p_port->map_item );
+ }
+
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__process_idle_time_queue_done(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qlist_t *p_list = &p_mgr->idle_time_list;
+ cl_list_item_t *p_list_item;
+ osm_idle_item_t *p_process_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_done );
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+ p_list_item = cl_qlist_remove_head( p_list );
+
+ if( p_list_item == cl_qlist_end( p_list ) )
+ {
+ cl_spinlock_release( &p_mgr->idle_lock );
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__process_idle_time_queue_done: ERR 3314: "
+ "Idle time queue is empty\n" );
+ return;
+ }
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+ if( p_process_item->pfn_done )
+ {
+
+ p_process_item->pfn_done( p_process_item->context1,
+ p_process_item->context2 );
+ }
+
+ free( p_process_item );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static osm_signal_t
+__process_idle_time_queue_start(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qlist_t *p_list = &p_mgr->idle_time_list;
+ cl_list_item_t *p_list_item;
+ osm_idle_item_t *p_process_item;
+ osm_signal_t signal;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __process_idle_time_queue_start );
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+
+ p_list_item = cl_qlist_head( p_list );
+ if( p_list_item == cl_qlist_end( p_list ) )
+ {
+ cl_spinlock_release( &p_mgr->idle_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return OSM_SIGNAL_NONE;
+ }
+
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ p_process_item = ( osm_idle_item_t * ) p_list_item;
+
+ CL_ASSERT( p_process_item->pfn_start );
+
+ signal = p_process_item->pfn_start( p_process_item->context1,
+ p_process_item->context2 );
+
+ CL_ASSERT( signal != OSM_SIGNAL_NONE );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return signal;
+}
+
+/**********************************************************************
+ * 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 TRUE, else - return FALSE.
+ **********************************************************************/
+static osm_remote_sm_t *
+__osm_state_mgr_exists_other_master_sm(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ cl_qmap_t *p_sm_tbl;
+ osm_remote_sm_t *p_sm;
+ osm_remote_sm_t *p_sm_res = NULL;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_exists_other_master_sm );
+
+ p_sm_tbl = &p_mgr->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 TRUE */
+ if( ib_sminfo_get_state( &p_sm->smi ) == IB_SMINFO_STATE_MASTER )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_exists_other_master_sm: "
+ "Found remote master SM with guid:0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sm->smi.guid) );
+ p_sm_res = p_sm;
+ goto Exit;
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->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 *
+__osm_state_mgr_get_highest_sm(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ 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_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_get_highest_sm );
+
+ p_sm_tbl = &p_mgr->p_subn->sm_guid_tbl;
+
+ /* Start with the local sm as the standard */
+ p_highest_sm = NULL;
+ highest_sm_priority = p_mgr->p_subn->opt.sm_priority;
+ highest_sm_guid = p_mgr->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 )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_get_highest_sm: "
+ "Found higher SM with guid: %016" PRIx64 "\n",
+ cl_ntoh64( p_highest_sm->smi.guid ) );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return ( p_highest_sm );
+}
+
+/**********************************************************************
+ * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
+ * remote_sm indicated.
+ **********************************************************************/
+static void
+__osm_state_mgr_send_handover(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_remote_sm_t * const 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( p_mgr->p_log, __osm_state_mgr_send_handover );
+
+ if( p_mgr->p_subn->opt.testability_mode ==
+ OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3315: "
+ "Exit on testability mode OSM_TEST_MODE_EXIT_BEFORE_SEND_HANDOVER\n" );
+ osm_exit_flag = TRUE;
+ sleep( 3 );
+ exit( 1 );
+ }
+
+ /*
+ * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given.
+ */
+
+ memset( &context, 0, sizeof( context ) );
+ p_port = p_sm->p_port;
+ if( p_port == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3316: "
+ "No port object on given remote_sm object\n" );
+ goto Exit;
+ }
+
+ /* update the master_guid in the p_sm_state_mgr object according to */
+ /* the guid of the port where the new Master SM should reside. */
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "__osm_state_mgr_send_handover: "
+ "Handing over mastership. Updating sm_state_mgr master_guid: %016"
+ PRIx64 "\n", cl_ntoh64( p_port->guid ) );
+ p_mgr->p_sm_state_mgr->master_guid = p_port->guid;
+
+ context.smi_context.port_guid = p_port->guid;
+ context.smi_context.set_method = TRUE;
+
+ p_smi->guid = p_mgr->p_subn->sm_port_guid;
+ p_smi->act_count = cl_hton32( p_mgr->p_stats->qp0_mads_sent );
+ p_smi->pri_state = ( uint8_t ) ( p_mgr->p_subn->sm_state |
+ p_mgr->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( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_send_handover: "
+ "Responding to master SM with real sm_key\n" );
+ p_smi->sm_key = p_mgr->p_subn->opt.sm_key;
+ }
+ else
+ {
+ /* The requester is not authenticated as master - set sm_key to zero */
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_state_mgr_send_handover: "
+ "Responding to SM not master with zero sm_key\n" );
+ p_smi->sm_key = 0;
+ }
+
+ status = osm_req_set( p_mgr->p_req,
+ osm_physp_get_dr_path_ptr
+ ( osm_port_get_default_phys_ptr( p_port ) ), payload,
+ sizeof(payload),
+ IB_MAD_ATTR_SM_INFO, IB_SMINFO_ATTR_MOD_HANDOVER,
+ CL_DISP_MSGID_NONE, &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_send_handover: ERR 3317: "
+ "Failure requesting SMInfo (%s)\n", ib_get_err_str( status ) );
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ * Send Trap 64 on all ports in new_ports_list.
+ **********************************************************************/
+static void
+__osm_state_mgr_report_new_ports(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ osm_port_t *p_port;
+ ib_gid_t port_gid;
+ ib_mad_notice_attr_t notice;
+ ib_api_status_t status;
+ ib_net64_t port_guid;
+ uint16_t min_lid_ho;
+ uint16_t max_lid_ho;
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_state_mgr_report_new_ports );
+
+ CL_PLOCK_ACQUIRE( p_mgr->p_lock );
+ p_port =
+ ( osm_port_t
+ * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+ while( p_port != NULL )
+ {
+ port_guid = osm_port_get_guid( p_port );
+ /* issue a notice - trap 64 */
+
+ /* details of the notice */
+ notice.generic_type = 0x83; /* is generic subn mgt type */
+ ib_notice_set_prod_type_ho( ¬ice, 4 ); /* A Class Manager generator */
+ /* endport becomes to be reachable */
+ notice.g_or_v.generic.trap_num = CL_HTON16( 64 );
+ /* The sm_base_lid is saved in network order already. */
+ notice.issuer_lid = p_mgr->p_subn->sm_base_lid;
+ /* following C14-72.1.1 and table 119 p725 */
+ /* we need to provide the GID */
+ port_gid.unicast.prefix = p_mgr->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 = p_mgr->p_subn->opt.subnet_prefix;
+ notice.issuer_gid.unicast.interface_id = p_mgr->p_subn->sm_port_guid;
+
+ status = osm_report_notice( p_mgr->p_log, p_mgr->p_subn, ¬ice );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_report_new_ports: 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 );
+ if (p_port->p_node)
+ {
+ memcpy(desc, p_port->p_node->node_desc.description,
+ IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+ }
+ osm_log( p_mgr->p_log, OSM_LOG_INFO,
+ "Discovered new port with GUID:0x%016" PRIx64
+ " LID range [0x%X,0x%X] of node:%s\n",
+ cl_ntoh64( port_gid.unicast.interface_id ),
+ min_lid_ho, max_lid_ho,
+ p_port->p_node ? desc : "UNKNOWN" );
+
+ p_port =
+ ( osm_port_t
+ * ) ( cl_list_remove_head( &p_mgr->p_subn->new_ports_list ) );
+ }
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+
+ OSM_LOG_EXIT( p_mgr->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
+__osm_state_mgr_check_tbl_consistency(
+ IN osm_state_mgr_t * const p_mgr )
+{
+ 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( p_mgr->p_log, __osm_state_mgr_check_tbl_consistency );
+
+ cl_ptr_vector_construct( &ref_port_lid_tbl );
+ cl_ptr_vector_init( &ref_port_lid_tbl,
+ cl_ptr_vector_get_size( &p_mgr->p_subn->port_lid_tbl ),
+ OSM_SUBNET_VECTOR_GROW_SIZE );
+
+ p_port_guid_tbl = &p_mgr->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 = &p_mgr->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, but with the
+ * new lid we wanted to give it in our port_lid_tbl. */
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3322: "
+ "lid 0x%zX is wrongly assigned to port 0x%016" PRIx64
+ " in port_lid_tbl\n",
+ lid, cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+ }
+ 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3323: "
+ "port 0x%016" PRIx64 " exists in new port_lid_tbl under "
+ "lid 0x%zX, but missing in subnet port_lid_tbl db\n",
+ cl_ntoh64( osm_port_get_guid( p_port_ref ) ), 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( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_state_mgr_check_tbl_consistency: ERR 3324: "
+ "lid 0x%zX has port 0x%016" PRIx64
+ " in new port_lid_tbl db, " "and port 0x%016" PRIx64
+ " in subnet port_lid_tbl db\n", lid,
+ cl_ntoh64( osm_port_get_guid( p_port_ref ) ),
+ cl_ntoh64( osm_port_get_guid( p_port_stored ) ) );
+ }
+ }
+ /* In any of these cases we want to set NULL in the port_lid_tbl, since this
+ * entry is invalid. Also, make sure we'll do another heavy sweep. */
+ cl_ptr_vector_set( p_port_lid_tbl, lid, NULL );
+ p_mgr->p_subn->subnet_initialization_error = TRUE;
+ }
+
+ cl_ptr_vector_destroy( &ref_port_lid_tbl );
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_process(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_signal_t signal )
+{
+ ib_api_status_t status;
+ osm_remote_sm_t *p_remote_sm;
+ osm_signal_t tmp_signal;
+
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process );
+
+ /* if we are exiting do nothing */
+ if( osm_exit_flag )
+ signal = OSM_SIGNAL_NONE;
+
+ /*
+ * The state lock prevents many race conditions from screwing
+ * up the state transition process. For example, if an function
+ * puts transactions on the wire, the state lock guarantees this
+ * loop will see the return code ("DONE PENDING") of the function
+ * before the "NO OUTSTANDING TRANSACTIONS" signal is asynchronously
+ * received.
+ */
+ cl_spinlock_acquire( &p_mgr->state_lock );
+
+ while( signal != OSM_SIGNAL_NONE )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_state_mgr_process: "
+ "Received signal %s in state %s\n",
+ osm_get_sm_signal_str( signal ),
+ osm_get_sm_state_str( p_mgr->state ) );
+ }
+
+ /*
+ * If we're already sweeping and we get the signal to sweep,
+ * just ignore it harmlessly.
+ */
+ if( ( p_mgr->state != OSM_SM_STATE_IDLE ) &&
+ ( p_mgr->state != OSM_SM_STATE_STANDBY ) &&
+ ( signal == OSM_SIGNAL_SWEEP ) )
+ {
+ break;
+ }
+
+ switch ( p_mgr->state )
+ {
+ case OSM_SM_STATE_IDLE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_SWEEP:
+ /*
+ * If the osm_sm_state_mgr is in INIT state - signal
+ * it with a INIT signal to move it to DISCOVERY state.
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_INIT )
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_INIT );
+
+ /*
+ * 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( &p_mgr->p_subn->sw_guid_tbl ) &&
+ p_mgr->p_subn->sm_state != IB_SMINFO_STATE_DISCOVERING &&
+ p_mgr->p_subn->opt.force_heavy_sweep == FALSE &&
+ p_mgr->p_subn->force_immediate_heavy_sweep == FALSE &&
+ p_mgr->p_subn->force_delayed_heavy_sweep == FALSE &&
+ p_mgr->p_subn->subnet_initialization_error == FALSE )
+ {
+ if( __osm_state_mgr_light_sweep_start( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT;
+ }
+ }
+ else
+ {
+ /* First of all - if force_immediate_heavy_sweep is TRUE then
+ * need to unset it */
+ p_mgr->p_subn->force_immediate_heavy_sweep = FALSE;
+ /* If force_delayed_heavy_sweep is TRUE then
+ * need to unset it */
+ p_mgr->p_subn->force_delayed_heavy_sweep = FALSE;
+ /* If subnet_initialization_error is TRUE then
+ * need to unset it. */
+ p_mgr->p_subn->subnet_initialization_error = FALSE;
+
+ /* rescan configuration updates */
+ osm_subn_rescan_conf_file(&p_mgr->p_subn->opt);
+
+ status = __osm_state_mgr_sweep_hop_0( p_mgr );
+ if( status == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+ }
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_PROCESS_REQUEST:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_IDLE_TIME_PROCESS:
+ signal = __process_idle_time_queue_start( p_mgr );
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NONE:
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_PROCESS_REQUEST_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_PROCESS_REQUEST_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* CALL the done function */
+ __process_idle_time_queue_done( p_mgr );
+
+ /*
+ * Set the signal to OSM_SIGNAL_IDLE_TIME_PROCESS
+ * so that the next element in the queue gets processed
+ */
+
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SWEEP_LIGHT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing else to do yet except change state.
+ */
+ p_mgr->state = OSM_SM_STATE_SWEEP_LIGHT_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * No change was detected on the subnet.
+ * We can return to the idle state.
+ */
+ __osm_state_mgr_light_sweep_done_msg( p_mgr );
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SWEEP_LIGHT_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_LIGHT_SWEEP_FAIL:
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another.... But needs to wait for all transactions to
+ * complete
+ */
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * A change was detected on the subnet.
+ * Initiate a heavy sweep.
+ */
+ if( __osm_state_mgr_sweep_hop_0( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SELF;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ break;
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SM_STATE_SWEEP_HEAVY_SELF:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typcially
+ * begets another.... But needs to wait for all transactions
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ if( __osm_state_mgr_is_sm_port_down( p_mgr ) == TRUE )
+ {
+ __osm_state_mgr_sm_port_down_msg( p_mgr );
+
+ /* Run the drop manager - we want to clear all records */
+ osm_drop_mgr_process( p_mgr->p_drop_mgr );
+
+ /* Move to DISCOVERING state */
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_DISCOVER );
+
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ }
+ else
+ {
+ if( __osm_state_mgr_sweep_hop_1( p_mgr ) == IB_SUCCESS )
+ {
+ p_mgr->state = OSM_SM_STATE_SWEEP_HEAVY_SUBNET;
+ }
+ signal = OSM_SIGNAL_NONE;
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ /*
+ * There is no 'OSM_SM_STATE_SWEEP_HEAVY_WAIT' state since we
+ * know that there are outstanding transactions on the wire already...
+ */
+ case OSM_SM_STATE_SWEEP_HEAVY_SUBNET:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typically
+ * begets another....
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ p_mgr->state = OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ __osm_state_mgr_sweep_heavy_done_msg( p_mgr );
+
+ /* If we are MASTER - get the highest remote_sm, and
+ * see if it is higher than our local sm. If
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_MASTER )
+ {
+ p_remote_sm = __osm_state_mgr_get_highest_sm( p_mgr );
+ if( p_remote_sm != NULL )
+ {
+ /* need to handover the mastership
+ * to the remote sm, and move to standby */
+ __osm_state_mgr_send_handover( p_mgr, p_remote_sm );
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_HANDOVER_SENT );
+ p_mgr->state = OSM_SM_STATE_STANDBY;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ else
+ {
+ /* We are the highest sm - check to see if there is
+ * a remote SM that is in master state. */
+ p_remote_sm = __osm_state_mgr_exists_other_master_sm( p_mgr );
+ 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.
+ * Also - need to start polling on that SM. */
+ p_mgr->p_sm_state_mgr->p_polling_sm = p_remote_sm;
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_WAIT_FOR_HANDOVER );
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+ break;
+ }
+ }
+ }
+
+ /* Need to continue with lid assignment */
+ osm_drop_mgr_process( p_mgr->p_drop_mgr );
+
+ p_mgr->state = OSM_SM_STATE_SET_PKEY;
+
+ /*
+ * If we are not MASTER already - this means that we are
+ * in discovery state. call osm_sm_state_mgr with signal
+ * DISCOVERY_COMPLETED
+ */
+ if( p_mgr->p_subn->sm_state == IB_SMINFO_STATE_DISCOVERING )
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_DISCOVERY_COMPLETED );
+
+ /* the returned signal might be DONE or DONE_PENDING */
+ signal = osm_pkey_mgr_process( p_mgr->p_subn->p_osm );
+
+ /* the returned signal is always DONE */
+ tmp_signal = osm_qos_setup(p_mgr->p_subn->p_osm);
+
+ if (tmp_signal == OSM_SIGNAL_DONE_PENDING)
+ signal = OSM_SIGNAL_DONE_PENDING;
+
+ /* 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(p_mgr->p_subn->p_osm);
+
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_PKEY:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_PKEY_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_PKEY_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_PKEY_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_PKEY_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID;
+ signal = osm_lid_mgr_process_sm( p_mgr->p_lid_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_SM_UCAST_LID_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SM_UCAST_LID_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ {
+ __osm_state_mgr_set_sm_lid_done_msg( p_mgr );
+ __osm_state_mgr_notify_lid_change( p_mgr );
+ }
+
+ /* Break on single step mode - if not continuous */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS;
+ signal = osm_lid_mgr_process_subnet( p_mgr->p_lid_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ /*
+ * The LID Manager is done processing.
+ * There are no outstanding transactions, so we
+ * can move on to configuring the forwarding tables.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The LID Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ /*
+ * In this state, the Unicast Manager has completed processing,
+ * but there are still transactions on the wire. Therefore,
+ * wait here until the wire clears.
+ */
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * The LID Manager is done processing.
+ * There are no outstanding transactions, so we
+ * can move on to configuring the forwarding tables.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_SUBNET_UCAST_LIDS_DONE:
+
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /* 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 reqeusts didn't reach
+ * their destination. */
+ __osm_state_mgr_check_tbl_consistency( p_mgr );
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_lid_assign_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ /*
+ * OK, the wire is clear, so proceed with
+ * unicast forwarding table configuration.
+ * First - send trap 64 on newly discovered endports
+ */
+ __osm_state_mgr_report_new_ports( p_mgr );
+
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES;
+ signal = osm_ucast_mgr_process( p_mgr->p_ucast_mgr );
+
+ /* Break on single step mode */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_CONTINUOUS )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ }
+
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Unicast Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_UCAST_TABLES_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_UCAST_TABLES_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* 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. */
+ p_mgr->p_subn->ignore_existing_lfts = FALSE;
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_switch_config_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ if( !p_mgr->p_subn->opt.disable_multicast )
+ {
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES;
+ signal = osm_mcast_mgr_process( p_mgr->p_mcast_mgr );
+ }
+ else
+ {
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_NO_CHANGE );
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Multicast Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_MCAST_TABLES_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_MCAST_TABLES_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_multicast_config_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_NO_CHANGE );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ /*
+ * The LINK_PORTS state is required since we can not 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.
+ */
+ case OSM_SM_STATE_SET_LINK_PORTS:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_LINK_PORTS_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_LINK_PORTS_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_LINK_PORTS_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+
+ __osm_state_mgr_links_ports_msg( p_mgr );
+
+ p_mgr->state = OSM_SM_STATE_SET_ARMED;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr, IB_LINK_ARMED );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_SET_ARMED_DONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ARMED_DONE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+
+ /* If we run single step we have already done this */
+ if( p_mgr->state_step_mode != OSM_STATE_STEP_TAKE_ONE )
+ __osm_state_mgr_links_armed_msg( p_mgr );
+
+ /* Break on single step mode - just before taking next step */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_BREAK )
+ {
+ p_mgr->next_stage_signal = signal;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ p_mgr->state = OSM_SM_STATE_SET_ACTIVE;
+ signal = osm_link_mgr_process( p_mgr->p_link_mgr,
+ IB_LINK_ACTIVE );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ACTIVE:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_DONE:
+ /*
+ * Don't change the signal, just the state.
+ */
+ p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+ break;
+
+ case OSM_SIGNAL_DONE_PENDING:
+ /*
+ * The Link Manager is done processing.
+ * There are outstanding transactions, so we
+ * must wait for the wire to clear.
+ */
+ p_mgr->state = OSM_SM_STATE_SET_ACTIVE_WAIT;
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SET_ACTIVE_WAIT:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * Don't change the signal, just the state.
+ */
+ p_mgr->state = OSM_SM_STATE_SUBNET_UP;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_SUBNET_UP:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ case OSM_SIGNAL_DONE:
+ /*
+ * The sweep completed!
+ */
+
+ /* in any case we zero this flag */
+ p_mgr->p_subn->coming_out_of_standby = FALSE;
+
+ /* If there were errors - then the subnet is not really up */
+ if( p_mgr->p_subn->subnet_initialization_error == TRUE )
+ {
+ __osm_state_mgr_init_errors_msg( p_mgr );
+ }
+ else
+ {
+ /* The subnet is up correctly - set the first_time_master_sweep flag
+ * (if it is on) to FALSE. */
+ if( p_mgr->p_subn->first_time_master_sweep == TRUE )
+ {
+ p_mgr->p_subn->first_time_master_sweep = FALSE;
+ }
+
+ __osm_topology_file_create( p_mgr );
+ __osm_state_mgr_report( p_mgr );
+ __osm_state_mgr_up_msg( p_mgr );
+
+ if( osm_log_is_active(p_mgr->p_log, OSM_LOG_VERBOSE) )
+ osm_sa_db_file_dump(p_mgr->p_subn->p_osm);
+ }
+ p_mgr->state = OSM_SM_STATE_PROCESS_REQUEST;
+ signal = OSM_SIGNAL_IDLE_TIME_PROCESS;
+
+ /*
+ * Finally signal the subnet up event
+ */
+ status = cl_event_signal( p_mgr->p_subnet_up_event );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process: ERR 3319: "
+ "Invalid SM state %u\n", p_mgr->state );
+ }
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ break;
+
+ case OSM_SM_STATE_MASTER_OR_HIGHER_SM_DETECTED:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_CHANGE_DETECTED:
+ /*
+ * Nothing to do here. One subnet change typically
+ * begets another....
+ */
+ break;
+
+ case OSM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED:
+ /*
+ * If we lost once, we might lose again. Nothing to do.
+ */
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ p_mgr->state = OSM_SM_STATE_STANDBY;
+ /*
+ * Call the sm_state_mgr with signal
+ * MASTER_OR_HIGHER_SM_DETECTED_DONE
+ */
+ osm_sm_state_mgr_process( p_mgr->p_sm_state_mgr,
+ OSM_SM_SIGNAL_MASTER_OR_HIGHER_SM_DETECTED_DONE );
+ __osm_state_mgr_standby_msg( p_mgr );
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ break;
+ }
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ case OSM_SM_STATE_STANDBY:
+ switch ( signal )
+ {
+ case OSM_SIGNAL_EXIT_STBY:
+ /*
+ * Need to force re-write of sm_base_lid to all ports
+ * to do that we want all the ports to be considered
+ * foriegn
+ */
+ signal = OSM_SIGNAL_SWEEP;
+ __osm_state_mgr_clean_known_lids( p_mgr );
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ break;
+
+ case OSM_SIGNAL_NO_PENDING_TRANSACTIONS:
+ /*
+ * Nothing to do here - need to stay at this state
+ */
+ signal = OSM_SIGNAL_NONE;
+ break;
+
+ default:
+ __osm_state_mgr_signal_error( p_mgr, signal );
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+ /* stay with the same signal - so we can start the sweep */
+ break;
+
+ default:
+ CL_ASSERT( FALSE );
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process: ERR 3320: "
+ "Invalid SM state %u\n", p_mgr->state );
+ p_mgr->state = OSM_SM_STATE_IDLE;
+ signal = OSM_SIGNAL_NONE;
+ break;
+ }
+
+ /* if we got a signal to force immediate heavy sweep in the middle of the sweep -
+ * try another sweep. */
+ if( ( p_mgr->p_subn->force_immediate_heavy_sweep ) &&
+ ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+ {
+ signal = OSM_SIGNAL_SWEEP;
+ }
+ /* if we got errors during the initialization in the middle of the sweep -
+ * try another sweep. */
+ if( ( p_mgr->p_subn->subnet_initialization_error ) &&
+ ( p_mgr->state == OSM_SM_STATE_IDLE ) )
+ {
+ signal = OSM_SIGNAL_SWEEP;
+ }
+
+ /*
+ * for single step mode - some stages need to break only
+ * after evaluating a single step.
+ * For those we track the fact we have already performed
+ * a single loop
+ */
+ if( p_mgr->state_step_mode == OSM_STATE_STEP_TAKE_ONE )
+ p_mgr->state_step_mode = OSM_STATE_STEP_BREAK;
+ }
+
+ cl_spinlock_release( &p_mgr->state_lock );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_process_idle(
+ IN osm_state_mgr_t * const p_mgr,
+ IN osm_pfn_start_t pfn_start,
+ IN osm_pfn_done_t pfn_done,
+ void *context1,
+ void *context2 )
+{
+ osm_idle_item_t *p_idle_item;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_state_mgr_process_idle );
+
+ p_idle_item = malloc( sizeof( osm_idle_item_t ) );
+ if( p_idle_item == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_process_idle: ERR 3321: "
+ "insufficient memory\n" );
+ return IB_ERROR;
+ }
+
+ memset( p_idle_item, 0, sizeof( osm_idle_item_t ) );
+ p_idle_item->pfn_start = pfn_start;
+ p_idle_item->pfn_done = pfn_done;
+ p_idle_item->context1 = context1;
+ p_idle_item->context2 = context2;
+
+ cl_spinlock_acquire( &p_mgr->idle_lock );
+ cl_qlist_insert_tail( &p_mgr->idle_time_list, &p_idle_item->list_item );
+ cl_spinlock_release( &p_mgr->idle_lock );
+
+ osm_state_mgr_process( p_mgr, OSM_SIGNAL_IDLE_TIME_PROCESS_REQUEST );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+
+ return IB_SUCCESS;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_state_mgr_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_state_mgr_ctrl_t.
+ * This object represents the State Manager Controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_state_mgr_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_state_mgr_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_state_mgr_process( ((osm_state_mgr_ctrl_t*)context)->p_mgr,
+ (osm_signal_t)(p_data) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_construct(
+ IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_state_mgr_ctrl_destroy(
+ IN osm_state_mgr_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_state_mgr_ctrl_init(
+ IN osm_state_mgr_ctrl_t* const p_ctrl,
+ IN osm_state_mgr_t* const p_mgr,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_state_mgr_ctrl_init );
+
+ osm_state_mgr_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_mgr = p_mgr;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ __osm_state_mgr_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_state_mgr_ctrl_init: ERR 3401: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_subnet.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_subn_t.
+ * This object represents an IBA subnet.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.9 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <stdio.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_port.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_remote_sm.h>
+#include <opensm/osm_partition.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_multicast.h>
+#include <opensm/osm_inform.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_construct(
+ IN osm_subn_t* const p_subn )
+{
+ memset( p_subn, 0, sizeof(*p_subn) );
+ cl_ptr_vector_construct( &p_subn->node_lid_tbl );
+ 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->sm_guid_tbl );
+ cl_qlist_init( &p_subn->sa_sr_list );
+ cl_qlist_init( &p_subn->sa_infr_list );
+ cl_qmap_init( &p_subn->rtr_guid_tbl );
+ cl_qmap_init( &p_subn->prtn_pkey_tbl );
+ cl_qmap_init( &p_subn->mgrp_mlid_tbl );
+ cl_list_construct( &p_subn->new_ports_list );
+ cl_list_init( &p_subn->new_ports_list, 10 );
+ cl_list_construct( &p_subn->light_sweep_physp_list );
+ cl_list_init( &p_subn->light_sweep_physp_list, 5 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_destroy(
+ IN osm_subn_t* const p_subn )
+{
+ osm_node_t *p_node, *p_next_node;
+ 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_mgrp_t *p_mgrp, *p_next_mgrp;
+ osm_infr_t *p_infr, *p_next_infr;
+
+ /* 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 );
+ }
+
+ cl_ptr_vector_destroy( &p_subn->node_lid_tbl );
+
+ 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_prtn );
+ }
+
+ p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
+ while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
+ {
+ p_mgrp = p_next_mgrp;
+ p_next_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ osm_mgrp_destroy( p_mgrp );
+ }
+
+ 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_destroy( p_infr );
+ }
+
+ cl_list_remove_all( &p_subn->new_ports_list );
+ cl_list_destroy( &p_subn->new_ports_list );
+
+ cl_list_remove_all( &p_subn->light_sweep_physp_list );
+ cl_list_destroy( &p_subn->light_sweep_physp_list );
+
+ cl_ptr_vector_destroy( &p_subn->port_lid_tbl );
+ cl_map_remove_all(&(p_subn->opt.port_prof_ignore_guids));
+ cl_map_destroy(&(p_subn->opt.port_prof_ignore_guids));
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_subn_init(
+ IN osm_subn_t* const p_subn,
+ IN osm_opensm_t * const p_osm,
+ IN const osm_subn_opt_t* const p_opt )
+{
+ cl_status_t status;
+
+ p_subn->p_osm = p_osm;
+
+ status = cl_ptr_vector_init( &p_subn->node_lid_tbl,
+ OSM_SUBNET_VECTOR_MIN_SIZE,
+ OSM_SUBNET_VECTOR_GROW_SIZE );
+ if( status != CL_SUCCESS )
+ return( status );
+
+ 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->node_lid_tbl,
+ OSM_SUBNET_VECTOR_CAPACITY );
+ 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->node_lid_tbl, 0, NULL );
+ cl_ptr_vector_set( &p_subn->port_lid_tbl, 0, NULL );
+
+ p_subn->opt = *p_opt;
+ p_subn->max_unicast_lid_ho = IB_LID_UCAST_END_HO;
+ p_subn->max_multicast_lid_ho = IB_LID_MCAST_END_HO;
+ p_subn->min_ca_mtu = IB_MAX_MTU;
+ p_subn->min_ca_rate = IB_MAX_RATE;
+
+ /* note that insert and remove are part of the port_profile thing */
+ cl_map_init(&(p_subn->opt.port_prof_ignore_guids), 10);
+
+ /* ignore_existing_lfts follows reassign_lfts on first sweep */
+ p_subn->ignore_existing_lfts = p_subn->opt.reassign_lfts;
+
+ /* we assume master by default - so we only need to set it true if STANDBY */
+ p_subn->coming_out_of_standby = FALSE;
+
+ return( IB_SUCCESS );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_get_gid_by_mad_addr(
+ IN osm_log_t* p_log,
+ IN const osm_subn_t *p_subn,
+ IN const osm_mad_addr_t *p_mad_addr,
+ OUT ib_gid_t *p_gid)
+{
+ const cl_ptr_vector_t* p_tbl;
+ const osm_port_t* p_port = NULL;
+ const osm_physp_t* p_physp = NULL;
+
+ if ( p_gid == NULL )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_gid_by_mad_addr: ERR 7505: "
+ "Provided output GID is NULL\n");
+ return(IB_INVALID_PARAMETER);
+ }
+
+ /* Find the port gid of the request in the subnet */
+ p_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ if ( p_port == NULL )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osm_get_gid_by_mad_addr: "
+ "Did not find any port with LID: 0x%X\n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ return(IB_INVALID_PARAMETER);
+ }
+ p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+ p_gid->unicast.interface_id = p_physp->port_guid;
+ p_gid->unicast.prefix = p_subn->opt.subnet_prefix;
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_gid_by_mad_addr: ERR 7501: "
+ "LID is out of range: 0x%X\n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ return(IB_INVALID_PARAMETER);
+ }
+
+ 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 )
+{
+ const cl_ptr_vector_t* p_port_lid_tbl;
+ osm_port_t* p_port = NULL;
+ osm_physp_t* p_physp = NULL;
+
+ /* Find the port gid of the request in the subnet */
+ p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port = cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ if (p_port == NULL)
+ {
+ /* The port is not in the port_lid table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_physp_by_mad_addr: ERR 7502: "
+ "Cannot locate port object by lid: 0x%X\n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+
+ goto Exit;
+ }
+ p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_physp_by_mad_addr: ERR 7503: "
+ "Lid is out of range: 0x%X\n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ }
+
+ Exit:
+ return p_physp;
+}
+
+/**********************************************************************
+ **********************************************************************/
+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 )
+{
+ const cl_ptr_vector_t* p_port_lid_tbl;
+ osm_port_t* p_port = NULL;
+
+ /* Find the port gid of the request in the subnet */
+ p_port_lid_tbl = &p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
+ cl_ntoh16(p_mad_addr->dest_lid))
+ {
+ p_port =
+ cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
+ }
+ else
+ {
+ /* The dest_lid is not in the subnet table - this is an error */
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_get_port_by_mad_addr: ERR 7504: "
+ "Lid is out of range: 0x%X\n",
+ cl_ntoh16(p_mad_addr->dest_lid)
+ );
+ }
+
+ return p_port;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t *
+osm_get_switch_by_guid(
+ IN const osm_subn_t *p_subn,
+ IN uint64_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 uint64_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 uint64_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;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+subn_set_default_qos_options(
+ IN osm_qos_options_t *opt)
+{
+ opt->max_vls = 15;
+ opt->high_limit = 0;
+ opt->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";
+ opt->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";
+ opt->sl2vl = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,7";
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_set_default_opt(
+ IN osm_subn_opt_t* const 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->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
+ p_opt->m_key_lease_period = 0;
+ p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
+ p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
+ p_opt->console = FALSE;
+ p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
+ /* 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 = 0;
+ p_opt->reassign_lids = FALSE;
+ p_opt->reassign_lfts = TRUE;
+ p_opt->ignore_other_sm = FALSE;
+ p_opt->single_thread = FALSE;
+ p_opt->no_multicast_option = 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->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 = 0;
+ p_opt->honor_guid2lid_file = FALSE;
+
+ 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 = OSM_DEFAULT_TMP_DIR;
+
+ p_opt->log_file = OSM_DEFAULT_LOG_FILE;
+ p_opt->log_max_size = 0;
+ p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
+ p_opt->no_partition_enforcement = FALSE;
+ p_opt->no_qos = TRUE;
+ p_opt->accum_log_file = TRUE;
+ p_opt->port_profile_switch_nodes = FALSE;
+ p_opt->pfn_ui_pre_lid_assign = NULL;
+ p_opt->ui_pre_lid_assign_ctx = NULL;
+ p_opt->pfn_ui_mcast_fdb_assign = NULL;
+ p_opt->ui_mcast_fdb_assign_ctx = NULL;
+ p_opt->sweep_on_trap = TRUE;
+ p_opt->testability_mode = OSM_TEST_MODE_NONE;
+ p_opt->routing_engine_name = NULL;
+ p_opt->lid_matrix_dump_file = NULL;
+ p_opt->ucast_dump_file = NULL;
+ p_opt->updn_guid_file = NULL;
+ p_opt->sa_db_file = NULL;
+ p_opt->exit_on_fatal = TRUE;
+ p_opt->enable_quirks = FALSE;
+ p_opt->no_clients_rereg = FALSE;
+ subn_set_default_qos_options(&p_opt->qos_options);
+ subn_set_default_qos_options(&p_opt->qos_ca_options);
+ subn_set_default_qos_options(&p_opt->qos_sw0_options);
+ subn_set_default_qos_options(&p_opt->qos_swe_options);
+ subn_set_default_qos_options(&p_opt->qos_rtr_options);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net64(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint64_t *p_val)
+{
+ uint64_t val;
+ if (!strcmp(p_req_key, p_key))
+ {
+#if __WORDSIZE == 64
+ val = strtoul(p_val_str, NULL, 0);
+#else
+ val = strtoull(p_val_str, NULL, 0);
+#endif
+ if (cl_hton64(val) != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = cl_ntoh64(val);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint32(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint32_t *p_val)
+{
+ uint32_t val;
+ if (!strcmp(p_req_key, p_key))
+ {
+ val = strtoul(p_val_str, NULL, 0);
+ if (val != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %u\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_net16(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint16_t *p_val)
+{
+ if (!strcmp(p_req_key, p_key))
+ {
+ uint32_t val;
+ val = strtoul(p_val_str, NULL, 0);
+ CL_ASSERT( val < 0x10000 );
+ if (cl_hton32(val) != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = 0x%04x\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = cl_hton16((uint16_t)val);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_uint8(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN uint8_t *p_val)
+{
+ if (!strcmp(p_req_key, p_key))
+ {
+ uint32_t val;
+ val = strtoul(p_val_str, NULL, 0);
+ CL_ASSERT( val < 0x100 );
+ if (val != *p_val)
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %u\n",
+ p_key, val);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = (uint8_t)val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_boolean(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN boolean_t *p_val)
+{
+ if (!strcmp(p_req_key, p_key) && p_val_str)
+ {
+ boolean_t val;
+ if (strcmp("TRUE", p_val_str))
+ val = FALSE;
+ else
+ val = TRUE;
+
+ if (val != *p_val) {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %s\n",
+ p_key, p_val_str);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+ *p_val = val;
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static inline void
+__osm_subn_opts_unpack_charp(
+ IN char *p_req_key,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN char **p_val)
+{
+ if (!strcmp(p_req_key, p_key) && p_val_str)
+ {
+ if ((*p_val == NULL) || strcmp(p_val_str, *p_val))
+ {
+ char buff[128];
+ sprintf(buff, " Using Cached Option:%s = %s\n",
+ p_key, p_val_str);
+ printf(buff);
+ cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
+
+ /*
+ Ignore the possible memory leak here;
+ the pointer may be to a static default.
+ */
+ *p_val = (char *)malloc( strlen(p_val_str) +1 );
+ strcpy( *p_val, p_val_str);
+ }
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+subn_parse_qos_options(
+ IN const char *prefix,
+ IN char *p_key,
+ IN char *p_val_str,
+ IN osm_qos_options_t *opt)
+{
+ char name[256];
+
+ snprintf(name, sizeof(name), "%s_max_vls", prefix);
+ __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls);
+ snprintf(name, sizeof(name), "%s_high_limit", prefix);
+ __osm_subn_opts_unpack_uint32(name, p_key, p_val_str, &opt->high_limit);
+ snprintf(name, sizeof(name), "%s_vlarb_high", prefix);
+ __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high);
+ snprintf(name, sizeof(name), "%s_vlarb_low", prefix);
+ __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low);
+ snprintf(name, sizeof(name), "%s_sl2vl", prefix);
+ __osm_subn_opts_unpack_charp(name, p_key, p_val_str, &opt->sl2vl);
+}
+
+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 %u\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);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_rescan_conf_file(
+ IN osm_subn_opt_t* const p_opts )
+{
+ char *p_cache_dir = getenv("OSM_CACHE_DIR");
+ char file_name[256];
+ FILE *opts_file;
+ char line[1024];
+ char *p_key, *p_val ,*p_last;
+
+ /* try to open the options file from the cache dir */
+ if (!p_cache_dir || !(*p_cache_dir))
+ p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+ strcpy(file_name, p_cache_dir);
+ strcat(file_name, "opensm.opts");
+
+ opts_file = fopen(file_name, "r");
+ if (!opts_file)
+ return;
+
+ while (fgets(line, 1023, opts_file) != NULL)
+ {
+ /* get the first token */
+ p_key = strtok_r(line, " \t\n", &p_last);
+ if (p_key)
+ {
+ p_val = strtok_r(NULL, " \t\n", &p_last);
+
+ subn_parse_qos_options("qos",
+ p_key, p_val, &p_opts->qos_options);
+
+ subn_parse_qos_options("qos_ca",
+ p_key, p_val, &p_opts->qos_ca_options);
+
+ subn_parse_qos_options("qos_sw0",
+ p_key, p_val, &p_opts->qos_sw0_options);
+
+ subn_parse_qos_options("qos_swe",
+ p_key, p_val, &p_opts->qos_swe_options);
+
+ subn_parse_qos_options("qos_rtr",
+ p_key, p_val, &p_opts->qos_rtr_options);
+
+ }
+ }
+ fclose(opts_file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_parse_conf_file(
+ IN osm_subn_opt_t* const p_opts )
+{
+ char *p_cache_dir = getenv("OSM_CACHE_DIR");
+ char file_name[256];
+ FILE *opts_file;
+ char line[1024];
+ char *p_key, *p_val ,*p_last;
+
+ /* try to open the options file from the cache dir */
+ if (!p_cache_dir || !(*p_cache_dir))
+ p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+ strcpy(file_name, p_cache_dir);
+ strcat(file_name, "opensm.opts");
+
+ opts_file = fopen(file_name, "r");
+ if (!opts_file) return;
+
+ while (fgets(line, 1023, opts_file) != NULL)
+ {
+ /* get the first token */
+ p_key = strtok_r(line, " \t\n", &p_last);
+ if (p_key)
+ {
+ p_val = strtok_r(NULL, " \t\n", &p_last);
+
+ __osm_subn_opts_unpack_net64(
+ "guid", p_key, p_val, &p_opts->guid);
+
+ __osm_subn_opts_unpack_net64(
+ "m_key", p_key, p_val, &p_opts->m_key);
+
+ __osm_subn_opts_unpack_net64(
+ "sm_key", p_key, p_val, &p_opts->sm_key);
+
+ __osm_subn_opts_unpack_net64(
+ "subnet_prefix",
+ p_key, p_val, &p_opts->subnet_prefix);
+
+ __osm_subn_opts_unpack_net16(
+ "m_key_lease_period",
+ p_key, p_val, &p_opts->m_key_lease_period);
+
+ __osm_subn_opts_unpack_uint32(
+ "sweep_interval",
+ p_key, p_val, &p_opts->sweep_interval);
+
+ __osm_subn_opts_unpack_uint32(
+ "max_wire_smps",
+ p_key, p_val, &p_opts->max_wire_smps);
+
+ __osm_subn_opts_unpack_uint32(
+ "transaction_timeout",
+ p_key, p_val, &p_opts->transaction_timeout);
+
+ __osm_subn_opts_unpack_uint32(
+ "max_msg_fifo_timeout",
+ p_key, p_val, &p_opts->max_msg_fifo_timeout);
+
+ __osm_subn_opts_unpack_uint8(
+ "sm_priority",
+ p_key, p_val, &p_opts->sm_priority);
+
+ __osm_subn_opts_unpack_uint8(
+ "lmc",
+ p_key, p_val, &p_opts->lmc);
+
+ __osm_subn_opts_unpack_boolean(
+ "lmc_esp0",
+ p_key, p_val, &p_opts->lmc_esp0);
+
+ __osm_subn_opts_unpack_uint8(
+ "max_op_vls",
+ p_key, p_val, &p_opts->max_op_vls);
+
+ __osm_subn_opts_unpack_uint8(
+ "force_link_speed",
+ p_key, p_val, &p_opts->force_link_speed);
+
+ __osm_subn_opts_unpack_boolean(
+ "reassign_lids",
+ p_key, p_val, &p_opts->reassign_lids);
+
+ __osm_subn_opts_unpack_boolean(
+ "reassign_lfts",
+ p_key, p_val, &p_opts->reassign_lfts);
+
+ __osm_subn_opts_unpack_boolean(
+ "ignore_other_sm",
+ p_key, p_val, &p_opts->ignore_other_sm);
+
+ __osm_subn_opts_unpack_boolean(
+ "single_thread",
+ p_key, p_val, &p_opts->single_thread);
+
+ __osm_subn_opts_unpack_boolean(
+ "no_multicast_option",
+ p_key, p_val, &p_opts->no_multicast_option);
+
+ __osm_subn_opts_unpack_boolean(
+ "disable_multicast",
+ p_key, p_val, &p_opts->disable_multicast);
+
+ __osm_subn_opts_unpack_boolean(
+ "force_log_flush",
+ p_key, p_val, &p_opts->force_log_flush);
+
+ __osm_subn_opts_unpack_uint8(
+ "subnet_timeout",
+ p_key, p_val, &p_opts->subnet_timeout);
+
+ __osm_subn_opts_unpack_uint8(
+ "packet_life_time",
+ p_key, p_val, &p_opts->packet_life_time);
+
+ __osm_subn_opts_unpack_uint8(
+ "vl_stall_count",
+ p_key, p_val, &p_opts->vl_stall_count);
+
+ __osm_subn_opts_unpack_uint8(
+ "leaf_vl_stall_count",
+ p_key, p_val, &p_opts->leaf_vl_stall_count);
+
+ __osm_subn_opts_unpack_uint8(
+ "head_of_queue_lifetime",
+ p_key, p_val, &p_opts->head_of_queue_lifetime);
+
+ __osm_subn_opts_unpack_uint8(
+ "leaf_head_of_queue_lifetime",
+ p_key, p_val, &p_opts->leaf_head_of_queue_lifetime);
+
+ __osm_subn_opts_unpack_uint8(
+ "local_phy_errors_threshold",
+ p_key, p_val, &p_opts->local_phy_errors_threshold);
+
+ __osm_subn_opts_unpack_uint8(
+ "overrun_errors_threshold",
+ p_key, p_val, &p_opts->overrun_errors_threshold);
+
+ __osm_subn_opts_unpack_uint32(
+ "sminfo_polling_timeout",
+ p_key, p_val, &p_opts->sminfo_polling_timeout);
+
+ __osm_subn_opts_unpack_uint32(
+ "polling_retry_number",
+ p_key, p_val, &p_opts->polling_retry_number);
+
+ __osm_subn_opts_unpack_boolean(
+ "force_heavy_sweep",
+ p_key, p_val, &p_opts->force_heavy_sweep);
+
+ __osm_subn_opts_unpack_uint8(
+ "log_flags",
+ p_key, p_val, &p_opts->log_flags);
+
+ __osm_subn_opts_unpack_boolean(
+ "port_profile_switch_nodes",
+ p_key, p_val, &p_opts->port_profile_switch_nodes);
+
+ __osm_subn_opts_unpack_boolean(
+ "sweep_on_trap",
+ p_key, p_val, &p_opts->sweep_on_trap);
+
+ __osm_subn_opts_unpack_charp(
+ "routing_engine",
+ p_key, p_val, &p_opts->routing_engine_name);
+
+ __osm_subn_opts_unpack_charp(
+ "log_file", p_key, p_val, &p_opts->log_file);
+
+ __osm_subn_opts_unpack_uint32(
+ "log_max_size",
+ p_key, p_val, (uint32_t *)&p_opts->log_max_size);
+
+ __osm_subn_opts_unpack_charp(
+ "partition_config_file",
+ p_key, p_val, &p_opts->partition_config_file);
+
+ __osm_subn_opts_unpack_boolean(
+ "no_partition_enforcement",
+ p_key, p_val, &p_opts->no_partition_enforcement);
+
+ __osm_subn_opts_unpack_boolean(
+ "no_qos",
+ p_key, p_val, &p_opts->no_qos);
+
+ __osm_subn_opts_unpack_boolean(
+ "accum_log_file",
+ p_key, p_val, &p_opts->accum_log_file);
+
+ __osm_subn_opts_unpack_charp(
+ "dump_files_dir",
+ p_key, p_val, &p_opts->dump_files_dir);
+
+ __osm_subn_opts_unpack_charp(
+ "lid_matrix_dump_file",
+ p_key, p_val, &p_opts->lid_matrix_dump_file);
+
+ __osm_subn_opts_unpack_charp(
+ "ucast_dump_file",
+ p_key, p_val, &p_opts->ucast_dump_file);
+
+ __osm_subn_opts_unpack_charp(
+ "updn_guid_file",
+ p_key, p_val, &p_opts->updn_guid_file);
+
+ __osm_subn_opts_unpack_charp(
+ "sa_db_file",
+ p_key, p_val, &p_opts->sa_db_file);
+
+ __osm_subn_opts_unpack_boolean(
+ "exit_on_fatal",
+ p_key, p_val, &p_opts->exit_on_fatal);
+
+ __osm_subn_opts_unpack_boolean(
+ "honor_guid2lid_file",
+ p_key, p_val, &p_opts->honor_guid2lid_file);
+
+ subn_parse_qos_options("qos",
+ p_key, p_val, &p_opts->qos_options);
+
+ subn_parse_qos_options("qos_ca",
+ p_key, p_val, &p_opts->qos_ca_options);
+
+ subn_parse_qos_options("qos_sw0",
+ p_key, p_val, &p_opts->qos_sw0_options);
+
+ subn_parse_qos_options("qos_swe",
+ p_key, p_val, &p_opts->qos_swe_options);
+
+ subn_parse_qos_options("qos_rtr",
+ p_key, p_val, &p_opts->qos_rtr_options);
+
+ __osm_subn_opts_unpack_boolean(
+ "enable_quirks",
+ p_key, p_val, &p_opts->enable_quirks);
+
+ }
+ }
+ fclose(opts_file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_subn_write_conf_file(
+ IN osm_subn_opt_t* const p_opts )
+{
+ char *p_cache_dir = getenv("OSM_CACHE_DIR");
+ char file_name[256];
+ FILE *opts_file;
+
+ /* try to open the options file from the cache dir */
+ if (!p_cache_dir || !(*p_cache_dir))
+ p_cache_dir = OSM_DEFAULT_CACHE_DIR;
+
+ strcpy(file_name, p_cache_dir);
+ strcat(file_name, "opensm.opts");
+
+ opts_file = fopen(file_name, "w");
+ if (!opts_file) return;
+
+ fprintf(
+ opts_file,
+ "#\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 [msec]\n"
+ "m_key_lease_period %u\n\n"
+ "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n"
+ "sm_key 0x%016" PRIx64 "\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"
+ "# The code of maximal time a packet can live in a switch\n"
+ "# The actual time is 4.096usec * 2^<packet_life_time>\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^<head_of_queue_lifetime>\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 switch links which are more than SDR capable to \n"
+ "# operate at SDR speed\n\n"
+ "force_link_speed %u\n\n"
+ "# The subnet_timeout code that will be set for all the ports\n"
+ "# The actual timeout is 4.096usec * 2^<subnet_timeout>\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 credits over-run errors for sending Trap 129\n"
+ "overrun_errors_threshold 0x%02x\n\n",
+ cl_ntoh64(p_opts->guid),
+ cl_ntoh64(p_opts->m_key),
+ cl_ntoh16(p_opts->m_key_lease_period),
+ cl_ntoh64(p_opts->sm_key),
+ cl_ntoh64(p_opts->subnet_prefix),
+ p_opts->lmc,
+ p_opts->lmc_esp0 ? "TRUE" : "FALSE",
+ 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->subnet_timeout,
+ p_opts->local_phy_errors_threshold,
+ p_opts->overrun_errors_threshold
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# PARTITIONING OPTIONS\n#\n"
+ "# Partition configuration file to be used\n"
+ "partition_config_file %s\n\n"
+ "# Disable partition enforcement by switches\n"
+ "no_partition_enforcement %s\n\n",
+ p_opts->partition_config_file,
+ p_opts->no_partition_enforcement ? "TRUE" : "FALSE");
+
+ fprintf(
+ opts_file,
+ "#\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 ignore existing LFT entries on first sweep (default).\n"
+ "# Otherwise only non minimal hop cases are modified.\n"
+ "# NOTE: A standby SM clears its first sweep flag - since the\n"
+ "# master SM already sweeps...\n"
+ "reassign_lfts %s\n\n"
+ "# If TRUE forces every sweep to be a heavy sweep\n"
+ "force_heavy_sweep %s\n\n"
+ "# If TRUE every trap 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->reassign_lfts ? "TRUE" : "FALSE",
+ p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
+ p_opts->sweep_on_trap ? "TRUE" : "FALSE"
+ );
+
+ fprintf(
+ opts_file,
+ "#\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");
+
+ if (p_opts->routing_engine_name)
+ fprintf( opts_file,
+ "# Routing engine\n"
+ "routing_engine %s\n\n",
+ p_opts->routing_engine_name);
+ if (p_opts->lid_matrix_dump_file)
+ fprintf( opts_file,
+ "# Lid matrix dump file name\n"
+ "lid_matrix_dump_file %s\n\n",
+ p_opts->lid_matrix_dump_file);
+ if (p_opts->ucast_dump_file)
+ fprintf( opts_file,
+ "# Ucast dump file name\n"
+ "ucast_dump_file %s\n\n",
+ p_opts->ucast_dump_file);
+ if (p_opts->updn_guid_file)
+ fprintf( opts_file,
+ "# The file holding the Up/Down root node guids\n"
+ "# One guid in each line\n"
+ "updn_guid_file %s\n\n",
+ p_opts->updn_guid_file);
+ if (p_opts->sa_db_file)
+ fprintf( opts_file,
+ "# SA database file name\n"
+ "sa_db_file %s\n\n",
+ p_opts->sa_db_file);
+
+ fprintf(
+ opts_file,
+ "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
+ "# SM priority used for deciding who is the master\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(
+ opts_file,
+ "#\n# TIMING AND THREADING OPTIONS\n#\n"
+ "# Number of MADs sent in parallel\n"
+ "max_wire_smps %u\n\n"
+ "# The time taken to a transaction to finish in [msec]\n"
+ "transaction_timeout %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 returned with a BUSY status.\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->transaction_timeout,
+ p_opts->max_msg_fifo_timeout,
+ p_opts->single_thread ? "TRUE" : "FALSE"
+ );
+
+ fprintf(
+ opts_file,
+ "#\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. If overrun, log is restarted\n"
+ "log_max_size %lu\n\n"
+ "# If TRUE will accumulate the log over multiple OpenSM sessions\n"
+ "accum_log_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 OpenSM should disable multicast support\n"
+ "no_multicast_option %s\n\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",
+ 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->dump_files_dir,
+ p_opts->enable_quirks ? "TRUE" : "FALSE",
+ p_opts->no_multicast_option ? "TRUE" : "FALSE",
+ p_opts->disable_multicast ? "TRUE" : "FALSE",
+ p_opts->exit_on_fatal ? "TRUE" : "FALSE"
+ );
+
+ fprintf(
+ opts_file,
+ "#\n# QoS OPTIONS\n#\n"
+ "# Disable QoS setup\n"
+ "no_qos %s\n\n",
+ p_opts->no_qos ? "TRUE" : "FALSE");
+
+ subn_dump_qos_options(opts_file,
+ "QoS default options", "qos", &p_opts->qos_options);
+ fprintf(opts_file, "\n");
+ subn_dump_qos_options(opts_file,
+ "QoS CA options", "qos_ca", &p_opts->qos_ca_options);
+ fprintf(opts_file, "\n");
+ subn_dump_qos_options(opts_file,
+ "QoS Switch Port 0 options", "qos_sw0", &p_opts->qos_sw0_options);
+ fprintf(opts_file, "\n");
+ subn_dump_qos_options(opts_file,
+ "QoS Switch external ports options", "qos_swe", &p_opts->qos_swe_options);
+ fprintf(opts_file, "\n");
+ subn_dump_qos_options(opts_file,
+ "QoS Router ports options", "qos_rtr", &p_opts->qos_rtr_options);
+
+ /* optional string attributes ... */
+
+ fclose(opts_file);
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sw_info_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_si_rcv_t.
+ * This object represents the SwitchInfo Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_sw_info_rcv.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_helper.h>
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_port_info(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const p_sw,
+ IN const osm_madw_t* const p_madw )
+{
+ osm_madw_context_t context;
+ uint8_t port_num;
+ osm_physp_t *p_physp;
+ osm_node_t *p_node;
+ uint8_t num_ports;
+ osm_dr_path_t dr_path;
+ const ib_smp_t* p_smp;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_port_info );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ /*
+ Request PortInfo attribute for each port on the switch.
+ Don't trust the port's own DR Path, since it may no longer
+ be a legitimate path through the subnet.
+ Build a path from the mad instead, since we know that path works.
+ The port's DR Path info gets updated when the PortInfo
+ attribute is received.
+ */
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ 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.update_master_sm_base_lid = FALSE;
+ context.pi_context.ignore_errors = FALSE;
+ context.pi_context.light_sweep = FALSE;
+ context.pi_context.active_transition = FALSE;
+
+ num_ports = osm_node_get_num_physp( p_node );
+ osm_dr_path_init( &dr_path,
+ osm_madw_get_bind_handle( p_madw ),
+ p_smp->hop_count, p_smp->initial_path );
+
+ for( port_num = 0; port_num < num_ports; port_num++)
+ {
+ status = osm_req_get(
+ p_rcv->p_req,
+ &dr_path,
+ IB_MAD_ATTR_PORT_INFO,
+ cl_hton32( port_num ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_port_info: ERR 3602: "
+ "Failure initiating PortInfo request (%s)\n",
+ ib_get_err_str(status));
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_fwd_tbl(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const 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( p_rcv->p_log, __osm_si_rcv_get_fwd_tbl );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ 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_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++)
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_fwd_tbl: "
+ "Retrieving FT block %u\n", block_id_ho );
+ }
+
+ status = osm_req_get(
+ p_rcv->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_LIN_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_fwd_tbl: ERR 3603: "
+ "Failure initiating PortInfo request (%s)\n",
+ ib_get_err_str(status));
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#if 0
+/**********************************************************************
+ The plock must be held before calling this function.
+**********************************************************************/
+static void
+__osm_si_rcv_get_mcast_fwd_tbl(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_switch_t* const 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( p_rcv->p_log, __osm_si_rcv_get_mcast_fwd_tbl );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Multicast not supported by switch 0x%016" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ goto Exit;
+ }
+
+ p_physp = osm_node_get_any_physp_ptr( p_node );
+ p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
+
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+
+ context.mft_context.node_guid = osm_node_get_node_guid( p_node );
+ context.mft_context.set_method = FALSE;
+
+ max_block_id_ho = osm_mcast_tbl_get_max_block( p_tbl );
+
+ if( max_block_id_ho > IB_MCAST_MAX_BLOCK_ID )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_mcast_fwd_tbl: 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( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Max MFT block = %u, Max position = %u\n", max_block_id_ho,
+ max_position );
+
+ 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++)
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Retrieving MFT block %u\n", block_id_ho );
+ }
+
+ for( position = 0; position <= max_position; position++ )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_get_mcast_fwd_tbl: "
+ "Retrieving MFT position %u\n", position );
+ }
+
+ attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT;
+ status = osm_req_get(
+ p_rcv->p_req,
+ p_dr_path,
+ IB_MAD_ATTR_MCAST_FWD_TBL,
+ cl_hton32( attr_mod_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+ if( status != IB_SUCCESS )
+ {
+ /* continue the loop despite the error */
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3607: "
+ "Failure initiating PortInfo request (%s)\n",
+ ib_get_err_str(status));
+ }
+ }
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
+/**********************************************************************
+ Lock must be held on entry to this function.
+**********************************************************************/
+static void
+__osm_si_rcv_process_new(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new );
+
+ CL_ASSERT( p_madw );
+
+ p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+
+ /*
+ Allocate a new switch object for this switch,
+ and place it in the switch table.
+ */
+ p_sw = osm_switch_new( p_node, p_madw );
+ if( p_sw == NULL )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_process_new: ERR 3608: "
+ "Unable to allocate new switch object\n" );
+ goto Exit;
+ }
+
+ /* set subnet max mlid to the minimum MulticastFDBCap of all switches */
+ if ( p_sw->mcast_tbl.max_mlid_ho < p_rcv->p_subn->max_multicast_lid_ho )
+ {
+ p_rcv->p_subn->max_multicast_lid_ho = p_sw->mcast_tbl.max_mlid_ho;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_new: "
+ "Subnet max multicast lid is 0x%X\n",
+ p_rcv->p_subn->max_multicast_lid_ho );
+ }
+
+ /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */
+ if ( p_sw->fwd_tbl.p_lin_tbl->size < p_rcv->p_subn->max_unicast_lid_ho )
+ {
+ p_rcv->p_subn->max_unicast_lid_ho = p_sw->fwd_tbl.p_lin_tbl->size;
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_new: "
+ "Subnet max unicast lid is 0x%X\n",
+ p_rcv->p_subn->max_unicast_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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_si_rcv_process_new: 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 );
+ osm_switch_discovery_count_inc( p_sw );
+
+ /*
+ Get the PortInfo attribute for every port.
+ */
+ __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+ __osm_si_rcv_get_fwd_tbl( p_rcv, p_sw );
+
+ /*
+ Don't bother retrieving the current 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.
+ */
+#if 0
+ if( !p_rcv->p_subn->opt.disable_multicast )
+ __osm_si_rcv_get_mcast_fwd_tbl( p_rcv, p_sw );
+#endif
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->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
+__osm_si_rcv_process_existing(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const 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;
+ boolean_t is_change_detected = FALSE;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_existing );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+ p_si_context = osm_madw_get_si_context_ptr( p_madw );
+
+ if( p_si_context->set_method )
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Received logical SetResp()\n" );
+ }
+
+ osm_switch_set_switch_info( p_sw, p_si );
+ }
+ else
+ {
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Received logical GetResp()\n" );
+ }
+
+ osm_switch_set_switch_info( p_sw, p_si );
+
+ /*
+ Check the port state change bit. If true, then this switch
+ has seen a port state transition, so continue probing.
+ */
+ if( p_si_context->light_sweep == TRUE )
+ {
+ /* This is a light sweep */
+ /* If the mad was returned with an error -
+ signal a change to the state manager. */
+ if ( ib_smp_get_status( p_smp ) != 0 )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_existing: "
+ "GetResp() received with error in light sweep. "
+ "Commencing heavy sweep\n" );
+ is_change_detected = TRUE;
+ }
+ else
+ {
+ /*
+ If something changed, then just signal the state
+ manager. Don't attempt to probe further during
+ a light sweep.
+ */
+ if( ib_switch_info_get_state_change( p_si ) )
+ {
+ osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
+ is_change_detected = TRUE;
+ }
+ }
+ }
+ else
+ {
+ /*
+ This is a heavy sweep. Get information regardless
+ of the state change bit.
+ */
+ osm_switch_discovery_count_inc( p_sw );
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_si_rcv_process_existing: "
+ "discovery_count is:%u\n",
+ osm_switch_discovery_count_get( p_sw ) );
+
+ /* If this is the first discovery - then get the port_info */
+ if ( osm_switch_discovery_count_get( p_sw ) == 1 )
+ __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_si_rcv_process_existing: "
+ "Not discovering again through switch:0x%"
+ PRIx64 "\n",
+ osm_node_get_node_guid( p_sw->p_node) );
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return is_change_detected;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_construct(
+ IN osm_si_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_destroy(
+ IN osm_si_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_init(
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN osm_req_t* const p_req,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ OSM_LOG_ENTER( p_log, osm_si_rcv_init );
+
+ osm_si_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_process(
+ IN const osm_si_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_node_guid_tbl;
+ 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
+
+ /*
+ Acquire the switch object and add the switch info.
+ */
+
+ p_context = osm_madw_get_si_context_ptr( p_madw );
+
+ node_guid = p_context->node_guid;
+
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "osm_si_rcv_process: "
+ "Switch GUID 0x%016" PRIx64
+ ", TID 0x%" PRIx64 "\n",
+ cl_ntoh64( node_guid ),
+ cl_ntoh64( p_smp->trans_id ) );
+ }
+
+ CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
+
+ p_node = (osm_node_t*)cl_qmap_get( p_node_guid_tbl, node_guid );
+ if( p_node == (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_process: ERR 3606: "
+ "SwitchInfo received for nonexistent node "
+ "with GUID 0x%" PRIx64 "\n",
+ cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+
+ /*
+ Hack for bad value in Mellanox switch
+ */
+ if( cl_ntoh16( p_si->lin_top ) > IB_LID_UCAST_END_HO )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_process: ERR 3610: "
+ "\n\t\t\t\tBad LinearFDBTop value = 0x%X "
+ "on switch 0x%" PRIx64
+ "\n\t\t\t\tForcing 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 )
+ {
+ __osm_si_rcv_process_new( p_rcv, p_node, p_madw );
+ /*
+ A new switch was found during the sweep so we need
+ to ignore the current LFT settings.
+ */
+ p_rcv->p_subn->ignore_existing_lfts = TRUE;
+ }
+ else
+ {
+ /* we might get back a request for signaling change was detected */
+ if (__osm_si_rcv_process_existing( p_rcv, p_node, p_madw ))
+ {
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ osm_state_mgr_process( p_rcv->p_state_mgr,
+ OSM_SIGNAL_CHANGE_DETECTED );
+ goto Exit;
+ }
+ }
+ }
+
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sw_info_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_si_rcv_ctrl_t.
+ * This object represents the SwitchInfo request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sw_info_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_si_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_si_rcv_process( ((osm_si_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_construct(
+ IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_si_rcv_ctrl_destroy(
+ IN osm_si_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_si_rcv_ctrl_init(
+ IN osm_si_rcv_ctrl_t* const p_ctrl,
+ IN osm_si_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_si_rcv_ctrl_init );
+
+ osm_si_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_SWITCH_INFO,
+ __osm_si_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_si_rcv_ctrl_init: ERR 3701: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_sweep_fail_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_sweep_fail_ctrl_t.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.5 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_sweep_fail_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_sweep_fail_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ osm_sweep_fail_ctrl_t* const p_ctrl = (osm_sweep_fail_ctrl_t*)context;
+
+ OSM_LOG_ENTER( p_ctrl->p_log, __osm_sweep_fail_ctrl_disp_callback );
+
+ UNUSED_PARAM( p_data );
+ /*
+ Notify the state manager that we had a light sweep failure.
+ */
+ osm_state_mgr_process( p_ctrl->p_state_mgr,
+ OSM_SIGNAL_LIGHT_SWEEP_FAIL );
+
+ OSM_LOG_EXIT( p_ctrl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_construct(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_sweep_fail_ctrl_destroy(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_sweep_fail_ctrl_init(
+ IN osm_sweep_fail_ctrl_t* const p_ctrl,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_sweep_fail_ctrl_init );
+
+ osm_sweep_fail_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_disp = p_disp;
+ p_ctrl->p_state_mgr = p_state_mgr;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_LIGHT_SWEEP_FAIL,
+ __osm_sweep_fail_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_sweep_fail_ctrl_init: ERR 3501: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_switch.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_switch_t.
+ * This object represents an Infiniband switch.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.13 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_math.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_switch.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_construct(
+ IN osm_switch_t* const p_sw )
+{
+ CL_ASSERT( p_sw );
+ memset( p_sw, 0, sizeof(*p_sw) );
+ osm_lid_matrix_construct( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_switch_init(
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status = IB_SUCCESS;
+ ib_switch_info_t *p_si;
+ ib_smp_t *p_smp;
+ uint8_t num_ports;
+ uint32_t port_num;
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_madw );
+ CL_ASSERT( p_node );
+
+ osm_switch_construct( p_sw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+ p_si = (ib_switch_info_t*)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 );
+
+ p_sw->p_node = p_node;
+ p_sw->switch_info = *p_si;
+
+ status = osm_lid_matrix_init( &p_sw->lmx, num_ports );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ status = osm_fwd_tbl_init( &p_sw->fwd_tbl, p_si );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ p_sw->p_prof = malloc( sizeof(*p_sw->p_prof) * num_ports );
+ if( p_sw->p_prof == NULL )
+ {
+ status = IB_INSUFFICIENT_MEMORY;
+ goto Exit;
+ }
+
+ memset( p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports );
+
+ status = osm_mcast_tbl_init( &p_sw->mcast_tbl,
+ osm_node_get_num_physp( p_node ), cl_ntoh16( p_si->mcast_cap ) );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ osm_port_prof_construct( &p_sw->p_prof[port_num] );
+
+ Exit:
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_destroy(
+ IN osm_switch_t* const p_sw )
+{
+ /* free memory to avoid leaks */
+ osm_mcast_tbl_destroy( &p_sw->mcast_tbl );
+ free( p_sw->p_prof );
+ osm_fwd_tbl_destroy( &p_sw->fwd_tbl );
+ osm_lid_matrix_destroy( &p_sw->lmx );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_delete(
+ IN OUT osm_switch_t** const pp_sw )
+{
+ osm_switch_destroy( *pp_sw );
+ free( *pp_sw );
+ *pp_sw = NULL;
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_switch_t*
+osm_switch_new(
+ IN osm_node_t* const p_node,
+ IN const osm_madw_t* const p_madw )
+{
+ ib_api_status_t status;
+ osm_switch_t *p_sw;
+
+ p_sw = (osm_switch_t*)malloc( sizeof(*p_sw) );
+ if( p_sw )
+ {
+ memset( p_sw, 0, sizeof(*p_sw) );
+ status = osm_switch_init( p_sw, p_node, p_madw );
+ if( status != IB_SUCCESS )
+ osm_switch_delete( &p_sw );
+ }
+
+ return( p_sw );
+}
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osm_switch_get_fwd_tbl_block(
+ IN const osm_switch_t* const p_sw,
+ IN const uint32_t block_id,
+ OUT uint8_t* const p_block )
+{
+ uint16_t base_lid_ho;
+ uint16_t max_lid_ho;
+ uint16_t lid_ho;
+ uint16_t block_top_lid_ho;
+ uint32_t lids_per_block;
+ osm_fwd_tbl_t *p_tbl;
+ boolean_t return_flag = FALSE;
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_block );
+
+ p_tbl = osm_switch_get_fwd_tbl_ptr( p_sw );
+ max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+ lids_per_block = osm_fwd_tbl_get_lids_per_block( &p_sw->fwd_tbl );
+ base_lid_ho = (uint16_t)(block_id * lids_per_block);
+
+ if( base_lid_ho <= max_lid_ho )
+ {
+ /* Initialize LIDs in block to invalid port number. */
+ memset( p_block, 0xff, IB_SMP_DATA_SIZE );
+ /*
+ Determine the range of LIDs we can return with this block.
+ */
+ block_top_lid_ho = (uint16_t)(base_lid_ho + lids_per_block - 1);
+ if( block_top_lid_ho > max_lid_ho )
+ block_top_lid_ho = max_lid_ho;
+
+ /*
+ Configure the forwarding table with the routing
+ information for the specified block of LIDs.
+ */
+ for( lid_ho = base_lid_ho; lid_ho <= block_top_lid_ho; lid_ho++ )
+ {
+ p_block[lid_ho - base_lid_ho] = osm_fwd_tbl_get( p_tbl, lid_ho );
+ }
+
+ return_flag = TRUE;
+ }
+
+ return( return_flag );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_path(
+ IN const osm_switch_t* const p_sw,
+ IN const uint16_t lid_ho,
+ IN const boolean_t ignore_existing,
+ IN OUT uint64_t *remote_sys_guids,
+ IN OUT uint16_t *p_num_used_sys,
+ IN OUT uint64_t *remote_node_guids,
+ IN OUT uint16_t *p_num_used_nodes
+ )
+{
+ /*
+ 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.
+
+ If the procedure is provided with the tracking arrays
+ and counters we can conduct this algorithm.
+ */
+ boolean_t routing_for_lmc = remote_sys_guids && remote_node_guids &&
+ p_num_used_sys && p_num_used_nodes;
+ boolean_t sys_used, node_used;
+ uint16_t i;
+ uint8_t hops;
+ uint8_t least_hops;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint32_t least_paths = 0xFFFFFFFF;
+ /*
+ 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 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;
+
+ CL_ASSERT( lid_ho > 0 );
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+
+ least_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+ 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_fwd_tbl_get( &p_sw->fwd_tbl, lid_ho );
+
+ if (port_num != OSM_NO_PATH)
+ {
+ 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( (port_num < num_ports ) &&
+ osm_physp_is_valid(p_physp) &&
+ osm_physp_is_healthy(p_physp) &&
+ osm_physp_get_remote(p_physp) )
+ {
+ hops = osm_switch_get_hop_count( p_sw, lid_ho, 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 zero and num_ports is 1 + num phys ports */
+ for ( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ if ( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops)
+ {
+ /* let us make sure it is not down or unhealthy */
+ p_physp = osm_node_get_physp_ptr(p_sw->p_node, port_num);
+ if (osm_physp_is_valid(p_physp) &&
+ osm_physp_is_healthy(p_physp) &&
+ /*
+ we require all - non sma ports to be linked
+ to be routed through
+ */
+ (!port_num || osm_physp_get_remote(p_physp)))
+ {
+
+ /*
+ 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] );
+
+ /*
+ Advanced LMC routing requires tracking of the
+ best port by the node connected to the other side of
+ it.
+ */
+ if (routing_for_lmc && port_num)
+ {
+#if 0
+ printf("LID:0x%X SYS:%d NODE:%d\n", lid_ho, *p_num_used_sys, *p_num_used_nodes);
+#endif
+
+ /* Get the Remote Node */
+ p_rem_physp = osm_physp_get_remote(p_physp);
+ p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+
+ /* Is the sys guid already used ? */
+ sys_used = FALSE;
+ for (i = 0; !sys_used && (i < *p_num_used_sys); i++)
+ if (!memcmp(&p_rem_node->node_info.sys_guid,
+ &remote_sys_guids[i],
+ sizeof(uint64_t)))
+ sys_used = TRUE;
+
+ /* If not update the least hops for this case */
+ if (!sys_used)
+ {
+ if (check_count < least_paths_other_sys)
+ {
+ least_paths_other_sys = check_count;
+ best_port_other_sys = port_num;
+ }
+ }
+ else
+ { /* same sys found - try node */
+
+ /* Else is the node guid already used ? */
+ node_used = FALSE;
+ for (i = 0; !node_used && (i < *p_num_used_nodes); i++)
+ if (!memcmp(&p_rem_node->node_info.node_guid,
+ &remote_node_guids[i],
+ sizeof(uint64_t)))
+ node_used = TRUE;
+
+
+ /* If not update the least hops for this case */
+ if (!node_used)
+ {
+ if (check_count < least_paths_other_nodes)
+ {
+ least_paths_other_nodes = check_count;
+ best_port_other_node = port_num;
+ }
+ }
+
+ } /* same sys found */
+ } /* 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;
+ }
+ }
+ }
+ }
+
+ if ( port_found == FALSE )
+ return (OSM_NO_PATH);
+
+ /*
+ if we are in enhanced routing mode and the best port is not
+ the local port 0
+ */
+ if (routing_for_lmc && best_port)
+ {
+ /* 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;
+
+ /* track the remote node and system of the port used. */
+ p_physp = osm_node_get_physp_ptr(p_sw->p_node, best_port);
+ p_rem_physp = osm_physp_get_remote(p_physp);
+ p_rem_node = osm_physp_get_node_ptr(p_rem_physp);
+ memcpy(&remote_node_guids[*p_num_used_nodes],
+ &(p_rem_node->node_info.node_guid),
+ sizeof(uint64_t));
+ (*p_num_used_nodes)++;
+ memcpy(&remote_sys_guids[*p_num_used_sys],
+ &(p_rem_node->node_info.sys_guid),
+ sizeof(uint64_t));
+ (*p_num_used_sys)++;
+ }
+
+ return( best_port );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_switch_prepare_path_rebuild(
+ IN osm_switch_t* const p_sw )
+{
+ uint8_t port_num;
+ uint8_t num_ports;
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+ osm_lid_matrix_clear( &p_sw->lmx );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ osm_port_prof_construct( &p_sw->p_prof[port_num] );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint8_t
+osm_switch_recommend_mcast_path(
+ IN osm_switch_t* const p_sw,
+ IN uint16_t const lid_ho,
+ IN uint16_t const mlid_ho,
+ IN boolean_t const ignore_existing )
+{
+ uint8_t hops;
+ uint8_t port_num;
+ uint8_t num_ports;
+ uint8_t least_hops;
+
+ CL_ASSERT( lid_ho > 0 );
+ CL_ASSERT( mlid_ho >= IB_LID_MCAST_START_HO );
+
+ num_ports = osm_switch_get_num_ports( p_sw );
+
+ /*
+ 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 ) )
+ {
+ /*
+ 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, lid_ho, 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, lid_ho );
+ for( port_num = 0; port_num < num_ports; port_num++ )
+ {
+ if( osm_switch_get_hop_count( p_sw, lid_ho, port_num ) == least_hops )
+ break;
+ }
+
+ CL_ASSERT( port_num < num_ports );
+ return( port_num );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_trap_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_trap_rcv_t.
+ * This object represents the Trap Receiver object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.12 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_trap_rcv.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_inform.h>
+#include <opensm/osm_opensm.h>
+
+/**********************************************************************
+ *
+ * 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.
+ *
+ **********************************************************************/
+
+typedef struct _osm_trap_aging_tracker_context
+{
+ osm_log_t* p_log;
+ osm_physp_t* p_physp;
+} osm_trap_aging_tracker_context_t;
+
+/**********************************************************************
+ **********************************************************************/
+osm_physp_t *
+__get_physp_by_lid_and_num(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN uint16_t lid,
+ IN uint8_t num)
+{
+ cl_ptr_vector_t *p_vec = &(p_rcv->p_subn->port_lid_tbl);
+ osm_port_t *p_port;
+
+ if (lid > cl_ptr_vector_get_size(p_vec))
+ return NULL;
+
+ p_port = (osm_port_t *)cl_ptr_vector_get(p_vec, lid);
+ if (! p_port)
+ return NULL;
+
+ if (osm_port_get_num_physp(p_port) < num)
+ return NULL;
+
+ return( osm_port_get_phys_ptr(p_port, num) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+uint64_t
+osm_trap_rcv_aging_tracker_callback(
+ IN uint64_t key,
+ IN uint32_t num_regs,
+ IN void* context )
+{
+ osm_trap_rcv_t* p_rcv = (osm_trap_rcv_t*)context;
+ uint16_t lid;
+ uint8_t port_num;
+ osm_physp_t* p_physp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_aging_tracker_callback );
+
+ if (osm_exit_flag)
+ /* We got an exit flag - do nothing */
+ return 0;
+
+ lid = cl_ntoh16((uint16_t)(( key & 0x0000FFFF00000000ULL) >> 32));
+ port_num = (uint8_t)(( key & 0x00FF000000000000ULL) >> 48);
+
+ p_physp = __get_physp_by_lid_and_num( p_rcv, lid, port_num );
+ if (!p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_trap_rcv_aging_tracker_callback: "
+ "Cannot find port num:0x%X with lid:%u\n",
+ port_num, lid );
+ }
+ else
+ {
+ /* make sure the physp is still valid */
+ if ( osm_physp_is_valid(p_physp) )
+ {
+ /* If the health port was false - set it to true */
+ if (!osm_physp_is_healthy(p_physp) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_trap_rcv_aging_tracker_callback: "
+ "Clearing health bit of port num:%u with lid:%u\n",
+ port_num, lid );
+
+ /* Clear its health bit */
+ osm_physp_set_health(p_physp, TRUE);
+ }
+ }
+ }
+
+ OSM_LOG_EXIT (p_rcv->p_log );
+
+ /* We want to remove the event from the tracker - so
+ need to return zero. */
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_construct(
+ IN osm_trap_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+ cl_event_wheel_construct( &p_rcv->trap_aging_tracker );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_destroy(
+ IN osm_trap_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_destroy );
+
+ cl_event_wheel_destroy( &p_rcv->trap_aging_tracker );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_init(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_subn_t* const p_subn,
+ IN osm_stats_t* const p_stats,
+ IN osm_resp_t* const p_resp,
+ IN osm_log_t* const p_log,
+ IN osm_state_mgr_t* const p_state_mgr,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_trap_rcv_init );
+
+ osm_trap_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_stats = p_stats;
+ p_rcv->p_resp = p_resp;
+ p_rcv->p_state_mgr = p_state_mgr;
+
+ cl_event_wheel_init( &p_rcv->trap_aging_tracker, p_log );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ * CRC calculation for notice identification
+ **********************************************************************/
+
+#define CRC32_POLYNOMIAL 0xEDB88320L
+
+/* calculate the crc for a given buffer */
+static uint32_t
+__osm_trap_calc_crc32(void *buffer, uint32_t count)
+{
+ uint32_t temp1, temp2;
+ uint32_t crc = -1L;
+ unsigned char *p = (unsigned char *)buffer;
+ /* pre - calculated 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 void
+__osm_trap_get_key(
+ IN uint16_t lid,
+ IN uint8_t port_num,
+ IN ib_mad_notice_attr_t* p_ntci,
+ OUT uint64_t *trap_key)
+{
+ uint32_t crc = 0;
+
+ CL_ASSERT(trap_key);
+
+ crc = __osm_trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t));
+ *trap_key = ((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 void
+__osm_trap_rcv_process_request(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN const osm_madw_t* const 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;
+ cl_ptr_vector_t* p_tbl;
+ 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;
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_request );
+
+ 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 Exit;
+ }
+
+ /* 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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3801: "
+ "Unsupported method 0x%X\n",
+ p_smp->method );
+ goto Exit;
+ }
+
+ /*
+ * 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 received 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 (p_rcv->p_subn->sm_base_lid == 0)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_trap_rcv_process_request: "
+ "Received SLID=0 Trap with local LID=0. Ignoring MAD\n");
+ goto Exit;
+ }
+ osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
+ "__osm_trap_rcv_process_request: "
+ "Received SLID=0 Trap. Using local LID:0x%04X instead\n",
+ cl_ntoh16(p_rcv->p_subn->sm_base_lid)
+ );
+ tmp_madw.mad_addr.addr_type.smi.source_lid = p_rcv->p_subn->sm_base_lid;
+ }
+
+ source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid;
+
+ /* Print some info about the incoming Trap */
+ if (ib_notice_is_generic(p_ntci))
+ {
+ if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131)))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: "
+ "Received Generic Notice type:0x%02X num:%u Producer:%u "
+ "from LID:0x%04X Port %d TID:0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntci),
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+ cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+ cl_hton16(source_lid),
+ p_ntci->data_details.ntc_129_131.port_num,
+ cl_ntoh64(p_smp->trans_id)
+ );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: "
+ "Received Generic Notice type:0x%02X num:%u Producer:%u "
+ "from LID:0x%04X TID:0x%016" PRIx64 "\n",
+ ib_notice_get_type(p_ntci),
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num),
+ cl_ntoh32(ib_notice_get_prod_type(p_ntci)),
+ cl_hton16(source_lid),
+ cl_ntoh64(p_smp->trans_id)
+ );
+ }
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: "
+ "Received Vendor Notice type:0x%02X vend:0x%06X dev:%u "
+ "from LID:0x%04X 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(p_smp->trans_id)
+ );
+ }
+ }
+
+ osm_dump_notice( p_rcv->p_log, p_ntci, OSM_LOG_VERBOSE );
+
+ status = osm_resp_send( p_rcv->p_resp, &tmp_madw, 0, payload );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: 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(129)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
+ (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131))) )
+ {
+ /* If this is a trap 129, 130, or 131 - then this is a trap
+ signaling a change on a physical port. Mark the flag physp_change_trap 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;
+ }
+
+ /* If physp_change_trap is TRUE - the key will include the port number.
+ If not - the port_number in the key will be zero. */
+ if ( physp_change_trap == TRUE )
+ {
+ port_num = p_ntci->data_details.ntc_129_131.port_num;
+ __osm_trap_get_key(source_lid, port_num, p_ntci, &trap_key);
+ }
+ else
+ __osm_trap_get_key(source_lid, 0, p_ntci, &trap_key);
+
+ /* try to find it in the aging tracker */
+ num_received = cl_event_wheel_num_regs(&p_rcv->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( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3804: "
+ "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)
+ {
+ /* get the port */
+ p_physp = __get_physp_by_lid_and_num(
+ p_rcv,
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ port_num
+ );
+
+ if (! p_physp)
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3805: "
+ "Failed to find physical port by lid:0x%02X num:%u\n",
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ p_ntci->data_details.ntc_129_131.port_num
+ );
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Marking unhealthy physical port by lid:0x%02X num:%u\n",
+ cl_ntoh16(p_ntci->data_details.ntc_129_131.lid),
+ p_ntci->data_details.ntc_129_131.port_num
+ );
+ /* 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 it is not - no need to mark it again - just restart the timer. */
+ if ( osm_physp_is_healthy(p_physp) )
+ {
+ osm_physp_set_health(p_physp, FALSE);
+ /* Make sure we sweep again - force a heavy sweep. */
+ /* The sweep should be done only after the re-registration, or
+ else we'll be losing track of the timer. */
+ run_heavy_sweep = TRUE;
+ }
+ /* If we are marking the port as unhealthy - we want to
+ keep this for a longer period of time than the
+ OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT. Use the
+ OSM_DEFAULT_UNHEALTHY_TIMEOUT */
+ 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(&p_rcv->trap_aging_tracker,
+ trap_key,
+ cl_get_time_stamp() + event_wheel_timeout,
+ osm_trap_rcv_aging_tracker_callback, /* no callback */
+ p_rcv /* no context */
+ );
+ else
+ cl_event_wheel_reg(&p_rcv->trap_aging_tracker,
+ trap_key,
+ cl_get_time_stamp() + event_wheel_timeout,
+ NULL, /* no callback */
+ NULL /* no context */
+ );
+
+ /* If was already registered do nothing more */
+ if ( num_received > 10 && run_heavy_sweep == FALSE )
+ {
+ if (__print_num_received(num_received))
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Continuously received this trap %u times. Ignoring it\n",
+ num_received);
+ goto Exit;
+ }
+ }
+
+ /* do a sweep if we received a trap */
+ if (p_rcv->p_subn->opt.sweep_on_trap)
+ {
+ /* if this is trap number 128 or run_heavy_sweep is TRUE - update the
+ force_single_heavy_sweep flag of the subnet.
+ Sweep also on traps 144/145 - these traps signal a change on a certain
+ port capability/system image guid.
+ TODO: In the future we can change this 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) == 128) ||
+ (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 144) ||
+ (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 145) ||
+ run_heavy_sweep ))
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Forcing immediate heavy sweep. "
+ "Received trap:%u\n",
+ cl_ntoh16(p_ntci->g_or_v.generic.trap_num) );
+
+ p_rcv->p_subn->force_immediate_heavy_sweep = TRUE;
+ }
+ osm_state_mgr_process( p_rcv->p_state_mgr, 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;
+
+ /* Add a call to osm_report_notice */
+ /* We are going to report the notice - so need to fix the IssuerGID
+ accordingly. See IBA 1.1 P.653 or IBA 1.2 P.739 for details. */
+ if (is_gsi)
+ {
+ if (tmp_madw.mad_addr.addr_type.gsi.global_route)
+ {
+ memcpy(&(p_ntci->issuer_gid),
+ &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid),
+ sizeof(ib_gid_t));
+ }
+ else
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3806: "
+ "Received gsi trap with global_route FALSE. "
+ "Cannot update issuer_gid!\n" );
+ goto Exit;
+ }
+ }
+ else
+ {
+ /* Need to use the IssuerLID */
+ p_tbl = &p_rcv->p_subn->port_lid_tbl;
+
+ CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
+
+ if ((uint16_t)cl_ptr_vector_get_size(p_tbl) <= cl_ntoh16(source_lid) )
+ {
+ /* the source lid is out of range */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "source lid is out of range:0x%X\n",
+ cl_ntoh16(source_lid) );
+
+ goto Exit;
+ }
+ p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(source_lid) );
+ if ( p_port == 0)
+ {
+ /* We have the lid - but no corresponding port */
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "__osm_trap_rcv_process_request: "
+ "Cannot find port according to lid:0x%X\n",
+ cl_ntoh16(source_lid) );
+
+ goto Exit;
+ }
+
+ p_ntci->issuer_gid.unicast.prefix = p_rcv->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 */
+ CL_PLOCK_ACQUIRE( p_rcv->p_lock );
+ status = osm_report_notice(p_rcv->p_log, p_rcv->p_subn, p_ntci);
+ CL_PLOCK_RELEASE( p_rcv->p_lock );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_request: ERR 3803: "
+ "Error sending trap reports (%s)\n",
+ ib_get_err_str( status ) );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+#if 0
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_sm(
+ IN const osm_trap_rcv_t* const p_rcv,
+ IN const osm_remote_sm_t* const p_sm )
+{
+ /* const ib_sm_info_t* p_smi; */
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_sm );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_sm: ERR 3807: "
+ "This function is not supported yet\n");
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+#endif
+
+/**********************************************************************
+ CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
+**********************************************************************/
+static void
+__osm_trap_rcv_process_response(
+ IN const osm_trap_rcv_t* const p_rcv,
+ IN const osm_madw_t* const p_madw )
+{
+
+ OSM_LOG_ENTER( p_rcv->p_log, __osm_trap_rcv_process_response );
+
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "__osm_trap_rcv_process_response: ERR 3808: "
+ "This function is not supported yet\n");
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_process(
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ ib_smp_t *p_smp;
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_trap_rcv_process );
+
+ CL_ASSERT( p_madw );
+
+ p_smp = osm_madw_get_smp_ptr( p_madw );
+
+ /*
+ Determine if this is a request for our own Trap
+ or if this is a response to our request for another
+ SM's Trap.
+ */
+ if( ib_smp_is_response( p_smp ) )
+ {
+ __osm_trap_rcv_process_response( p_rcv, p_madw );
+ }
+ else
+ {
+ __osm_trap_rcv_process_request( p_rcv, p_madw );
+ }
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_trap_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_trap_rcv_ctrl_t.
+ * This object represents the Trap request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_trap_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_trap_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_trap_rcv_process( ((osm_trap_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_construct(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_trap_rcv_ctrl_destroy(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_trap_rcv_ctrl_init(
+ IN osm_trap_rcv_ctrl_t* const p_ctrl,
+ IN osm_trap_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_trap_rcv_ctrl_init );
+
+ osm_trap_rcv_ctrl_construct( p_ctrl );
+
+ p_ctrl->p_log = p_log;
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_NOTICE,
+ __osm_trap_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_trap_rcv_ctrl_init: ERR 3901: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of OpenSM unicast routing module which loads
+ * routes from the dump file
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_log.h>
+
+
+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_port_t *)cl_qmap_get(&p_osm->subn.port_guid_tbl, guid);
+ if (!p_port ||
+ p_port == (osm_port_t *)cl_qmap_end(&p_osm->subn.port_guid_tbl)) {
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "remap_lid: 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_fwd_tbl_get(osm_switch_get_fwd_tbl_ptr(p_sw), new_lid);
+ if (old_port != OSM_NO_PATH && old_port != port_num) {
+ osm_log(&p_osm->log, OSM_LOG_VERBOSE,
+ "add_path: LID collision is detected on switch "
+ "0x016%" PRIx64 ", will overwrite LID 0x%x entry\n",
+ cl_ntoh64(osm_node_get_node_guid
+ (osm_switch_get_node_ptr(p_sw))), new_lid);
+ }
+
+ p_osm->sm.ucast_mgr.lft_buf[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,
+ "add_path: 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
+ (osm_switch_get_node_ptr(p_sw))));
+}
+
+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)
+{
+ uint16_t new_lid;
+ uint8_t i;
+
+ new_lid = guid ? remap_lid(p_osm, lid, guid) : lid;
+ if (len > osm_switch_get_num_ports(p_sw))
+ len = osm_switch_get_num_ports(p_sw);
+
+ 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;
+
+ file_name = p_osm->subn.opt.ucast_dump_file;
+ if (!file_name) {
+ osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+ "do_ucast_file_load: ERR 6301: "
+ "ucast dump file name is not defined; "
+ "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,
+ "do_ucast_file_load: ERR 6302: "
+ "cannot open ucast dump file \'%s\'; "
+ "using default routing algorithm\n", file_name);
+ return -1;
+ }
+
+ 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,
+ "do_ucast_file_load: ERR 6303: "
+ "Multicast dump file detected; "
+ "skipping parsing. Using default "
+ "routing algorithm\n");
+ } else if (!strncmp(p, "Unicast lids", 12)) {
+ if (p_sw)
+ osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
+ 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);
+ return -1;
+ }
+ 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);
+ return -1;
+ }
+ 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,
+ "do_ucast_file_load: "
+ "cannot find switch %016" PRIx64 "\n",
+ cl_ntoh64(sw_guid));
+ continue;
+ }
+ memset(p_osm->sm.ucast_mgr.lft_buf, 0xff, IB_LID_UCAST_END_HO + 1);
+ } 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);
+ return -1;
+ }
+ 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);
+ return -1;
+ }
+ p = q;
+ /* additionally try to exract 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);
+ }
+ }
+
+ if (p_sw)
+ osm_ucast_mgr_set_fwd_table(&p_osm->sm.ucast_mgr, p_sw);
+
+ fclose(file);
+ return 0;
+}
+
+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;
+
+ file_name = p_osm->subn.opt.lid_matrix_dump_file;
+ if (!file_name) {
+ osm_log(&p_osm->log, OSM_LOG_ERROR|OSM_LOG_SYS,
+ "do_lid_matrix_file_load: ERR 6304: "
+ "lid matrix file name is not defined; "
+ "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,
+ "do_lid_matrix_file_load: ERR 6305: "
+ "cannot open lid matrix file \'%s\'; "
+ "using default lid matrix generation algorithm\n",
+ file_name);
+ return -1;
+ }
+
+ 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);
+ return -1;
+ }
+ 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);
+ return -1;
+ }
+ 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,
+ "do_lid_matrix_file_load: "
+ "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);
+ return -1;
+ }
+ /* 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);
+ return -1;
+ }
+ /* 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);
+ }
+ }
+
+ fclose(file);
+ return 0;
+}
+
+int osm_ucast_file_setup(osm_opensm_t * p_osm)
+{
+ p_osm->routing_engine.context = (void *)p_osm;
+ p_osm->routing_engine.build_lid_matrices = do_lid_matrix_file_load;
+ p_osm->routing_engine.ucast_build_fwd_tables = do_ucast_file_load;
+ return 0;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id$
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of OpenSM FatTree routing
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_pool.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_opensm.h>
+#include <opensm/osm_switch.h>
+
+/*
+ * FatTree rank is bounded between 2 and 8:
+ * - Tree of rank 1 has only trivial routing pathes,
+ * 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 lenght 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_fwd_tbl_t definition
+ **
+ ***************************************************/
+
+typedef uint8_t * ftree_fwd_tbl_t;
+#define FTREE_FWD_TBL_LEN (IB_LID_UCAST_END_HO + 1)
+
+/***************************************************
+ **
+ ** 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 routs upwards */
+ uint32_t counter_down; /* number of allocated routs downwards */
+} ftree_port_t;
+
+/***************************************************
+ **
+ ** ftree_port_group_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_port_group_t_
+{
+ cl_map_item_t map_item;
+ ib_net16_t base_lid; /* base lid of the current node */
+ ib_net16_t remote_base_lid; /* base lid of the remote node */
+ ib_net64_t port_guid; /* port guid of this port */
+ 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,...} */
+ union remote_hca_or_sw_
+ {
+ struct ftree_hca_t_ * remote_hca;
+ struct ftree_sw_t_ * remote_sw;
+ } remote_hca_or_sw; /* pointer to remote hca/switch */
+ cl_ptr_vector_t ports; /* vector of ports to the same lid */
+} 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;
+ uint8_t rank;
+ ftree_tuple_t tuple;
+ ib_net16_t base_lid;
+ ftree_port_group_t ** down_port_groups;
+ uint8_t down_port_groups_num;
+ ftree_port_group_t ** up_port_groups;
+ uint8_t up_port_groups_num;
+ ftree_fwd_tbl_t lft_buf;
+} 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;
+ uint16_t up_port_groups_num;
+} ftree_hca_t;
+
+/***************************************************
+ **
+ ** ftree_fabric_t definition
+ **
+ ***************************************************/
+
+typedef struct ftree_fabric_t_
+{
+ osm_opensm_t * p_osm;
+ cl_qmap_t hca_tbl;
+ cl_qmap_t sw_tbl;
+ cl_qmap_t sw_by_tuple_tbl;
+ uint8_t tree_rank;
+ ftree_sw_t ** leaf_switches;
+ uint32_t leaf_switches_num;
+ uint16_t max_hcas_per_leaf;
+ cl_pool_t sw_fwd_tbl_pool;
+ uint16_t lft_max_lid_ho;
+ boolean_t fabric_built;
+} ftree_fabric_t;
+
+/***************************************************
+ **
+ ** comparators
+ **
+ ***************************************************/
+
+static int OSM_CDECL
+__osm_ftree_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 OSM_CDECL
+__osm_ftree_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 __osm_ftree_compare_switches_by_index(
+ &((*pp_g1)->remote_hca_or_sw.remote_sw),
+ &((*pp_g2)->remote_hca_or_sw.remote_sw) );
+}
+
+/***************************************************/
+
+boolean_t
+__osm_ftree_sw_less_by_index(
+ IN ftree_sw_t * p_sw1,
+ IN ftree_sw_t * p_sw2)
+{
+ if (__osm_ftree_compare_switches_by_index((void *)&p_sw1,
+ (void *)&p_sw2) < 0)
+ return TRUE;
+ return FALSE;
+}
+
+/***************************************************/
+
+boolean_t
+__osm_ftree_sw_greater_by_index(
+ IN ftree_sw_t * p_sw1,
+ IN ftree_sw_t * p_sw2)
+{
+ if (__osm_ftree_compare_switches_by_index((void *)&p_sw1,
+ (void *)&p_sw2) > 0)
+ return TRUE;
+ return FALSE;
+}
+
+/***************************************************
+ **
+ ** ftree_tuple_t functions
+ **
+ ***************************************************/
+
+static void
+__osm_ftree_tuple_init(
+ IN ftree_tuple_t tuple)
+{
+ memset(tuple, 0xFF, FTREE_TUPLE_LEN);
+}
+
+/***************************************************/
+
+static inline boolean_t
+__osm_ftree_tuple_assigned(
+ IN ftree_tuple_t tuple)
+{
+ return (tuple[0] != 0xFF);
+}
+
+/***************************************************/
+
+#define FTREE_TUPLE_BUFFERS_NUM 6
+
+static char *
+__osm_ftree_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 (!__osm_ftree_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;
+} /* __osm_ftree_tuple_to_str() */
+
+/***************************************************/
+
+static inline ftree_tuple_key_t
+__osm_ftree_tuple_to_key(
+ IN ftree_tuple_t tuple)
+{
+ ftree_tuple_key_t key;
+ memcpy(&key, tuple, FTREE_TUPLE_LEN);
+ return key;
+}
+
+/***************************************************/
+
+static inline void
+__osm_ftree_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 *
+__osm_ftree_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));
+
+ if (p_element)
+ p_element->p_sw = p_sw;
+ return p_element;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_sw_tbl_element_destroy(
+ IN ftree_sw_tbl_element_t * p_element)
+{
+ if (!p_element)
+ return;
+ free(p_element);
+}
+
+/***************************************************
+ **
+ ** ftree_port_t functions
+ **
+ ***************************************************/
+
+static ftree_port_t *
+__osm_ftree_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
+__osm_ftree_port_destroy(
+ IN ftree_port_t * p_port)
+{
+ if(p_port)
+ free(p_port);
+}
+
+/***************************************************
+ **
+ ** ftree_port_group_t functions
+ **
+ ***************************************************/
+
+static ftree_port_group_t *
+__osm_ftree_port_group_create(
+ IN ib_net16_t base_lid,
+ IN ib_net16_t remote_base_lid,
+ IN ib_net64_t * p_port_guid,
+ IN ib_net64_t * p_remote_port_guid,
+ IN ib_net64_t * p_remote_node_guid,
+ IN uint8_t remote_node_type,
+ IN void * p_remote_hca_or_sw)
+{
+ 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->base_lid = base_lid;
+ p_group->remote_base_lid = remote_base_lid;
+ memcpy(&p_group->port_guid, p_port_guid, sizeof(ib_net64_t));
+ memcpy(&p_group->remote_port_guid, p_remote_port_guid, sizeof(ib_net64_t));
+ memcpy(&p_group->remote_node_guid, p_remote_node_guid, sizeof(ib_net64_t));
+
+ p_group->remote_node_type = remote_node_type;
+ switch (remote_node_type)
+ {
+ case IB_NODE_TYPE_CA:
+ p_group->remote_hca_or_sw.remote_hca = (ftree_hca_t *)p_remote_hca_or_sw;
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ p_group->remote_hca_or_sw.remote_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 */
+ return p_group;
+} /* __osm_ftree_port_group_create() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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++)
+ {
+ cl_ptr_vector_at(&p_group->ports, i, (void **)&p_port);
+ __osm_ftree_port_destroy(p_port);
+ }
+ cl_ptr_vector_destroy(&p_group->ports);
+ free(p_group);
+} /* __osm_ftree_port_group_destroy() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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[10*1024];
+
+ if (!p_group)
+ return;
+
+ if (!osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+ return;
+
+ size = cl_ptr_vector_get_size(&p_group->ports);
+ buff[0] = '\0';
+
+ 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,
+ "__osm_ftree_port_group_dump:"
+ " Port Group of size %u, port(s): %s, direction: %s\n"
+ " Local <--> Remote GUID (LID):"
+ "0x%016" PRIx64 " (0x%x) <--> 0x%016" PRIx64 " (0x%x)\n",
+ size,
+ buff,
+ (direction == FTREE_DIRECTION_DOWN)? "DOWN" : "UP",
+ cl_ntoh64(p_group->port_guid),
+ cl_ntoh16(p_group->base_lid),
+ cl_ntoh64(p_group->remote_port_guid),
+ cl_ntoh16(p_group->remote_base_lid));
+
+} /* __osm_ftree_port_group_dump() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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 = __osm_ftree_port_create(port_num,remote_port_num);
+ cl_ptr_vector_insert(&p_group->ports, p_port, NULL);
+}
+
+/***************************************************
+ **
+ ** ftree_sw_t functions
+ **
+ ***************************************************/
+
+static ftree_sw_t *
+__osm_ftree_sw_create(
+ IN ftree_fabric_t * p_ftree,
+ IN osm_switch_t * p_osm_sw)
+{
+ ftree_sw_t * p_sw;
+ uint8_t ports_num;
+
+ /* make sure that the switch has ports */
+ if (osm_switch_get_num_ports(p_osm_sw) == 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 = 0xFF;
+ __osm_ftree_tuple_init(p_sw->tuple);
+
+ p_sw->base_lid = osm_node_get_base_lid(osm_switch_get_node_ptr(p_sw->p_osm_sw),0);
+
+ ports_num = osm_node_get_num_physp(osm_switch_get_node_ptr(p_sw->p_osm_sw));
+ p_sw->down_port_groups =
+ (ftree_port_group_t **) malloc(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->down_port_groups || !p_sw->up_port_groups)
+ return NULL;
+ p_sw->down_port_groups_num = 0;
+ p_sw->up_port_groups_num = 0;
+
+ /* initialize lft buffer */
+ p_sw->lft_buf = (ftree_fwd_tbl_t)cl_pool_get(&p_ftree->sw_fwd_tbl_pool);
+ memset(p_sw->lft_buf, OSM_NO_PATH, FTREE_FWD_TBL_LEN);
+
+ return p_sw;
+} /* __osm_ftree_sw_create() */
+
+/***************************************************/
+
+static void
+__osm_ftree_sw_destroy(
+ IN ftree_fabric_t * p_ftree,
+ IN ftree_sw_t * p_sw)
+{
+ uint8_t i;
+
+ if (!p_sw)
+ return;
+
+ for (i = 0; i < p_sw->down_port_groups_num; i++)
+ __osm_ftree_port_group_destroy(p_sw->down_port_groups[i]);
+ for (i = 0; i < p_sw->up_port_groups_num; i++)
+ __osm_ftree_port_group_destroy(p_sw->up_port_groups[i]);
+ if (p_sw->down_port_groups)
+ free(p_sw->down_port_groups);
+ if (p_sw->up_port_groups)
+ free(p_sw->up_port_groups);
+
+ /* return switch fwd_tbl to pool */
+ if (p_sw->lft_buf)
+ cl_pool_put(&p_ftree->sw_fwd_tbl_pool, (void *)p_sw->lft_buf);
+
+ free(p_sw);
+} /* __osm_ftree_sw_destroy() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+ return;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_sw_dump: "
+ "Switch index: %s, GUID: 0x%016" PRIx64 ", Ports: %u DOWN, %u UP\n",
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ p_sw->down_port_groups_num,
+ p_sw->up_port_groups_num);
+
+ for( i = 0; i < p_sw->down_port_groups_num; i++ )
+ __osm_ftree_port_group_dump(p_ftree,
+ p_sw->down_port_groups[i],
+ FTREE_DIRECTION_DOWN);
+ for( i = 0; i < p_sw->up_port_groups_num; i++ )
+ __osm_ftree_port_group_dump(p_ftree,
+ p_sw->up_port_groups[i],
+ FTREE_DIRECTION_UP);
+
+} /* __osm_ftree_sw_dump() */
+
+/***************************************************/
+
+static boolean_t
+__osm_ftree_sw_ranked(
+ IN ftree_sw_t * p_sw)
+{
+ return (p_sw->rank != 0xFF);
+}
+
+/***************************************************/
+
+static ftree_port_group_t *
+__osm_ftree_sw_get_port_group_by_remote_lid(
+ IN ftree_sw_t * p_sw,
+ IN ib_net16_t remote_base_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
+ {
+ port_groups = p_sw->down_port_groups;
+ size = p_sw->down_port_groups_num;
+ }
+
+ for (i = 0; i < size; i++)
+ if (remote_base_lid == port_groups[i]->remote_base_lid)
+ return port_groups[i];
+
+ return NULL;
+} /* __osm_ftree_sw_get_port_group_by_remote_lid() */
+
+/***************************************************/
+
+static void
+__osm_ftree_sw_add_port(
+ IN ftree_sw_t * p_sw,
+ IN uint8_t port_num,
+ IN uint8_t remote_port_num,
+ IN ib_net16_t base_lid,
+ IN ib_net16_t remote_base_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 =
+ __osm_ftree_sw_get_port_group_by_remote_lid(p_sw,remote_base_lid,direction);
+
+ if (!p_group)
+ {
+ p_group = __osm_ftree_port_group_create(
+ base_lid,
+ remote_base_lid,
+ &port_guid,
+ &remote_port_guid,
+ &remote_node_guid,
+ remote_node_type,
+ p_remote_hca_or_sw);
+ CL_ASSERT(p_group);
+
+ if (direction == FTREE_DIRECTION_UP)
+ p_sw->up_port_groups[p_sw->up_port_groups_num++] = p_group;
+ else
+ p_sw->down_port_groups[p_sw->down_port_groups_num++] = p_group;
+ }
+ __osm_ftree_port_group_add_port(p_group,port_num,remote_port_num);
+
+} /* __osm_ftree_sw_add_port() */
+
+/***************************************************/
+
+static inline void
+__osm_ftree_sw_set_fwd_table_block(
+ IN ftree_sw_t * p_sw,
+ IN uint16_t lid_ho,
+ IN uint8_t port_num)
+{
+ p_sw->lft_buf[lid_ho] = port_num;
+}
+
+/***************************************************/
+
+static inline uint8_t
+__osm_ftree_sw_get_fwd_table_block(
+ IN ftree_sw_t * p_sw,
+ IN uint16_t lid_ho)
+{
+ return p_sw->lft_buf[lid_ho];
+}
+
+/***************************************************/
+
+static inline cl_status_t
+__osm_ftree_sw_set_hops(
+ IN ftree_sw_t * p_sw,
+ IN uint16_t max_lid_ho,
+ IN uint16_t lid_ho,
+ IN uint8_t port_num,
+ IN uint8_t hops)
+{
+ /* make sure the lid matrix has enough room */
+ osm_switch_set_min_lid_size(p_sw->p_osm_sw, max_lid_ho);
+
+ /* set local min hop table(LID) */
+ return osm_switch_set_hops(p_sw->p_osm_sw,
+ lid_ho,
+ port_num,
+ hops);
+}
+
+/***************************************************
+ **
+ ** ftree_hca_t functions
+ **
+ ***************************************************/
+
+static ftree_hca_t *
+__osm_ftree_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)
+ return NULL;
+ p_hca->up_port_groups_num = 0;
+ return p_hca;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_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++)
+ __osm_ftree_port_group_destroy(p_hca->up_port_groups[i]);
+
+ if (p_hca->up_port_groups)
+ free(p_hca->up_port_groups);
+
+ free(p_hca);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_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(&p_ftree->p_osm->log,OSM_LOG_DEBUG))
+ return;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_hca_dump: "
+ "HCA GUID: 0x%016" PRIx64 ", Ports: %u UP\n",
+ cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)),
+ p_hca->up_port_groups_num);
+
+ for( i = 0; i < p_hca->up_port_groups_num; i++ )
+ __osm_ftree_port_group_dump(p_ftree,
+ p_hca->up_port_groups[i],
+ FTREE_DIRECTION_UP);
+}
+
+/***************************************************/
+
+static ftree_port_group_t *
+__osm_ftree_hca_get_port_group_by_remote_lid(
+ IN ftree_hca_t * p_hca,
+ IN ib_net16_t remote_base_lid)
+{
+ uint32_t i;
+ for (i = 0; i < p_hca->up_port_groups_num; i++)
+ if (remote_base_lid == p_hca->up_port_groups[i]->remote_base_lid)
+ return p_hca->up_port_groups[i];
+
+ return NULL;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_hca_add_port(
+ IN ftree_hca_t * p_hca,
+ IN uint8_t port_num,
+ IN uint8_t remote_port_num,
+ IN ib_net16_t base_lid,
+ IN ib_net16_t remote_base_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)
+{
+ 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 = __osm_ftree_hca_get_port_group_by_remote_lid(p_hca,remote_base_lid);
+
+ if (!p_group)
+ {
+ p_group = __osm_ftree_port_group_create(
+ base_lid,
+ remote_base_lid,
+ &port_guid,
+ &remote_port_guid,
+ &remote_node_guid,
+ remote_node_type,
+ p_remote_hca_or_sw);
+ p_hca->up_port_groups[p_hca->up_port_groups_num++] = p_group;
+ }
+ __osm_ftree_port_group_add_port(p_group, port_num, remote_port_num);
+
+} /* __osm_ftree_hca_add_port() */
+
+/***************************************************
+ **
+ ** ftree_fabric_t functions
+ **
+ ***************************************************/
+
+static ftree_fabric_t *
+__osm_ftree_fabric_create()
+{
+ cl_status_t status;
+ 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);
+
+ status = cl_pool_init( &p_ftree->sw_fwd_tbl_pool,
+ 8, /* min pool size */
+ 0, /* max pool size - unlimited */
+ 8, /* grow size */
+ FTREE_FWD_TBL_LEN, /* object_size */
+ NULL, /* object initializer */
+ NULL, /* object destructor */
+ NULL ); /* context */
+ if (status != CL_SUCCESS)
+ return NULL;
+
+ p_ftree->tree_rank = 1;
+ return p_ftree;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_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;
+
+ 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 );
+ __osm_ftree_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 );
+ __osm_ftree_sw_destroy(p_ftree,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);
+ __osm_ftree_sw_tbl_element_destroy(p_element);
+ }
+ cl_qmap_remove_all(&p_ftree->sw_by_tuple_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->leaf_switches = NULL;
+ p_ftree->fabric_built = FALSE;
+
+} /* __osm_ftree_fabric_destroy() */
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_destroy(ftree_fabric_t * p_ftree)
+{
+ if (!p_ftree)
+ return;
+ __osm_ftree_fabric_clear(p_ftree);
+ cl_pool_destroy(&p_ftree->sw_fwd_tbl_pool);
+ free(p_ftree);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_set_rank(ftree_fabric_t * p_ftree, uint8_t rank)
+{
+ if (rank > p_ftree->tree_rank)
+ p_ftree->tree_rank = rank;
+}
+
+/***************************************************/
+
+static uint8_t
+__osm_ftree_fabric_get_rank(ftree_fabric_t * p_ftree)
+{
+ return p_ftree->tree_rank;
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_add_hca(ftree_fabric_t * p_ftree, osm_node_t * p_osm_node)
+{
+ ftree_hca_t * p_hca = __osm_ftree_hca_create(p_osm_node);
+
+ CL_ASSERT(osm_node_get_type(p_osm_node) == IB_NODE_TYPE_CA);
+
+ cl_qmap_insert(&p_ftree->hca_tbl,
+ p_osm_node->node_info.node_guid,
+ &p_hca->map_item);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_add_sw(ftree_fabric_t * p_ftree, osm_switch_t * p_osm_sw)
+{
+ ftree_sw_t * p_sw = __osm_ftree_sw_create(p_ftree,p_osm_sw);
+
+ CL_ASSERT(osm_node_get_type(p_osm_sw->p_node) == IB_NODE_TYPE_SWITCH);
+
+ 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 (cl_ntoh16(p_sw->base_lid) > p_ftree->lft_max_lid_ho)
+ p_ftree->lft_max_lid_ho = cl_ntoh16(p_sw->base_lid);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_add_sw_by_tuple(
+ IN ftree_fabric_t * p_ftree,
+ IN ftree_sw_t * p_sw)
+{
+ CL_ASSERT(__osm_ftree_tuple_assigned(p_sw->tuple));
+
+ cl_qmap_insert(&p_ftree->sw_by_tuple_tbl,
+ __osm_ftree_tuple_to_key(p_sw->tuple),
+ &__osm_ftree_sw_tbl_element_create(p_sw)->map_item);
+}
+
+/***************************************************/
+
+static ftree_sw_t *
+__osm_ftree_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(__osm_ftree_tuple_assigned(tuple));
+
+ __osm_ftree_tuple_to_key(tuple);
+
+ p_element = (ftree_sw_tbl_element_t * )cl_qmap_get(&p_ftree->sw_by_tuple_tbl,
+ __osm_ftree_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 void
+__osm_ftree_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(&p_ftree->p_osm->log,OSM_LOG_DEBUG))
+ return;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n"
+ " |-------------------------------|\n"
+ " |- Full fabric topology dump -|\n"
+ " |-------------------------------|\n\n");
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_dump: -- HCAs:\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) )
+ {
+ __osm_ftree_hca_dump(p_ftree, p_hca);
+ }
+
+ for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); i++)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_dump: -- 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)
+ __osm_ftree_sw_dump(p_ftree, p_sw);
+ }
+ }
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_dump: \n"
+ " |---------------------------------------|\n"
+ " |- Full fabric topology dump completed -|\n"
+ " |---------------------------------------|\n\n");
+} /* __osm_ftree_fabric_dump() */
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_dump_general_info(
+ IN ftree_fabric_t * p_ftree)
+{
+ uint32_t i,j;
+ ftree_sw_t * p_sw;
+ char * addition_str;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+ "__osm_ftree_fabric_dump_general_info: "
+ "General fabric topology info\n");
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,"__osm_ftree_fabric_dump_general_info: "
+ "============================\n");
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+ "__osm_ftree_fabric_dump_general_info: "
+ " - FatTree rank (switches only): %u\n",
+ p_ftree->tree_rank);
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+ "__osm_ftree_fabric_dump_general_info: "
+ " - Fabric has %u HCAs, %u switches\n",
+ cl_qmap_count(&p_ftree->hca_tbl),
+ cl_qmap_count(&p_ftree->sw_tbl));
+
+ for (i = 0; i < __osm_ftree_fabric_get_rank(p_ftree); 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)
+ addition_str = " (root) ";
+ else
+ if (i == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ addition_str = " (leaf) ";
+ else
+ addition_str = " ";
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+ "__osm_ftree_fabric_dump_general_info: "
+ " - Fabric has %u rank %u%s switches\n",
+ j, i, addition_str);
+ }
+
+ if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_VERBOSE))
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_fabric_dump_general_info: "
+ " - 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,
+ "__osm_ftree_fabric_dump_general_info: "
+ " GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n",
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ __osm_ftree_tuple_to_str(p_sw->tuple));
+ }
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_fabric_dump_general_info: "
+ " - 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,
+ "__osm_ftree_fabric_dump_general_info: "
+ " GUID: 0x%016" PRIx64 ", LID: 0x%x, Index %s\n",
+ cl_ntoh64(osm_node_get_node_guid(
+ osm_switch_get_node_ptr(
+ p_ftree->leaf_switches[i]->p_osm_sw))),
+ cl_ntoh16(p_ftree->leaf_switches[i]->base_lid),
+ __osm_ftree_tuple_to_str(p_ftree->leaf_switches[i]->tuple));
+ }
+ }
+} /* __osm_ftree_fabric_dump_general_info() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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;
+ uint32_t i;
+ uint32_t j;
+
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+ char path[1024];
+ FILE * p_hca_ordering_file;
+ char * filename = "osm-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,
+ "__osm_ftree_fabric_dump_hca_ordering: ERR AB01: "
+ "cannot open file \'%s\': %s\n",
+ filename, strerror(errno));
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ 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];
+ /* for each real HCA connected to this switch */
+ for (j = 0; j < p_sw->down_port_groups_num; j++)
+ {
+ p_group = p_sw->down_port_groups[j];
+ p_hca = p_group->remote_hca_or_sw.remote_hca;
+ memcpy(desc,p_hca->p_osm_node->node_desc.description,IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+
+ fprintf(p_hca_ordering_file,"0x%x\t%s\n",
+ cl_ntoh16(p_group->remote_base_lid), desc);
+ }
+
+ /* now print dummy HCAs */
+ for (j = p_sw->down_port_groups_num; j < p_ftree->max_hcas_per_leaf; j++)
+ {
+ fprintf(p_hca_ordering_file,"0xFFFF\tDUMMY\n");
+ }
+
+ }
+ /* done going through all the leaf switches */
+
+ fclose(p_hca_ordering_file);
+} /* __osm_ftree_fabric_dump_hca_ordering() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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);
+ __osm_ftree_fabric_add_sw_by_tuple(p_ftree,p_sw);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_assign_first_tuple(
+ IN ftree_fabric_t * p_ftree,
+ IN ftree_sw_t * p_sw)
+{
+ uint8_t i;
+ ftree_tuple_t new_tuple;
+
+ __osm_ftree_tuple_init(new_tuple);
+ new_tuple[0] = p_sw->rank;
+ for (i = 1; i <= p_sw->rank; i++)
+ new_tuple[i] = 0;
+
+ __osm_ftree_fabric_assign_tuple(p_ftree,p_sw,new_tuple);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_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;
+
+ __osm_ftree_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 = __osm_ftree_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);
+
+} /* __osm_ftree_fabric_get_new_tuple() */
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_calculate_rank(
+ IN ftree_fabric_t * p_ftree)
+{
+ ftree_sw_t * p_sw;
+ ftree_sw_t * p_next_sw;
+ uint16_t max_rank = 0;
+
+ /* go over all the switches and find maximal switch rank */
+
+ 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;
+ if(p_sw->rank > max_rank)
+ max_rank = p_sw->rank;
+ p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+ }
+
+ /* set FatTree rank */
+ __osm_ftree_fabric_set_rank(p_ftree, max_rank + 1);
+}
+
+/***************************************************/
+
+static void
+__osm_ftree_fabric_make_indexing(
+ IN ftree_fabric_t * p_ftree)
+{
+ ftree_sw_t * p_remote_sw;
+ ftree_sw_t * p_sw;
+ ftree_sw_t * p_next_sw;
+ ftree_tuple_t new_tuple;
+ uint32_t i;
+ cl_list_t bfs_list;
+ ftree_sw_tbl_element_t * p_sw_tbl_element;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_make_indexing);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_fabric_make_indexing: "
+ "Starting FatTree indexing\n");
+
+ /* create array of leaf switches */
+ p_ftree->leaf_switches = (ftree_sw_t **)
+ malloc(cl_qmap_count(&p_ftree->sw_tbl) * sizeof(ftree_sw_t *));
+
+ /* Looking for a leaf switch - the one that has rank equal to (tree_rank - 1).
+ This switch will be used as a starting point for indexing algorithm. */
+
+ 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;
+ if(p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ break;
+ p_next_sw = (ftree_sw_t *)cl_qmap_next(&p_sw->map_item );
+ }
+
+ CL_ASSERT(p_next_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+
+ /* Assign the first tuple to the switch that is used as BFS starting point.
+ The tuple will be as follows: [rank].0.0.0...
+ This fuction also adds the switch it into the switch_by_tuple table. */
+ __osm_ftree_fabric_assign_first_tuple(p_ftree,p_sw);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_fabric_make_indexing: Indexing starting point:\n"
+ " - Switch rank : %u\n"
+ " - Switch index : %s\n"
+ " - Node LID : 0x%x\n"
+ " - Node GUID : 0x%016" PRIx64 "\n",
+ p_sw->rank,
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ cl_ntoh16(p_sw->base_lid),
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))));
+
+ /*
+ * 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_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl));
+ cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_sw)->map_item);
+
+ while (!cl_is_list_empty(&bfs_list))
+ {
+ p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list);
+ p_sw = p_sw_tbl_element->p_sw;
+ __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element);
+
+ /* Discover all the nodes from ports that are pointing down */
+
+ if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ {
+ /* add switch to leaf switches array */
+ p_ftree->leaf_switches[p_ftree->leaf_switches_num++] = p_sw;
+ /* update the max_hcas_per_leaf value */
+ if (p_sw->down_port_groups_num > p_ftree->max_hcas_per_leaf)
+ p_ftree->max_hcas_per_leaf = p_sw->down_port_groups_num;
+ }
+ else
+ {
+ /* This is not the leaf switch, which means that all the
+ ports that point down are taking us to another switches.
+ No need to assign indexing to HCAs */
+ for( i = 0; i < p_sw->down_port_groups_num; i++ )
+ {
+ p_remote_sw = p_sw->down_port_groups[i]->remote_hca_or_sw.remote_sw;
+ if (__osm_ftree_tuple_assigned(p_remote_sw->tuple))
+ {
+ /* this switch has been already indexed */
+ continue;
+ }
+ /* allocate new tuple */
+ __osm_ftree_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. */
+ __osm_ftree_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,
+ &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+ }
+ /* 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 */
+ __osm_ftree_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 (p_sw->rank != 0)
+ {
+ /* 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.remote_sw;
+ if (__osm_ftree_tuple_assigned(p_remote_sw->tuple))
+ continue;
+ /* allocate new tuple */
+ __osm_ftree_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. */
+ __osm_ftree_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,
+ &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+ }
+ /* 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 */
+ __osm_ftree_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 */
+ }
+
+ /* sort array of leaf switches by index */
+ qsort(p_ftree->leaf_switches, /* array */
+ p_ftree->leaf_switches_num, /* number of elements */
+ sizeof(ftree_sw_t *), /* size of each element */
+ __osm_ftree_compare_switches_by_index); /* comparator */
+
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_make_indexing() */
+
+/***************************************************/
+
+static boolean_t
+__osm_ftree_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 = __osm_ftree_fabric_get_rank(p_ftree);
+ boolean_t res = TRUE;
+ uint8_t i;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_validate_topology);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_fabric_validate_topology: "
+ "Validating fabric topology\n");
+
+ reference_sw_arr = (ftree_sw_t **)malloc(tree_rank * sizeof(ftree_sw_t *));
+ if ( reference_sw_arr == NULL )
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "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,
+ "__osm_ftree_fabric_validate_topology: "
+ "ERR AB09: Different number of upward port groups on switches:\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u groups\n",
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+ cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+ __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+ reference_sw_arr[p_sw->rank]->up_port_groups_num,
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ p_sw->up_port_groups_num);
+ res = FALSE;
+ break;
+ }
+
+ if ( p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 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,
+ "__osm_ftree_fabric_validate_topology: "
+ "ERR AB0A: Different number of downward port groups on switches:\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u port groups\n",
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+ cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+ __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+ reference_sw_arr[p_sw->rank]->down_port_groups_num,
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ __osm_ftree_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,
+ "__osm_ftree_fabric_validate_topology: "
+ "ERR AB0B: Different number of ports in an upward port group on switches:\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n",
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+ cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+ __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+ cl_ptr_vector_get_size(&p_ref_group->ports),
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ __osm_ftree_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,
+ "__osm_ftree_fabric_validate_topology: "
+ "ERR AB0C: Different number of ports in an downward port group on switches:\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, Index %s - %u ports\n",
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(reference_sw_arr[p_sw->rank]->p_osm_sw))),
+ cl_ntoh16(reference_sw_arr[p_sw->rank]->base_lid),
+ __osm_ftree_tuple_to_str(reference_sw_arr[p_sw->rank]->tuple),
+ cl_ptr_vector_get_size(&p_ref_group->ports),
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ __osm_ftree_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,
+ "__osm_ftree_fabric_validate_topology: "
+ "Fabric topology has been identified as FatTree\n");
+ else
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_validate_topology: "
+ "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;
+} /* __osm_ftree_fabric_validate_topology() */
+
+/***************************************************
+ ***************************************************/
+
+static void
+__osm_ftree_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;
+
+ /* calculate lft length rounded up to a multiple of 64 (block length) */
+ uint16_t lft_len = 64 * ((p_ftree->lft_max_lid_ho + 1 + 63) / 64);
+
+ p_sw->p_osm_sw->max_lid_ho = p_ftree->lft_max_lid_ho;
+
+ memcpy(p_ftree->p_osm->sm.ucast_mgr.lft_buf,
+ p_sw->lft_buf,
+ lft_len);
+ osm_ucast_mgr_set_fwd_table(&p_ftree->p_osm->sm.ucast_mgr, p_sw->p_osm_sw);
+}
+
+/***************************************************
+ ***************************************************/
+
+/*
+ * 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 void
+__osm_ftree_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 ib_net16_t target_lid,
+ IN uint8_t target_rank,
+ IN boolean_t is_real_lid,
+ IN boolean_t is_main_path,
+ IN uint8_t highest_rank_in_route)
+{
+ 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 i;
+ uint16_t j;
+
+ /* we shouldn't enter here if both real_lid and main_path are false */
+ CL_ASSERT(is_real_lid || is_main_path);
+
+ /* can't be here for leaf switch, */
+ CL_ASSERT(p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1));
+
+ /* if there is no down-going ports */
+ if (p_sw->down_port_groups_num == 0)
+ return;
+
+ /* foreach down-going port group (in indexing order) */
+ for (i = 0; i < p_sw->down_port_groups_num; i++)
+ {
+ p_group = p_sw->down_port_groups[i];
+
+ if ( p_prev_sw && (p_group->remote_base_lid == p_prev_sw->base_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);
+ /* ToDo: no need to select a least loaded port for non-main path.
+ Think about optimization. */
+ 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 - set as port with the lowest load */
+ p_min_port = p_port;
+ }
+ else if (p_port->counter_up < p_min_port->counter_up)
+ {
+ /* this port is less loaded - use it as min */
+ 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.remote_sw;
+
+ /* Four possible cases:
+ *
+ * 1. is_real_lid == TRUE && 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_real_lid == TRUE && is_main_path == FALSE:
+ * - going DOWN(TRUE,FALSE) through ALL the groups 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
+ *
+ * 3. is_real_lid == FALSE && is_main_path == TRUE:
+ * - going DOWN(FALSE,TRUE) through ALL the groups
+ * + promoting port counter
+ * + NOT setting path in remote switch fwd tbl
+ * + NOT setting hops in remote switch
+ *
+ * 4. is_real_lid == FALSE && is_main_path == FALSE:
+ * - illegal state - we shouldn't get here
+ */
+
+ /* second case: skip the port group if the remote (upper)
+ switch has been already configured for this target LID */
+ if ( is_real_lid && !is_main_path &&
+ __osm_ftree_sw_get_fwd_table_block(p_remote_sw,
+ cl_ntoh16(target_lid)) != OSM_NO_PATH )
+ continue;
+
+ /* setting fwd tbl port only if this is real LID */
+ if (is_real_lid)
+ {
+ __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+ cl_ntoh16(target_lid),
+ p_min_port->remote_port_num);
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_upgoing_by_going_down: "
+ "Switch %s: set path to HCA LID 0x%x through port %u\n",
+ __osm_ftree_tuple_to_str(p_remote_sw->tuple),
+ cl_ntoh16(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. */
+
+ for (j = 0; j < ports_num; j++)
+ {
+ cl_ptr_vector_at(&p_group->ports, j, (void **)&p_port);
+
+ __osm_ftree_sw_set_hops(p_remote_sw,
+ p_ftree->lft_max_lid_ho,
+ cl_ntoh16(target_lid),
+ p_port->remote_port_num,
+ ( (target_rank - highest_rank_in_route) +
+ (p_remote_sw->rank - highest_rank_in_route) ));
+ }
+
+
+ }
+
+ /* The number of upgoing routes is tracked in the
+ p_port->counter_up counter of the port that belongs to
+ the upper side of the link (on switch with lower rank).
+ Counter is promoted only if we're routing LID on the main
+ path (whether it's a real LID or a dummy one). */
+ if (is_main_path)
+ p_min_port->counter_up++;
+
+ /* Recursion step:
+ Assign upgoing ports by stepping down, starting on REMOTE switch.
+ Recursion stop condition - if the REMOTE switch is a leaf switch. */
+ if (p_remote_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ {
+ __osm_ftree_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 */
+ target_rank, /* rank of the LID that we're routing to */
+ is_real_lid, /* whether the target LID is real or dummy */
+ is_main_path, /* whether this is path to HCA that should by tracked by counters */
+ highest_rank_in_route); /* highest visited point in the tree before going down */
+ }
+ }
+ /* done scanning all the down-going port groups */
+
+} /* __osm_ftree_fabric_route_upgoing_by_going_down() */
+
+/***************************************************/
+
+/*
+ * Function: assign-down-going-port-by-descending-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-descending-up on REMOTE switch (recursion)
+ */
+
+static void
+__osm_ftree_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 ib_net16_t target_lid,
+ IN uint8_t target_rank,
+ IN boolean_t is_real_lid,
+ IN boolean_t is_main_path)
+{
+ 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;
+
+ /* we shouldn't enter here if both real_lid and main_path are false */
+ CL_ASSERT(is_real_lid || is_main_path);
+
+ /* If this switch isn't a leaf switch:
+ Assign upgoing ports by stepping down, starting on THIS switch. */
+ if (p_sw->rank != (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ {
+ __osm_ftree_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 */
+ target_rank, /* rank of the LID that we're routing to */
+ is_real_lid, /* whether this target LID is real or dummy */
+ is_main_path, /* whether this path to HCA should by tracked by counters */
+ p_sw->rank); /* the highest visited point in the tree before going down */
+ }
+
+ /* recursion stop condition - if it's a root switch, */
+ if (p_sw->rank == 0)
+ return;
+
+ /* Find the least loaded port of all the upgoing port groups
+ (in indexing order of the remote switches). */
+ p_min_group = NULL;
+ p_min_port = NULL;
+ for (i = 0; i < p_sw->up_port_groups_num; i++)
+ {
+ p_group = p_sw->up_port_groups[i];
+
+ 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_group)
+ {
+ /* first port that we're checking - use
+ it as a port with the lowest load */
+ p_min_group = p_group;
+ 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_group = p_group;
+ 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.remote_sw;
+
+ /* Four possible cases:
+ *
+ * 1. is_real_lid == TRUE && 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_real_lid == TRUE && 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
+ *
+ * 3. is_real_lid == FALSE && is_main_path == TRUE:
+ * - going UP(FALSE,TRUE) ONLY on selected min_group and min_port
+ * + promoting port counter
+ * + NOT setting path in remote switch fwd tbl
+ * + NOT setting hops in remote switch
+ *
+ * 4. is_real_lid == FALSE && is_main_path == FALSE:
+ * - illegal state - we shouldn't get here
+ */
+
+ /* covering first half of case 1, and case 3 */
+ if (is_main_path)
+ {
+ if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_downgoing_by_going_up: "
+ " - Routing MAIN path for %s HCA LID 0x%x: %s --> %s\n",
+ (is_real_lid)? "real" : "DUMMY",
+ cl_ntoh16(target_lid),
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ __osm_ftree_tuple_to_str(p_remote_sw->tuple));
+ }
+ /* The number of downgoing routes is tracked in the
+ p_port->counter_down counter of the port that belongs to
+ the lower side of the link (on switch with higher rank) */
+ p_min_port->counter_down++;
+ if (is_real_lid)
+ {
+ __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+ cl_ntoh16(target_lid),
+ p_min_port->remote_port_num);
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_downgoing_by_going_up: "
+ "Switch %s: set path to HCA LID 0x%x through port %u\n",
+ __osm_ftree_tuple_to_str(p_remote_sw->tuple),
+ cl_ntoh16(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. */
+
+ 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);
+ __osm_ftree_sw_set_hops(p_remote_sw,
+ p_ftree->lft_max_lid_ho,
+ cl_ntoh16(target_lid),
+ p_port->remote_port_num,
+ target_rank - p_remote_sw->rank);
+ }
+ }
+
+ /* Recursion step:
+ Assign downgoing ports by stepping up, starting on REMOTE switch. */
+ __osm_ftree_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 */
+ target_rank, /* rank of the LID that we're routing to */
+ is_real_lid, /* whether this target LID is real or dummy */
+ is_main_path); /* whether this is path to HCA that should by tracked by counters */
+ }
+
+ /* we're done for the third case */
+ if (!is_real_lid)
+ return;
+
+ /* What's left to do at this point:
+ *
+ * 1. is_real_lid == TRUE && 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_real_lid == TRUE && 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 = 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.remote_sw;
+
+ /* skip if target lid has been already set on remote switch fwd tbl */
+ if (__osm_ftree_sw_get_fwd_table_block(
+ p_remote_sw,cl_ntoh16(target_lid)) != OSM_NO_PATH)
+ continue;
+
+ if (p_sw->rank == (__osm_ftree_fabric_get_rank(p_ftree) - 1))
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_downgoing_by_going_up: "
+ " - Routing SECONDARY path for LID 0x%x: %s --> %s\n",
+ cl_ntoh16(target_lid),
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ __osm_ftree_tuple_to_str(p_remote_sw->tuple));
+ }
+
+ cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port);
+ __osm_ftree_sw_set_fwd_table_block(p_remote_sw,
+ cl_ntoh16(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. */
+
+ 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);
+
+ __osm_ftree_sw_set_hops(p_remote_sw,
+ p_ftree->lft_max_lid_ho,
+ cl_ntoh16(target_lid),
+ p_port->remote_port_num,
+ target_rank - p_remote_sw->rank);
+ }
+
+ /* Recursion step:
+ Assign downgoing ports by stepping up, starting on REMOTE switch. */
+ __osm_ftree_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 */
+ target_rank, /* rank of the LID that we're routing to */
+ TRUE, /* whether the target LID is real or dummy */
+ FALSE); /* whether this is path to HCA that should by tracked by counters */
+ }
+
+} /* 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-descending-up(TRUE,TRUE) on CURRENT switch
+ * for each MISSING compute node
+ * call assign-down-going-port-by-descending-up(FALSE,TRUE) on CURRENT switch
+ */
+
+static void
+__osm_ftree_fabric_route_to_hcas(
+ IN ftree_fabric_t * p_ftree)
+{
+ ftree_sw_t * p_sw;
+ ftree_port_group_t * p_group;
+ ftree_port_t * p_port;
+ uint32_t i;
+ uint32_t j;
+ ib_net16_t remote_lid;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_route_to_hcas);
+
+ /* for each leaf switch (in indexing order) */
+ for(i = 0; i < p_ftree->leaf_switches_num; i++)
+ {
+ p_sw = p_ftree->leaf_switches[i];
+
+ /* for each HCA connected to this switch */
+ for (j = 0; j < p_sw->down_port_groups_num; j++)
+ {
+ /* obtain the LID of HCA port */
+ p_group = p_sw->down_port_groups[j];
+ remote_lid = p_group->remote_base_lid;
+
+ /* set local LFT(LID) to the port that is connected to HCA */
+ cl_ptr_vector_at(&p_group->ports, 0, (void **)&p_port);
+ __osm_ftree_sw_set_fwd_table_block(p_sw,
+ cl_ntoh16(remote_lid),
+ p_port->port_num);
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_to_hcas: "
+ "Switch %s: set path to HCA LID 0x%x through port %u\n",
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ cl_ntoh16(remote_lid),
+ p_port->port_num);
+
+ /* set local min hop table(LID) to route to the CA */
+ __osm_ftree_sw_set_hops(p_sw,
+ p_ftree->lft_max_lid_ho,
+ cl_ntoh16(remote_lid),
+ p_port->port_num,
+ 1);
+
+ /* assign downgoing ports by stepping up */
+ __osm_ftree_fabric_route_downgoing_by_going_up(
+ p_ftree,
+ p_sw, /* local switch - used as a route-downgoing alg. start point */
+ NULL, /* prev. position switch */
+ remote_lid, /* LID that we're routing to */
+ __osm_ftree_fabric_get_rank(p_ftree), /* rank of the LID that we're routing to */
+ TRUE, /* whether this HCA LID is real or dummy */
+ TRUE); /* whether this path to HCA should by tracked by counters */
+ }
+
+ /* We're done with the real HCAs. Now route the dummy HCAs that are missing.
+ When routing to dummy HCAs we don't fill lid matrices. */
+
+ if (p_ftree->max_hcas_per_leaf > p_sw->down_port_groups_num)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,"__osm_ftree_fabric_route_to_hcas: "
+ "Routing %u dummy HCAs\n",
+ p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num);
+ for ( j = 0;
+ ((int)j) < (p_ftree->max_hcas_per_leaf - p_sw->down_port_groups_num);
+ j++)
+ {
+ /* assign downgoing ports by stepping up */
+ __osm_ftree_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 */
+ 0, /* rank of the LID that we're routing to - ignored for dummy HCA */
+ FALSE, /* whether this HCA LID is real or dummy */
+ TRUE); /* whether this path to HCA should by tracked by counters */
+ }
+ }
+ }
+ /* done going through all the leaf switches */
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_route_to_hcas() */
+
+/***************************************************/
+
+/*
+ * Pseudo code:
+ * foreach switch in fabric
+ * obtain its LID
+ * set local LFT(LID) to port 0
+ * call assign-down-going-port-by-descending-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
+__osm_ftree_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, __osm_ftree_fabric_route_to_switches);
+
+ 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) */
+ __osm_ftree_sw_set_fwd_table_block(p_sw,
+ cl_ntoh16(p_sw->base_lid),
+ 0);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_fabric_route_to_switches: "
+ "Switch %s (LID 0x%x): routing switch-to-switch pathes\n",
+ __osm_ftree_tuple_to_str(p_sw->tuple),
+ cl_ntoh16(p_sw->base_lid));
+
+ /* set min hop table of the switch to itself */
+ __osm_ftree_sw_set_hops(p_sw,
+ p_ftree->lft_max_lid_ho,
+ cl_ntoh16(p_sw->base_lid),
+ 0, /* port_num */
+ 0);/* hops */
+
+ __osm_ftree_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->base_lid, /* LID that we're routing to */
+ p_sw->rank, /* rank of the LID that we're routing to */
+ TRUE, /* whether the target LID is a real or dummy */
+ FALSE); /* whether this path should by tracked by counters */
+ }
+
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+} /* __osm_ftree_fabric_route_to_switches() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_fabric_populate_switches(
+ IN ftree_fabric_t * p_ftree)
+{
+ osm_switch_t * p_osm_sw;
+ osm_switch_t * p_next_osm_sw;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_populate_switches);
+
+ p_next_osm_sw = (osm_switch_t *)cl_qmap_head(&p_ftree->p_osm->subn.sw_guid_tbl);
+ while( p_next_osm_sw != (osm_switch_t *)cl_qmap_end(&p_ftree->p_osm->subn.sw_guid_tbl) )
+ {
+ p_osm_sw = p_next_osm_sw;
+ p_next_osm_sw = (osm_switch_t *)cl_qmap_next(&p_osm_sw->map_item );
+ __osm_ftree_fabric_add_sw(p_ftree,p_osm_sw);
+ }
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return 0;
+} /* __osm_ftree_fabric_populate_switches() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_fabric_populate_hcas(
+ 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, __osm_ftree_fabric_populate_hcas);
+
+ 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:
+ __osm_ftree_fabric_add_hca(p_ftree,p_osm_node);
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ break;
+ case IB_NODE_TYPE_SWITCH:
+ /* all the switches added separately */
+ break;
+ default:
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_populate_hcas: 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;
+} /* __osm_ftree_fabric_populate_hcas() */
+
+/***************************************************
+ ***************************************************/
+
+static void
+__osm_ftree_rank_from_switch(
+ IN ftree_fabric_t * p_ftree,
+ IN ftree_sw_t * p_starting_sw)
+{
+ 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;
+ cl_list_t bfs_list;
+ ftree_sw_tbl_element_t * p_sw_tbl_element = NULL;
+
+ p_starting_sw->rank = 0;
+
+ /* Run BFS scan of the tree, starting from this switch */
+
+ cl_list_init(&bfs_list, cl_qmap_count(&p_ftree->sw_tbl));
+ cl_list_insert_tail(&bfs_list, &__osm_ftree_sw_tbl_element_create(p_starting_sw)->map_item);
+
+ while (!cl_is_list_empty(&bfs_list))
+ {
+ p_sw_tbl_element = (ftree_sw_tbl_element_t *)cl_list_remove_head(&bfs_list);
+ p_sw = p_sw_tbl_element->p_sw;
+ __osm_ftree_sw_tbl_element_destroy(p_sw_tbl_element);
+
+ p_node = osm_switch_get_node_ptr(p_sw->p_osm_sw);
+
+ /* 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 (!osm_physp_is_valid(p_osm_port))
+ continue;
+ if (!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 = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,
+ osm_node_get_node_guid(p_remote_node));
+ if (p_remote_sw == (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl))
+ {
+ /* remote node is not a switch */
+ continue;
+ }
+ if (__osm_ftree_sw_ranked(p_remote_sw) && p_remote_sw->rank <= (p_sw->rank + 1))
+ continue;
+
+ /* rank the remote switch and add it to the BFS list */
+ p_remote_sw->rank = p_sw->rank + 1;
+ cl_list_insert_tail(&bfs_list,
+ &__osm_ftree_sw_tbl_element_create(p_remote_sw)->map_item);
+ }
+ }
+} /* __osm_ftree_rank_from_switch() */
+
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_rank_switches_from_hca(
+ IN ftree_fabric_t * p_ftree,
+ IN ftree_hca_t * p_hca)
+{
+ 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, __osm_ftree_rank_switches_from_hca);
+
+ 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 (!osm_physp_is_valid(p_osm_port))
+ continue;
+ if (!osm_link_is_healthy(p_osm_port))
+ continue;
+
+ p_remote_osm_node = osm_node_get_remote_node(p_osm_node,i,NULL);
+
+ 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,
+ "__osm_ftree_rank_switches_from_hca: ERR AB0F: "
+ "HCA conected directly to another HCA: "
+ "0x%016" PRIx64 " <---> 0x%016" PRIx64 "\n",
+ cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)),
+ 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,
+ "__osm_ftree_rank_switches_from_hca: 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 = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,
+ p_osm_port->p_remote_physp->p_node->node_info.node_guid);
+
+ CL_ASSERT(p_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+
+ if (__osm_ftree_sw_ranked(p_sw) && p_sw->rank == 0)
+ continue;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_ftree_rank_switches_from_hca: "
+ "Marking rank of switch that is directly connected to HCA:\n"
+ " - HCA guid : 0x%016" PRIx64 "\n"
+ " - Switch guid: 0x%016" PRIx64 "\n"
+ " - Switch LID : 0x%x\n",
+ cl_ntoh64(osm_node_get_node_guid(p_hca->p_osm_node)),
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid));
+ __osm_ftree_rank_from_switch(p_ftree, p_sw);
+ }
+
+ Exit:
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return res;
+} /* __osm_ftree_rank_switches_from_hca() */
+
+/***************************************************/
+
+static void
+__osm_ftree_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;
+ p_sw->rank = __osm_ftree_fabric_get_rank(p_ftree) - p_sw->rank - 1;
+}
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_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;
+ 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);
+
+ if (!osm_physp_is_valid(p_osm_port))
+ continue;
+ if (!osm_link_is_healthy(p_osm_port))
+ 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)
+ 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,
+ "__osm_ftree_fabric_construct_hca_ports: ERR AB11: "
+ "HCA conected directly to another HCA: "
+ "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,
+ "__osm_ftree_fabric_construct_hca_ports: 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 = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid);
+ CL_ASSERT( p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl) );
+ CL_ASSERT( (p_remote_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree) );
+
+ __osm_ftree_hca_add_port(
+ p_hca, /* local ftree_hca object */
+ i, /* local port number */
+ remote_port_num, /* remote port number */
+ osm_node_get_base_lid(p_node, i), /* local lid */
+ 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 */
+ }
+
+ Exit:
+ return res;
+} /* __osm_ftree_fabric_construct_hca_ports() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_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 = osm_switch_get_node_ptr(p_sw->p_osm_sw);
+ osm_node_t * p_remote_node;
+ ib_net16_t remote_base_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 = 0; i < osm_node_get_num_physp(p_node); i++)
+ {
+ osm_physp_t * p_osm_port = osm_node_get_physp_ptr(p_node,i);
+
+ if (!osm_physp_is_valid(p_osm_port))
+ continue;
+ if (!osm_link_is_healthy(p_osm_port))
+ 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)
+ 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 */
+
+ CL_ASSERT((p_sw->rank + 1) == __osm_ftree_fabric_get_rank(p_ftree));
+
+ p_remote_hca = (ftree_hca_t *)cl_qmap_get(&p_ftree->hca_tbl,remote_node_guid);
+ CL_ASSERT(p_remote_hca != (ftree_hca_t *)cl_qmap_end(&p_ftree->hca_tbl));
+
+ p_remote_hca_or_sw = (void *)p_remote_hca;
+ direction = FTREE_DIRECTION_DOWN;
+
+ remote_base_lid = osm_physp_get_base_lid(p_remote_osm_port);
+ break;
+
+ case IB_NODE_TYPE_SWITCH:
+ /* switch connected to another switch */
+
+ p_remote_sw = (ftree_sw_t *)cl_qmap_get(&p_ftree->sw_tbl,remote_node_guid);
+ CL_ASSERT(p_remote_sw != (ftree_sw_t *)cl_qmap_end(&p_ftree->sw_tbl));
+ p_remote_hca_or_sw = (void *)p_remote_sw;
+
+ if (abs(p_sw->rank - p_remote_sw->rank) != 1)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_construct_sw_ports: ERR AB16: "
+ "Illegal link between switches with ranks %u and %u:\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n"
+ " GUID 0x%016" PRIx64 ", LID 0x%x, rank %u\n",
+ p_sw->rank,
+ p_remote_sw->rank,
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_sw->p_osm_sw))),
+ cl_ntoh16(p_sw->base_lid),
+ p_sw->rank,
+ cl_ntoh64(osm_node_get_node_guid(osm_switch_get_node_ptr(p_remote_sw->p_osm_sw))),
+ cl_ntoh16(p_remote_sw->base_lid),
+ p_remote_sw->rank);
+ res = -1;
+ goto Exit;
+ }
+
+ if (p_sw->rank > p_remote_sw->rank)
+ direction = FTREE_DIRECTION_UP;
+ else
+ direction = FTREE_DIRECTION_DOWN;
+
+ /* switch LID is only in port 0 port_info structure */
+ remote_base_lid = osm_node_get_base_lid(p_remote_node, 0);
+
+ break;
+
+ default:
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_construct_sw_ports: 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;
+ }
+ __osm_ftree_sw_add_port(
+ p_sw, /* local ftree_sw object */
+ i, /* local port number */
+ remote_port_num, /* remote port number */
+ p_sw->base_lid, /* local lid */
+ remote_base_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 (cl_ntoh16(remote_base_lid) > p_ftree->lft_max_lid_ho)
+ p_ftree->lft_max_lid_ho = cl_ntoh16(remote_base_lid);
+ }
+
+ Exit:
+ return res;
+} /* __osm_ftree_fabric_construct_sw_ports() */
+
+/***************************************************
+ ***************************************************/
+
+/* ToDo: improve ranking algorithm complexity
+ by propogating BFS from more nodes */
+static int
+__osm_ftree_fabric_perform_ranking(
+ IN ftree_fabric_t * p_ftree)
+{
+ ftree_hca_t * p_hca;
+ ftree_hca_t * p_next_hca;
+ int res = 0;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_fabric_perform_ranking);
+
+ /* 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 (__osm_ftree_rank_switches_from_hca(p_ftree,p_hca) != 0)
+ {
+ res = -1;
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_perform_ranking: ERR AB14: "
+ "Subnet ranking failed - subnet is not FatTree");
+ goto Exit;
+ }
+ }
+
+ /* calculate and set FatTree rank */
+ __osm_ftree_fabric_calculate_rank(p_ftree);
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_INFO,
+ "__osm_ftree_fabric_perform_ranking: "
+ "FatTree rank is %u\n", __osm_ftree_fabric_get_rank(p_ftree));
+
+ /* fix ranking of the switches by reversing the ranking direction */
+ cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_sw_reverse_rank, (void *)p_ftree);
+
+ if ( __osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK ||
+ __osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK )
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_ERROR,
+ "__osm_ftree_fabric_perform_ranking: ERR AB15: "
+ "Tree rank is %u (should be between %u and %u)\n",
+ __osm_ftree_fabric_get_rank(p_ftree),
+ FAT_TREE_MIN_RANK,
+ FAT_TREE_MAX_RANK);
+ res = -1;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return res;
+} /* __osm_ftree_fabric_perform_ranking() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_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, __osm_ftree_fabric_populate_ports);
+
+ 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 (__osm_ftree_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 (__osm_ftree_fabric_construct_sw_ports(p_ftree,p_sw) != 0)
+ {
+ res = -1;
+ goto Exit;
+ }
+ }
+ Exit:
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return res;
+} /* __osm_ftree_fabric_populate_ports() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_construct_fabric(
+ IN void * context)
+{
+ ftree_fabric_t * p_ftree = context;
+ int status = 0;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_construct_fabric);
+
+ if (p_ftree->p_osm->subn.opt.lmc > 0)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "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(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "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(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "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,"__osm_ftree_construct_fabric: \n"
+ " |----------------------------------------|\n"
+ " |- Starting FatTree fabric construction -|\n"
+ " |----------------------------------------|\n\n");
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: "
+ "Populating FatTree switch table\n");
+ /* ToDo: now that the pointer from node to switch exists,
+ no need to fill the switch table in a separate loop */
+ if (__osm_ftree_fabric_populate_switches(p_ftree) != 0)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "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,
+ "__osm_ftree_construct_fabric: "
+ "Populating FatTree HCA table\n");
+ if (__osm_ftree_fabric_populate_hcas(p_ftree) != 0)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric topology is not fat-tree - "
+ "falling back to default routing\n");
+ status = -1;
+ goto Exit;
+ }
+
+ if (cl_qmap_count(&p_ftree->hca_tbl) < 2)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric has %u HCAa - topology is not fat-tree.\n"
+ "Falling back to default routing.\n",
+ cl_qmap_count(&p_ftree->hca_tbl));
+ status = -1;
+ goto Exit;
+ }
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: Ranking FatTree\n");
+
+ if (__osm_ftree_fabric_perform_ranking(p_ftree) != 0)
+ {
+ if (__osm_ftree_fabric_get_rank(p_ftree) > FAT_TREE_MAX_RANK)
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric rank is %u (>%u) - "
+ "fat-tree routing falls back to default routing\n",
+ __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MAX_RANK);
+ else if (__osm_ftree_fabric_get_rank(p_ftree) < FAT_TREE_MIN_RANK)
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric rank is %u (<%u) - "
+ "fat-tree routing falls back to default routing\n",
+ __osm_ftree_fabric_get_rank(p_ftree), FAT_TREE_MIN_RANK);
+ 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.*/
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: "
+ "Populating HCA & switch ports\n");
+ if (__osm_ftree_fabric_populate_ports(p_ftree) != 0)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric topology is not a fat-tree - "
+ "routing falls back to default routing\n");
+ status = -1;
+ goto Exit;
+ }
+
+ /* Assign index to all the switches and hca's in the fabric.
+ This function also sorts all the port arrays of the switches
+ by the remote switch index, creates a leaf switch array
+ sorted by the switch index, and tracks the maximal number of
+ hcas per leaf switch. */
+ __osm_ftree_fabric_make_indexing(p_ftree);
+
+ /* print general info about fabric topology */
+ __osm_ftree_fabric_dump_general_info(p_ftree);
+
+ /* dump full tree topology */
+ if (osm_log_is_active(&p_ftree->p_osm->log, OSM_LOG_DEBUG))
+ __osm_ftree_fabric_dump(p_ftree);
+
+ if (! __osm_ftree_fabric_validate_topology(p_ftree))
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_SYS,
+ "Fabric topology is not a fat-tree - "
+ "routing falls back to default routing\n");
+ status = -1;
+ goto Exit;
+ }
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: "
+ "Max LID in switch LFTs (in host order): 0x%x\n",
+ p_ftree->lft_max_lid_ho);
+
+ Exit:
+ if (status != 0)
+ {
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: "
+ "Clearing FatTree Fabric data structures\n");
+ __osm_ftree_fabric_clear(p_ftree);
+ }
+ else
+ p_ftree->fabric_built = TRUE;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_ftree_construct_fabric: \n"
+ " |--------------------------------------------------|\n"
+ " |- Done constructing FatTree fabric (status = %d) -|\n"
+ " |--------------------------------------------------|\n\n",
+ status);
+
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return status;
+} /* __osm_ftree_construct_fabric() */
+
+/***************************************************
+ ***************************************************/
+
+static int
+__osm_ftree_do_routing(
+ IN void * context)
+{
+ ftree_fabric_t * p_ftree = context;
+
+ OSM_LOG_ENTER(&p_ftree->p_osm->log, __osm_ftree_do_routing);
+
+ if (!p_ftree->fabric_built)
+ goto Exit;
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+ "Starting FatTree routing\n");
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+ "Filling switch forwarding tables for routes to HCAs\n");
+ __osm_ftree_fabric_route_to_hcas(p_ftree);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+ "Filling switch forwarding tables for switch-to-switch pathes\n");
+ __osm_ftree_fabric_route_to_switches(p_ftree);
+
+ /* for each switch, set its fwd table */
+ cl_qmap_apply_func(&p_ftree->sw_tbl, __osm_ftree_set_sw_fwd_table, (void *)p_ftree);
+
+ /* write out hca ordering file */
+ __osm_ftree_fabric_dump_hca_ordering(p_ftree);
+
+ osm_log(&p_ftree->p_osm->log, OSM_LOG_VERBOSE,"__osm_ftree_do_routing: "
+ "FatTree routing is done\n");
+
+ Exit:
+ OSM_LOG_EXIT(&p_ftree->p_osm->log);
+ return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+static void
+__osm_ftree_delete(
+ IN void * context)
+{
+ if (!context)
+ return;
+ __osm_ftree_fabric_destroy((ftree_fabric_t *)context);
+}
+
+/***************************************************
+ ***************************************************/
+
+int osm_ucast_ftree_setup(osm_opensm_t * p_osm)
+{
+ ftree_fabric_t * p_ftree = __osm_ftree_fabric_create();
+ if (!p_ftree)
+ return -1;
+
+ p_ftree->p_osm = p_osm;
+
+ p_osm->routing_engine.context = (void *)p_ftree;
+ p_osm->routing_engine.build_lid_matrices = __osm_ftree_construct_fabric;
+ p_osm->routing_engine.ucast_build_fwd_tables = __osm_ftree_do_routing;
+ p_osm->routing_engine.delete = __osm_ftree_delete;
+ return 0;
+}
+
+/***************************************************
+ ***************************************************/
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_ucast_mgr.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of osm_ucast_mgr_t.
+ * This file implements the Unicast Manager object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.14 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_ucast_mgr.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_helper.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_opensm.h>
+
+#define LINE_LENGTH 256
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * This flag is used for stopping the relaxation algorithm if no
+ * change detected during the fabric scan
+ */
+static boolean_t __some_hop_count_set;
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_construct(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ memset( p_mgr, 0, sizeof(*p_mgr) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_destroy(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ CL_ASSERT( p_mgr );
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_destroy );
+
+ if (p_mgr->lft_buf)
+ free(p_mgr->lft_buf);
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_ucast_mgr_init(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_ucast_mgr_init );
+
+ CL_ASSERT( p_req );
+ CL_ASSERT( p_subn );
+ CL_ASSERT( p_lock );
+
+ osm_ucast_mgr_construct( p_mgr );
+
+ p_mgr->p_log = p_log;
+ p_mgr->p_subn = p_subn;
+ p_mgr->p_lock = p_lock;
+ p_mgr->p_req = p_req;
+
+ p_mgr->lft_buf = malloc(IB_LID_UCAST_END_HO + 1);
+ if (!p_mgr->lft_buf)
+ return IB_INSUFFICIENT_MEMORY;
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+struct ucast_mgr_dump_context {
+ osm_ucast_mgr_t *p_mgr;
+ FILE *file;
+};
+
+static void
+ucast_mgr_dump(osm_ucast_mgr_t *p_mgr, FILE *file,
+ void (*func)(cl_map_item_t *, void *))
+{
+ struct ucast_mgr_dump_context dump_context;
+
+ dump_context.p_mgr = p_mgr;
+ dump_context.file = file;
+
+ cl_qmap_apply_func(&p_mgr->p_subn->sw_guid_tbl, func, &dump_context);
+}
+
+void
+ucast_mgr_dump_to_file(osm_ucast_mgr_t *p_mgr, const char *file_name,
+ void (*func)(cl_map_item_t *, void *))
+{
+ char path[1024];
+ FILE *file;
+
+ snprintf(path, sizeof(path), "%s/%s",
+ p_mgr->p_subn->opt.dump_files_dir, file_name);
+
+ file = fopen(path, "w");
+ if (!file) {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "ucast_mgr_dump_to_file: ERR 3A12: "
+ "Failed to open fdb file (%s)\n", path );
+ return;
+ }
+
+ ucast_mgr_dump(p_mgr, file, func);
+
+ fclose(file);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_dump_path_distribution(
+ IN cl_map_item_t *p_map_item,
+ IN 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 *)p_map_item;
+ osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_path_distribution );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ num_ports = osm_switch_get_num_ports( p_sw );
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_dump_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 );
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG,"\n %03u : %u", i, num_paths );
+ if( i == 0 )
+ {
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (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_remote_type( p_node, i ) )
+ {
+ case IB_NODE_TYPE_SWITCH:
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to switch" );
+ break;
+ case IB_NODE_TYPE_ROUTER:
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to router" );
+ break;
+ case IB_NODE_TYPE_CA:
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to CA" );
+ break;
+ default:
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " (link to unknown node type" );
+ break;
+ }
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, " 0x%" PRIx64 ")",
+ remote_guid_ho );
+ }
+
+ osm_log_printf( p_mgr->p_log, OSM_LOG_DEBUG, "\n" );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_dump_ucast_routes(
+ IN cl_map_item_t *p_map_item,
+ IN void *cxt )
+{
+ const osm_node_t* p_node;
+ 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;
+ osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+ osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+ FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_dump_ucast_routes );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ max_lid_ho = osm_switch_get_max_lid_ho( p_sw );
+
+ fprintf( file, "__osm_ucast_mgr_dump_ucast_routes: "
+ "Switch 0x%016" PRIx64 "\n"
+ "LID : Port : Hops : Optimal\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
+ for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ fprintf(file, "0x%04X : ", lid_ho);
+
+ port_num = osm_switch_get_port_by_lid( p_sw, lid_ho );
+ 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.
+ */
+ num_hops = osm_switch_get_hop_count( p_sw, lid_ho, port_num );
+ if( num_hops == OSM_NO_PATH )
+ {
+ fprintf( file, "UNREACHABLE\n" );
+ continue;
+ }
+
+ best_hops = osm_switch_get_least_hops( p_sw, lid_ho );
+ fprintf( file, "%03u : %02u : ", port_num, num_hops );
+
+ if( best_hops == num_hops )
+ fprintf( file, "yes" );
+ else
+ {
+ best_port = osm_switch_recommend_path(
+ p_sw, lid_ho, TRUE,
+ NULL, NULL, NULL, NULL ); /* No LMC Optimization */
+ fprintf( file, "No %u hop path possible via port %u!",
+ best_hops, best_port );
+ }
+
+ fprintf( file, "\n" );
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+ucast_mgr_dump_lid_matrix(cl_map_item_t *p_map_item, void *cxt)
+{
+ osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+ osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+ FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+ osm_node_t *p_node = osm_switch_get_node_ptr(p_sw);
+ unsigned max_lid = osm_switch_get_max_lid_ho(p_sw);
+ unsigned max_port = osm_switch_get_num_ports(p_sw);
+ 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;
+
+ 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 = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid);
+ if (p_port)
+ fprintf(file, " # portguid 0x%" PRIx64,
+ cl_ntoh64(osm_port_get_guid(p_port)));
+ fprintf(file, "\n");
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+ucast_mgr_dump_lfts(cl_map_item_t *p_map_item, void *cxt)
+{
+ osm_switch_t* p_sw = (osm_switch_t *)p_map_item;
+ osm_ucast_mgr_t* p_mgr = ((struct ucast_mgr_dump_context *)cxt)->p_mgr;
+ FILE *file = ((struct ucast_mgr_dump_context *)cxt)->file;
+ osm_node_t *p_node = osm_switch_get_node_ptr(p_sw);
+ unsigned max_lid = osm_switch_get_max_lid_ho(p_sw);
+ unsigned max_port = osm_switch_get_num_ports(p_sw);
+ uint16_t lid;
+ uint8_t port;
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];
+
+ memcpy(desc, p_node->node_desc.description, IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+ fprintf(file, "Unicast lids [0x0-0x%x] of switch Lid %u guid 0x%016"
+ PRIx64 " (\'%s\'):\n",
+ max_lid, osm_node_get_base_lid(p_node, 0),
+ cl_ntoh64(osm_node_get_node_guid(p_node)), desc);
+ for (lid = 0; lid <= max_lid; lid++) {
+ osm_port_t *p_port;
+ port = osm_switch_get_port_by_lid(p_sw, lid);
+
+ if (port >= max_port)
+ continue;
+
+ fprintf(file, "0x%04x %03u # ", lid, port);
+
+ p_port = cl_ptr_vector_get(&p_mgr->p_subn->port_lid_tbl, lid);
+ if (p_port) {
+ p_node = osm_port_get_parent_node(p_port);
+ memcpy(desc, p_node->node_desc.description,
+ IB_NODE_DESCRIPTION_SIZE);
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';
+ fprintf(file, "%s portguid 0x016%" PRIx64 ": \'%s\'",
+ ib_get_node_type_str(osm_node_get_type(p_node)),
+ cl_ntoh64(osm_port_get_guid(p_port)), desc);
+ }
+ else
+ fprintf(file, "unknown node and type");
+ fprintf(file, "\n");
+ }
+ fprintf(file, "%u lids dumped\n", max_lid);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void __osm_ucast_mgr_dump_tables(osm_ucast_mgr_t *p_mgr)
+{
+ ucast_mgr_dump_to_file(p_mgr, "opensm-lid-matrix.dump",
+ ucast_mgr_dump_lid_matrix);
+ ucast_mgr_dump_to_file(p_mgr, "opensm-lfts.dump", ucast_mgr_dump_lfts);
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ ucast_mgr_dump(p_mgr, NULL, __osm_ucast_mgr_dump_path_distribution);
+ ucast_mgr_dump_to_file(p_mgr, "osm.fdbs", __osm_ucast_mgr_dump_ucast_routes);
+}
+
+/**********************************************************************
+ Starting a rebuild, so notify the switch so it can clear tables, etc...
+**********************************************************************/
+static void
+__osm_ucast_mgr_clean_switch(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_prepare_path_rebuild((osm_switch_t *)p_map_item);
+}
+
+/**********************************************************************
+ Add each switch's own LID(s) to its LID matrix.
+**********************************************************************/
+static void
+__osm_ucast_mgr_process_hop_0(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ uint16_t lid_ho, base_lid_ho, max_lid_ho;
+ cl_status_t status;
+ uint8_t lmc;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_hop_0 );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ base_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_node, 0 ) );
+ if (osm_switch_sp0_is_lmc_capable( p_sw, p_mgr->p_subn ))
+ lmc = osm_node_get_lmc( p_node, 0 );
+ else
+ lmc = 0;
+ max_lid_ho = (uint16_t)( base_lid_ho + (1 << lmc) - 1 );
+
+ for (lid_ho = base_lid_ho; lid_ho <= max_lid_ho; lid_ho++)
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_hop_0: "
+ "Processing switch GUID 0x%" PRIx64 ", LID 0x%X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ lid_ho );
+ }
+
+ status = osm_switch_set_hops( p_sw, lid_ho, 0, 0 );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_hop_0: ERR 3A02: "
+ "Setting hop count failed (%s) for "
+ "switch GUID 0x%" PRIx64 ", LID 0x%X\n",
+ CL_STATUS_MSG( status ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ lid_ho );
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbor(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN osm_switch_t* const p_remote_sw,
+ IN const uint8_t port_num,
+ IN const uint8_t remote_port_num )
+{
+ uint16_t lid_ho;
+ uint16_t max_lid_ho;
+ osm_node_t* p_node;
+ const osm_node_t* p_remote_node;
+ uint8_t hops;
+ cl_status_t status;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_neighbor );
+
+ CL_ASSERT( p_sw );
+ CL_ASSERT( p_remote_sw );
+ CL_ASSERT( port_num );
+ CL_ASSERT( remote_port_num );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+ p_remote_node = osm_switch_get_node_ptr( p_remote_sw );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_remote_node );
+
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+ CL_ASSERT( osm_node_get_type( p_remote_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbor: "
+ "Node 0x%" PRIx64 ", remote node 0x%" PRIx64 "\n"
+ "\t\t\t\tport 0x%X, remote port 0x%X\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ),
+ cl_ntoh64( osm_node_get_node_guid( p_remote_node ) ),
+ port_num, remote_port_num );
+ }
+
+ /*
+ Iterate through all the LIDs in the neighbor switch.
+ */
+ max_lid_ho = osm_switch_get_max_lid_ho( p_remote_sw );
+
+ /*
+ Make sure the local lid matrix has enough room to hold
+ all the LID info coming from the remote LID matrix.
+ */
+ osm_switch_set_min_lid_size( p_sw, max_lid_ho );
+
+ hops = OSM_NO_PATH;
+ for( lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ /*
+ Find the lowest hop count value to this LID.
+ */
+ hops = osm_switch_get_least_hops( p_remote_sw, lid_ho );
+
+ if( hops != OSM_NO_PATH )
+ {
+ /*
+ Increment hop count of the neighbor by 1, since it
+ takes 1 hop to get to the neighbor.
+ */
+ hops++;
+
+ CL_ASSERT( hops <= osm_switch_get_hop_count( p_sw, lid_ho,
+ port_num ) );
+ if( osm_switch_get_hop_count( p_sw, lid_ho,
+ port_num ) > hops )
+ {
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbor: "
+ "New best path is %u hops for LID 0x%X\n",
+ hops, lid_ho );
+ }
+
+ /* mark the fact we have got to change anything */
+ __some_hop_count_set = TRUE;
+
+ status = osm_switch_set_hops( p_sw, lid_ho,
+ port_num, hops );
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_neighbor: ERR 3A03: "
+ "Setting hop count failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaf(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN osm_node_t* const p_node,
+ IN const uint8_t port_num,
+ IN osm_node_t* const p_remote_node,
+ IN const uint8_t remote_port_num )
+{
+ uint16_t i;
+ uint16_t base_lid_ho;
+ uint16_t max_lid_ho;
+ uint8_t lmc;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaf );
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( p_remote_node );
+ CL_ASSERT( port_num );
+ CL_ASSERT( remote_port_num );
+
+ switch( osm_node_get_type( p_remote_node ) )
+ {
+ case IB_NODE_TYPE_CA:
+ case IB_NODE_TYPE_ROUTER:
+ base_lid_ho = cl_ntoh16( osm_node_get_base_lid(
+ p_remote_node, remote_port_num ) );
+ lmc = osm_node_get_lmc( p_remote_node, remote_port_num );
+ break;
+#if 0
+ case IB_NODE_TYPE_SWITCH:
+ base_lid_ho = cl_ntoh16( osm_node_get_base_lid(
+ p_remote_node, 0 ) );
+ lmc = 0;
+ break;
+#endif
+
+ default:
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_leaf: ERR 3A01: "
+ "Bad node type %u, GUID 0x%" PRIx64 "\n",
+ osm_node_get_type( p_remote_node ),
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ goto Exit;
+ }
+
+ max_lid_ho = (uint16_t)(base_lid_ho + (1 << lmc) - 1 );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_leaf: "
+ "Discovered LIDs [0x%X,0x%X]\n"
+ "\t\t\t\tport number 0x%X, node 0x%" PRIx64 "\n",
+ base_lid_ho, max_lid_ho,
+ port_num, cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ for( i = base_lid_ho; i <= max_lid_ho; i++ )
+ osm_switch_set_hops( p_sw, i, port_num, 1 );
+
+ Exit:
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_leaves(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)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_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_leaves );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_leaves: "
+ "Processing switch 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ /*
+ Add the LIDs of all leaves of this switch to the LID matrix.
+ Don't bother processing loopback paths from one port of
+ this switch to the another port.
+ Don't process neighbor switches yet.
+ Start with port 1 to skip the switch's management port.
+ */
+ num_ports = osm_node_get_num_physp( p_node );
+
+ 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 != p_node )
+ && (osm_node_get_type( p_remote_node ) != IB_NODE_TYPE_SWITCH ) )
+ {
+ __osm_ucast_mgr_process_leaf(
+ p_mgr,
+ p_sw,
+ p_node,
+ (uint8_t)port_num,
+ p_remote_node,
+ remote_port_num );
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_port(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw,
+ IN const osm_port_t* const p_port )
+{
+ 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;
+ /*
+ The following are temporary structures that will aid
+ in providing better routing in LMC > 0 situations
+ */
+ uint16_t lids_per_port = 1 << p_mgr->p_subn->opt.lmc;
+ uint64_t *remote_sys_guids = NULL;
+ uint64_t *remote_node_guids = NULL;
+ uint16_t num_used_sys = 0;
+ uint16_t num_used_nodes = 0;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_port );
+
+ remote_sys_guids = malloc( sizeof(uint64_t) * lids_per_port );
+ if( remote_sys_guids == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A09: "
+ "Cannot allocate array. Insufficient memory\n");
+ goto Exit;
+ }
+
+ memset( remote_sys_guids, 0, sizeof(uint64_t) * lids_per_port );
+
+ remote_node_guids = malloc( sizeof(uint64_t) * lids_per_port );
+ if( remote_node_guids == NULL )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A0A: "
+ "Cannot allocate array. Insufficient memory\n");
+ goto Exit;
+ }
+
+ memset( remote_node_guids, 0, sizeof(uint64_t) * lids_per_port );
+
+ 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,
+ "__osm_ucast_mgr_process_port: ERR 3A04: "
+ "Port 0x%" PRIx64 " has LID 0. An initialization "
+ "error occurred. Ignoring port\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ) );
+ goto Exit;
+ }
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "Processing port 0x%" PRIx64
+ ", LIDs [0x%X,0x%X]\n",
+ cl_ntoh64( osm_port_get_guid( p_port ) ),
+ min_lid_ho, max_lid_ho );
+ }
+
+ /*
+ TO DO - This should be runtime error, not a CL_ASSERT()
+ */
+ CL_ASSERT( max_lid_ho < osm_switch_get_fwd_tbl_size( p_sw ) );
+
+ node_guid = osm_node_get_node_guid(osm_switch_get_node_ptr( p_sw ) );
+
+ /*
+ 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.
+ */
+ for( lid_ho = min_lid_ho; lid_ho <= max_lid_ho; lid_ho++ )
+ {
+ /* Use the enhanced algorithm only for LMC > 0 */
+ if (lids_per_port > 1)
+ port = osm_switch_recommend_path( p_sw, lid_ho,
+ p_mgr->p_subn->ignore_existing_lfts,
+ remote_sys_guids, &num_used_sys,
+ remote_node_guids, &num_used_nodes );
+ else
+ port = osm_switch_recommend_path( p_sw, lid_ho,
+ p_mgr->p_subn->ignore_existing_lfts,
+ NULL, NULL, NULL, NULL );
+
+ /*
+ There might be no path to the target
+ */
+ if (port == OSM_NO_PATH)
+ {
+ /* do not try to overwrite the ppro of non existing port ... */
+ is_ignored_by_port_prof = TRUE;
+
+ /* Up/Down routing can cause unreachable routes between some
+ switches so we do not report that as an error in that case */
+ if (!p_mgr->p_subn->p_osm->routing_engine.build_lid_matrices)
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "__osm_ucast_mgr_process_port: ERR 3A08: "
+ "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n",
+ lid_ho, cl_ntoh64( node_guid ) );
+ /* trigger a new sweep - try again ... */
+ p_mgr->p_subn->subnet_initialization_error = TRUE;
+ }
+ else
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "No path to get to LID 0x%X from switch 0x%" PRIx64 "\n",
+ lid_ho, cl_ntoh64( node_guid ) );
+ }
+ else
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_port: "
+ "Routing LID 0x%X to port 0x%X"
+ "\n\t\t\t\tFor switch 0x%" PRIx64 "\n",
+ lid_ho, port, cl_ntoh64( node_guid ) );
+
+ /*
+ we would like to optionally ignore this port in equalization
+ like in the case of the Mellanox Anafa Internal PCI TCA port
+ */
+ is_ignored_by_port_prof =
+ osm_port_prof_is_ignored_port(p_mgr->p_subn, cl_ntoh64(node_guid), port);
+
+ /*
+ 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(osm_port_get_parent_node(p_port)) ==
+ IB_NODE_TYPE_SWITCH);
+ }
+ }
+
+ /*
+ We have selected the port for this LID.
+ Write it to the forwarding tables.
+ */
+ p_mgr->lft_buf[lid_ho] = port;
+ if (!is_ignored_by_port_prof)
+ osm_switch_count_path(p_sw, port);
+ }
+
+ Exit:
+ if (remote_sys_guids)
+ free(remote_sys_guids);
+ if (remote_node_guids)
+ free(remote_node_guids);
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_set_fwd_table(
+ IN osm_ucast_mgr_t* const p_mgr,
+ IN osm_switch_t* const p_sw )
+{
+ osm_node_t *p_node;
+ osm_dr_path_t *p_path;
+ osm_madw_context_t context;
+ ib_api_status_t status;
+ ib_switch_info_t si;
+ uint32_t block_id_ho = 0;
+ uint8_t block[IB_SMP_DATA_SIZE];
+ 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, osm_ucast_mgr_set_fwd_table );
+
+ CL_ASSERT( p_sw );
+
+ p_node = osm_switch_get_node_ptr( p_sw );
+
+ CL_ASSERT( p_node );
+
+ p_path = osm_node_get_any_dr_path_ptr( p_node );
+
+ CL_ASSERT( p_path );
+
+ /*
+ Set the top of the unicast forwarding table.
+ */
+ si = *osm_switch_get_si_ptr( p_sw );
+ lin_top = cl_hton16( osm_switch_get_max_lid_ho( p_sw ) );
+ if (lin_top != si.lin_top)
+ {
+ set_swinfo_require = TRUE;
+ si.lin_top = lin_top;
+ }
+
+ /* check to see if the change state bit is on. If it is - then we
+ need to clear it. */
+ if ( ib_switch_info_get_state_change( &si ) )
+ life_state = ( (p_mgr->p_subn->opt.packet_life_time <<3 )
+ | ( si.life_state & IB_SWITCH_PSC ) ) & 0xfc;
+ else
+ life_state = (p_mgr->p_subn->opt.packet_life_time <<3 ) & 0xf8;
+
+ if ( (life_state != si.life_state) || ib_switch_info_get_state_change( &si ) )
+ {
+ set_swinfo_require = TRUE;
+ si.life_state = life_state;
+ }
+
+ if ( set_swinfo_require )
+ {
+ if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_set_fwd_table: "
+ "Setting switch FT top to LID 0x%X\n",
+ osm_switch_get_max_lid_ho( p_sw ) );
+ }
+
+ 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->p_req,
+ p_path,
+ (uint8_t*)&si,
+ sizeof(si),
+ IB_MAD_ATTR_SWITCH_INFO,
+ 0,
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_ucast_mgr_set_fwd_table: ERR 3A06: "
+ "Sending SwitchInfo attribute failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ else
+ p_mgr->any_change = TRUE;
+ }
+
+ /*
+ Send linear forwarding table blocks to the switch
+ as long as the switch indicates it has blocks needing
+ configuration.
+ */
+
+ context.lft_context.node_guid = osm_node_get_node_guid( p_node );
+ context.lft_context.set_method = TRUE;
+
+ for (block_id_ho = 0;
+ osm_switch_get_fwd_tbl_block( p_sw, block_id_ho, block ) ;
+ block_id_ho++ )
+ {
+ if (!memcmp(block, p_mgr->lft_buf + block_id_ho * 64, 64))
+ continue;
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_set_fwd_table: "
+ "Writing FT block %u\n", block_id_ho );
+ }
+
+ status = osm_req_set( p_mgr->p_req,
+ p_path,
+ p_mgr->lft_buf + block_id_ho * 64,
+ sizeof(block),
+ IB_MAD_ATTR_LIN_FWD_TBL,
+ cl_hton32( block_id_ho ),
+ CL_DISP_MSGID_NONE,
+ &context );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_ERROR,
+ "osm_ucast_mgr_set_fwd_table: ERR 3A05: "
+ "Sending linear fwd. tbl. block failed (%s)\n",
+ ib_get_err_str( status ) );
+ }
+ else
+ {
+ p_mgr->any_change = TRUE;
+ /*
+ HACK: for now we will assume we succeeded to send
+ and set the local DB based on it. This should allow
+ us to immediatly dump out our routing.
+ */
+ osm_switch_set_ft_block(
+ p_sw, p_mgr->lft_buf + block_id_ho * 64, block_id_ho );
+ }
+ }
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_tbl(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)context;
+ osm_node_t *p_node;
+ const osm_port_t *p_port;
+ const cl_qmap_t* p_port_tbl;
+
+ OSM_LOG_ENTER( p_mgr->p_log, __osm_ucast_mgr_process_tbl );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_tbl: "
+ "Processing switch 0x%" PRIx64 "\n",
+ cl_ntoh64( osm_node_get_node_guid( p_node ) ));
+ }
+
+ /* Initialize LIDs in buffer to invalid port number. */
+ memset(p_mgr->lft_buf, 0xff, IB_LID_UCAST_END_HO + 1);
+
+ p_port_tbl = &p_mgr->p_subn->port_guid_tbl;
+
+ /*
+ Iterate through every port setting LID routes for each
+ port based on base LID and LMC value.
+ */
+
+ 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 ) )
+ {
+ __osm_ucast_mgr_process_port( p_mgr, p_sw, p_port );
+ }
+
+ osm_ucast_mgr_set_fwd_table( p_mgr, p_sw );
+
+ OSM_LOG_EXIT( p_mgr->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_ucast_mgr_process_neighbors(
+ IN cl_map_item_t* const p_map_item,
+ IN void* context )
+{
+ osm_switch_t* const p_sw = (osm_switch_t*)p_map_item;
+ osm_ucast_mgr_t* const p_mgr = (osm_ucast_mgr_t*)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, __osm_ucast_mgr_process_neighbors );
+
+ p_node = p_sw->p_node;
+
+ CL_ASSERT( p_node );
+ CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
+
+ if( osm_log_is_active( p_mgr->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "__osm_ucast_mgr_process_neighbors: "
+ "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 != p_node )
+ && p_remote_node->sw )
+ {
+ /* 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 (!osm_link_is_healthy( p_physp ) )
+ continue;
+
+ __osm_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 );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_ucast_mgr_build_lid_matrices(
+ IN osm_ucast_mgr_t* const 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,
+ "osm_ucast_mgr_build_lid_matrices: "
+ "Starting switches Min Hop Table Assignment\n" );
+
+ /*
+ 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,
+ __osm_ucast_mgr_process_hop_0, p_mgr );
+
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_leaves, 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
+ */
+ __some_hop_count_set = TRUE;
+ for( i = 0; (i < iteration_max) && __some_hop_count_set; i++ )
+ {
+ __some_hop_count_set = FALSE;
+ cl_qmap_apply_func( p_sw_guid_tbl,
+ __osm_ucast_mgr_process_neighbors, p_mgr );
+ }
+ osm_log( p_mgr->p_log, OSM_LOG_DEBUG,
+ "osm_ucast_mgr_build_lid_matrices: "
+ "Min-hop propagated in %d steps\n", i );
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+osm_signal_t
+osm_ucast_mgr_process(
+ IN osm_ucast_mgr_t* const p_mgr )
+{
+ struct osm_routing_engine *p_routing_eng;
+ osm_signal_t signal = OSM_SIGNAL_DONE;
+ cl_qmap_t *p_sw_guid_tbl;
+ boolean_t default_routing = TRUE;
+
+ OSM_LOG_ENTER( p_mgr->p_log, osm_ucast_mgr_process );
+
+ p_sw_guid_tbl = &p_mgr->p_subn->sw_guid_tbl;
+ p_routing_eng = &p_mgr->p_subn->p_osm->routing_engine;
+
+ 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)
+ goto Exit;
+
+ p_mgr->any_change = FALSE;
+ cl_qmap_apply_func(p_sw_guid_tbl, __osm_ucast_mgr_clean_switch, NULL);
+
+ if (!p_routing_eng->build_lid_matrices ||
+ p_routing_eng->build_lid_matrices(p_routing_eng->context) != 0)
+ osm_ucast_mgr_build_lid_matrices(p_mgr);
+
+ osm_log( p_mgr->p_log, OSM_LOG_INFO,
+ "osm_ucast_mgr_process: "
+ "Min Hop Tables configured on all switches\n" );
+
+ /*
+ Now that the lid matrices have been built, we can
+ build and download the switch forwarding tables.
+ */
+
+ if ( p_routing_eng->ucast_build_fwd_tables &&
+ (p_routing_eng->ucast_build_fwd_tables(p_routing_eng->context) == 0) )
+ default_routing = FALSE;
+ else
+ cl_qmap_apply_func( p_sw_guid_tbl, __osm_ucast_mgr_process_tbl, p_mgr );
+
+ /* dump fdb into file: */
+ if ( osm_log_is_active( p_mgr->p_log, OSM_LOG_ROUTING ) )
+ {
+ if ( !default_routing && p_routing_eng->ucast_dump_tables != 0 )
+ p_routing_eng->ucast_dump_tables(p_routing_eng->context);
+ else
+ __osm_ucast_mgr_dump_tables( p_mgr );
+ }
+
+ if (p_mgr->any_change)
+ {
+ signal = OSM_SIGNAL_DONE_PENDING;
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_ucast_mgr_process: "
+ "LFT Tables configured on all switches\n");
+ }
+ else
+ {
+ signal = OSM_SIGNAL_DONE;
+ osm_log( p_mgr->p_log, OSM_LOG_VERBOSE,
+ "osm_ucast_mgr_process: "
+ "No need to set any LFT Tables on any switches\n");
+ }
+
+ Exit:
+ CL_PLOCK_RELEASE( p_mgr->p_lock );
+ OSM_LOG_EXIT( p_mgr->p_log );
+ return( signal );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_ucast_updn.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of Up Down Algorithm using ranking & Min Hop
+ * Calculation functions
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.0 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_switch.h>
+#include <opensm/osm_opensm.h>
+
+/* //////////////////////////// */
+/* Local types */
+/* //////////////////////////// */
+
+/* direction */
+typedef enum _updn_switch_dir
+{
+ UP = 0,
+ DOWN
+} updn_switch_dir_t;
+
+/* This enum respresent available states in the UPDN algorithm */
+typedef enum _updn_state
+{
+ UPDN_INIT = 0,
+ UPDN_RANK,
+ UPDN_MIN_HOP_CALC,
+} updn_state_t;
+
+/* Rank value of this node */
+typedef struct _updn_rank
+{
+ cl_map_item_t map_item;
+ uint8_t rank;
+} updn_rank_t;
+
+/* Histogram element - the number of occurences of the same hop value */
+typedef struct _updn_hist
+{
+ cl_map_item_t map_item;
+ uint32_t bar_value;
+} updn_hist_t;
+
+typedef struct _updn_next_step
+{
+ updn_switch_dir_t state;
+ osm_switch_t *p_sw;
+} updn_next_step_t;
+
+/* guids list */
+typedef struct _updn_input
+{
+ uint32_t num_guids;
+ uint64_t * guid_list;
+} updn_input_t;
+
+/* updn structure */
+typedef struct _updn
+{
+ updn_state_t state;
+ boolean_t auto_detect_root_nodes;
+ cl_qmap_t guid_rank_tbl;
+ updn_input_t updn_ucast_reg_inputs;
+ cl_list_t * p_root_nodes;
+ osm_opensm_t *p_osm;
+} updn_t;
+
+/* ///////////////////////////////// */
+/* Statics */
+/* ///////////////////////////////// */
+static int __osm_updn_find_root_nodes_by_min_hop(OUT updn_t *p_updn);
+
+/**********************************************************************
+ **********************************************************************/
+/* This function returns direction based on rank and guid info of current &
+ remote ports */
+static updn_switch_dir_t
+__updn_get_dir(
+ IN updn_t *p_updn,
+ IN uint8_t cur_rank,
+ IN uint8_t rem_rank,
+ IN uint64_t cur_guid,
+ IN uint64_t rem_guid )
+{
+ uint32_t i = 0, max_num_guids = p_updn->updn_ucast_reg_inputs.num_guids;
+ uint64_t *p_guid = p_updn->updn_ucast_reg_inputs.guid_list;
+ boolean_t cur_is_root = FALSE, rem_is_root = FALSE;
+
+ /* 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 discover
+ the subnet correctly (and not from the point of view of the last root node).
+ */
+ for ( i = 0; i < max_num_guids; i++ )
+ {
+ if (cur_guid == p_guid[i])
+ cur_is_root = TRUE;
+ if (rem_guid == p_guid[i])
+ rem_is_root = TRUE;
+ }
+ if (cur_is_root && rem_is_root)
+ return UP;
+
+ if (cur_rank < rem_rank)
+ return DOWN;
+ else if (cur_rank > rem_rank)
+ return UP;
+ else
+ {
+ /* Equal rank, decide by guid number, bigger == UP direction */
+ if (cur_guid > rem_guid)
+ return UP;
+ else
+ return DOWN;
+ }
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* This function creates a new element of updn_next_step_t type then return its
+ pointer , Null if malloc has failed */
+static updn_next_step_t*
+__updn_create_updn_next_step_t(
+ IN updn_switch_dir_t state,
+ IN osm_switch_t* const p_sw )
+{
+ updn_next_step_t *p_next_step;
+
+ p_next_step = (updn_next_step_t*) malloc(sizeof(*p_next_step));
+ if (p_next_step)
+ {
+ memset(p_next_step, 0, sizeof(*p_next_step));
+ p_next_step->state = state;
+ p_next_step->p_sw = p_sw;
+ }
+
+ return p_next_step;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* This function updates an element in the qmap list by guid index and rank value */
+/* Return 0 if no need to futher update 1 if brought a new value */
+static int
+__updn_update_rank(
+ IN cl_qmap_t *p_guid_rank_tbl,
+ IN ib_net64_t guid,
+ IN uint8_t rank )
+{
+ updn_rank_t *p_updn_rank;
+
+ p_updn_rank = (updn_rank_t*) cl_qmap_get(p_guid_rank_tbl, guid);
+ if (p_updn_rank == (updn_rank_t*) cl_qmap_end(p_guid_rank_tbl))
+ {
+ p_updn_rank = (updn_rank_t*) malloc(sizeof(updn_rank_t));
+
+ CL_ASSERT (p_updn_rank);
+
+ p_updn_rank->rank = rank;
+
+ cl_qmap_insert(p_guid_rank_tbl, guid, &p_updn_rank->map_item);
+ return 1;
+ }
+ else
+ {
+ if (p_updn_rank->rank > rank)
+ {
+ p_updn_rank->rank = rank;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**********************************************************************
+ * This function does the bfs of min hop table calculation by guid index
+ * as a starting point.
+ **********************************************************************/
+static int
+__updn_bfs_by_node(
+ IN updn_t *p_updn,
+ IN osm_subn_t *p_subn,
+ IN osm_port_t *p_port,
+ IN cl_qmap_t *p_guid_rank_tbl )
+{
+ /* Init local vars */
+ osm_switch_t *p_self_node = NULL;
+ uint8_t pn, pn_rem;
+ osm_physp_t *p_physp, *p_remote_physp;
+ cl_list_t *p_currList, *p_nextList;
+ uint16_t root_lid, max_sw_lid;
+ updn_next_step_t *p_updn_switch, *p_tmp;
+ updn_switch_dir_t next_dir, current_dir;
+ osm_log_t *p_log = &p_updn->p_osm->log;
+
+ OSM_LOG_ENTER( p_log, __updn_bfs_by_node );
+
+ /* Init the list pointers */
+ p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_currList = p_nextList;
+
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ /* Check valid pointer */
+ if (!p_physp || !osm_physp_is_valid(p_physp ))
+ {
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ /* The Root BFS - lid */
+ root_lid = cl_ntoh16(osm_physp_get_base_lid( p_physp ));
+ /* printf ("-V- BFS through lid : 0x%x\n", root_lid); */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting lid : 0x%x \n", root_lid );
+
+ if (p_port->p_node->sw)
+ {
+ p_self_node = p_port->p_node->sw;
+ /* Update its Min Hop Table */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Update Min Hop Table of GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(p_port->guid) );
+ osm_switch_set_hops(p_self_node, root_lid, 0, 0);
+ }
+ else
+ {
+ /* This is a CA or router - need to take its remote port */
+ p_remote_physp = p_physp->p_remote_physp;
+ /*
+ make sure that the following occur:
+ 1. The port isn't NULL
+ 2. The port is a valid port
+ */
+ if ( p_remote_physp && osm_physp_is_valid ( p_remote_physp ))
+ {
+ /* Check if the remote port is a switch, if it is update root_lid,
+ Min Hop Table */
+ if (!p_remote_physp->p_node->sw)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA07: "
+ "This is a non switched subnet OR non valid connection, cannot perform UPDN algorithm\n" );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ else
+ {
+ p_self_node = p_remote_physp->p_node->sw;
+ max_sw_lid = osm_switch_get_max_lid_ho(p_self_node);
+ if ((1 <= root_lid) && (root_lid <= max_sw_lid))
+ /* Update its Min Hop Table */
+ {
+ /* NOTE : Check if there is a function which prints the Min Hop Table */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Update Min Hop Table of GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(p_remote_physp->port_guid) );
+ osm_switch_set_hops(p_self_node, root_lid,
+ p_remote_physp->port_num, 1);
+
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA09: "
+ " Invalid lid value 0x%x for switch 0x%" PRIx64 "\n",
+ root_lid,
+ cl_ntoh64(p_self_node->p_node->node_info.port_guid) );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ }
+ }
+ }
+
+ CL_ASSERT(p_self_node);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting from switch - port GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(p_self_node->p_node->node_info.port_guid) );
+
+ /* Update list with the updn_next_step_t new element */
+ /* NOTE : When inserting an item which is a pointer to a struct, does remove
+ action also free its memory */
+ if (!(p_tmp=__updn_create_updn_next_step_t(UP, p_self_node)))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA08: "
+ "Could not create updn_next_step_t\n" );
+ return 1;
+ }
+
+ cl_list_insert_tail(p_currList, p_tmp);
+
+ /* BFS the list till no next element */
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "__updn_bfs_by_node:"
+ "BFS the subnet [\n" );
+
+ while (!cl_is_list_empty(p_currList))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Starting a new iteration with %zu elements in current list\n",
+ cl_list_count(p_currList) );
+ /* Init the switch directed list */
+ p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ /* Go over all current list items till it's empty */
+ /* printf ("-V- In inner while\n"); */
+ p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+ /* While there is a pointer to updn struct we continue to BFS */
+ while (p_updn_switch)
+ {
+ current_dir = p_updn_switch->state;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "Visiting port GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(p_updn_switch->p_sw->p_node->node_info.port_guid) );
+ /* Go over all ports of the switch and find unvisited remote nodes */
+ for ( pn = 0; pn < osm_switch_get_num_ports(p_updn_switch->p_sw); pn++ )
+ {
+ /* printf("-V- Inner for in port num 0x%X\n", pn); */
+ osm_node_t *p_remote_node;
+ cl_list_iterator_t updn_switch_iterator;
+ boolean_t HasVisited = FALSE;
+ ib_net64_t remote_guid,current_guid;
+ updn_rank_t *p_rem_rank, *p_cur_rank;
+ uint8_t current_min_hop, remote_min_hop, set_hop_return_value;
+ osm_switch_t *p_remote_sw;
+
+ current_guid = osm_node_get_node_guid(p_updn_switch->p_sw->p_node);
+ p_remote_node = osm_node_get_remote_node( p_updn_switch->p_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 ||
+ (osm_node_get_type(p_remote_node) != IB_NODE_TYPE_SWITCH) )
+ continue;
+ /* Fetch remote guid only after validation of remote node */
+ remote_guid = osm_node_get_node_guid(p_remote_node);
+ /* printf ("-V- Current guid : 0x%" PRIx64 " Remote guid : 0x%" PRIx64 "\n", */
+ /* cl_ntoh64(current_guid), cl_ntoh64(remote_guid)); */
+ p_remote_sw = p_remote_node->sw;
+ p_rem_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, remote_guid);
+ p_cur_rank = (updn_rank_t*)cl_qmap_get(p_guid_rank_tbl, current_guid);
+ /* Decide which direction to mark it (UP/DOWN) */
+ next_dir = __updn_get_dir (p_updn, p_cur_rank->rank, p_rem_rank->rank,
+ current_guid, remote_guid);
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node:"
+ "move from 0x%016" PRIx64 " rank: %u "
+ "to 0x%016" PRIx64" rank: %u\n",
+ cl_ntoh64(current_guid), p_cur_rank->rank,
+ cl_ntoh64(remote_guid), p_rem_rank->rank );
+ /* 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,
+ "__updn_bfs_by_node:"
+ "Avoiding move from 0x%016" PRIx64 " to 0x%016" PRIx64"\n",
+ cl_ntoh64(current_guid), cl_ntoh64(remote_guid) );
+ /* Illegal step */
+ continue;
+ }
+ /* Set MinHop value for the current lid */
+ current_min_hop = osm_switch_get_least_hops(p_updn_switch->p_sw,root_lid);
+ /* Check hop count if better insert into NextState list && update
+ the remote node Min Hop Table */
+ remote_min_hop = osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem);
+ if (current_min_hop + 1 < remote_min_hop)
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node (less):"
+ "Setting Min Hop Table of switch: 0x%" PRIx64
+ "\n\t\tCurrent hop count is: %d, next hop count: %d"
+ "\n\tlid to set: 0x%x"
+ "\n\tport number: 0x%X"
+ " \n\thops number: %d\n",
+ cl_ntoh64(remote_guid), remote_min_hop,current_min_hop + 1,
+ root_lid, pn_rem, current_min_hop + 1 );
+ set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1);
+ if (set_hop_return_value)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node (less) ERR AA01: "
+ "Invalid value returned from set min hop is: %d\n",
+ set_hop_return_value );
+ }
+ /* Check if remote port is allready has been visited */
+ updn_switch_iterator = cl_list_head(p_nextList);
+ while( updn_switch_iterator != cl_list_end(p_nextList) )
+ {
+ updn_next_step_t *p_updn;
+ p_updn = (updn_next_step_t*)cl_list_obj(updn_switch_iterator);
+ /* Mark HasVisited only if:
+ 1. Same node guid
+ 2. Same direction
+ */
+ if ((p_updn->p_sw->p_node == p_remote_node) && (p_updn->state == next_dir))
+ HasVisited = TRUE;
+ updn_switch_iterator = cl_list_next(updn_switch_iterator);
+ }
+ if (!HasVisited)
+ {
+ /* Insert updn_switch item into the next list */
+ if(!(p_tmp=__updn_create_updn_next_step_t(next_dir, p_remote_sw)))
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node: ERR AA11: "
+ "Could not create updn_next_step_t\n" );
+ return 1;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node: "
+ "Inserting new element to the next list: guid=0x%" PRIx64 " %s\n",
+ cl_ntoh64(p_tmp->p_sw->p_node->node_info.port_guid),
+ (p_tmp->state == UP ? "UP" : "DOWN")
+ );
+ cl_list_insert_tail(p_nextList, p_tmp);
+ }
+ /* If the same value only update entry - at the min hop table */
+ } else if (current_min_hop + 1 == osm_switch_get_hop_count(p_remote_sw,
+ root_lid,
+ pn_rem))
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__updn_bfs_by_node (equal):"
+ "Setting Min Hop Table of switch: 0x%" PRIx64
+ "\n\t\tCurrent hop count is: %d, next hop count: %d"
+ "\n\tlid to set: 0x%x"
+ "\n\tport number: 0x%X"
+ "\n\thops number: %d\n",
+ cl_ntoh64(remote_guid),
+ osm_switch_get_hop_count(p_remote_sw, root_lid, pn_rem),
+ current_min_hop + 1, root_lid, pn_rem, current_min_hop + 1 );
+ set_hop_return_value = osm_switch_set_hops(p_remote_sw, root_lid, pn_rem, current_min_hop + 1);
+
+ if (set_hop_return_value)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__updn_bfs_by_node (less) ERR AA12: "
+ "Invalid value returned from set min hop is: %d\n",
+ set_hop_return_value );
+ }
+ }
+ }
+ free (p_updn_switch);
+ p_updn_switch = (updn_next_step_t*)cl_list_remove_head( p_currList );
+ }
+ /* Cleanup p_currList */
+ cl_list_destroy( p_currList );
+ free (p_currList);
+
+ /* Reassign p_currList to p_nextList */
+ p_currList = p_nextList;
+ }
+ /* Cleanup p_currList - Had the pointer to cl_list_t */
+ cl_list_destroy( p_currList );
+ free (p_currList);
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "__updn_bfs_by_node:"
+ "BFS the subnet ]\n" );
+ OSM_LOG_EXIT( p_log );
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+updn_destroy(
+ IN updn_t* const p_updn )
+{
+ cl_map_item_t *p_map_item;
+ uint64_t *p_guid_list_item;
+
+ /* Destroy the updn struct */
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+ {
+ osm_log ( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+ "osm_subn_calc_up_down_min_hop_table: "
+ "guid = 0x%" PRIx64 " rank = %u\n",
+ cl_ntoh64(cl_qmap_key(p_map_item)),
+ ((updn_rank_t *)p_map_item)->rank );
+ cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+ free( (updn_rank_t *)p_map_item);
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ }
+
+ /* free the array of guids */
+ if (p_updn->updn_ucast_reg_inputs.guid_list)
+ free(p_updn->updn_ucast_reg_inputs.guid_list);
+
+ /* destroy the list of root nodes */
+ while ((p_guid_list_item = cl_list_remove_head( p_updn->p_root_nodes )))
+ free( p_guid_list_item );
+
+ cl_list_remove_all( p_updn->p_root_nodes );
+ cl_list_destroy( p_updn->p_root_nodes );
+ free ( p_updn->p_root_nodes );
+ free (p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static updn_t*
+updn_construct(osm_log_t *p_log)
+{
+ updn_t* p_updn;
+
+ OSM_LOG_ENTER( p_log, updn_construct );
+ p_updn = malloc(sizeof(updn_t));
+ if (p_updn)
+ memset(p_updn, 0, sizeof(updn_t));
+ OSM_LOG_EXIT( p_log );
+ return(p_updn);
+}
+
+/**********************************************************************
+ **********************************************************************/
+static cl_status_t
+updn_init(
+ IN updn_t* const p_updn,
+ IN osm_opensm_t *p_osm )
+{
+ cl_list_t * p_list;
+ FILE* p_updn_guid_file;
+ char line[MAX_UPDN_GUID_FILE_LINE_LENGTH];
+ uint64_t * p_tmp;
+ cl_list_iterator_t guid_iterator;
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osm->log, updn_init );
+
+ p_updn->p_osm = p_osm;
+ p_updn->state = UPDN_INIT;
+ cl_qmap_init( &p_updn->guid_rank_tbl );
+ p_list = (cl_list_t*)malloc(sizeof(cl_list_t));
+ if (!p_list)
+ {
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ cl_list_construct( p_list );
+ cl_list_init( p_list, 10 );
+ p_updn->p_root_nodes = p_list;
+ p_updn->updn_ucast_reg_inputs.num_guids = 0;
+ p_updn->updn_ucast_reg_inputs.guid_list = NULL;
+ p_updn->auto_detect_root_nodes = FALSE;
+
+ /*
+ Check the source for root node list, if file parse it, otherwise
+ wait for a callback to activate auto detection
+ */
+ if (p_osm->subn.opt.updn_guid_file)
+ {
+ /* Now parse guid from file */
+ p_updn_guid_file = fopen(p_osm->subn.opt.updn_guid_file, "r");
+ if (p_updn_guid_file == NULL)
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "osm_opensm_init : ERR AA02: "
+ "Failed to open guid list file (%s)\n",
+ p_osm->subn.opt.updn_guid_file );
+ status = IB_NOT_FOUND;
+ goto Exit;
+ }
+
+ while ( fgets(line, MAX_UPDN_GUID_FILE_LINE_LENGTH, p_updn_guid_file) )
+ {
+ if (strcspn(line, " ,;.") == strlen(line))
+ {
+ /* Skip empty lines anywhere in the file - only one char means the Null termination */
+ if (strlen(line) > 1)
+ {
+ p_tmp = malloc(sizeof(uint64_t));
+ *p_tmp = strtoull(line, NULL, 16);
+ cl_list_insert_tail(p_updn->p_root_nodes, p_tmp);
+ }
+ }
+ else
+ {
+ osm_log( &p_osm->log, OSM_LOG_ERROR,
+ "osm_opensm_init: ERR AA03: "
+ "Bad formatted guid in file (%s): %s\n",
+ p_osm->subn.opt.updn_guid_file, line );
+ status = IB_NOT_FOUND;
+ break;
+ }
+ }
+
+ /* For Debug Purposes ... */
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "osm_opensm_init: "
+ "UPDN - Root nodes fetching by file %s\n",
+ p_osm->subn.opt.updn_guid_file );
+ guid_iterator = cl_list_head(p_updn->p_root_nodes);
+ while( guid_iterator != cl_list_end(p_updn->p_root_nodes) )
+ {
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "osm_opensm_init: "
+ "Inserting GUID 0x%" PRIx64 " as root node\n",
+ *((uint64_t*)cl_list_obj(guid_iterator)) );
+ guid_iterator = cl_list_next(guid_iterator);
+ }
+ }
+ else
+ {
+ p_updn->auto_detect_root_nodes = TRUE;
+ }
+ /* If auto mode detection required - will be executed in main b4 the assignment of UI Ucast */
+
+Exit :
+ OSM_LOG_EXIT( &p_osm->log );
+ return (status);
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* NOTE : PLS check if we need to decide that the first */
+/* rank is a SWITCH for BFS purpose */
+static int
+updn_subn_rank(
+ IN uint64_t root_guid,
+ IN uint8_t base_rank,
+ IN updn_t* p_updn )
+{
+ /* Init local vars */
+ osm_port_t *p_root_port = NULL;
+ uint16_t tbl_size;
+ uint8_t rank = base_rank;
+ osm_physp_t *p_physp, *p_remote_physp, *p_physp_temp;
+ cl_list_t *p_currList,*p_nextList;
+ cl_status_t did_cause_update;
+ uint8_t num_ports, port_num;
+ osm_log_t *p_log = &p_updn->p_osm->log;
+
+ OSM_LOG_ENTER( p_log, updn_subn_rank );
+
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Ranking starts from GUID 0x%" PRIx64 "\n", root_guid );
+
+ /* Init the list pointers */
+ p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_currList = p_nextList;
+
+ /* Check valid subnet & guid */
+ tbl_size = (uint16_t)(cl_qmap_count(&p_updn->p_osm->subn.port_guid_tbl));
+ if (tbl_size == 0)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "updn_subn_rank: ERR AA04: "
+ "Port guid table is empty, cannot perform ranking\n" );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+
+ p_root_port = (osm_port_t*) cl_qmap_get(&p_updn->p_osm->subn.port_guid_tbl,
+ cl_ntoh64(root_guid));
+ if( p_root_port == (osm_port_t*)cl_qmap_end( &p_updn->p_osm->subn.port_guid_tbl ) )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "updn_subn_rank: ERR AA05: "
+ "Wrong guid value: 0x%" PRIx64 "\n", root_guid );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+
+ /* Rank the first chosen guid anyway since its the base rank */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Ranking port GUID 0x%" PRIx64 "\n", root_guid );
+
+ __updn_update_rank(&p_updn->guid_rank_tbl, cl_ntoh64(root_guid), rank);
+ /*
+ 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 = osm_port_get_default_phys_ptr( p_root_port );
+ CL_ASSERT( p_physp );
+ CL_ASSERT( osm_physp_is_valid( p_physp ) );
+ /* We can safely add the node to the list */
+ cl_list_insert_tail(p_nextList, p_physp);
+ /* Assign pointer to the list for BFS */
+ p_currList = p_nextList;
+
+ /* BFS the list till its empty */
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "BFS the subnet [\n" );
+
+ while (!cl_is_list_empty(p_currList))
+ {
+ rank++;
+ p_nextList = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_nextList );
+ cl_list_init( p_nextList, 10 );
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+ /* Go over all remote nodes and rank them (if not allready visited) till
+ no elemtent in the list p_currList */
+ while ( p_physp != NULL )
+ {
+ num_ports = osm_node_get_num_physp( p_physp->p_node );
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Handling port GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(p_physp->port_guid) );
+ 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_temp = osm_node_get_physp_ptr( p_physp->p_node, port_num );
+ p_remote_physp = p_physp_temp->p_remote_physp;
+
+ /*
+ make sure that all the following occur on p_remote_physp:
+ 1. The port isn't NULL
+ 2. The port is a valid port
+ */
+ if ( p_remote_physp &&
+ osm_physp_is_valid ( p_remote_physp ))
+ {
+ port_guid = p_remote_physp->port_guid;
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Visiting remote port GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(port_guid) );
+ /* Was it visited ?
+ Only if the pointer equal to cl_qmap_end its not
+ found in the list */
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "updn_subn_rank: "
+ "Ranking port GUID 0x%" PRIx64 "\n", cl_ntoh64(port_guid) );
+ did_cause_update = __updn_update_rank(&p_updn->guid_rank_tbl, port_guid, rank);
+
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Rank of port GUID 0x%" PRIx64 " = %u\n", cl_ntoh64(port_guid),
+ ((updn_rank_t*)cl_qmap_get(&p_updn->guid_rank_tbl, port_guid))->rank
+ );
+
+ if (did_cause_update)
+ {
+ cl_list_insert_tail(p_nextList, p_remote_physp);
+ }
+ }
+ }
+ /* Propagte through the next item in the p_currList */
+ p_physp = (osm_physp_t*)cl_list_remove_head( p_currList );
+ }
+ /* First free the allocation of cl_list pointer then reallocate */
+ cl_list_destroy( p_currList );
+ free(p_currList);
+ /* p_currList is empty - need to assign it to p_nextList */
+ p_currList = p_nextList;
+ }
+
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "BFS the subnet ]\n" );
+
+ cl_list_destroy( p_currList );
+ free(p_currList);
+
+ /* Print Summary of ranking */
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "updn_subn_rank: "
+ "Rank Info :\n\t Root Guid = 0x%" PRIx64 "\n\t Max Node Rank = %d\n",
+ cl_ntoh64(p_root_port->guid), rank );
+ p_updn->state = UPDN_RANK;
+ OSM_LOG_EXIT( p_log );
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__osm_subn_set_up_down_min_hop_table(
+ IN updn_t* p_updn )
+{
+ /* Init local vars */
+ osm_subn_t *p_subn = &p_updn->p_osm->subn;
+ osm_log_t *p_log = &p_updn->p_osm->log;
+ osm_switch_t *p_next_sw,*p_sw;
+ osm_port_t *p_next_port,*p_port;
+ ib_net64_t port_guid;
+
+ OSM_LOG_ENTER( p_log, __osm_subn_set_up_down_min_hop_table );
+ if (p_updn->state == UPDN_INIT)
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_subn_set_up_down_min_hop_table: ERR AA06: "
+ "Calculating Min Hop only allowed after ranking\n" );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+
+ /* Check if its a non switched subnet .. */
+ if ( cl_is_qmap_empty( &p_subn->sw_guid_tbl ) )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "__osm_subn_set_up_down_min_hop_table: ERR AA10: "
+ "This is a non switched subnet, cannot perform UPDN algorithm\n" );
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ /* Go over all the switches in the subnet - for each init their Min Hop
+ Table */
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "__osm_subn_set_up_down_min_hop_table: "
+ "Init Min Hop Table of all switches [\n" );
+
+ 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 );
+ /* Clear Min Hop Table */
+ osm_lid_matrix_clear(&(p_sw->lmx));
+ }
+
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "__osm_subn_set_up_down_min_hop_table: "
+ "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,
+ "__osm_subn_set_up_down_min_hop_table: "
+ "BFS through all port guids in the subnet [\n" );
+ 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 );
+ port_guid = cl_qmap_key(&(p_port->map_item));
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "__osm_subn_set_up_down_min_hop_table: "
+ "BFS through port GUID 0x%" PRIx64 "\n",
+ cl_ntoh64(port_guid) );
+ if(__updn_bfs_by_node(p_updn, p_subn, p_port,
+ &p_updn->guid_rank_tbl))
+ {
+ OSM_LOG_EXIT( p_log );
+ return 1;
+ }
+ }
+
+ osm_log( p_log, OSM_LOG_VERBOSE,
+ "__osm_subn_set_up_down_min_hop_table: "
+ "BFS through all port guids in the subnet ]\n" );
+ /* Cleanup */
+ OSM_LOG_EXIT( p_log );
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static int
+__osm_subn_calc_up_down_min_hop_table(
+ IN uint32_t num_guids,
+ IN uint64_t * guid_list,
+ IN updn_t* p_updn )
+{
+ uint8_t idx = 0;
+ cl_map_item_t *p_map_item;
+ int status;
+
+ OSM_LOG_ENTER( &p_updn->p_osm->log, osm_subn_calc_up_down_min_hop_table );
+ osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_subn_calc_up_down_min_hop_table: "
+ "Ranking all port guids in the list\n" );
+ if (num_guids == 0)
+ {
+ osm_log( &p_updn->p_osm->log, OSM_LOG_ERROR,
+ "__osm_subn_calc_up_down_min_hop_table: ERR AA0A: "
+ "No guids were given or number of guids is 0\n" );
+ return 1;
+ }
+
+ for (idx = 0; idx < num_guids; idx++)
+ {
+ /* Apply the ranking for each guid given by user - bypass illegal ones */
+ updn_subn_rank(guid_list[idx], 0, p_updn);
+ }
+ /* After multiple ranking need to set Min Hop Table by UpDn algorithm */
+ osm_log( &p_updn->p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_subn_calc_up_down_min_hop_table: "
+ "Setting all switches' Min Hop Table\n" );
+
+ status = __osm_subn_set_up_down_min_hop_table (p_updn);
+
+ /* Cleanup updn rank tbl */
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ while( p_map_item != cl_qmap_end( &p_updn->guid_rank_tbl))
+ {
+ osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_subn_calc_up_down_min_hop_table: "
+ "guid = 0x%" PRIx64 " rank = %u\n",
+ cl_ntoh64(cl_qmap_key(p_map_item)),
+ ((updn_rank_t *)p_map_item)->rank );
+ cl_qmap_remove_item( &p_updn->guid_rank_tbl, p_map_item);
+ free( (updn_rank_t *)p_map_item);
+ p_map_item = cl_qmap_head( &p_updn->guid_rank_tbl);
+ }
+
+ OSM_LOG_EXIT( &p_updn->p_osm->log );
+ return status;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN callback function */
+static int
+__osm_updn_call(
+ void *ctx )
+{
+ updn_t *p_updn = ctx;
+
+ OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_call );
+
+ /* First auto detect root nodes - if required */
+ if ( p_updn->auto_detect_root_nodes )
+ {
+ osm_ucast_mgr_build_lid_matrices( &p_updn->p_osm->sm.ucast_mgr );
+ /* printf ("-V- b4 osm_updn_find_root_nodes_by_min_hop\n"); */
+ __osm_updn_find_root_nodes_by_min_hop( p_updn );
+ }
+ /* printf ("-V- after osm_updn_find_root_nodes_by_min_hop\n"); */
+ /* Only if there are assigned root nodes do the algorithm , otherwise perform do nothing */
+ if ( p_updn->updn_ucast_reg_inputs.num_guids > 0)
+ {
+ osm_log( &(p_updn->p_osm->log), OSM_LOG_DEBUG,
+ "__osm_updn_call: "
+ "activating UPDN algorithm\n" );
+ __osm_subn_calc_up_down_min_hop_table( p_updn->updn_ucast_reg_inputs.num_guids,
+ p_updn->updn_ucast_reg_inputs.guid_list,
+ p_updn );
+ }
+ else
+ osm_log( &p_updn->p_osm->log, OSM_LOG_INFO,
+ "__osm_updn_call: "
+ "disable UPDN algorithm, no root nodes were found\n" );
+
+ OSM_LOG_EXIT( &p_updn->p_osm->log );
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* UPDN convert cl_list to guid array in updn struct */
+static void
+__osm_updn_convert_list2array(
+ IN updn_t * p_updn )
+{
+ uint32_t i = 0, max_num = 0;
+ uint64_t *p_guid;
+
+ OSM_LOG_ENTER( &p_updn->p_osm->log, __osm_updn_convert_list2array );
+
+ p_updn->updn_ucast_reg_inputs.num_guids = cl_list_count(
+ p_updn->p_root_nodes);
+ if (p_updn->updn_ucast_reg_inputs.guid_list)
+ free(p_updn->updn_ucast_reg_inputs.guid_list);
+ p_updn->updn_ucast_reg_inputs.guid_list = (uint64_t *)malloc(
+ p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t));
+ if (p_updn->updn_ucast_reg_inputs.guid_list)
+ memset(p_updn->updn_ucast_reg_inputs.guid_list, 0,
+ p_updn->updn_ucast_reg_inputs.num_guids*sizeof(uint64_t));
+ if (!cl_is_list_empty(p_updn->p_root_nodes))
+ {
+ while( (p_guid = (uint64_t*)cl_list_remove_head(p_updn->p_root_nodes)) )
+ {
+ p_updn->updn_ucast_reg_inputs.guid_list[i] = *p_guid;
+ free(p_guid);
+ i++;
+ }
+ max_num = i;
+ for (i = 0; i < max_num; i++ )
+ osm_log( &p_updn->p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_convert_list2array: "
+ "Map GUID 0x%" PRIx64 " into UPDN array\n",
+ p_updn->updn_ucast_reg_inputs.guid_list[i] );
+ }
+ /* Since we need the template list for other sweeps, we wont destroy & free it */
+ OSM_LOG_EXIT( &p_updn->p_osm->log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/* Find Root nodes automatically by Min Hop Table info */
+static int
+__osm_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_next_sw, *p_sw;
+ osm_port_t *p_next_port, *p_port;
+ osm_physp_t *p_physp;
+ uint32_t numCas = 0;
+ uint32_t numSws = cl_qmap_count(&p_osm->subn.sw_guid_tbl);
+ cl_qmap_t min_hop_hist; /* Histogram container */
+ updn_hist_t *p_updn_hist, *p_up_ht;
+ uint8_t maxHops = 0; /* contain the max histogram index */
+ uint64_t *p_guid;
+ cl_list_t *p_root_nodes_list = p_updn->p_root_nodes;
+ cl_map_t ca_by_lid_map; /* map holding all CA lids */
+ uint16_t self_lid_ho;
+
+ OSM_LOG_ENTER( &p_osm->log, osm_updn_find_root_nodes_by_min_hop );
+
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "current number of ports in the subnet is %d\n",
+ cl_qmap_count(&p_osm->subn.port_guid_tbl) );
+ /* Init the required vars */
+ cl_qmap_init( &min_hop_hist );
+ cl_map_construct( &ca_by_lid_map );
+ cl_map_init( &ca_by_lid_map, 10 );
+
+ /* EZ:
+ p_ca_list = (cl_list_t*)malloc(sizeof(cl_list_t));
+ cl_list_construct( p_ca_list );
+ cl_list_init( p_ca_list, 10 );
+ */
+
+ /* Find the Maximum number of CAs (and routers) for histogram normalization */
+ osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Find the number of CAs and store them in cl_list\n" );
+ p_next_port = (osm_port_t*)cl_qmap_head( &p_osm->subn.port_guid_tbl );
+ while( p_next_port != (osm_port_t*)cl_qmap_end( &p_osm->subn.port_guid_tbl ) ) {
+ p_port = p_next_port;
+ p_next_port = (osm_port_t*)cl_qmap_next( &p_next_port->map_item );
+ if ( osm_node_get_type(p_port->p_node) != IB_NODE_TYPE_SWITCH )
+ {
+ p_physp = osm_port_get_default_phys_ptr(p_port);
+ self_lid_ho = cl_ntoh16( osm_physp_get_base_lid(p_physp) );
+ numCas++;
+ /* EZ:
+ self = malloc(sizeof(uint16_t));
+ *self = self_lid_ho;
+ cl_list_insert_tail(p_ca_list, self);
+ */
+ cl_map_insert( &ca_by_lid_map, self_lid_ho, (void *)0x1);
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Inserting into array GUID 0x%" PRIx64 ", Lid: 0x%X\n",
+ cl_ntoh64(osm_port_get_guid(p_port)), self_lid_ho );
+ }
+ }
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Found %u CA, %u SW in the subnet\n", numCas, numSws );
+ p_next_sw = (osm_switch_t*)cl_qmap_head( &p_osm->subn.sw_guid_tbl );
+ osm_log( &p_osm->log, OSM_LOG_VERBOSE,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Passing through all switches to collect Min Hop info\n" );
+ while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_osm->subn.sw_guid_tbl ) )
+ {
+ uint16_t max_lid_ho, lid_ho;
+ uint8_t hop_val;
+ uint16_t numHopBarsOverThd1 = 0;
+ uint16_t numHopBarsOverThd2 = 0;
+ double thd1, thd2;
+
+ p_sw = p_next_sw;
+ /* Roll to the next switch */
+ p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
+
+ /* Clear Min Hop Table && FWD Tbls - This should caused opensm to
+ rebuild its FWD tables , post setting Min Hop Tables */
+ max_lid_ho = osm_switch_get_max_lid_ho(p_sw);
+ /* Get base lid of switch by retrieving port 0 lid of node pointer */
+ self_lid_ho = cl_ntoh16( osm_node_get_base_lid( p_sw->p_node, 0 ) );
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Passing through switch lid 0x%X\n", self_lid_ho );
+ for (lid_ho = 1; lid_ho <= max_lid_ho; lid_ho++)
+ {
+ /* Skip lids which are not CAs -
+ for the histogram purposes we care only about CAs */
+
+ /* EZ:
+ boolean_t LidFound = FALSE;
+ cl_list_iterator_t ca_lid_iterator= cl_list_head(p_ca_list);
+ while( (ca_lid_iterator != cl_list_end(p_ca_list)) && !LidFound )
+ {
+ uint16_t *p_lid;
+
+ p_lid = (uint16_t*)cl_list_obj(ca_lid_iterator);
+ if ( *p_lid == lid_ho )
+ LidFound = TRUE;
+ ca_lid_iterator = cl_list_next(ca_lid_iterator);
+
+ }
+ if ( LidFound )
+ */
+ if (cl_map_get( &ca_by_lid_map, lid_ho ))
+ {
+ hop_val = osm_switch_get_least_hops( p_sw, lid_ho );
+ if (hop_val > maxHops)
+ maxHops = hop_val;
+ p_updn_hist =
+ (updn_hist_t*)cl_qmap_get( &min_hop_hist , (uint64_t)hop_val );
+ if ( p_updn_hist == (updn_hist_t*)cl_qmap_end( &min_hop_hist))
+ {
+ /* New entry in the histogram , first create it */
+ p_updn_hist = (updn_hist_t*) malloc(sizeof(updn_hist_t));
+ CL_ASSERT (p_updn_hist);
+ p_updn_hist->bar_value = 1;
+ cl_qmap_insert(&min_hop_hist, (uint64_t)hop_val, &p_updn_hist->map_item);
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Creating new entry in histogram %u with bar value 1\n",
+ hop_val );
+ }
+ else
+ {
+ /* Entry exist in the table , just increment the value */
+ p_updn_hist->bar_value++;
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Updating entry in histogram %u with bar value %d\n",
+ hop_val, p_updn_hist->bar_value );
+ }
+ }
+ }
+
+ /* Now recognize the spines by requiring one bar to be above 90% of the
+ number of CAs */
+ thd1 = numCas * 0.9;
+ thd2 = numCas * 0.05;
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Pass over the histogram value and find only one root node above "
+ "thd1 = %f && thd2 = %f\n", thd1, thd2 );
+
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ while( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+ {
+ p_up_ht = p_updn_hist;
+ p_updn_hist = (updn_hist_t*)cl_qmap_next( &p_updn_hist->map_item ) ;
+ if ( p_up_ht->bar_value > thd1 )
+ numHopBarsOverThd1++;
+ if ( p_up_ht->bar_value > thd2 )
+ numHopBarsOverThd2++;
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Passing through histogram - Hop Index %u: "
+ "numHopBarsOverThd1 = %u, numHopBarsOverThd2 = %u\n",
+ (uint16_t)cl_qmap_key((cl_map_item_t*)p_up_ht),
+ numHopBarsOverThd1, numHopBarsOverThd2 );
+ }
+
+ /* destroy the qmap table and all its content - no longer needed */
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Cleanup: delete histogram "
+ "UPDN - Root nodes fetching by auto detect\n" );
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ while ( p_updn_hist != (updn_hist_t*)cl_qmap_end( &min_hop_hist ) )
+ {
+ cl_qmap_remove_item( &min_hop_hist, (cl_map_item_t*)p_updn_hist );
+ free( p_updn_hist );
+ p_updn_hist = (updn_hist_t*) cl_qmap_head( &min_hop_hist );
+ }
+
+ /* If thd conditions are valid insert the root node to the list */
+ if ( (numHopBarsOverThd1 == 1) && (numHopBarsOverThd2 == 1) )
+ {
+ p_guid = malloc(sizeof(uint64_t));
+ *p_guid = cl_ntoh64(osm_node_get_node_guid(p_sw->p_node));
+ osm_log( &p_osm->log, OSM_LOG_DEBUG,
+ "__osm_updn_find_root_nodes_by_min_hop: "
+ "Inserting GUID 0x%" PRIx64 " as root node\n",
+ *p_guid );
+ cl_list_insert_tail(p_root_nodes_list, p_guid);
+ }
+ }
+
+ /* destroy the map of CA lids */
+ cl_map_remove_all( &ca_by_lid_map );
+ cl_map_destroy( &ca_by_lid_map );
+
+ /* Now convert the cl_list to array */
+ __osm_updn_convert_list2array(p_updn);
+
+ OSM_LOG_EXIT( &p_osm->log );
+ return 0;
+}
+
+/**********************************************************************
+ **********************************************************************/
+static void
+__osm_updn_delete(
+ void *context )
+{
+ updn_t *p_updn = context;
+
+ updn_destroy(p_updn);
+}
+
+int
+osm_ucast_updn_setup(
+ osm_opensm_t *p_osm )
+{
+ updn_t *p_updn;
+
+ p_updn = updn_construct(&p_osm->log);
+ if (!p_updn)
+ return -1;
+ p_osm->routing_engine.context = p_updn;
+ p_osm->routing_engine.delete = __osm_updn_delete;
+ p_osm->routing_engine.build_lid_matrices = __osm_updn_call;
+
+ if (updn_init(p_updn, p_osm) != IB_SUCCESS)
+ return -1;
+ if (!p_updn->auto_detect_root_nodes)
+ __osm_updn_convert_list2array(p_updn);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl15intf.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vl15_t.
+ * This object represents the VL15 Interface object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <opensm/osm_vl15intf.h>
+#include <opensm/osm_madw.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_helper.h>
+#include <complib/cl_thread.h>
+#include <signal.h>
+
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vl15_poller(
+ IN void *p_ptr )
+{
+ ib_api_status_t status;
+ osm_madw_t *p_madw;
+ uint32_t mads_sent;
+ uint32_t unicasts_sent;
+ uint32_t mads_on_wire;
+ osm_vl15_t* const p_vl = (osm_vl15_t*)p_ptr;
+ cl_qlist_t* p_fifo;
+
+ OSM_LOG_ENTER( p_vl->p_log, __osm_vl15_poller );
+
+ 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 ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "Servicing p_madw = %p\n", p_madw );
+ }
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_FRAMES ) )
+ {
+ osm_dump_dr_smp( p_vl->p_log,
+ osm_madw_get_smp_ptr( p_madw ), OSM_LOG_FRAMES );
+ }
+
+ /*
+ Non-response-expected mads are not throttled on the wire
+ since we can have no confirmation that they arrived
+ at their destination.
+ */
+ if( p_madw->resp_expected == TRUE )
+ {
+ /*
+ 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.
+ */
+ mads_on_wire = cl_atomic_inc(
+ &p_vl->p_stats->qp0_mads_outstanding_on_wire );
+ CL_ASSERT( mads_on_wire <= p_vl->max_wire_smps );
+ }
+ else
+ {
+ unicasts_sent = cl_atomic_inc(
+ &p_vl->p_stats->qp0_unicasts_sent );
+ }
+
+ mads_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 )
+ {
+ uint32_t outstanding;
+ cl_status_t cl_status;
+
+ osm_log( p_vl->p_log, OSM_LOG_ERROR,
+ "__osm_vl15_poller: 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 and qp0_mads_outstanding_on_wire
+ that was incremented in the code above. */
+ mads_sent = cl_atomic_dec( &p_vl->p_stats->qp0_mads_sent );
+ if( p_madw->resp_expected == TRUE )
+ cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding_on_wire );
+
+ /*
+ The following code is similar to the code in
+ __osm_sm_mad_ctrl_retire_trans_mad. We need to decrement the
+ qp0_mads_outstanding counter, and if we reached 0 - need to call
+ the cl_disp_post with OSM_SIGNAL_NO_PENDING_TRANSACTION (in order
+ to wake up the state mgr).
+ There is one difference from the code in __osm_sm_mad_ctrl_retire_trans_mad.
+ This code is called on all mads, if osm_vendor_send() failed, unlike
+ __osm_sm_mad_ctrl_retire_trans_mad which is called only on mads where
+ resp_expected == TRUE. As a result, the qp0_mads_outstanding counter
+ should be decremented and handled accordingly only if this is a mad
+ with resp_expected == TRUE.
+ */
+ if ( p_madw->resp_expected == TRUE )
+ {
+ outstanding = cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "%u QP0 MADs outstanding\n",
+ p_vl->p_stats->qp0_mads_outstanding );
+
+ if( outstanding == 0 )
+ {
+ /*
+ The wire is clean.
+ Signal the state manager.
+ */
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "Posting Dispatcher message %s\n",
+ osm_get_disp_msg_str( OSM_MSG_NO_SMPS_OUTSTANDING ) );
+ }
+
+ cl_status = cl_disp_post( p_vl->h_disp,
+ OSM_MSG_NO_SMPS_OUTSTANDING,
+ (void *)OSM_SIGNAL_NO_PENDING_TRANSACTIONS,
+ NULL,
+ NULL );
+
+ if( cl_status != CL_SUCCESS )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_ERROR,
+ "__osm_vl15_poller: ERR 3E06: "
+ "Dispatcher post message failed (%s)\n",
+ CL_STATUS_MSG( cl_status ) );
+ }
+ }
+ }
+ }
+ else
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "__osm_vl15_poller: "
+ "%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 );
+ }
+ }
+ }
+ 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 >=
+ (int32_t)p_vl->max_wire_smps ) &&
+ (p_vl->thread_state == OSM_THREAD_STATE_RUN ) )
+ {
+ status = cl_event_wait_on( &p_vl->signal,
+ EVENT_NO_TIMEOUT, TRUE );
+ }
+
+ if( status != CL_SUCCESS )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_ERROR,
+ "__osm_vl15_poller: ERR 3E02: "
+ "Event wait failed (%s)\n",
+ CL_STATUS_MSG( status ) );
+ }
+ }
+
+ /*
+ 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 back these mads...
+ */
+
+ OSM_LOG_EXIT( p_vl->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_construct(
+ IN osm_vl15_t* const 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 );
+ p_vl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_destroy(
+ IN osm_vl15_t* const p_vl,
+ IN struct _osm_mad_pool *p_pool)
+{
+ osm_madw_t* p_madw;
+
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_destroy );
+
+ /*
+ 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* const p_vl,
+ IN osm_vendor_t* const p_vend,
+ IN osm_log_t* const p_log,
+ IN osm_stats_t* const p_stats,
+ IN const int32_t max_wire_smps,
+ IN osm_subn_t* const p_subn,
+ IN cl_dispatcher_t* const p_disp,
+ IN cl_plock_t* const p_lock
+ )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vl15_init );
+
+ p_vl->p_vend = p_vend;
+ p_vl->p_log = p_log;
+ p_vl->p_stats = p_stats;
+ p_vl->max_wire_smps = max_wire_smps;
+ p_vl->p_subn = p_subn;
+ p_vl->p_lock = p_lock;
+
+ 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, __osm_vl15_poller, p_vl,
+ "opensm poller" );
+ if( status != IB_SUCCESS )
+ goto Exit;
+
+ p_vl->h_disp = cl_disp_register(
+ p_disp,
+ CL_DISP_MSGID_NONE,
+ NULL,
+ NULL );
+
+ if( p_vl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_vl15_init: ERR 3E01: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vl15_poll(
+ IN osm_vl15_t* const p_vl )
+{
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_poll );
+
+ 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 )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_poll: "
+ "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* const p_vl,
+ IN osm_madw_t* const p_madw )
+{
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_post );
+
+ CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_post: "
+ "Posting p_madw = 0x%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, (cl_list_item_t*)p_madw );
+ cl_atomic_inc( &p_vl->p_stats->qp0_mads_outstanding );
+ }
+ else
+ {
+ cl_qlist_insert_tail( &p_vl->ufifo, (cl_list_item_t*)p_madw );
+ }
+ cl_spinlock_release( &p_vl->lock );
+
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_post: "
+ "%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* const p_vl,
+ IN osm_mad_pool_t* const p_mad_pool)
+{
+ osm_madw_t* p_madw;
+
+ OSM_LOG_ENTER( p_vl->p_log, osm_vl15_shutdown );
+
+ /* we only should get here after the VL15 interface was initialized */
+ CL_ASSERT( p_vl->state == OSM_VL15_STATE_READY );
+
+ /* grap a lock on the object */
+ cl_spinlock_acquire( &p_vl->lock );
+
+ cl_disp_unregister( p_vl->h_disp );
+
+ /* 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 ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_shutdown: "
+ "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 ) )
+ {
+ if( osm_log_is_active( p_vl->p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_vl->p_log, OSM_LOG_DEBUG,
+ "osm_vl15_shutdown: "
+ "Releasing Request p_madw = %p\n", p_madw );
+ }
+
+ osm_mad_pool_put( p_mad_pool, p_madw );
+ cl_atomic_dec( &p_vl->p_stats->qp0_mads_outstanding );
+
+ 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 );
+}
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl_arb_rcv.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * 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.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <iba/ib_types.h>
+#include <complib/cl_qmap.h>
+#include <complib/cl_passivelock.h>
+#include <complib/cl_debug.h>
+#include <opensm/osm_vl_arb_rcv.h>
+#include <opensm/osm_node_info_rcv.h>
+#include <opensm/osm_req.h>
+#include <opensm/osm_madw.h>
+#include <opensm/osm_log.h>
+#include <opensm/osm_node.h>
+#include <opensm/osm_subnet.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_msgdef.h>
+#include <opensm/osm_helper.h>
+#include <vendor/osm_vendor_api.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_construct(
+ IN osm_vla_rcv_t* const p_rcv )
+{
+ memset( p_rcv, 0, sizeof(*p_rcv) );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_destroy(
+ IN osm_vla_rcv_t* const p_rcv )
+{
+ CL_ASSERT( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_destroy );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_init(
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_req_t* const p_req,
+ IN osm_subn_t* const p_subn,
+ IN osm_log_t* const p_log,
+ IN cl_plock_t* const p_lock )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vla_rcv_init );
+
+ osm_vla_rcv_construct( p_rcv );
+
+ p_rcv->p_log = p_log;
+ p_rcv->p_subn = p_subn;
+ p_rcv->p_lock = p_lock;
+ p_rcv->p_req = p_req;
+
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+/**********************************************************************
+ **********************************************************************/
+/*
+ * WE MIGHT ONLY RECEIVE GET or SET responses
+ */
+void
+osm_vla_rcv_process(
+ IN const osm_vla_rcv_t* const p_rcv,
+ IN osm_madw_t* const p_madw )
+{
+ cl_qmap_t *p_guid_tbl;
+ 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( p_rcv );
+
+ OSM_LOG_ENTER( p_rcv->p_log, osm_vla_rcv_process );
+
+ 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_vl_arb_table_t*)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 );
+
+ p_guid_tbl = &p_rcv->p_subn->port_guid_tbl;
+ cl_plock_excl_acquire( p_rcv->p_lock );
+ p_port = (osm_port_t*)cl_qmap_get( p_guid_tbl, port_guid );
+
+ if( p_port == (osm_port_t*)cl_qmap_end( p_guid_tbl ) )
+ {
+ cl_plock_release( p_rcv->p_lock );
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: 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 = osm_port_get_parent_node( p_port );
+ 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 = osm_port_get_default_phys_ptr(p_port);
+ port_num = p_port->default_port_num;
+ }
+
+ CL_ASSERT( p_physp );
+
+ /*
+ We do not mind if this is a result of a set or get - all we want is to update
+ the subnet.
+ */
+ if( osm_log_is_active( p_rcv->p_log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
+ "osm_vla_rcv_process: "
+ "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( !osm_physp_is_valid( p_physp ) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: "
+ "Got invalid port number 0x%X\n",
+ port_num );
+ goto Exit;
+ }
+
+ osm_dump_vl_arb_table( p_rcv->p_log,
+ port_guid, block_num,
+ port_num, p_vla_tbl,
+ OSM_LOG_DEBUG );
+
+ if ( (block_num < 1) || (block_num > 4) )
+ {
+ osm_log( p_rcv->p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_process: "
+ "Got invalid block number 0x%X\n",
+ block_num );
+ goto Exit;
+ }
+ osm_physp_set_vla_tbl( p_physp, p_vla_tbl, block_num);
+
+ Exit:
+ cl_plock_release( p_rcv->p_lock );
+
+ OSM_LOG_EXIT( p_rcv->p_log );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osm_vl_arb_rcv_ctrl.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/*
+ * Abstract:
+ * Implementation of osm_vla_rcv_ctrl_t.
+ * This object represents the Vl Arbitration request controller object.
+ * This object is part of the opensm family of objects.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.4 $
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <string.h>
+#include <opensm/osm_vl_arb_rcv_ctrl.h>
+#include <opensm/osm_msgdef.h>
+
+/**********************************************************************
+ **********************************************************************/
+void
+__osm_vla_rcv_ctrl_disp_callback(
+ IN void *context,
+ IN void *p_data )
+{
+ /* ignore return status when invoked via the dispatcher */
+ osm_vla_rcv_process( ((osm_vla_rcv_ctrl_t*)context)->p_rcv,
+ (osm_madw_t*)p_data );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_construct(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+ memset( p_ctrl, 0, sizeof(*p_ctrl) );
+ p_ctrl->h_disp = CL_DISP_INVALID_HANDLE;
+}
+
+/**********************************************************************
+ **********************************************************************/
+void
+osm_vla_rcv_ctrl_destroy(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl )
+{
+ CL_ASSERT( p_ctrl );
+ cl_disp_unregister( p_ctrl->h_disp );
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_api_status_t
+osm_vla_rcv_ctrl_init(
+ IN osm_vla_rcv_ctrl_t* const p_ctrl,
+ IN osm_vla_rcv_t* const p_rcv,
+ IN osm_log_t* const p_log,
+ IN cl_dispatcher_t* const p_disp )
+{
+ ib_api_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( p_log, osm_vla_rcv_ctrl_init );
+
+ osm_vla_rcv_ctrl_construct( p_ctrl );
+ p_ctrl->p_log = p_log;
+
+ p_ctrl->p_rcv = p_rcv;
+ p_ctrl->p_disp = p_disp;
+
+ p_ctrl->h_disp = cl_disp_register(
+ p_disp,
+ OSM_MSG_MAD_VL_ARB,
+ __osm_vla_rcv_ctrl_disp_callback,
+ p_ctrl );
+
+ if( p_ctrl->h_disp == CL_DISP_INVALID_HANDLE )
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osm_vla_rcv_ctrl_init: ERR 4001: "
+ "Dispatcher registration failed\n" );
+ status = IB_INSUFFICIENT_RESOURCES;
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( p_log );
+ return( status );
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: st.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+
+/* static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible"; */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <string.h>
+#include <opensm/st.h>
+
+#ifdef _WIN32
+#include <malloc.h>
+#endif
+
+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 -1; /* 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 */
+
+ 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);
+ 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;
+}
+
--- /dev/null
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE $(NTMAKEENV)\makefile.def\r
--- /dev/null
+!if $(FREEBUILD)\r
+TARGETNAME=osmtest\r
+!else\r
+TARGETNAME=osmtestd\r
+!endif\r
+\r
+!if !defined(WINIBHOME)\r
+WINIBHOME=..\..\..\..\r
+!endif\r
+\r
+LIBPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+\r
+!if defined(OSM_TARGET)\r
+TARGETPATH=$(OSM_TARGET)\bin\user\obj$(BUILD_ALT_DIR)\r
+!else\r
+TARGETPATH=$(WINIBHOME)\bin\user\obj$(BUILD_ALT_DIR)\r
+!endif\r
+\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+OVR_DIR=..\addon\r
+\r
+\r
+SOURCES=\\r
+ osmt_slvl_vl_arb.c \\r
+ osmt_service.c \\r
+ osmt_multicast.c \\r
+ osmt_inform.c \\r
+ osmtest.c \\r
+ main.c \r
+\r
+OSM_HOME=..\r
+\r
+TARGETLIBS=\\r
+!if $(FREEBUILD)\r
+ $(LIBPATH)\*\ibal.lib \\r
+ $(LIBPATH)\*\complib.lib \\r
+ $(TARGETPATH)\*\osmv_ibal.lib \\r
+ $(TARGETPATH)\*\opensm_ibal.lib\r
+\r
+!else\r
+ $(LIBPATH)\*\ibald.lib \\r
+ $(LIBPATH)\*\complibd.lib \\r
+ $(TARGETPATH)\*\osmv_ibald.lib \\r
+ $(TARGETPATH)\*\opensm_ibald.lib\r
+!endif\r
+\r
+#DO NOT TOUCH the order of search path , until ib_types.h merging process will be done\r
+INCLUDES= \\r
+ $(OSM_HOME)\osmtest\include; \\r
+ $(OSM_HOME)\include; \\r
+ $(OSM_HOME); \\r
+ $(WINIBHOME)\inc; \\r
+ $(WINIBHOME)\inc\user;\r
+\r
+# Could be any special flag needed for this project \r
+USER_C_FLAGS=$(USER_C_FLAGS) /MD\r
+#Add preproccessor definitions\r
+C_DEFINES=$(C_DEFINES) -DWIN32 -D__WIN__ -D__i386__ -Dinline=__inline -DMT_LITTLE_ENDIAN -DOSM_VENDOR_INTF_AL\r
+C_DEFINES=$(C_DEFINES) -I.. -DHAVE_CONFIG_H\r
+!if !$(FREEBUILD)\r
+#C_DEFINES=$(C_DEFINES) -D_DEBUG -DDEBUG -DDBG\r
+C_DEFINES=$(C_DEFINES) \r
+!endif\r
+\r
+LINKER_FLAGS= $(LINKER_FLAGS)\r
+MSC_WARNING_LEVEL= /W3\r
+\r
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: error.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of error code ranges for the various osmtest modules.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+
+/*
+ osmtest object
+ 0x0100 - 0x01FF
+
+ parser object
+ 0x0200 - 0x02FF
+
+ osmtest object
+ 0x0300 - 0x03FF
+
+*/
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_inform.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#ifndef __OSMT_INFORM__
+#define __OSMT_INFORM__
+
+#ifdef OSM_VENDOR_INTF_MTL
+#include <vendor/osm_vendor_mlx_inout.h>
+#include <ib_mgt.h>
+#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__ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_mtl_regular_qp.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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 <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+
+
+#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
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmtest.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.6 $
+ */
+
+#ifndef _OSMTEST_H_
+#define _OSMTEST_H_
+
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+#include <vendor/osm_vendor_sa_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+#include "osmtest_base.h"
+#include "osmtest_subnet.h"
+
+/****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;
+ 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;
+} 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;
+ 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_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmtest_base.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+#ifndef _OSMTEST_BASE_H_
+#define _OSMTEST_BASE_H_
+
+#ifndef __WIN__
+#include <limits.h>
+#else
+#include <vendor/winosm_common.h>
+#endif
+
+#define OSMTEST_MAX_LINE_LEN 120
+#ifdef WIN32
+#define OSMTEST_FILE_PATH_MAX 4096
+#else
+#define OSMTEST_FILE_PATH_MAX PATH_MAX
+#endif
+
+#define STRESS_SMALL_RMPP_THR 100000
+/*
+ Take long times when quering 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
+
+extern const char *const p_file;
+
+#endif /* _OSMTEST_BASE_H_ */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmtest_subnet.h 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Declaration of osmtest_t.
+ * This object represents the OSMTest Test object.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef _OSMTEST_SUBNET_H_
+#define _OSMTEST_SUBNET_H_
+
+#include <stdlib.h>
+#include <complib/cl_qmap.h>
+#include <opensm/osm_log.h>
+#include <vendor/osm_vendor_api.h>
+#include <opensm/osm_mad_pool.h>
+#include <opensm/osm_helper.h>
+
+
+/****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
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: main.c 1940 2009-02-11 10:14:39Z tzachid $
+ */
+
+/*
+ * Abstract:
+ * Command line interface for osmtest.
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.3 $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <complib/cl_debug.h>
+#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 GUID_ARRAY_SIZE 64
+#define OSMT_DEFAULT_RETRY_COUNT 3
+#define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000
+#define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10
+
+/**********************************************************************
+ **********************************************************************/
+boolean_t
+osmt_is_debug(void)
+{
+#if defined( _DEBUG_ )
+ return TRUE;
+#else
+ return FALSE;
+#endif /* defined( _DEBUG_ ) */
+}
+
+/**********************************************************************
+ **********************************************************************/
+ib_net64_t
+get_port_guid(
+ IN osmtest_t *p_osm, uint64_t port_guid,
+ IN boolean_t is_service)
+{
+ uint32_t i;
+ uint32_t choice = 0;
+ char junk[128];
+ boolean_t done_flag = FALSE;
+ ib_api_status_t status;
+ uint32_t num_ports = GUID_ARRAY_SIZE;
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
+
+ /*
+ 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 defined ( OSM_VENDOR_INTF_OPENIB )
+ /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
+ if ( port_guid == 0 )
+ {
+ printf("Using default GUID 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
+ return( attr_array[0].port_guid );
+ }
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ /* If port_guid is 0, and we are in windows - find the first port with link_state != DOWN and
+ use it as default port. */
+ if ( port_guid == 0 )
+ {
+ for ( i = 0; i < num_ports; i++ )
+ {
+ if (attr_array[i].link_state > IB_LINK_DOWN)
+ {
+ /* Use this port */
+ printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[i].port_guid));
+ return( attr_array[i].port_guid );
+ }
+ }
+ /* If we are running as a service, and all ports are down we return the
+ first port (we can't open a window, as a service)*/
+ if (is_service) {
+ return( attr_array[0].port_guid );
+ }
+ }
+
+ /* More than one possible port - list all ports and let the user to choose. */
+ while( done_flag == FALSE )
+ {
+ printf( "\nChoose a local port number with which to bind:\n\n" );
+ /* If this is gen2 code - then port 0 has details of the default port used.
+ no need to print it.
+ If this is not gen2 code - need to print details of all ports. */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ for( i = 1; i < num_ports; i++ )
+ {
+ printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
+ i, cl_ntoh64( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i-1 );
+# else
+ 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( attr_array[i].port_guid ),
+ attr_array[i].lid,
+ ib_get_port_state_str( attr_array[i].link_state ) );
+ }
+ printf( "\nEnter choice (1-%u): ", i );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+
+ fflush( stdout );
+ if (scanf( "%u", &choice ))
+ {
+ /* If gen2 code - choice can be between 1 to num_ports-1
+ if not gen2 code - choice can be between 1 to num_ports */
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ if( choice >= num_ports )
+# else
+ if( choice > num_ports || choice < 1 )
+#endif /* OSM_VENDOR_INTF_OPENIB */
+ {
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ else
+ {
+ done_flag = TRUE;
+ }
+ }
+ else
+ {
+ /* get rid of the junk in the selection line */
+ scanf( "%s", junk );
+ printf("\nError: Lame choice!\n");
+ fflush( stdin );
+ }
+ }
+#if defined ( OSM_VENDOR_INTF_OPENIB )
+ printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));
+ return( attr_array[choice].port_guid );
+# else
+ return( attr_array[choice - 1].port_guid );
+#endif /* OSM_VENDOR_INTF_OPENIB */
+}
+/**********************************************************************
+ **********************************************************************/
+void show_usage(void);
+
+void
+show_usage( )
+{
+ printf
+ ( "\n------- osmtest - Usage and options ----------------------\n" );
+ printf( "Usage: osmtest [options]\n" );
+ printf( "Options:\n" );
+ printf( "-f <c|a|v|s|e|f|m|q|t>\n"
+ "--flow <c|a|v|s|e|f|m|q|t>\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, un-registration and lease.\n"
+ " e = run event forwarding test.\n"
+ " f = flood the SA with queries accoring to the stress mode.\n"
+ " m = multicast flow.\n"
+ " q = QoS info - VLArb and SLtoVL tables.\n"
+ " t = run trap 64/65 flow. This flow requires running of external tool.\n"
+ " (default is all but QoS).\n\n" );
+ printf( "-w <trap_wait_time>\n"
+ "--wait <trap_wait_time>\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" );
+ printf( "-d <number>\n"
+ "--debug <number>\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"
+ " -d3 - Use mem tracking.\n"
+ " Without -d, no debug options are enabled.\n\n" );
+ printf( "-m <LID in hex>\n"
+ "--max_lid <LID in hex>\n"
+ " This option specifies the maximal LID number to be searched\n"
+ " for during inventory file build (default to 100).\n");
+ printf( "-g <GUID in hex>\n"
+ "--guid <GUID in hex>\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"
+ " Without -g, osmtest displays a menu of possible\n"
+ " port GUIDs and waits for user input.\n\n" );
+ printf( "-h\n"
+ "--help\n" " Display this usage info then exit.\n\n" );
+ printf( "-i <filename>\n"
+ "--inventory <filename>\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 the -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 response SA queries .\n"
+ " -s2 - Multi-MAD (RMPP) response SA queries.\n"
+ " -s3 - Multi-MAD (RMPP) Path Record SA queries.\n"
+ " Without -s, stress testing is not performed.\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 vs. OpenSM MC.\n"
+ " Multiple mode - Could be run with other apps using MC vs.\n"
+ " OpenSM."
+ " Without -M, default flow testing is performed.\n\n" );
+
+ printf( "-t <milliseconds>\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 <flags>\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" );
+}
+
+/**********************************************************************
+ **********************************************************************/
+void show_menu(void);
+
+void
+show_menu( )
+{
+ printf( "\n------- Interactive Menu -------\n" );
+ printf( "X - Exit.\n\n" );
+}
+void OsmReportState(IN const char *p_str)
+{
+}
+
+/**********************************************************************
+ **********************************************************************/
+int OSM_CDECL
+main( int argc,
+ char *argv[] )
+{
+ static osmtest_t osm_test;
+ osmtest_opt_t opt = { 0 };
+ ib_net64_t guid = 0;
+ int max_lid = 100;
+ ib_api_status_t status;
+ uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
+ char flow_name[64];
+ boolean_t mem_track = FALSE;
+ uint32_t next_option;
+ const char *const short_option = "f:l:m:M:d:g:s:t:i:cvVh";
+
+ /*
+ * 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'},
+ {"help", 0, NULL, 'h'},
+ {"stress", 1, NULL, 's'},
+ {"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 */
+ };
+
+ 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.flow = 0; /* run all validation tests */
+ 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 = 1;
+ } else if (!strcmp("v",optarg)) {
+ strcpy(flow_name, "Validate Inventory");
+ opt.flow = 2;
+ } else if (!strcmp("s",optarg)) {
+ strcpy(flow_name, "Services Registration");
+ opt.flow = 3;
+ } else if (!strcmp("e",optarg)) {
+ strcpy(flow_name, "Event Forwarding");
+ opt.flow = 4;
+ } else if (!strcmp("f",optarg)) {
+ strcpy(flow_name, "Stress SA");
+ opt.flow = 5;
+ } else if (!strcmp("m",optarg)) {
+ strcpy(flow_name, "Multicast");
+ opt.flow = 6;
+ } else if (!strcmp("q",optarg)) {
+ strcpy(flow_name, "QoS: VLArb and SLtoVL");
+ opt.flow = 7;
+ } else if (!strcmp("t", optarg)) {
+ strcpy(flow_name, "Trap 64/65");
+ opt.flow = 8;
+ } else if (!strcmp("a",optarg)) {
+ strcpy(flow_name, "All Validations");
+ opt.flow = 0;
+ } else {
+ printf( "\nError: un-known 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 = 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( "\tGUID 0x%016" PRIx64 "\n", 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;
+ default:
+ printf( "Unknown value %u (ignored)\n", opt.stress );
+ opt.stress = 0;
+ break;
+ }
+ break;
+
+ case 'M':
+ /*
+ * Perform stress 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 3:
+ printf( "Use Mem Tracking.\n" );
+ mem_track = TRUE;
+ break;
+ 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( "\t\t\t\tVerbose option -vf (log flags = 0x%X)\n",
+ log_flags );
+ break;
+
+ case -1:
+ printf( "Done with args\n" );
+ break;
+
+ default: /* something wrong */
+ abort( );
+ }
+
+ }
+ while( next_option != -1 );
+
+ printf( "\tFlow = %s\n", flow_name );
+
+ if (mem_track) __cl_mem_track(TRUE);
+
+
+ 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 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,1))) {
+ 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, (uint16_t)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 );
+
+ if (mem_track) cl_mem_display();
+
+ Exit:
+ return ( status );
+}
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_inform.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#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
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <vendor/osm_vendor_mlx_hca.h>
+#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, osmt_bind_inform_qp );
+
+ port_guid = p_osmt->local_port.port_guid;
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: "
+ "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,
+ "osmt_bind_inform_qp: "
+ "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,
+ "osmt_bind_inform_qp: 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,
+ "osmt_bind_inform_qp: 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,
+ "osmt_bind_inform_qp: "
+ "Initialized QP:0x%X in VAPI Mode\n",
+ p_qp_ctx->qp_bind_hndl.qp_id
+ );
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_bind_inform_qp: " "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,
+ "osmt_bind_inform_qp: 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_unbind_inform_qp );
+
+ 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,
+ "osmt_unbind_inform_qp: "
+ "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, osmt_reg_unreg_inform_info );
+
+ /* 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,
+ "osmt_reg_unreg_inform_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,
+ "osmt_reg_unreg_inform_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,
+ "osmt_reg_unreg_inform_info: ERR 0120: "
+ "Error posting recv bufs\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: ERR 0121: "
+ "Error Preparing AVH (%s)\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: 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,
+ "osmt_reg_unreg_inform_info: 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,
+ "osmt_reg_unreg_inform_info: 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,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: 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,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: "
+ "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,
+ "osmt_reg_unreg_inform_info: 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, osmt_send_trap_wait_for_forward );
+
+ osm_log( p_log, OSM_LOG_INFO,
+ "osmt_send_trap_wait_for_forward: "
+ "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,
+ "osmt_send_trap_wait_for_forward: ERR 0127: "
+ "Error posting recv bufs\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "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; */
+
+ if( osm_log_is_active( p_log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "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,
+ "osmt_send_trap_wait_for_forward: 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,
+ "osmt_send_trap_wait_for_forward: ERR 0129: "
+ "Error Preparing AVH (%s)\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "Prepared AVH\n");
+
+ osm_log( p_log, OSM_LOG_DEBUG,
+ "osmt_send_trap_wait_for_forward: "
+ "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,
+ "osmt_send_trap_wait_for_forward: ERR 0130: "
+ "Timeout receiving mad (%s)\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_TIMEOUT;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: 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,
+ "osmt_send_trap_wait_for_forward: "
+ "Received the Report!\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_send_trap_wait_for_forward: 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,
+ "osmt_send_trap_wait_for_forward: 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, osmt_trap_wait );
+
+ osm_log( p_log, OSM_LOG_INFO,
+ "osmt_trap_wait: "
+ "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,
+ "osmt_trap_wait: ERR 0130: "
+ "Timeout receiving mad (%s)\n",
+ VAPI_strerror_sym(vapi_ret) );
+ status = IB_TIMEOUT;
+ }
+ else
+ {
+ osm_log( p_log, OSM_LOG_ERROR,
+ "osmt_trap_wait: 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,
+ "osmt_trap_wait: "
+ "Received the Report!\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_trap_wait: 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,
+ "osmt_trap_wait: 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 match the sent one
+ *
+ */
+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, osmt_run_inform_info_flow);
+
+ /* 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,
+ "osmt_run_inform_info_flow:"
+ "Error during UnSubscribe: (%s)\n",
+ ib_get_err_str( status ));
+ goto Exit;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_inform_info_flow:"
+ "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,
+ "osmt_run_inform_info_flow:"
+ "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,
+ "osmt_run_inform_info_flow:"
+ "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,
+ "osmt_run_inform_info_flow:"
+ "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, osmt_run_trap64_65_flow);
+
+ /* 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,
+ "osmt_run_trap64_65_flow: ERR 0127: "
+ "Error posting recv bufs for trap 64\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_run_trap64_65_flow: "
+ "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 reveive the report */
+ GRH_LEN + MAD_BLOCK_SIZE,
+ 1) != 1) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_trap64_65_flow: ERR 0127: "
+ "Error posting recv bufs for trap 65\n");
+ status = IB_ERROR;
+ goto Exit;
+ }
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_run_trap64_65_flow: "
+ "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,
+ "osmt_run_trap64_65_flow:"
+ "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,
+ "osmt_run_trap64_65_flow:"
+ "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 */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+#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: osmt_mtl_regular_qp.c 571 2007-01-25 12:58:44Z sleybo $
+ *
+ * Authors:
+ * Eitan Zahavi
+ *
+ * Changes:
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <mtl_common.h>
+#include <vapi.h>
+#include <evapi.h>
+#include <vapi_common.h>
+#include <ib_defs.h>
+#include <osmt_mtl_regular_qp.h>
+#include <complib/cl_types.h>
+/*
+ * 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)(uintn_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)(uintn_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)(uintn_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 */
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_multicast.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * Abstract:
+ * Implementation of Multicast Member testing flow..
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#include <complib/cl_map.h>
+#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;
+ user.attr_offset = ib_get_attr_offset(sizeof(*mcast_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;
+
+ /* 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,
+ "__osmt_print_all_multicast_records: 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,
+ "__osmt_print_all_multicast_records: 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, osmt_query_mcast );
+
+ /*
+ * 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;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+
+ 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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: 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,
+ "osmt_query_mcast: 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,
+ "osmt_query_mcast: "
+ "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,
+ "osmt_query_mcast: "
+ "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 ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_mcast: ERR 0265: "
+ "MCG MGIDs are the same - invalid MGID : 0x%016" PRIx64 " 0x%016"
+ PRIx64 "\n",
+ cl_ntoh64(p_rec->mgid.unicast.prefix),
+ cl_ntoh64(p_rec->mgid.unicast.interface_id));
+ 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,
+ "osmt_query_mcast: 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,
+ "osmt_query_mcast: 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, osmt_send_mcast_request );
+
+ /*
+ * 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,
+ "osmt_send_mcast_request: 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;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ } else if (is_set == 0xff)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_send_mcast_request: 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;
+ user.attr_offset = ib_get_attr_offset( sizeof( ib_member_rec_t ) );
+ }
+
+ /* 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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_send_mcast_request: 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,
+ "osmt_send_mcast_request: 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,
+ "osmt_send_mcast_request: "
+ "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(0xFE80000000000000ULL);
+
+ /* 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_LINK_WIDTH_ACTIVE_4X;
+ /* 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 - implicitlly 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.
+ ***********************************************************************/
+
+/* The following macro can be used only within the osmt_run_mcast_flow() function */
+#define IS_IPOIB_MGID(p_mgid) \
+ ( !memcmp(&osm_ipoib_good_mgid, (p_mgid), sizeof(osm_ipoib_good_mgid)) || \
+ !memcmp(&osm_ts_ipoib_good_mgid, (p_mgid), sizeof(osm_ts_ipoib_good_mgid)) )
+
+ib_api_status_t
+osmt_run_mcast_flow( IN osmtest_t * const p_osmt ) {
+ ib_api_status_t status;
+ ib_member_rec_t mc_req_rec;
+ ib_member_rec_t *p_mc_res;
+ ib_sa_mad_t res_sa_mad;
+ 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;
+ boolean_t ReachedMlidLimit = FALSE;
+ 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 */
+ ib_member_rec_t* p_recvd_rec;
+ 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 */
+ },
+ };
+ 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 */
+ },
+ };
+ 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, osmt_run_mcast_flow );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "GetTable of all current MCGs...\n"
+ );
+ status = osmt_query_mcast( p_osmt );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 2FF "
+ "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);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_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,
+ "osmt_run_mcast_flow (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,
+ "osmt_run_mcast_flow: "
+ "Non-IPoIB MC Groups exist: mgid=0x%016" PRIx64 ":0x%016" PRIx64 "\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) );
+ mcg_outside_test_cnt++;
+ }
+
+ p_mgrp = (osmtest_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Joining an existing IPoIB multicast group\n");
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Sent Join request with :\n\t\tport_gid=0x%016"PRIx64
+ ":0x%016" PRIx64 ", mgid=0x%016" PRIx64 ":0x%016" PRIx64
+ "\n\t\tjoin state= 0x%x, response is : %s\n",
+ cl_ntoh64(mc_req_rec.port_gid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.port_gid.unicast.interface_id),
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+ (mc_req_rec.scope_state & 0x0F),
+ ib_get_err_str(status));
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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 */
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+ osm_log(&p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: ERR 02EF: "
+ "Query as Full Member of already existing ipoib group 0x%016"
+ PRIx64 ":0x%016" PRIx64 " has failed\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E0 "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 0xee, /* User Defined query Get */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E4 "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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 | intentionaly 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02EE: "
+ "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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 */
+ 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02ED: "
+ "Expectedd REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ 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;
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficient comp mask - flow label (o15.0.1.3)...\n"
+ );
+
+ /* 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 |
+ IB_MCR_COMPMASK_SL |
+ /* IB_MCR_COMPMASK_FLOW | intentionaly 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02EC: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with insufficient comp mask - tclass (o15.0.1.3)...\n"
+ );
+
+ /* 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 |
+ 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02EA: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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 */
+ 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 | intentionaly 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 | intentionaly missed to raise the error */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02E9: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* o15.0.1.8: */
+ /* - Request join with irrelevant RATE : get a ERR_INSUFFICIENT_COMPONENTS */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with unrealistic rate (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_12X |
+ 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Check Valid value which is unreasonable now */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Join with unrealistic rate 120GB (o15.0.1.8)...\n"
+ );
+
+ /* impossible requested rate */
+ mc_req_rec.rate =
+ IB_PATH_RECORD_RATE_120_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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Check Valid value which is unreasonable now */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Checking above max value of MTU which is impossible */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Checking below min value of MTU which is impossible */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip service level (o15.0.1.4)...\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* 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 |
+ /* 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02A8: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ 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,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow (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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip Qkey and Pkey (o15.0.1.4)...\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02A7: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ 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,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 skip TClass (o15.0.1.4)...\n"
+ );
+
+ osmt_init_mc_query_rec(p_osmt, &mc_req_rec);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* 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 |
+ 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR ||
+ (( ib_net16_t ) (res_sa_mad.status & IB_SMP_STATUS_MASK )) !=
+ IB_SA_MAD_STATUS_INSUF_COMPS) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02A6: "
+ "Expected REMOTE ERROR IB_SA_MAD_STATUS_INSUF_COMPS got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0 valid Set several options :\n\t\t"
+ "First above min RATE, Second less than max RATE\n\t\t"
+ "Third above min MTU, Second 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 */
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ 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_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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_12X |
+ 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert( &test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* o15.0.1.5: */
+ /* - Check the returned MGID is valid. (p 804) */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: ERR 0209: "
+ "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n",
+ cl_ntoh64( p_mc_res->mgid.unicast.prefix ),
+ cl_ntoh64( p_mc_res->mgid.unicast.interface_id )
+ );
+ 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,
+ "osmt_run_mcast_flow: "
+ "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);
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+
+ /* 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);
+
+ 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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.mgid = good_mgid;
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given valid MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " (o15.0.1.6)...\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ /* Before creation, need to check that this group doesn't exist */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1, /* join */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID))
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "Now creating group with given valid MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " (o15.0.1.6)...\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0211: "
+ "Failed to create MCG for MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " (o15.0.1.6) - got %s/%s\n",
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad)) );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: ERR 0212: "
+ "Validating MGID failed. MGID:0x%016" PRIx64 ":%016" PRIx64 "\n",
+ cl_ntoh64( p_mc_res->mgid.unicast.prefix ),
+ cl_ntoh64( p_mc_res->mgid.unicast.interface_id )
+ );
+ 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,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MGID=0xFA..... (o15.0.1.6)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+ mc_req_rec.mgid.raw[0] = 0xFA;
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Change the mgid prefix - get back ERR_REQ_INVALID */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Change the scope to reserved - get back VALID REQ */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking local scope with full member \n\t\tand valid mgid 0x%016"
+ PRIx64 ":0x%016" PRIx64 " ... (o15.0.1.6)...\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id));
+
+ 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 0216: "
+ "Failed to create MCG for MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " - got %s/%s\n",
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* Change the flags to invalid value 0x2 - get back INVALID REQ */
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking invalid flags=0xFF 22 ... (o15.0.1.6)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* o15.0.1.7 - implicitlly checked during the prev steps. */
+ /* o15.0.1.8 - implicitlly 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,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Lets try a valid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ) );
+ cl_map_insert( &test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* Lets try another invalid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID with invalid join state (o15.0.1.9)...\n"
+ );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+ /* We have created a new MCG so now we need different mgid when cresting 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Lets try another valid join scope state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking new MGID creation with valid join state (o15.0.1.9)...\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,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow: "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+
+ /* 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 */
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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, /* User Defined query */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02CC: "
+ "Failed to join MCG with valid req, returned status = %s\n",
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ));
+ 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,
+ "osmt_run_mcast_flow: "
+ "Checking Retry of existing MGID - See JoinState update (o15.0.1.11)...\n"
+ );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.scope_state = 0x22; /* link-local scope, send only member */
+
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02CD: "
+ "Failed to update existing MGID - got %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow: "
+ "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;
+ /* link-local scope, non member (so we should not be able to delete) */
+ /* but the FullMember bit should be gone */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Partially delete JoinState (o15.0.1.14)...\n"
+ );
+ mc_req_rec.scope_state = 0x22;
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if ((status != IB_SUCCESS) || (p_mc_res->scope_state != 0x21))
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02CF: "
+ "Failed to partially update JoinState : %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C0: "
+ "Failed to update existing MCG - got %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C2: "
+ "Failed to update existing MGID - got %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C4: "
+ "Failed to update existing MGID - got %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ goto Exit;
+ }
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow: "
+ "Checking BAD RATE when connecting to existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+ mc_req_rec.mgid = good_mgid;
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C6: "
+ "Failed to catch BAD RATE joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Try MTU that does not exist in any MCG */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MTU (higher them max) when connecting to "
+ "existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C7: "
+ "Failed to catch BAD RATE (higher them max) joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "Checking BAD MTU (less than min) when connecting "
+ "to existing MGID (o15.0.1.13)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02C8: "
+ "Failed to catch BAD RATE (less them min) joining an exiting MGID: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "Checking partial JoinState delete request - removing NonMember (o15.0.1.14)...\n"
+ );
+
+ mc_req_rec.rate =
+ IB_LINK_WIDTH_ACTIVE_1X |
+ IB_PATH_SELECTOR_GREATER_THAN << 6;
+ 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 */
+ IB_MCR_COMPMASK_RATE_SEL |
+ IB_MCR_COMPMASK_RATE;
+ /* link-local scope, non member (so we should not be able to delete) */
+ /* but the FullMember bit should be gone */
+ mc_req_rec.scope_state = 0x22;
+
+ status = osmt_send_mcast_request( p_osmt, 0,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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 non member & send only member have left */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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,
+ &res_sa_mad );
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02CB: "
+ "Failed to update JoinState during delete: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Validating Join State update remove (o15.0.1.14)...\n"
+ );
+
+ if (p_mc_res->scope_state != 0x25) /* scope is MSB - now only 0x0 so port is removed from MCG */
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02BF: "
+ "Validating JoinState update failed. Expected 0x25 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1, /* join */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status != IB_REMOTE_ERROR)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02BC: "
+ "Succeeded Joining Deleted Group: %s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "Checking BAD Delete of Mgid membership (no prev join) (o15.0.1.15)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) )
+ );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ /* Prepare another MCG for the following tests : */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Checking Create given MGID=0x%016" PRIx64 " : "
+ "0x%016" PRIx64 "\n\t\t(o15.0.1.4)...\n",
+ cl_ntoh64(osm_ipoib_mgid.unicast.prefix),
+ cl_ntoh64(osm_ipoib_mgid.unicast.interface_id) );
+
+ 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 memeber */
+ 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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02BE: "
+ "Failed to create MCG for 0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " - got %s/%s\n",
+ cl_ntoh64(good_mgid.unicast.prefix),
+ cl_ntoh64(good_mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+ goto Exit;
+ }
+
+ /* - Try delete with valid join state */
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_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,
+ "osmt_run_mcast_flow: "
+ "Checking BAD Delete of IPoIB membership (no prev join) (o15.0.1.15)...\n"
+ );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " 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,
+ &res_sa_mad );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if ((status != IB_REMOTE_ERROR) ||
+ (res_sa_mad.status != IB_SA_MAD_STATUS_REQ_INVALID)) {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_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,
+ "osmt_run_mcast_flow: "
+ "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 */
+ 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,
+ &res_sa_mad );
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+ status = osmt_send_mcast_request( p_osmt, 1,
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02E4: "
+ "Expected REMOTE ERROR got:%s/%s\n",
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_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,
+ "osmt_run_mcast_flow (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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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)
+ {
+ 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,
+ &res_sa_mad );
+
+
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: 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*)(&res_sa_mad) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_START "\n" );
+
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: " EXPECTING_ERRORS_END "\n" );
+
+ if (status == IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02A9: "
+ "Successful deletion of remote port guid with local one MGID : "
+ "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+ status = IB_ERROR;
+ goto Exit;
+ }
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02B0: "
+ "Failed to delete mgid with remote port guid MGID : "
+ "0x%016" PRIx64 " : 0x%016" PRIx64 ", Got : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_sa_mad) ) );
+ goto Exit;
+ }
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "Checking Creation of Maximum avaliable Groups (MulticastFDBCap)...\n"
+ );
+ tmp_mlid = cl_ntoh16(max_mlid) - cnt;
+
+ while (tmp_mlid > 0 && !ReachedMlidLimit) {
+ 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,
+ &res_sa_mad );
+
+ p_mc_res = ib_sa_mad_get_payload_ptr(&res_sa_mad);
+ if (status != IB_SUCCESS)
+ {
+
+ if (cur_mlid > cl_ntoh16(max_mlid))
+ {
+
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow : ERR 2E1 "
+ "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 (( res_sa_mad.status & IB_SMP_STATUS_MASK ) == IB_SA_MAD_STATUS_NO_RESOURCES) {
+ /* You can quitly exit the loop since no available mlid in SA DB
+ i.e. reached the maximum valiad avalable mlid */
+ ReachedMlidLimit = TRUE;
+ }
+ }
+ else
+ {
+ cur_mlid = cl_ntoh16(p_mc_res->mlid);
+ /* Save the mlid created in test_created_mlids map */
+ p_recvd_rec = (ib_member_rec_t*)ib_sa_mad_get_payload_ptr( &res_sa_mad );
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_run_mcast_flow : "
+ "Created MGID:0x%016" PRIx64 " : "
+ "0x%016" PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64( p_recvd_rec->mgid.unicast.prefix ),
+ cl_ntoh64( p_recvd_rec->mgid.unicast.interface_id ),
+ cl_ntoh16( p_recvd_rec->mlid ));
+ cl_map_insert(&test_created_mlids,
+ cl_ntoh16(p_recvd_rec->mlid), p_recvd_rec );
+ }
+ 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,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow (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,
+ "osmt_run_mcast_flow : "
+ "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,
+ "osmt_run_mcast_flow : "
+ "Sending request to delete MGID : 0x%016" PRIx64
+ " : 0x%016" PRIx64 ", scope_state : 0x%02X\n",
+ cl_ntoh64(mc_req_rec.mgid.unicast.prefix),
+ cl_ntoh64(mc_req_rec.mgid.unicast.interface_id),
+ mc_req_rec.scope_state );
+ status = osmt_send_mcast_request( p_osmt, 0, /* delete flag */
+ &mc_req_rec,
+ comp_mask,
+ &res_sa_mad );
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_mcast_flow: ERR 02FF: "
+ "Failed to delete MGID : 0x%016" PRIx64 " : 0x%016" PRIx64
+ " ,\n\t\t it is not our MCG, Status : %s/%s\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ ib_get_err_str( status ),
+ ib_get_mad_status_str( (ib_mad_t*)(&res_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,
+ "osmt_run_mcast_flow: 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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: "
+ "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,
+ "osmt_run_mcast_flow: ERR 02FE: "
+ "Wasn't able to erase mgrp with MGID:0x%016" PRIx64 " : 0x%016"
+ PRIx64 " MLID:0x%04X\n",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
+ mlid );
+ got_error = TRUE;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_run_mcast_flow: "
+ "Still exists %s MGID:0x%016" PRIx64 " : 0x%016" PRIx64 "\n",
+ (IS_IPOIB_MGID(&p_mgrp->mcmember_rec.mgid)) ? "IPoIB" : "non-IPoIB",
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
+ cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id) );
+ }
+ 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;
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_service.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.1 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#else
+#include <time.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#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, osmt_register_service );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service: "
+ "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 = 0;
+ 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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service: 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,
+ "osmt_register_service: 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,
+ "osmt_register_service: "
+ "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, osmt_register_service_with_full_key );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service_with_full_key: "
+ "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 = 0;
+ 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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_full_key: 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,
+ "osmt_register_service_with_full_key: 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,
+ "osmt_register_service_with_full_key: "
+ "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,
+ "osmt_register_service_with_full_key: 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, osmt_register_service_with_data );
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_register_service_with_data: "
+ "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 = 0;
+ 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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ /* Dump to Service Data b4 send */
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_register_service_with_data:"
+ "Dumping service data b4 send\n");
+ osm_dump_service_record(&p_osmt->log,&svc_rec,OSM_LOG_VERBOSE);
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_register_service_with_data: 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,
+ "osmt_register_service_with_data: 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,
+ "osmt_register_service_with_data: "
+ "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,
+ "osmt_register_service_with_data: "
+ "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;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_id );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id_and_name: "
+ "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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: 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 )
+ {
+ 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,
+ "osmt_get_service_by_id_and_name: "
+ "IS EXPECTED ERROR ^^^^\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id_and_name: 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,
+ "osmt_get_service_by_id_and_name: "
+ "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,
+ "osmt_get_service_by_id_and_name: "
+ "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,
+ "osmt_get_service_by_id_and_name: "
+ "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, osmt_get_service_by_id );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_id: "
+ "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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: 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,
+ "osmt_get_service_by_id: "
+ "IS EXPECTED ERROR ^^^^\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_id: 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,
+ "osmt_get_service_by_id: 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,
+ "osmt_get_service_by_id: "
+ "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,
+ "osmt_get_service_by_id: "
+ "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;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmt_get_service_by_name_and_key );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ char buf_service_key[33];
+
+ sprintf(buf_service_key,
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ 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]);
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name_and_key: "
+ "Getting service record: name: %s and key: %s\n",
+ sr_name, buf_service_key );
+ }
+
+ /*
+ * 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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: 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 )
+ {
+ 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,
+ "osmt_get_service_by_name_and_key: "
+ "IS EXPECTED ERROR ^^^^\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name_and_key: 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,
+ "osmt_get_service_by_name_and_key: "
+ "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,
+ "osmt_get_service_by_name_and_key: "
+ "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,
+ "osmt_get_service_by_name_and_key: "
+ "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, osmt_get_service_by_name );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_service_by_name: "
+ "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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: 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,
+ "osmt_get_service_by_name: "
+ "IS EXPECTED ERROR ^^^^\n");
+ status = IB_SUCCESS;
+ }
+ else
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_service_by_name: 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,
+ "osmt_get_service_by_name: 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,
+ "osmt_get_service_by_name: "
+ "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,
+ "osmt_get_service_by_name: "
+ "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, osmt_get_all_services_and_check_names );
+
+ /* 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;
+ }
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_get_all_services_and_check_names: "
+ "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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_get_all_services_and_check_names: 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,
+ "osmt_get_all_services_and_check_names: 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,
+ "osmt_get_all_services_and_check_names: "
+ "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,
+ "osmt_get_all_services_and_check_names: "
+ "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,
+ "osmt_get_all_services_and_check_names: "
+ "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,
+ "osmt_get_all_services_and_check_names: "
+ "-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,
+ "osmt_get_all_services_and_check_names: "
+ "-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,
+ "osmt_get_all_services_and_check_names: 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, osmt_delete_service_by_name);
+
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_delete_service_by_name: "
+ "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,
+ "osmt_delete_service_by_name: 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.attr_offset = ib_get_attr_offset( sizeof( ib_service_record_t ) );
+ user.p_attr = &svc_rec;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+ if( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_delete_service_by_name: 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,
+ "osmt_delete_service_by_name: 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,
+ "osmt_delete_service_by_name: 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,
+ "osmt_delete_service_by_name: 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,
+ "osmt_run_service_records_flow: "
+ "IS EXPECTED ERROR ^^^^\n");
+ osm_log( &p_osmt->log, OSM_LOG_INFO,
+ "osmt_delete_service_by_name: "
+ "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, osmt_run_service_records_flow);
+
+ /* Init Service names */
+ for (i = 0; i <= 6; 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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[7] */
+ status = osmt_get_service_by_id(p_osmt, 0, cl_ntoh64(id[7]), &srv_rec);
+ if (status != IB_SUCCESS)
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_run_service_records_flow: ERR 4A20: "
+ "Found service: id: 0x%016" PRIx64 " "
+ "that is invalid\n",
+ id[7] );
+ 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: 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,
+ "osmt_run_service_records_flow: ERR 4A32: "
+ "Failed to delete service name: %s\n",
+ (char*)service_name[6] );
+ goto Exit;
+ }
+
+ Exit:
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
--- /dev/null
+/*
+ * 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 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.
+ *
+ * $Id: osmt_slvl_vl_arb.c 571 2007-01-25 12:58:44Z sleybo $
+ */
+
+
+/*
+ * 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
+ *
+ * Environment:
+ * Linux User Mode
+ *
+ * $Revision: 1.2 $
+ */
+
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <complib/cl_debug.h>
+#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 result,i;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_vl_arb_table );
+
+ result = 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, osmt_query_vl_arb );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_query_vl_arb: "
+ "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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_vl_arb: 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,
+ "osmt_query_vl_arb: 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,
+ "osmt_query_vl_arb: "
+ "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, osmt_query_all_ports_vl_arb );
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_query_all_ports_vl_arb: "
+ "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,
+ "osmt_query_all_ports_vl_arb: 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,
+ "osmt_query_all_ports_vl_arb: 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 result, i;
+ cl_status_t status = IB_SUCCESS;
+
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_slvl_map_table );
+
+ result = 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, osmt_query_slvl_map );
+
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,
+ "osmt_query_slvl_map: "
+ "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;
+
+ status = osmv_query_sa( p_osmt->h_bind, &req );
+
+ if ( status != IB_SUCCESS )
+ {
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,
+ "osmt_query_slvl_map: 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,
+ "osmt_query_slvl_map: 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,
+ "osmt_query_slvl_map: "
+ "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, osmt_query_all_ports_slvl_map );
+
+ /*
+ * Go over all ports that exist in the subnet
+ * get the relevant SLtoVLs
+ */
+
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,
+ "osmt_query_all_ports_slvl_map: "
+ "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,
+ "osmt_query_all_ports_slvl_map: 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,
+ "osmt_query_all_ports_slvl_map: 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,
+ "osmt_query_all_ports_slvl_map: 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, osmt_run_slvl_and_vlarb_records_flow );
+
+ fh = fopen("qos.txt","w");
+
+ /* 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:
+ fclose(fh);
+ OSM_LOG_EXIT( &p_osmt->log );
+ return status;
+}
+
+
--- /dev/null
+/*\r
+ * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * - Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * - Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id: osmtest.c 1928 2009-02-04 15:23:03Z tzachid $\r
+ */\r
+\r
+\r
+/* TODO : Check why we dont free the cl_qmap_items we store when reading DB */\r
+\r
+/*\r
+ * Abstract:\r
+ * Implementation of osmtest_t.\r
+ * This object represents the OSMTest Test object.\r
+ *\r
+ * Environment:\r
+ * Linux User Mode\r
+ *\r
+ * $Revision: 1.10 $\r
+ */\r
+\r
+#ifdef __WIN__\r
+#pragma warning(disable : 4996)\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#ifdef __WIN__\r
+#include <complib/cl_timer.h>\r
+#else\r
+#include <strings.h>\r
+#include <sys/time.h>\r
+#endif\r
+#include <complib/cl_debug.h>\r
+#include "osmtest.h"\r
+\r
+#ifndef __WIN__\r
+#define strnicmp strncasecmp\r
+#endif\r
+\r
+#define POOL_MIN_ITEMS 64\r
+#define GUID_ARRAY_SIZE 64\r
+\r
+typedef enum _osmtest_token_val\r
+{\r
+ OSMTEST_TOKEN_COMMENT = 0,\r
+ OSMTEST_TOKEN_END,\r
+ OSMTEST_TOKEN_DEFINE_NODE,\r
+ OSMTEST_TOKEN_DEFINE_PORT,\r
+ OSMTEST_TOKEN_DEFINE_PATH,\r
+ OSMTEST_TOKEN_DEFINE_LINK,\r
+ OSMTEST_TOKEN_LID,\r
+ OSMTEST_TOKEN_BASE_VERSION,\r
+ OSMTEST_TOKEN_CLASS_VERSION,\r
+ OSMTEST_TOKEN_NODE_TYPE,\r
+ OSMTEST_TOKEN_NUM_PORTS,\r
+ OSMTEST_TOKEN_SYS_GUID,\r
+ OSMTEST_TOKEN_NODE_GUID,\r
+ OSMTEST_TOKEN_PORT_GUID,\r
+ OSMTEST_TOKEN_PARTITION_CAP,\r
+ OSMTEST_TOKEN_DEVICE_ID,\r
+ OSMTEST_TOKEN_REVISION,\r
+ OSMTEST_TOKEN_PORT_NUM,\r
+ OSMTEST_TOKEN_VENDOR_ID,\r
+ OSMTEST_TOKEN_DGID,\r
+ OSMTEST_TOKEN_SGID,\r
+ OSMTEST_TOKEN_DLID,\r
+ OSMTEST_TOKEN_SLID,\r
+ OSMTEST_TOKEN_HOP_FLOW_RAW,\r
+ OSMTEST_TOKEN_TCLASS,\r
+ OSMTEST_TOKEN_NUM_PATH,\r
+ OSMTEST_TOKEN_PKEY,\r
+ OSMTEST_TOKEN_SL,\r
+ OSMTEST_TOKEN_RATE,\r
+ OSMTEST_TOKEN_PKT_LIFE,\r
+ OSMTEST_TOKEN_PREFERENCE,\r
+ OSMTEST_TOKEN_MKEY,\r
+ OSMTEST_TOKEN_SUBN_PREF,\r
+ OSMTEST_TOKEN_BASE_LID,\r
+ OSMTEST_TOKEN_SM_BASE_LID,\r
+ OSMTEST_TOKEN_CAP_MASK,\r
+ OSMTEST_TOKEN_DIAG_CODE,\r
+ OSMTEST_TOKEN_MKEY_LEASE_PER,\r
+ OSMTEST_TOKEN_LOC_PORT_NUM,\r
+ OSMTEST_TOKEN_LINK_WID_EN,\r
+ OSMTEST_TOKEN_LINK_WID_SUP,\r
+ OSMTEST_TOKEN_LINK_WID_ACT,\r
+ OSMTEST_TOKEN_LINK_SPEED_SUP,\r
+ OSMTEST_TOKEN_PORT_STATE,\r
+ OSMTEST_TOKEN_STATE_INFO2,\r
+ OSMTEST_TOKEN_MKEY_PROT_BITS,\r
+ OSMTEST_TOKEN_LMC,\r
+ OSMTEST_TOKEN_LINK_SPEED,\r
+ OSMTEST_TOKEN_MTU_SMSL,\r
+ OSMTEST_TOKEN_VL_CAP,\r
+ OSMTEST_TOKEN_VL_HIGH_LIMIT,\r
+ OSMTEST_TOKEN_VL_ARB_HIGH_CAP,\r
+ OSMTEST_TOKEN_VL_ARB_LOW_CAP,\r
+ OSMTEST_TOKEN_MTU_CAP,\r
+ OSMTEST_TOKEN_VL_STALL_LIFE,\r
+ OSMTEST_TOKEN_VL_ENFORCE,\r
+ OSMTEST_TOKEN_MKEY_VIOL,\r
+ OSMTEST_TOKEN_PKEY_VIOL,\r
+ OSMTEST_TOKEN_QKEY_VIOL,\r
+ OSMTEST_TOKEN_GUID_CAP,\r
+ OSMTEST_TOKEN_SUBN_TIMEOUT,\r
+ OSMTEST_TOKEN_RESP_TIME_VAL,\r
+ OSMTEST_TOKEN_ERR_THRESHOLD,\r
+ OSMTEST_TOKEN_MTU,\r
+ OSMTEST_TOKEN_FROMLID,\r
+ OSMTEST_TOKEN_FROMPORTNUM,\r
+ OSMTEST_TOKEN_TOPORTNUM,\r
+ OSMTEST_TOKEN_TOLID,\r
+ OSMTEST_TOKEN_UNKNOWN\r
+} osmtest_token_val_t;\r
+\r
+typedef struct _osmtest_token\r
+{\r
+ osmtest_token_val_t val;\r
+ size_t str_size;\r
+ const char *str;\r
+} osmtest_token_t;\r
+\r
+const osmtest_token_t token_array[] = {\r
+ {OSMTEST_TOKEN_COMMENT, 1, "#"},\r
+ {OSMTEST_TOKEN_END, 3, "END"},\r
+ {OSMTEST_TOKEN_DEFINE_NODE, 11, "DEFINE_NODE"},\r
+ {OSMTEST_TOKEN_DEFINE_PORT, 11, "DEFINE_PORT"},\r
+ {OSMTEST_TOKEN_DEFINE_PATH, 11, "DEFINE_PATH"},\r
+ {OSMTEST_TOKEN_DEFINE_LINK, 11, "DEFINE_LINK"},\r
+ {OSMTEST_TOKEN_LID, 3, "LID"},\r
+ {OSMTEST_TOKEN_BASE_VERSION, 12, "BASE_VERSION"},\r
+ {OSMTEST_TOKEN_CLASS_VERSION, 13, "CLASS_VERSION"},\r
+ {OSMTEST_TOKEN_NODE_TYPE, 9, "NODE_TYPE"},\r
+ {OSMTEST_TOKEN_NUM_PORTS, 9, "NUM_PORTS"},\r
+ {OSMTEST_TOKEN_SYS_GUID, 8, "SYS_GUID"},\r
+ {OSMTEST_TOKEN_NODE_GUID, 9, "NODE_GUID"},\r
+ {OSMTEST_TOKEN_PORT_GUID, 9, "PORT_GUID"},\r
+ {OSMTEST_TOKEN_PARTITION_CAP, 13, "PARTITION_CAP"},\r
+ {OSMTEST_TOKEN_DEVICE_ID, 9, "DEVICE_ID"},\r
+ {OSMTEST_TOKEN_REVISION, 8, "REVISION"},\r
+ {OSMTEST_TOKEN_PORT_NUM, 8, "PORT_NUM"},\r
+ {OSMTEST_TOKEN_VENDOR_ID, 9, "VENDOR_ID"},\r
+ {OSMTEST_TOKEN_DGID, 4, "DGID"},\r
+ {OSMTEST_TOKEN_SGID, 4, "SGID"},\r
+ {OSMTEST_TOKEN_DLID, 4, "DLID"},\r
+ {OSMTEST_TOKEN_SLID, 4, "SLID"},\r
+ {OSMTEST_TOKEN_HOP_FLOW_RAW, 12, "HOP_FLOW_RAW"},\r
+ {OSMTEST_TOKEN_TCLASS, 6, "TCLASS"},\r
+ {OSMTEST_TOKEN_NUM_PATH, 8, "NUM_PATH"},\r
+ {OSMTEST_TOKEN_PKEY, 4, "PKEY"},\r
+ {OSMTEST_TOKEN_SL, 2, "SL"},\r
+ {OSMTEST_TOKEN_RATE, 4, "RATE"},\r
+ {OSMTEST_TOKEN_PKT_LIFE, 8, "PKT_LIFE"},\r
+ {OSMTEST_TOKEN_PREFERENCE, 10, "PREFERENCE"},\r
+ {OSMTEST_TOKEN_MKEY, 4, "M_KEY"},\r
+ {OSMTEST_TOKEN_SUBN_PREF, 13, "SUBNET_PREFIX"},\r
+ {OSMTEST_TOKEN_BASE_LID, 8, "BASE_LID"},\r
+ {OSMTEST_TOKEN_SM_BASE_LID, 18, "MASTER_SM_BASE_LID"},\r
+ {OSMTEST_TOKEN_CAP_MASK, 15, "CAPABILITY_MASK"},\r
+ {OSMTEST_TOKEN_DIAG_CODE, 9, "DIAG_CODE"},\r
+ {OSMTEST_TOKEN_MKEY_LEASE_PER, 18, "m_key_lease_period"},\r
+ {OSMTEST_TOKEN_LOC_PORT_NUM, 14, "local_port_num"},\r
+ {OSMTEST_TOKEN_LINK_WID_EN, 18, "link_width_enabled"},\r
+ {OSMTEST_TOKEN_LINK_WID_SUP, 20, "link_width_supported"},\r
+ {OSMTEST_TOKEN_LINK_WID_ACT, 17, "link_width_active"},\r
+ {OSMTEST_TOKEN_LINK_SPEED_SUP, 20, "link_speed_supported"},\r
+ {OSMTEST_TOKEN_PORT_STATE, 10, "port_state"},\r
+ {OSMTEST_TOKEN_STATE_INFO2, 10, "state_info2"},\r
+ {OSMTEST_TOKEN_MKEY_PROT_BITS, 3, "mpb"},\r
+ {OSMTEST_TOKEN_LMC, 3, "lmc"},\r
+ {OSMTEST_TOKEN_LINK_SPEED, 10, "link_speed"},\r
+ {OSMTEST_TOKEN_MTU_SMSL, 8, "mtu_smsl"},\r
+ {OSMTEST_TOKEN_VL_CAP, 6, "vl_cap"},\r
+ {OSMTEST_TOKEN_VL_HIGH_LIMIT, 13, "vl_high_limit"},\r
+ {OSMTEST_TOKEN_VL_ARB_HIGH_CAP, 15, "vl_arb_high_cap"},\r
+ {OSMTEST_TOKEN_VL_ARB_LOW_CAP, 14, "vl_arb_low_cap"},\r
+ {OSMTEST_TOKEN_MTU_CAP, 7, "mtu_cap"},\r
+ {OSMTEST_TOKEN_VL_STALL_LIFE, 13, "vl_stall_life"},\r
+ {OSMTEST_TOKEN_VL_ENFORCE, 10, "vl_enforce"},\r
+ {OSMTEST_TOKEN_MKEY_VIOL, 16, "m_key_violations"},\r
+ {OSMTEST_TOKEN_PKEY_VIOL, 16, "p_key_violations"},\r
+ {OSMTEST_TOKEN_QKEY_VIOL, 16, "q_key_violations"},\r
+ {OSMTEST_TOKEN_GUID_CAP, 8, "guid_cap"},\r
+ {OSMTEST_TOKEN_SUBN_TIMEOUT, 14, "subnet_timeout"},\r
+ {OSMTEST_TOKEN_RESP_TIME_VAL, 15, "resp_time_value"},\r
+ {OSMTEST_TOKEN_ERR_THRESHOLD, 15, "error_threshold"},\r
+ {OSMTEST_TOKEN_MTU, 3, "MTU"}, /* must be after the other mtu... tokens. */\r
+ {OSMTEST_TOKEN_FROMLID, 8, "from_lid"},\r
+ {OSMTEST_TOKEN_FROMPORTNUM, 13, "from_port_num"},\r
+ {OSMTEST_TOKEN_TOPORTNUM, 11, "to_port_num"},\r
+ {OSMTEST_TOKEN_TOLID, 6, "to_lid"},\r
+ {OSMTEST_TOKEN_UNKNOWN, 0, ""} /* must be last entry */\r
+};\r
+\r
+#define IB_MAD_STATUS_CLASS_MASK (CL_HTON16(0xFF00))\r
+\r
+static const char ib_mad_status_str_busy[] = "IB_MAD_STATUS_BUSY";\r
+static const char ib_mad_status_str_redirect[] = "IB_MAD_STATUS_REDIRECT";\r
+static const char ib_mad_status_str_unsup_class_ver[] =\r
+"IB_MAD_STATUS_UNSUP_CLASS_VER";\r
+static const char ib_mad_status_str_unsup_method[] =\r
+"IB_MAD_STATUS_UNSUP_METHOD";\r
+static const char ib_mad_status_str_unsup_method_attr[] =\r
+"IB_MAD_STATUS_UNSUP_METHOD_ATTR";\r
+static const char ib_mad_status_str_invalid_field[] =\r
+"IB_MAD_STATUS_INVALID_FIELD";\r
+static const char ib_mad_status_str_no_resources[] =\r
+"IB_SA_MAD_STATUS_NO_RESOURCES";\r
+static const char ib_mad_status_str_req_invalid[] =\r
+"IB_SA_MAD_STATUS_REQ_INVALID";\r
+static const char ib_mad_status_str_no_records[] =\r
+"IB_SA_MAD_STATUS_NO_RECORDS";\r
+static const char ib_mad_status_str_too_many_records[] =\r
+"IB_SA_MAD_STATUS_TOO_MANY_RECORDS";\r
+static const char ib_mad_status_str_invalid_gid[] =\r
+"IB_SA_MAD_STATUS_INVALID_GID";\r
+static const char ib_mad_status_str_insuf_comps[] =\r
+"IB_SA_MAD_STATUS_INSUF_COMPS";\r
+static const char generic_or_str[] = " | ";\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+const char *\r
+ib_get_mad_status_str( IN const ib_mad_t * const p_mad )\r
+{\r
+ static char line[512];\r
+ uint32_t offset = 0;\r
+ ib_net16_t status;\r
+ boolean_t first = TRUE;\r
+\r
+ line[offset] = '\0';\r
+\r
+ status = ( ib_net16_t ) ( p_mad->status & IB_SMP_STATUS_MASK );\r
+\r
+ if( status == 0 )\r
+ {\r
+ strcat( &line[offset], "IB_SUCCESS" );\r
+ return ( line );\r
+ }\r
+\r
+ if( status & IB_MAD_STATUS_BUSY )\r
+ {\r
+ strcat( &line[offset], ib_mad_status_str_busy );\r
+ offset += sizeof( ib_mad_status_str_busy );\r
+ }\r
+ if( status & IB_MAD_STATUS_REDIRECT )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_redirect );\r
+ offset += sizeof( ib_mad_status_str_redirect ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_CLASS_VER )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_unsup_class_ver );\r
+ offset += sizeof( ib_mad_status_str_unsup_class_ver ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_METHOD )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_unsup_method );\r
+ offset += sizeof( ib_mad_status_str_unsup_method ) - 1;\r
+ }\r
+ if( (status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_UNSUP_METHOD_ATTR )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_unsup_method_attr );\r
+ offset += sizeof( ib_mad_status_str_unsup_method_attr ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_INVALID_FIELD ) == IB_MAD_STATUS_INVALID_FIELD )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_invalid_field );\r
+ offset += sizeof( ib_mad_status_str_invalid_field ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+ IB_SA_MAD_STATUS_NO_RESOURCES )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_no_resources );\r
+ offset += sizeof( ib_mad_status_str_no_resources ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+ IB_SA_MAD_STATUS_REQ_INVALID )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_req_invalid );\r
+ offset += sizeof( ib_mad_status_str_req_invalid ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) == IB_SA_MAD_STATUS_NO_RECORDS )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_no_records );\r
+ offset += sizeof( ib_mad_status_str_no_records ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+ IB_SA_MAD_STATUS_TOO_MANY_RECORDS )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_too_many_records );\r
+ offset += sizeof( ib_mad_status_str_too_many_records ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+ IB_SA_MAD_STATUS_INVALID_GID )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_invalid_gid );\r
+ offset += sizeof( ib_mad_status_str_invalid_gid ) - 1;\r
+ }\r
+ if( ( status & IB_MAD_STATUS_CLASS_MASK ) ==\r
+ IB_SA_MAD_STATUS_INSUF_COMPS )\r
+ {\r
+ if( !first )\r
+ {\r
+ strcat( &line[offset], generic_or_str );\r
+ offset += sizeof( generic_or_str ) - 1;\r
+ }\r
+ first = FALSE;\r
+ strcat( &line[offset], ib_mad_status_str_insuf_comps );\r
+ offset += sizeof( ib_mad_status_str_insuf_comps ) - 1;\r
+ }\r
+\r
+ return ( line );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+subnet_construct( IN subnet_t * const p_subn )\r
+{\r
+ cl_qmap_init( &p_subn->link_tbl );\r
+ cl_qmap_init( &p_subn->node_lid_tbl );\r
+ cl_qmap_init( &p_subn->node_guid_tbl );\r
+ cl_qmap_init( &p_subn->mgrp_mlid_tbl );\r
+\r
+ /* NO WAY TO HAVE UNIQUE PORT BY LID OR GUID */\r
+ /* cl_qmap_init( &p_subn->port_lid_tbl ); */\r
+ /* cl_qmap_init( &p_subn->port_guid_tbl ); */\r
+\r
+ /* port key is a lid and num pair */\r
+ cl_qmap_init( &p_subn->port_key_tbl );\r
+ cl_qmap_init( &p_subn->path_tbl );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+cl_status_t\r
+subnet_init( IN subnet_t * const p_subn )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ subnet_construct( p_subn );\r
+\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_construct( IN osmtest_t * const p_osmt )\r
+{\r
+ memset( p_osmt, 0, sizeof( *p_osmt ) );\r
+ osm_log_construct( &p_osmt->log );\r
+ subnet_construct( &p_osmt->exp_subn );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_destroy( IN osmtest_t * const p_osmt )\r
+{\r
+ cl_map_item_t *p_item,*p_next_item;\r
+\r
+\r
+\r
+ /* Currently there is a problem with IBAL exit flow - memory overrun , so we bypass the vendor deletion\r
+ Since it's already will be cleaned by the Windows OS . */\r
+\r
+#ifndef __WIN__\r
+ if( p_osmt->p_vendor )\r
+ {\r
+ osm_vendor_delete( &p_osmt->p_vendor );\r
+ }\r
+#endif\r
+ cl_qpool_destroy( &p_osmt->port_pool );\r
+ cl_qpool_destroy( &p_osmt->node_pool );\r
+\r
+ /* destroy the qmap tables */\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.link_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.link_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.mgrp_mlid_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.mgrp_mlid_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_guid_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_guid_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.node_lid_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.node_lid_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.path_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.path_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+ p_next_item = cl_qmap_head( &p_osmt->exp_subn.port_key_tbl );\r
+ while( p_next_item != cl_qmap_end( &p_osmt->exp_subn.port_key_tbl ) )\r
+ {\r
+ p_item = p_next_item;\r
+ p_next_item = cl_qmap_next( p_item );\r
+ free( p_item );\r
+ }\r
+\r
+ osm_log_destroy( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_init( IN osmtest_t * const p_osmt,\r
+ IN const osmtest_opt_t * const p_opt,\r
+ IN const osm_log_level_t log_flags\r
+ )\r
+{\r
+ ib_api_status_t status;\r
+\r
+ /* Can't use log macros here, since we're initializing the log. */\r
+ osmtest_construct( p_osmt );\r
+\r
+ status = osm_log_init_v2( &p_osmt->log, p_opt->force_log_flush,\r
+ 0x0001, p_opt->log_file, 0, TRUE );\r
+ if( status != IB_SUCCESS )\r
+ return ( status );\r
+\r
+ /* but we do not want any extra stuff here */\r
+ osm_log_set_level( &p_osmt->log, log_flags );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_FUNCS,\r
+ "osmtest_init: [\n" );\r
+\r
+ p_osmt->opt = *p_opt;\r
+\r
+ status = cl_qpool_init( &p_osmt->node_pool, POOL_MIN_ITEMS, 0,\r
+ POOL_MIN_ITEMS, sizeof( node_t ), NULL, NULL,\r
+ NULL );\r
+ CL_ASSERT( status == CL_SUCCESS );\r
+\r
+ status = cl_qpool_init( &p_osmt->port_pool, POOL_MIN_ITEMS, 0,\r
+ POOL_MIN_ITEMS, sizeof( port_t ), NULL, NULL,\r
+ NULL );\r
+ CL_ASSERT( status == CL_SUCCESS );\r
+\r
+ p_osmt->p_vendor = osm_vendor_new( &p_osmt->log,\r
+ p_opt->transaction_timeout );\r
+\r
+ if( p_osmt->p_vendor == NULL )\r
+ {\r
+ status = IB_INSUFFICIENT_RESOURCES;\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_init: ERR 0001: "\r
+ "Unable to allocate vendor object" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ osm_mad_pool_construct( &p_osmt->mad_pool );\r
+ status = osm_mad_pool_init( &p_osmt->mad_pool, &p_osmt->log );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ Exit:\r
+ osm_log( &p_osmt->log, OSM_LOG_FUNCS,\r
+ "osmtest_init: ]\n" );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+void\r
+osmtest_query_res_cb( IN osmv_query_res_t * p_rec )\r
+{\r
+ osmtest_req_context_t *const p_ctxt =\r
+ ( osmtest_req_context_t * ) p_rec->query_context;\r
+ osmtest_t *const p_osmt = p_ctxt->p_osmt;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_query_res_cb );\r
+\r
+ p_ctxt->result = *p_rec;\r
+\r
+ if( p_rec->status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_query_res_cb: ERR 0003: "\r
+ "Error on query (%s)\n", ib_get_err_str( p_rec->status ) );\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_all_recs( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const attr_id,\r
+ IN size_t const attr_size,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_all_recs );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_get_all_recs: "\r
+ "Getting all %s records\n", ib_get_sa_attr_str( attr_id ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for all <attr_id> records in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ user.attr_id = attr_id;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( attr_size >> 3 ) );\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_all_recs: ERR 0004: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_all_recs: ERR 0064: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_all_recs: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( p_context->result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_validate_sa_class_port_info( IN osmtest_t * const p_osmt)\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_query_req_t req;\r
+ ib_class_port_info_t *p_cpi;\r
+ osmtest_req_context_t context;\r
+ osmtest_req_context_t *p_context = &context;\r
+ ib_sa_mad_t *p_resp_sa_madp;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_sa_class_port_info );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_sa_class_port_info: "\r
+ "Getting ClassPortInfo\n");\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ req.query_type = OSMV_QUERY_CLASS_PORT_INFO;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = 0;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_sa_class_port_info: ERR 0065: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_sa_class_port_info: ERR 0070: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_sa_class_port_info: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( p_context->result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ /* ok we got it so please print it out */\r
+ p_resp_sa_madp = (ib_sa_mad_t*)osm_madw_get_mad_ptr(context.result.p_result_madw);\r
+ p_cpi = (ib_class_port_info_t*)ib_sa_mad_get_payload_ptr(p_resp_sa_madp );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+ "osmtest_validate_sa_class_port_info:\n-----------------------------\nSA Class Port Info:\n"\r
+ " base_ver:%u\n class_ver:%u\n cap_mask:0x%X\n resp_time_val:0x%X\n-----------------------------\n",\r
+ p_cpi->base_ver, p_cpi->class_ver, cl_ntoh16(p_cpi->cap_mask), p_cpi->cap_mask2_resp_time\r
+ );\r
+\r
+ Exit:\r
+#if 0\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+#endif\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_node_rec( IN osmtest_t * const p_osmt,\r
+ IN ib_net64_t const node_guid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_node_record_t record;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_node_rec: "\r
+ "Getting node record for 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( node_guid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.node_info.node_guid = node_guid;\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_NR_COMPMASK_NODEGUID;\r
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec: ERR 0071: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec: ERR 0072: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( p_context->result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get a node record by node LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_node_rec_by_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_node_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_node_rec_by_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_node_rec_by_lid: "\r
+ "Getting node record for LID 0x%02X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_NR_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec_by_lid: ERR 0073: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec_by_lid: ERR 0074: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_node_rec_by_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_guid_pair( IN osmtest_t * const p_osmt,\r
+ IN ib_net64_t sguid,\r
+ IN ib_net64_t dguid,\r
+ IN osmtest_req_context_t *p_context)\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ osmv_query_req_t req;\r
+ osmv_guid_pair_t guid_pair;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_guid_pair);\r
+\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+ req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;\r
+\r
+ guid_pair.dest_guid = dguid;\r
+ guid_pair.src_guid = sguid;\r
+\r
+ req.p_query_input = &guid_pair;\r
+ req.sm_key = 0;\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_path_rec_by_guid_pair: "\r
+ "Query for path from 0x%" PRIx64 " to 0x%" PRIx64"\n",\r
+ sguid, dguid );\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_guid_pair: ERR 0063: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = (*p_context).result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_guid_pair: ERR 0066: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_guid_pair: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( (*p_context).result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_gid_pair( IN osmtest_t * const p_osmt,\r
+ IN ib_gid_t sgid,\r
+ IN ib_gid_t dgid,\r
+ IN osmtest_req_context_t *p_context)\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ osmv_query_req_t req;\r
+ osmv_gid_pair_t gid_pair;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_gid_pair);\r
+\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+ req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;\r
+\r
+ gid_pair.dest_gid = dgid;\r
+ gid_pair.src_gid = sgid;\r
+\r
+ req.p_query_input = &gid_pair;\r
+ req.sm_key = 0;\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_path_rec_by_gid_pair: "\r
+ "Query for path from 0x%016" PRIx64 " 0x%016" PRIx64 " to 0x%016" PRIx64 " 0x%016" PRIx64"\n",\r
+ sgid.unicast.prefix, sgid.unicast.interface_id,\r
+ dgid.unicast.prefix, dgid.unicast.interface_id );\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_gid_pair: ERR 006A: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = (*p_context).result.status;\r
+\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_gid_pair: ERR 006B: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_gid_pair: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( (*p_context).result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_multipath_rec( IN osmtest_t * const p_osmt,\r
+ IN osmv_multipath_req_t *p_request,\r
+ IN osmtest_req_context_t *p_context)\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ osmv_query_req_t req;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_multipath_rec );\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+ req.query_type = OSMV_QUERY_MULTIPATH_REC;\r
+\r
+ req.p_query_input = p_request;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: ERR 0068: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: ERR 0069: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( p_context->result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_port_rec( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_portinfo_record_t record;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_get_port_rec: "\r
+ "Getting PortInfoRecord for port with LID 0x%X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_PIR_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_PORTINFO_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec: ERR 0075: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec: ERR 0076: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( p_context->result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_port_rec_by_num( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN uint8_t const port_num,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_portinfo_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_port_rec_by_num );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_get_port_rec_by_num: "\r
+ "Getting PortInfoRecord for port with LID 0x%X Num:0x%X\n",\r
+ cl_ntoh16( lid ),\r
+ port_num);\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+ record.port_num = port_num;\r
+ user.p_attr = &record;\r
+\r
+ p_context->p_osmt = p_osmt;\r
+\r
+ req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec_by_num: ERR 0077: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec_by_num: ERR 0078: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_port_rec_by_num: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_port_recs_large( IN osmtest_t * const p_osmt,\r
+ OUT uint32_t * const p_num_recs,\r
+ OUT uint32_t * const p_num_queries )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_portinfo_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ uint32_t num_recs = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_large );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ /*\r
+ * Do a blocking query for all PortInfoRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_stress_port_recs_large: ERR 0006: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Populate the database with the received records.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+ *p_num_recs += num_recs;\r
+ ++*p_num_queries;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_port_recs_large: "\r
+ "Received %u records\n", num_recs );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+ osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_node_recs_large( IN osmtest_t * const p_osmt,\r
+ OUT uint32_t * const p_num_recs,\r
+ OUT uint32_t * const p_num_queries )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_node_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ uint32_t num_recs = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_node_recs_large );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all NodeRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_stress_node_recs_large: ERR 0007: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Populate the database with the received records.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+ *p_num_recs += num_recs;\r
+ ++*p_num_queries;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_node_recs_large: "\r
+ "Received %u records\n", num_recs );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+ osm_dump_node_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_path_recs_large( IN osmtest_t * const p_osmt,\r
+ OUT uint32_t * const p_num_recs,\r
+ OUT uint32_t * const p_num_queries )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_path_rec_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ uint32_t num_recs = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_large );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all PathRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_stress_path_recs_large: ERR 0008: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Populate the database with the received records.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+ *p_num_recs += num_recs;\r
+ ++*p_num_queries;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_path_recs_large: "\r
+ "Received %u records\n", num_recs );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+ osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_path_recs_by_guid ( IN osmtest_t * const p_osmt,\r
+ OUT uint32_t * const p_num_recs,\r
+ OUT uint32_t * const p_num_queries )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_path_rec_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status = IB_SUCCESS;\r
+ uint32_t num_recs = 0;\r
+ node_t *p_src_node, *p_dst_node;\r
+ cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_path_recs_by_guid );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ context.p_osmt = p_osmt;\r
+\r
+ p_tbl = &p_osmt->exp_subn.node_guid_tbl;\r
+\r
+ p_src_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ /*\r
+ * Go over all nodes that exist in the subnet\r
+ * for each pair that are not switch nodes get the path record\r
+ */\r
+ while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ /*\r
+ * Do a blocking query for CA to CA Path Record\r
+ */\r
+ osm_log(&p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_path_recs_by_guid:"\r
+ "Source : guid = 0x%" PRIx64 " type = %d"\r
+ "Target : guid = 0x%" PRIx64 " type = %d\n",\r
+ cl_ntoh64(p_src_node->rec.node_info.port_guid),\r
+ p_src_node->rec.node_info.node_type,\r
+ cl_ntoh64(p_dst_node->rec.node_info.port_guid),\r
+ p_dst_node->rec.node_info.node_type);\r
+\r
+ if (p_src_node->rec.node_info.node_type == IB_NODE_TYPE_CA &&\r
+ p_dst_node->rec.node_info.node_type == IB_NODE_TYPE_CA)\r
+ {\r
+ status = osmtest_get_path_rec_by_guid_pair(p_osmt,\r
+ p_src_node->rec.node_info.port_guid,\r
+ p_dst_node->rec.node_info.port_guid,\r
+ &context);\r
+\r
+ /* In a case of TIMEOUT you still can try sending but cant count, maybe its a temporary issue */\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_stress_path_recs_by_guid: ERR 0009: "\r
+ "osmtest_get_path_rec_by_guid_pair failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ if (status != IB_TIMEOUT)\r
+ goto Exit;\r
+ }\r
+ else\r
+ {\r
+ /* we might have received several records */\r
+ num_recs = context.result.result_cnt;\r
+ /*\r
+ * Populate the database with the received records.\r
+ */\r
+ *p_num_recs += num_recs;\r
+ ++*p_num_queries;\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_path_recs_by_guid: "\r
+ "Received %u records\n", num_recs );\r
+ /* Dont waste time if not VERBOSE and above */\r
+ if (p_osmt->log.level & OSM_LOG_VERBOSE)\r
+ {\r
+ for (i = 0; i < num_recs; i++)\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i);\r
+ osm_dump_path_record(&p_osmt->log,p_rec,OSM_LOG_VERBOSE);\r
+ }\r
+ }\r
+ }\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+ }\r
+ /* next one please */\r
+ p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );\r
+ }\r
+\r
+ p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_stress_port_recs_small( IN osmtest_t * const p_osmt,\r
+ OUT uint32_t * const p_num_recs,\r
+ OUT uint32_t * const p_num_queries )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_portinfo_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ uint32_t num_recs = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_port_recs_small );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for our own PortInfoRecord in the subnet.\r
+ */\r
+ status = osmtest_get_port_rec( p_osmt,\r
+ cl_ntoh16(p_osmt->local_port.lid),\r
+ &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_stress_port_recs_small: ERR 0010: "\r
+ "osmtest_get_port_rec failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Populate the database with the received records.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+ *p_num_recs += num_recs;\r
+ ++*p_num_queries;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_stress_port_recs_small: "\r
+ "Received %u records\n", num_recs );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+ osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_local_port_lmc( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t lid,\r
+ OUT uint8_t * const p_lmc )\r
+{\r
+ osmtest_req_context_t context;\r
+ ib_portinfo_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ uint32_t num_recs = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_local_port_lmc );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for our own PortInfoRecord in the subnet.\r
+ */\r
+ status = osmtest_get_port_rec( p_osmt,\r
+ cl_ntoh16( lid ),\r
+ &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_local_port_lmc: ERR 001A: "\r
+ "osmtest_get_port_rec failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_local_port_lmc: "\r
+ "Received %u records\n", num_recs );\r
+ }\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+ osm_dump_portinfo_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ if ( p_lmc)\r
+ {\r
+ *p_lmc = ib_port_info_get_lmc( &p_rec->port_info );\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_get_local_port_lmc: "\r
+ "LMC %d\n", *p_lmc );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Use a wrong SM_Key in a simple port query and report success if\r
+ * failed.\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_wrong_sm_key_ignored( IN osmtest_t * const p_osmt)\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_portinfo_record_t record;\r
+ osmtest_req_context_t context;\r
+ osmtest_req_context_t *p_context = &context;\r
+ uint8_t port_num = 1;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_wrong_sm_key_ignored );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_INFO ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+ "osmtest_wrong_sm_key_ignored: "\r
+ "Trying PortInfoRecord for port with LID 0x%X Num:0x%X\n",\r
+ p_osmt->local_port.sm_lid, \r
+ port_num );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = p_osmt->local_port.sm_lid;\r
+ record.port_num = port_num;\r
+ user.p_attr = &record;\r
+\r
+ p_context->p_osmt = p_osmt;\r
+\r
+ req.query_type = OSMV_QUERY_PORT_REC_BY_LID_AND_NUM;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 9999;\r
+ context.result.p_result_madw = NULL;\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_wrong_sm_key_ignored: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ /* since we use a wrong sm_key we should get a timeout */\r
+ if( status != IB_TIMEOUT )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_wrong_sm_key_ignored: ERR 0011: "\r
+ "Did not get a timeout but got (%s)\n", ib_get_err_str( status ) );\r
+ if ( status == IB_SUCCESS )\r
+ {\r
+ /* assign some error value to status, since IB_SUCCESS is a bad rc */\r
+ status = IB_ERROR;\r
+ }\r
+ goto Exit;\r
+ }\r
+ else\r
+ {\r
+ status = IB_SUCCESS;\r
+ }\r
+\r
+ Exit:\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_port_info( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh,\r
+ IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+ int result;\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_port_info );\r
+\r
+ result = fprintf( fh,\r
+ "DEFINE_PORT\n"\r
+ "lid 0x%X\n"\r
+ "port_num 0x%X\n"\r
+ "m_key 0x%016" PRIx64 "\n"\r
+ "subnet_prefix 0x%016" PRIx64 "\n"\r
+ "base_lid 0x%X\n"\r
+ "master_sm_base_lid 0x%X\n"\r
+ "capability_mask 0x%X\n"\r
+ "diag_code 0x%X\n"\r
+ "m_key_lease_period 0x%X\n"\r
+ "local_port_num 0x%X\n"\r
+ "link_width_enabled 0x%X\n"\r
+ "link_width_supported 0x%X\n"\r
+ "link_width_active 0x%X\n"\r
+ "link_speed_supported 0x%X\n"\r
+ "port_state %s\n"\r
+ "state_info2 0x%X\n"\r
+ "mpb 0x%X\n"\r
+ "lmc 0x%X\n"\r
+ "link_speed 0x%X\n"\r
+ "mtu_smsl 0x%X\n"\r
+ "vl_cap 0x%X\n"\r
+ "vl_high_limit 0x%X\n"\r
+ "vl_arb_high_cap 0x%X\n"\r
+ "vl_arb_low_cap 0x%X\n"\r
+ "mtu_cap 0x%X\n"\r
+ "vl_stall_life 0x%X\n"\r
+ "vl_enforce 0x%X\n"\r
+ "m_key_violations 0x%X\n"\r
+ "p_key_violations 0x%X\n"\r
+ "q_key_violations 0x%X\n"\r
+ "guid_cap 0x%X\n"\r
+ "subnet_timeout 0x%X\n"\r
+ "resp_time_value 0x%X\n"\r
+ "error_threshold 0x%X\n"\r
+ "END\n\n",\r
+ cl_ntoh16( p_rec->lid ),\r
+ p_rec->port_num,\r
+ cl_ntoh64( p_rec->port_info.m_key ),\r
+ cl_ntoh64( p_rec->port_info.subnet_prefix ),\r
+ cl_ntoh16( p_rec->port_info.base_lid ),\r
+ cl_ntoh16( p_rec->port_info.master_sm_base_lid ),\r
+ cl_ntoh32( p_rec->port_info.capability_mask ),\r
+ cl_ntoh16( p_rec->port_info.diag_code ),\r
+ cl_ntoh16( p_rec->port_info.m_key_lease_period ),\r
+ p_rec->port_info.local_port_num,\r
+ p_rec->port_info.link_width_enabled,\r
+ p_rec->port_info.link_width_supported,\r
+ p_rec->port_info.link_width_active,\r
+ ib_port_info_get_link_speed_sup( &p_rec->port_info ),\r
+ ib_get_port_state_str( ib_port_info_get_port_state\r
+ ( &p_rec->port_info ) ),\r
+ p_rec->port_info.state_info2,\r
+ ib_port_info_get_mpb( &p_rec->port_info ),\r
+ ib_port_info_get_lmc( &p_rec->port_info ),\r
+ p_rec->port_info.link_speed, p_rec->port_info.mtu_smsl,\r
+ p_rec->port_info.vl_cap, p_rec->port_info.vl_high_limit,\r
+ p_rec->port_info.vl_arb_high_cap,\r
+ p_rec->port_info.vl_arb_low_cap,\r
+ p_rec->port_info.mtu_cap,\r
+ p_rec->port_info.vl_stall_life,\r
+ p_rec->port_info.vl_enforce,\r
+ cl_ntoh16( p_rec->port_info.m_key_violations ),\r
+ cl_ntoh16( p_rec->port_info.p_key_violations ),\r
+ cl_ntoh16( p_rec->port_info.q_key_violations ),\r
+ p_rec->port_info.guid_cap,\r
+ ib_port_info_get_timeout(&p_rec->port_info),\r
+ p_rec->port_info.resp_time_value,\r
+ p_rec->port_info.error_threshold );\r
+\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_port_info: ERR 0161: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_path_info( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh,\r
+ IN const ib_path_rec_t * const p_rec )\r
+{\r
+ int result;\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_path_info );\r
+\r
+ result = fprintf( fh,\r
+ "DEFINE_PATH\n"\r
+ "dgid 0x%016" PRIx64 " 0x%016" PRIx64\r
+ "\nsgid 0x%016" PRIx64 " 0x%016" PRIx64\r
+ "\ndlid 0x%X\n"\r
+ "slid 0x%X\n"\r
+ "# hop_flow_raw 0x%X\n"\r
+ "# tclass 0x%X\n"\r
+ "# num_path 0x%X\n"\r
+ "pkey 0x%X\n"\r
+ "# sl 0x%X\n"\r
+ "# mtu 0x%X\n"\r
+ "# rate 0x%X\n"\r
+ "# pkt_life 0x%X\n"\r
+ "# preference 0x%X\n" "END\n\n",\r
+ cl_ntoh64( p_rec->dgid.unicast.prefix ),\r
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ),\r
+ cl_ntoh64( p_rec->sgid.unicast.prefix ),\r
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ),\r
+ cl_ntoh16( p_rec->dlid ), cl_ntoh16( p_rec->slid ),\r
+ cl_ntoh32( p_rec->hop_flow_raw ), p_rec->tclass,\r
+ p_rec->num_path, cl_ntoh16( p_rec->pkey ),\r
+ p_rec->qos_class_sl,\r
+ p_rec->mtu, p_rec->rate, p_rec->pkt_life,\r
+ p_rec->preference );\r
+\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_path_info: ERR 0162: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_node_info( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh,\r
+ IN const ib_node_record_t * const p_rec )\r
+{\r
+ int result;\r
+ cl_status_t status = IB_SUCCESS;\r
+ char desc[IB_NODE_DESCRIPTION_SIZE + 1];\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_node_info );\r
+\r
+ memcpy(desc, p_rec->node_desc.description, IB_NODE_DESCRIPTION_SIZE);\r
+ desc[IB_NODE_DESCRIPTION_SIZE] = '\0';\r
+\r
+ result = fprintf( fh,\r
+ "DEFINE_NODE\n"\r
+ "lid 0x%X\n"\r
+ "base_version 0x%X\n"\r
+ "class_version 0x%X\n"\r
+ "node_type 0x%X # (%s)\n"\r
+ "num_ports 0x%X\n"\r
+ "sys_guid 0x%016" PRIx64 "\n"\r
+ "node_guid 0x%016" PRIx64 "\n"\r
+ "port_guid 0x%016" PRIx64 "\n"\r
+ "partition_cap 0x%X\n"\r
+ "device_id 0x%X\n"\r
+ "revision 0x%X\n"\r
+ "# port_num 0x%X\n"\r
+ "# vendor_id 0x%X\n"\r
+ "# node_desc %s\n"\r
+ "END\n\n",\r
+ cl_ntoh16( p_rec->lid ),\r
+ p_rec->node_info.base_version,\r
+ p_rec->node_info.class_version,\r
+ p_rec->node_info.node_type,\r
+ ib_get_node_type_str( p_rec->node_info.node_type ),\r
+ p_rec->node_info.num_ports,\r
+ cl_ntoh64( p_rec->node_info.sys_guid ),\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh64( p_rec->node_info.port_guid ),\r
+ cl_ntoh16( p_rec->node_info.partition_cap ),\r
+ cl_ntoh16( p_rec->node_info.device_id ),\r
+ cl_ntoh32( p_rec->node_info.revision ),\r
+ ib_node_info_get_local_port_num( &p_rec->node_info ),\r
+ cl_ntoh32( ib_node_info_get_vendor_id\r
+ ( &p_rec->node_info ) ),\r
+ desc );\r
+\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_node_info: ERR 0163: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_link( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh,\r
+ IN const ib_link_record_t * const p_rec )\r
+{\r
+ int result;\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_link );\r
+\r
+ result = fprintf( fh,\r
+ "DEFINE_LINK\n"\r
+ "from_lid 0x%X\n"\r
+ "from_port_num 0x%X\n"\r
+ "to_port_num 0x%X\n"\r
+ "to_lid 0x%X\n"\r
+ "END\n\n",\r
+ cl_ntoh16( p_rec->from_lid ),\r
+ p_rec->from_port_num,\r
+ p_rec->to_port_num, cl_ntoh16( p_rec->to_lid ) );\r
+\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_link: ERR 0164: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_link_recs( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_link_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+ int result;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_link_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all NodeRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_LINK_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_link_recs: ERR 0165: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Write the received records out to the file.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_write_all_link_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ result = fprintf( fh, "#\n" "# Link Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_link_recs: ERR 0166: "\r
+ "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = ( ib_link_record_t * ) osmv_get_query_result( context.result.\r
+ p_result_madw, i );\r
+\r
+ osmtest_write_link( p_osmt, fh, p_rec );\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_get_path_rec_by_lid_pair( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t slid,\r
+ IN ib_net16_t dlid,\r
+ IN osmtest_req_context_t *p_context )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ osmv_query_req_t req;\r
+ osmv_lid_pair_t lid_pair;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_path_rec_by_lid_pair );\r
+\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( p_context, 0, sizeof( *p_context ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+ req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;\r
+\r
+ lid_pair.dest_lid = dlid;\r
+ lid_pair.src_lid = slid;\r
+\r
+ req.p_query_input = &lid_pair;\r
+ req.sm_key = 0;\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_path_rec_by_lid_pair: "\r
+ "Query for path from 0x%X to 0x%X\n",\r
+ slid,dlid );\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: ERR 0053: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = (*p_context).result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: ERR 0067: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( (*p_context).result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_node_recs( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_node_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+ int result;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all NodeRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_node_recs: ERR 0022: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Write the received records out to the file.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_write_all_node_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_node_recs: ERR 0023: "\r
+ "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+ osmtest_write_node_info( p_osmt, fh, p_rec );\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_portinfo_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+ int result;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all NodeRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PORTINFO_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_port_recs: ERR 0167: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Write the received records out to the file.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_write_all_port_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_port_recs: ERR 0024: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, i );\r
+ osmtest_write_port_info( p_osmt, fh, p_rec );\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_path_recs(\r
+ IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_path_rec_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+ int result;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all PathRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_path_recs: ERR 0025: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Write the received records out to the file.\r
+ */\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_write_all_path_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ result = fprintf( fh, "#\n" "# Path Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_path_recs: ERR 0026: "\r
+ "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+ osmtest_write_path_info( p_osmt, fh, p_rec );\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+#else\r
+/*\r
+ * NON RMPP BASED QUERY FOR ALL NODES: BASED ON THE MAX LID GIVEN BY THE USER\r
+ */\r
+static ib_api_status_t\r
+osmtest_write_all_node_recs(\r
+ IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ node_t *p_node;\r
+ node_t *p_guid_node;\r
+ const ib_node_record_t *p_rec;\r
+ cl_status_t status = CL_SUCCESS;\r
+ int result;\r
+ uint16_t lid;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_node_recs );\r
+\r
+ result = fprintf( fh, "#\n" "# Node Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_node_recs: ERR 0027: "\r
+ "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Go over all LIDs in the range 1 to max_lid and do a\r
+ * NodeRecord query by that lid.\r
+ */\r
+ for (lid = 1; lid <= p_osmt->max_lid; lid++)\r
+ {\r
+ /* prepare the query context */\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ status = osmtest_get_node_rec_by_lid( p_osmt, cl_ntoh16( lid ), &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ if ( status != IB_SA_MAD_STATUS_NO_RECORDS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_write_all_node_recs: ERR 0028: "\r
+ "failed to get node info for LID:0x%02X (%s)\n",\r
+ cl_ntoh16( lid ),\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ else\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_write_all_node_recs: WRN 0121: "\r
+ "failed to get node info for LID:0x%02X (%s)\n",\r
+ cl_ntoh16( lid ),\r
+ ib_get_err_str( status ) );\r
+ status = IB_SUCCESS;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* OK we got something */\r
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, 0 );\r
+ osmtest_write_node_info( p_osmt, fh, p_rec );\r
+\r
+ /* create a subnet object */\r
+ p_node = node_new( );\r
+ CL_ASSERT( p_node != NULL );\r
+\r
+ /* copy the info to the subnet node object */\r
+ p_node->rec = *p_rec;\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,\r
+ p_node->rec.lid, &p_node->map_item );\r
+\r
+ p_guid_node = node_new( );\r
+ CL_ASSERT( p_guid_node != NULL );\r
+\r
+ *p_guid_node = *p_node;\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,\r
+ p_guid_node->rec.node_info.node_guid,\r
+ &p_guid_node->map_item );\r
+\r
+ }\r
+\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/*\r
+ * GET ALL PORT RECORDS IN THE FABRIC -\r
+ * one by one by using the node info received\r
+ */\r
+static ib_api_status_t\r
+osmtest_write_all_port_recs( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_node_record_t *p_node_rec;\r
+ const ib_portinfo_record_t *p_rec;\r
+ uint8_t port_num;\r
+ cl_status_t status = CL_SUCCESS;\r
+ cl_qmap_t *p_tbl;\r
+ node_t *p_node;\r
+ port_t *p_port;\r
+ int result;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_port_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /* print header */\r
+ result = fprintf( fh, "#\n" "# PortInfo Records\n" "#\n" );\r
+ if( result < 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_port_recs: ERR 0029: " "Write failed\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /* use the pre-explored set of nodes */\r
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+ p_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ /*\r
+ * Go over all LIDs in the range 1 to max_lid and do a\r
+ * NodeRecord query by that lid.\r
+ */\r
+ while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+\r
+ p_node_rec = &(p_node->rec);\r
+\r
+ /* go through all ports of the node: */\r
+ for (port_num = 0; port_num <= p_node_rec->node_info.num_ports; port_num++)\r
+ {\r
+ /* prepare the query context */\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ status = osmtest_get_port_rec_by_num( p_osmt,\r
+ p_node_rec->lid,\r
+ port_num,\r
+ &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ if( status != IB_SA_MAD_STATUS_NO_RECORDS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_port_recs: WRN 0122: "\r
+ "Error encountered getting port info for LID:0x%04X Num:0x%02X (%s)\n",\r
+ p_node_rec->lid, port_num,\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ else\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_write_all_port_recs: WRN 0123: "\r
+ "failed to get port info for LID:0x%04X Num:0x%02X (%s)\n",\r
+ p_node_rec->lid, port_num,\r
+ ib_get_err_str( status ) );\r
+ status = IB_SUCCESS;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* OK we got something */\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0 );\r
+ osmtest_write_port_info( p_osmt, fh, p_rec );\r
+\r
+ /* create a subnet object */\r
+ p_port = port_new( );\r
+ CL_ASSERT( p_port != NULL );\r
+\r
+ /* copy the info to the subnet node object */\r
+ p_port->rec = *p_rec;\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,\r
+ port_gen_id(p_node_rec->lid, port_num), &p_port->map_item );\r
+ }\r
+\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+ }\r
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+ }\r
+\r
+ /* we must set the exist status to avoid abort of the over all algorith */\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * ASSUMES NO RMPP\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_write_all_path_recs( IN osmtest_t * const p_osmt,\r
+ IN FILE * fh )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_path_rec_t *p_rec;\r
+ cl_status_t status = CL_SUCCESS;\r
+ int num_recs, i;\r
+ cl_qmap_t *p_tbl;\r
+ node_t *p_src_node, *p_dst_node;\r
+ ib_api_status_t got_status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_write_all_path_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Go over all nodes that exist in the subnet\r
+ * for each pair that are not switch nodes get the path record\r
+ */\r
+\r
+ context.p_osmt = p_osmt;\r
+\r
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+ p_src_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_src_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ /* HACK we use capability_mask to know diff a CA node from switch node */\r
+ /* if(p_src_node->rec.node_info.capability_mask ) { */\r
+ p_dst_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_dst_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ /* HACK we use capability_mask to know diff a CA node from switch node */\r
+ /* if (p_dst_node->rec.node_info.capability_mask) { */\r
+\r
+ /* query for it: */\r
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt,\r
+ p_src_node->rec.lid,\r
+ p_dst_node->rec.lid,\r
+ &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_write_all_path_recs: ERR 012D: "\r
+ "failed to get path info from LID:0x%X To LID:0x%X (%s)\n",\r
+ p_src_node->rec.lid, p_dst_node->rec.lid,\r
+ ib_get_err_str( status ) );\r
+ /* remember the first error status */\r
+ got_status = ( got_status == IB_SUCCESS ) ? status : got_status;\r
+ }\r
+ else\r
+ {\r
+ /* we might have received several records */\r
+ num_recs = context.result.result_cnt;\r
+ for (i = 0; i < num_recs; i++)\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+ osmtest_write_path_info( p_osmt, fh, p_rec );\r
+ }\r
+ }\r
+/* } */\r
+\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ /* next one please */\r
+ p_dst_node = ( node_t * ) cl_qmap_next( &p_dst_node->map_item );\r
+ }\r
+/* } */\r
+\r
+ p_src_node = ( node_t * ) cl_qmap_next( &p_src_node->map_item );\r
+ }\r
+\r
+ if( got_status != IB_SUCCESS )\r
+ status = got_status;\r
+\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_create_inventory_file( IN osmtest_t * const p_osmt )\r
+{\r
+ FILE *fh;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_create_inventory_file );\r
+\r
+ fh = fopen( p_osmt->opt.file_name, "w" );\r
+ if( fh == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_create_inventory_file: ERR 0079: "\r
+ "Unable to open inventory file (%s)\n",\r
+ p_osmt->opt.file_name );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /* HACK: the order is important: nodes ports paths */\r
+ status = osmtest_write_all_node_recs( p_osmt, fh );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ status = osmtest_write_all_port_recs( p_osmt, fh );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ if (! p_osmt->opt.ignore_path_records)\r
+ {\r
+ status = osmtest_write_all_path_recs( p_osmt, fh );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_write_all_link_recs( p_osmt, fh );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ fclose( fh );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_large_rmpp_pr( IN osmtest_t * const p_osmt )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint64_t num_recs = 0;\r
+ uint64_t num_queries = 0;\r
+ uint32_t delta_recs;\r
+ uint32_t delta_queries;\r
+ uint32_t print_freq = 0;\r
+ struct timeval start_tv,end_tv;\r
+ long sec_diff,usec_diff;\r
+ float ratio;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp_pr );\r
+ gettimeofday( &start_tv, NULL );\r
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+ while( num_queries < STRESS_LARGE_PR_RMPP_THR )\r
+ {\r
+ delta_recs = 0;\r
+ delta_queries = 0;\r
+\r
+ status = osmtest_stress_path_recs_by_guid( p_osmt, &delta_recs,\r
+ &delta_queries );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ num_recs += delta_recs;\r
+ num_queries += delta_queries;\r
+\r
+ print_freq += delta_recs;\r
+ if( print_freq > 10000 )\r
+ {\r
+ gettimeofday( &end_tv, NULL );\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ printf("-I- Querying %" PRId64 " Path Record queries CA to CA (rmpp)\n\ttook %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+ if (num_recs == 0)\r
+ ratio = 0;\r
+ else\r
+ ratio = ((float)num_queries / (float)num_recs);\r
+ printf( "-I- Queries to Record Ratio is %" PRIu64 " records, %" PRIu64 " queries : %.2f \n",\r
+ num_recs, num_queries, ratio);\r
+ print_freq = 0;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ gettimeofday( &end_tv, NULL );\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+\r
+ printf("-I- Querying %" PRId64 " Path Record queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_large_rmpp( IN osmtest_t * const p_osmt )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint64_t num_recs = 0;\r
+ uint64_t num_queries = 0;\r
+ uint32_t delta_recs;\r
+ uint32_t delta_queries;\r
+ uint32_t print_freq = 0;\r
+ struct timeval start_tv,end_tv;\r
+ long sec_diff,usec_diff;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_large_rmpp );\r
+ gettimeofday( &start_tv, NULL );\r
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n", start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+ while( num_queries < STRESS_LARGE_RMPP_THR )\r
+ {\r
+ delta_recs = 0;\r
+ delta_queries = 0;\r
+\r
+ status = osmtest_stress_node_recs_large( p_osmt, &delta_recs,\r
+ &delta_queries );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ status = osmtest_stress_path_recs_large( p_osmt, &delta_recs,\r
+ &delta_queries );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ status = osmtest_stress_port_recs_large( p_osmt, &delta_recs,\r
+ &delta_queries );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ num_recs += delta_recs;\r
+ num_queries += delta_queries;\r
+\r
+ print_freq += delta_recs;\r
+\r
+ if( print_freq > 100000 )\r
+ {\r
+ gettimeofday( &end_tv, NULL );\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+ printf("%" PRIu64 " records, %" PRIu64 " queries\n",\r
+ num_recs, num_queries);\r
+ print_freq = 0;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ gettimeofday( &end_tv, NULL );\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+\r
+ printf("-I- Querying %" PRId64 " large mixed queries (rmpp) took %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_stress_small_rmpp( IN osmtest_t * const p_osmt )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint64_t num_recs = 0;\r
+ uint64_t num_queries = 0;\r
+ uint32_t delta_recs;\r
+ uint32_t delta_queries;\r
+ uint32_t print_freq = 0;\r
+ int num_timeouts = 0;\r
+ struct timeval start_tv,end_tv;\r
+ long sec_diff,usec_diff;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_stress_small_rmpp );\r
+ gettimeofday( &start_tv, NULL );\r
+ printf("-I- Start time is : %09ld:%06ld [sec:usec]\n",\r
+ start_tv.tv_sec, (long)start_tv.tv_usec);\r
+\r
+ while( (num_queries < STRESS_SMALL_RMPP_THR) && (num_timeouts < 100) )\r
+ {\r
+ delta_recs = 0;\r
+ delta_queries = 0;\r
+\r
+ status = osmtest_stress_port_recs_small( p_osmt, &delta_recs,\r
+ &delta_queries );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ num_recs += delta_recs;\r
+ num_queries += delta_queries;\r
+\r
+ print_freq += delta_recs;\r
+ if( print_freq > 5000 )\r
+ {\r
+ gettimeofday( &end_tv, NULL );\r
+ printf( "%" PRIu64 " records, %" PRIu64 " queries\n",\r
+ num_recs, num_queries );\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+ print_freq = 0;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ gettimeofday( &end_tv, NULL );\r
+ printf("-I- End time is : %09ld:%06ld [sec:usec]\n",\r
+ end_tv.tv_sec, (long)end_tv.tv_usec);\r
+ if (end_tv.tv_usec > start_tv.tv_usec)\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec;\r
+ usec_diff = end_tv.tv_usec-start_tv.tv_usec;\r
+ }\r
+ else\r
+ {\r
+ sec_diff = end_tv.tv_sec-start_tv.tv_sec - 1;\r
+ usec_diff = 1000000 - (start_tv.tv_usec - end_tv.tv_usec);\r
+ }\r
+\r
+ printf("-I- Querying %" PRId64 " port_info queries (single mad) took %04ld:%06ld [sec:usec]\n",\r
+ num_queries, sec_diff, usec_diff);\r
+ if (num_timeouts > 50)\r
+ {\r
+ status = IB_TIMEOUT;\r
+ }\r
+ /* Exit: */\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+osmtest_prepare_db_generic( IN osmtest_t * const p_osmt,\r
+ IN cl_qmap_t * const p_tbl )\r
+{\r
+ generic_t *p_generic;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db_generic );\r
+\r
+ p_generic = ( generic_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_generic != ( generic_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ p_generic->count = 0;\r
+ p_generic = ( generic_t * ) cl_qmap_next( &p_generic->map_item );\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static void\r
+osmtest_prepare_db( IN osmtest_t * const p_osmt )\r
+{\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_prepare_db );\r
+\r
+ osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.node_lid_tbl );\r
+ osmtest_prepare_db_generic( p_osmt, &p_osmt->exp_subn.path_tbl );\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_nodes( IN osmtest_t * const p_osmt )\r
+{\r
+ const node_t *p_node;\r
+ cl_status_t status = IB_SUCCESS;\r
+ cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_nodes );\r
+\r
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+ p_node = ( node_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_node != ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ if( p_node->count == 0 )\r
+ {\r
+ /*\r
+ * This node was not reported by the SA\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_check_missing_nodes: ERR 0080: "\r
+ "Missing node 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+ status = IB_ERROR;\r
+ }\r
+\r
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_ports( IN osmtest_t * const p_osmt )\r
+{\r
+ const port_t *p_port;\r
+ cl_status_t status = IB_SUCCESS;\r
+ cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_ports );\r
+\r
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+\r
+ p_port = ( port_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_port != ( port_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ if( p_port->count == 0 )\r
+ {\r
+ /*\r
+ * This port was not reported by the SA\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_check_missing_ports: ERR 0081: "\r
+ "Missing port LID:0x%X Num:0x%X\n",\r
+ cl_ntoh16( p_port->rec.lid), p_port->rec.port_num);\r
+ status = IB_ERROR;\r
+ }\r
+\r
+ p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_check_missing_paths( IN osmtest_t * const p_osmt )\r
+{\r
+ const path_t *p_path;\r
+ cl_status_t status = IB_SUCCESS;\r
+ cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_check_missing_paths );\r
+\r
+ p_tbl = &p_osmt->exp_subn.path_tbl;\r
+\r
+ p_path = ( path_t * ) cl_qmap_head( p_tbl );\r
+\r
+ while( p_path != ( path_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ if( p_path->count == 0 )\r
+ {\r
+ /*\r
+ * This path was not reported by the SA\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_check_missing_paths: ERR 0051: "\r
+ "SA did not return path SLID 0x%X to DLID 0x%X\n",\r
+ cl_ntoh16( p_path->rec.slid ),\r
+ cl_ntoh16( p_path->rec.dlid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+inline uint32_t\r
+osmtest_path_rec_key_get( IN const ib_path_rec_t * const p_rec )\r
+{\r
+ return ( p_rec->dlid << 16 | p_rec->slid );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static boolean_t\r
+osmtest_path_rec_kay_is_valid( IN osmtest_t * const p_osmt,\r
+ IN const path_t * const p_path )\r
+{\r
+ if( ( p_path->comp.dlid == 0 ) || ( p_path->comp.slid == 0 ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_path_rec_kay_is_valid: ERR 0168: "\r
+ "SLID and DLID must be specified for defined paths\n" );\r
+ return ( FALSE );\r
+ }\r
+\r
+ return ( TRUE );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_path_data( IN osmtest_t * const p_osmt,\r
+ IN path_t * const p_path,\r
+ IN const ib_path_rec_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ uint8_t lmc = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_data );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: "\r
+ "Checking path SLID 0x%X to DLID 0x%X\n",\r
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+ }\r
+\r
+ status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc );\r
+ if (status != IB_SUCCESS)\r
+ goto Exit;\r
+\r
+ /* HACK: Assume uniform LMC across endports in the subnet */ \r
+ /* This is the only LMC mode which OpenSM currently supports */\r
+ /* In absence of this assumption, validation of this is much more complicated */\r
+ if ( lmc == 0 )\r
+ {\r
+ /*\r
+ * Has this record already been returned?\r
+ */\r
+ if( p_path->count != 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: ERR 0056: "\r
+ "Already received path SLID 0x%X to DLID 0x%X\n",\r
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /* Also, this doesn't detect fewer than the correct number of paths being returned */\r
+ if ( p_path->count >= (uint32_t)( 1 << (2*lmc) ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: ERR 0052: "\r
+ "Already received path SLID 0x%X to DLID 0x%X count %d LMC %d\n",\r
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ),\r
+ p_path->count, lmc );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ ++p_path->count;\r
+\r
+ /*\r
+ * Check the fields the user wants checked.\r
+ */\r
+ if( ( p_path->comp.dgid.unicast.interface_id &\r
+ p_path->rec.dgid.unicast.interface_id ) !=\r
+ ( p_path->comp.dgid.unicast.interface_id &\r
+ p_rec->dgid.unicast.interface_id ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: ERR 0169: "\r
+ "DGID mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+ "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 "\n"\r
+ "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+ cl_ntoh16( p_path->rec.slid ),\r
+ cl_ntoh16( p_path->rec.dlid ),\r
+ cl_ntoh64( p_path->rec.dgid.unicast.prefix ),\r
+ cl_ntoh64( p_path->rec.dgid.unicast.interface_id ),\r
+ cl_ntoh64( p_rec->dgid.unicast.prefix ),\r
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Check the fields the user wants checked.\r
+ */\r
+ if( ( p_path->comp.sgid.unicast.interface_id &\r
+ p_path->rec.sgid.unicast.interface_id ) !=\r
+ ( p_path->comp.sgid.unicast.interface_id &\r
+ p_rec->sgid.unicast.interface_id ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: ERR 0057: "\r
+ "SGID mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+ "\t\t\t\tExpected 0x%016" PRIx64 " 0x%016" PRIx64 ",\n"\r
+ "\t\t\t\tReceived 0x%016" PRIx64 " 0x%016" PRIx64 ".\n",\r
+ cl_ntoh16( p_path->rec.slid ),\r
+ cl_ntoh16( p_path->rec.dlid ),\r
+ cl_ntoh64( p_path->rec.sgid.unicast.prefix ),\r
+ cl_ntoh64( p_path->rec.sgid.unicast.interface_id ),\r
+ cl_ntoh64( p_rec->sgid.unicast.prefix ),\r
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Compare the fields the user wishes to validate.\r
+ */\r
+ if( ( p_path->comp.pkey & p_path->rec.pkey ) !=\r
+ ( p_path->comp.pkey & p_rec->pkey ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_data: ERR 0012: "\r
+ "PKEY mismatch on path SLID 0x%X to DLID 0x%X\n"\r
+ "\t\t\t\tExpected 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_path->rec.slid ),\r
+ cl_ntoh16( p_path->rec.dlid ),\r
+ cl_ntoh16( p_path->rec.pkey ),\r
+ cl_ntoh16( p_rec->pkey ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_node_data( IN osmtest_t * const p_osmt,\r
+ IN node_t * const p_node,\r
+ IN const ib_node_record_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_data );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: "\r
+ "Checking node 0x%016" PRIx64 ", LID 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ) );\r
+ }\r
+\r
+ /*\r
+ * Has this record already been returned?\r
+ */\r
+ if( p_node->count != 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0013: "\r
+ "Already received node 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++p_node->count;\r
+\r
+ /*\r
+ * Compare the fields the user wishes to validate.\r
+ */\r
+ if( ( p_node->comp.lid & p_node->rec.lid ) !=\r
+ ( p_node->comp.lid & p_rec->lid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0014: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected LID 0x%X, received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ), p_node->rec.lid, p_rec->lid );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.base_version &\r
+ p_node->rec.node_info.base_version ) !=\r
+ ( p_node->comp.node_info.base_version &\r
+ p_rec->node_info.base_version ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0015: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected base_version 0x%X, received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ p_node->rec.node_info.base_version,\r
+ p_rec->node_info.base_version );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.class_version &\r
+ p_node->rec.node_info.class_version ) !=\r
+ ( p_node->comp.node_info.class_version &\r
+ p_rec->node_info.class_version ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0016: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected class_version 0x%X, received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ p_node->rec.node_info.class_version,\r
+ p_rec->node_info.class_version );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.node_type &\r
+ p_node->rec.node_info.node_type ) !=\r
+ ( p_node->comp.node_info.node_type & p_rec->node_info.node_type ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0017: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected node_type 0x%X, received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ p_node->rec.node_info.node_type,\r
+ p_rec->node_info.node_type );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.sys_guid &\r
+ p_node->rec.node_info.sys_guid ) !=\r
+ ( p_node->comp.node_info.sys_guid & p_rec->node_info.sys_guid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0018: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected sys_guid 0x%016" PRIx64\r
+ ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh64( p_node->rec.node_info.sys_guid ),\r
+ cl_ntoh64( p_rec->node_info.sys_guid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.node_guid &\r
+ p_node->rec.node_info.node_guid ) !=\r
+ ( p_node->comp.node_info.node_guid & p_rec->node_info.node_guid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0019: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected node_guid 0x%016" PRIx64\r
+ ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh64( p_node->rec.node_info.node_guid ),\r
+ cl_ntoh64( p_rec->node_info.node_guid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.port_guid &\r
+ p_node->rec.node_info.port_guid ) !=\r
+ ( p_node->comp.node_info.port_guid & p_rec->node_info.port_guid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0031: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected port_guid 0x%016" PRIx64\r
+ ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh64( p_node->rec.node_info.port_guid ),\r
+ cl_ntoh64( p_rec->node_info.port_guid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.partition_cap &\r
+ p_node->rec.node_info.partition_cap ) !=\r
+ ( p_node->comp.node_info.partition_cap &\r
+ p_rec->node_info.partition_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0032: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected partition_cap 0x%X"\r
+ ", received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh16( p_node->rec.node_info.partition_cap ),\r
+ cl_ntoh16( p_rec->node_info.partition_cap ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.device_id &\r
+ p_node->rec.node_info.device_id ) !=\r
+ ( p_node->comp.node_info.device_id & p_rec->node_info.device_id ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0033: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected device_id 0x%X"\r
+ ", received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh16( p_node->rec.node_info.device_id ),\r
+ cl_ntoh16( p_rec->node_info.device_id ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_node->comp.node_info.revision &\r
+ p_node->rec.node_info.revision ) !=\r
+ ( p_node->comp.node_info.revision & p_rec->node_info.revision ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_data: ERR 0034: "\r
+ "Field mismatch node 0x%016" PRIx64 ", LID 0x%X\n"\r
+ "\t\t\t\tExpected revision 0x%X"\r
+ ", received 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ),\r
+ cl_ntoh32( p_node->rec.node_info.revision ),\r
+ cl_ntoh32( p_rec->node_info.revision ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_node_rec( IN osmtest_t * const p_osmt,\r
+ IN const ib_node_record_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ node_t *p_node;\r
+ const cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_node_rec );\r
+\r
+ /*\r
+ * Find proper node record in the database.\r
+ */\r
+ p_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+ p_node = ( node_t * ) cl_qmap_get( p_tbl, p_rec->lid );\r
+ if( p_node == ( node_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_node_rec: ERR 0035: "\r
+ "Unexpected node 0x%016" PRIx64 ", LID 0x%X\n",\r
+ cl_ntoh64( p_rec->node_info.node_guid ),\r
+ cl_ntoh16( p_rec->lid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_validate_node_data( p_osmt, p_node, p_rec );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_port_data( IN osmtest_t * const p_osmt,\r
+ IN port_t * const p_port,\r
+ IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_data );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: "\r
+ "Checking port LID 0x%X, Num 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num);\r
+ }\r
+\r
+ /*\r
+ * Has this record already been returned?\r
+ */\r
+ if( p_port->count != 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0036: "\r
+ "Already received port LID 0x%X, Num 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num);\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++p_port->count;\r
+\r
+ /*\r
+ * Compare the fields the user wishes to validate.\r
+ */\r
+ if( ( p_port->comp.lid & p_port->rec.lid ) !=\r
+ ( p_port->comp.lid & p_rec->lid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0037: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected LID 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.lid, p_rec->lid );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_num & p_port->rec.port_num ) !=\r
+ ( p_port->comp.port_num & p_rec->port_num ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0038: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected port_num 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_num, p_rec->port_num );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.m_key & p_port->rec.port_info.m_key ) !=\r
+ ( p_port->comp.port_info.m_key & p_rec->port_info.m_key ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0039: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected m_key 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.m_key, p_rec->port_info.m_key );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.subnet_prefix & p_port->rec.port_info.subnet_prefix ) !=\r
+ ( p_port->comp.port_info.subnet_prefix & p_rec->port_info.subnet_prefix ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0040: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected subnet_prefix 0x%016" PRIx64 ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.subnet_prefix, p_rec->port_info.subnet_prefix );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.base_lid & p_port->rec.port_info.base_lid ) !=\r
+ ( p_port->comp.port_info.base_lid & p_rec->port_info.base_lid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0041: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected base_lid 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.base_lid, p_rec->port_info.base_lid );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.master_sm_base_lid & p_port->rec.port_info.master_sm_base_lid ) !=\r
+ ( p_port->comp.port_info.master_sm_base_lid & p_rec->port_info.master_sm_base_lid ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0042: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected master_sm_base_lid 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.master_sm_base_lid, p_rec->port_info.master_sm_base_lid );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.capability_mask & p_port->rec.port_info.capability_mask ) !=\r
+ ( p_port->comp.port_info.capability_mask & p_rec->port_info.capability_mask ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0043: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected capability_mask 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.capability_mask, p_rec->port_info.capability_mask );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.diag_code & p_port->rec.port_info.diag_code ) !=\r
+ ( p_port->comp.port_info.diag_code & p_rec->port_info.diag_code ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0044: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected diag_code 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.diag_code, p_rec->port_info.diag_code );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.m_key_lease_period & p_port->rec.port_info.m_key_lease_period ) !=\r
+ ( p_port->comp.port_info.m_key_lease_period & p_rec->port_info.m_key_lease_period ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0045: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected m_key_lease_period 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.m_key_lease_period, p_rec->port_info.m_key_lease_period );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.local_port_num & p_port->rec.port_info.local_port_num ) !=\r
+ ( p_port->comp.port_info.local_port_num & p_rec->port_info.local_port_num ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0046: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected local_port_num 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.local_port_num, p_rec->port_info.local_port_num );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.link_width_enabled & p_port->rec.port_info.link_width_enabled ) !=\r
+ ( p_port->comp.port_info.link_width_enabled & p_rec->port_info.link_width_enabled ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0047: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected link_width_enabled 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.link_width_enabled, p_rec->port_info.link_width_enabled );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.link_width_supported & p_port->rec.port_info.link_width_supported ) !=\r
+ ( p_port->comp.port_info.link_width_supported & p_rec->port_info.link_width_supported ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0048: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected link_width_supported 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.link_width_supported, p_rec->port_info.link_width_supported );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.link_width_active & p_port->rec.port_info.link_width_active ) !=\r
+ ( p_port->comp.port_info.link_width_active & p_rec->port_info.link_width_active ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0049: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected link_width_active 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.link_width_active, p_rec->port_info.link_width_active );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=\r
+ ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0054: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.state_info1 & p_port->rec.port_info.state_info1 ) !=\r
+ ( p_port->comp.port_info.state_info1 & p_rec->port_info.state_info1 ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0055: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected state_info1 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.state_info1, p_rec->port_info.state_info1 );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.state_info2 & p_port->rec.port_info.state_info2 ) !=\r
+ ( p_port->comp.port_info.state_info2 & p_rec->port_info.state_info2 ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0058: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected state_info2 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.state_info2, p_rec->port_info.state_info2 );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.mkey_lmc & p_port->rec.port_info.mkey_lmc ) !=\r
+ ( p_port->comp.port_info.mkey_lmc & p_rec->port_info.mkey_lmc ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0059: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected mkey_lmc 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.mkey_lmc, p_rec->port_info.mkey_lmc );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.link_speed & p_port->rec.port_info.link_speed ) !=\r
+ ( p_port->comp.port_info.link_speed & p_rec->port_info.link_speed ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0060: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected link_speed 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.link_speed, p_rec->port_info.link_speed );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.mtu_smsl & p_port->rec.port_info.mtu_smsl ) !=\r
+ ( p_port->comp.port_info.mtu_smsl & p_rec->port_info.mtu_smsl ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0061: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected mtu_smsl 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.mtu_smsl, p_rec->port_info.mtu_smsl );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.vl_cap & p_port->rec.port_info.vl_cap ) !=\r
+ ( p_port->comp.port_info.vl_cap & p_rec->port_info.vl_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0062: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_cap 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_cap, p_rec->port_info.vl_cap );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.vl_high_limit & p_port->rec.port_info.vl_high_limit ) !=\r
+ ( p_port->comp.port_info.vl_high_limit & p_rec->port_info.vl_high_limit ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0082: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_high_limit 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_high_limit, p_rec->port_info.vl_high_limit );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.vl_arb_high_cap & p_port->rec.port_info.vl_arb_high_cap ) !=\r
+ ( p_port->comp.port_info.vl_arb_high_cap & p_rec->port_info.vl_arb_high_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0083: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_arb_high_cap 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_arb_high_cap, p_rec->port_info.vl_arb_high_cap );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.vl_arb_low_cap & p_port->rec.port_info.vl_arb_low_cap ) !=\r
+ ( p_port->comp.port_info.vl_arb_low_cap & p_rec->port_info.vl_arb_low_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0084: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_arb_low_cap 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_arb_low_cap, p_rec->port_info.vl_arb_low_cap );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.mtu_cap & p_port->rec.port_info.mtu_cap ) !=\r
+ ( p_port->comp.port_info.mtu_cap & p_rec->port_info.mtu_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0085: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected mtu_cap 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.mtu_cap, p_rec->port_info.mtu_cap );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+#if 0\r
+ /* this is a dynamic attribute */\r
+ if( ( p_port->comp.port_info.vl_stall_life & p_port->rec.port_info.vl_stall_life ) !=\r
+ ( p_port->comp.port_info.vl_stall_life & p_rec->port_info.vl_stall_life ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 012F: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_stall_life 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_stall_life,\r
+ p_rec->port_info.vl_stall_life );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+#endif\r
+\r
+ if( ( p_port->comp.port_info.vl_enforce & p_port->rec.port_info.vl_enforce ) !=\r
+ ( p_port->comp.port_info.vl_enforce & p_rec->port_info.vl_enforce ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0086: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected vl_enforce 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.vl_enforce, p_rec->port_info.vl_enforce );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.m_key_violations & p_port->rec.port_info.m_key_violations ) !=\r
+ ( p_port->comp.port_info.m_key_violations & p_rec->port_info.m_key_violations ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0087: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected m_key_violations 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ cl_ntoh16( p_port->rec.port_info.m_key_violations ),\r
+ cl_ntoh16( p_rec->port_info.m_key_violations ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.p_key_violations & p_port->rec.port_info.p_key_violations ) !=\r
+ ( p_port->comp.port_info.p_key_violations & p_rec->port_info.p_key_violations ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0088: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected p_key_violations 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ cl_ntoh16( p_port->rec.port_info.p_key_violations ),\r
+ cl_ntoh16( p_rec->port_info.p_key_violations ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.q_key_violations & p_port->rec.port_info.q_key_violations ) !=\r
+ ( p_port->comp.port_info.q_key_violations & p_rec->port_info.q_key_violations ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0089: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected q_key_violations 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ cl_ntoh16( p_port->rec.port_info.q_key_violations ),\r
+ cl_ntoh16( p_rec->port_info.q_key_violations ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.guid_cap & p_port->rec.port_info.guid_cap ) !=\r
+ ( p_port->comp.port_info.guid_cap & p_rec->port_info.guid_cap ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0090: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected guid_cap 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.guid_cap, p_rec->port_info.guid_cap );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.subnet_timeout & p_port->rec.port_info.subnet_timeout ) !=\r
+ ( p_port->comp.port_info.subnet_timeout & p_rec->port_info.subnet_timeout ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0091: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected subnet_timeout 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ ib_port_info_get_timeout(&p_port->rec.port_info),\r
+ ib_port_info_get_timeout(&p_rec->port_info) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.resp_time_value & p_port->rec.port_info.resp_time_value ) !=\r
+ ( p_port->comp.port_info.resp_time_value & p_rec->port_info.resp_time_value ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0092: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected resp_time_value 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.resp_time_value,\r
+ p_rec->port_info.resp_time_value );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ if( ( p_port->comp.port_info.error_threshold & p_port->rec.port_info.error_threshold ) !=\r
+ ( p_port->comp.port_info.error_threshold & p_rec->port_info.error_threshold ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_data: ERR 0093: "\r
+ "Field mismatch port LID 0x%X Num:0x%X\n"\r
+ "\t\t\t\tExpected error_threshold 0x%X, received 0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num,\r
+ p_port->rec.port_info.error_threshold,\r
+ p_rec->port_info.error_threshold );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_port_rec( IN osmtest_t * const p_osmt,\r
+ IN const ib_portinfo_record_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ port_t *p_port;\r
+ const cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_port_rec );\r
+\r
+ /*\r
+ * Find proper port record in the database.\r
+ * (we use by guid - since lid is not unique)\r
+ */\r
+ p_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+ p_port = ( port_t * ) cl_qmap_get( p_tbl, port_gen_id( p_rec->lid, p_rec->port_num));\r
+ if( p_port == ( port_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_port_rec: ERR 0094: "\r
+ "Unexpected port LID 0x%X, Num:0x%X\n",\r
+ cl_ntoh16( p_rec->lid ), p_rec->port_num );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_validate_port_data( p_osmt, p_port, p_rec );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_path_rec( IN osmtest_t * const p_osmt,\r
+ IN const ib_path_rec_t * const p_rec )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ path_t *p_path;\r
+ const cl_qmap_t *p_tbl;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_path_rec );\r
+\r
+ /*\r
+ * Find proper path record in the database.\r
+ */\r
+ p_tbl = &p_osmt->exp_subn.path_tbl;\r
+ p_path =\r
+ ( path_t * ) cl_qmap_get( p_tbl, osmtest_path_rec_key_get( p_rec ) );\r
+ if( p_path == ( path_t * ) cl_qmap_end( p_tbl ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_path_rec: ERR 0095: "\r
+ "Unexpected path SLID 0x%X to DLID 0x%X\n",\r
+ cl_ntoh16( p_rec->slid ), cl_ntoh16( p_rec->dlid ) );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_validate_path_data( p_osmt, p_path, p_rec );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+ib_net64_t portguid = 0;\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_node_recs( IN osmtest_t * const p_osmt )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_node_record_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_node_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all NodeRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_NODE_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_node_recs: ERR 0096: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_all_node_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ /*\r
+ * Compare the received records to the database.\r
+ */\r
+ osmtest_prepare_db( p_osmt );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+\r
+ status = osmtest_validate_node_rec( p_osmt, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_node_recs: ERR 0097: "\r
+ "osmtest_valid_node_rec failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ if (!portguid)\r
+ portguid = p_rec->node_info.port_guid;\r
+ }\r
+\r
+ status = osmtest_check_missing_nodes( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_node_recs: ERR 0098: "\r
+ "osmtest_check_missing_nodes failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_guidinfo_recs( IN osmtest_t * const p_osmt )\r
+{ \r
+ osmtest_req_context_t context;\r
+ const ib_guidinfo_record_t *p_rec;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_guidinfo_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all GuidInfoRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_GUIDINFO_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_guidinfo_recs: ERR 0099: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_all_guidinfo_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ /* No validation as yet */\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_all_path_recs( IN osmtest_t * const p_osmt )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_path_rec_t *p_rec;\r
+ uint32_t i;\r
+ cl_status_t status;\r
+ size_t num_recs;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_all_path_recs );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ /*\r
+ * Do a blocking query for all PathRecords in the subnet.\r
+ */\r
+ status = osmtest_get_all_recs( p_osmt, IB_MAD_ATTR_PATH_RECORD,\r
+ sizeof( *p_rec ), &context );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_path_recs: ERR 009A: "\r
+ "osmtest_get_all_recs failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_all_path_recs: "\r
+ "Received %zu records\n", num_recs );\r
+ }\r
+\r
+ /*\r
+ * Compare the received records to the database.\r
+ */\r
+ osmtest_prepare_db( p_osmt );\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+\r
+ status = osmtest_validate_path_rec( p_osmt, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_path_recs: ERR 0100: "\r
+ "osmtest_validate_path_rec failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ status = osmtest_check_missing_paths( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_all_path_recs: ERR 0101: "\r
+ "osmtest_check_missing_paths failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get link record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_link_rec_by_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const from_lid,\r
+ IN ib_net16_t const to_lid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_link_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_link_rec_by_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_link_rec_by_lid: "\r
+ "Getting link record from LID 0x%02X to LID 0x%02X\n",\r
+ cl_ntoh16( from_lid ), cl_ntoh16( to_lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.from_lid = from_lid;\r
+ record.to_lid = to_lid;\r
+ p_context->p_osmt = p_osmt;\r
+ if (from_lid)\r
+ user.comp_mask |= IB_LR_COMPMASK_FROM_LID;\r
+ if (to_lid)\r
+ user.comp_mask |= IB_LR_COMPMASK_TO_LID;\r
+ user.attr_id = IB_MAD_ATTR_LINK_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_link_rec_by_lid: ERR 007A: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_link_rec_by_lid: ERR 007B: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_link_rec_by_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get GUIDInfo record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_guidinfo_rec_by_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{ \r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_guidinfo_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_guidinfo_rec_by_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_guidinfo_rec_by_lid: "\r
+ "Getting GUIDInfo record for LID 0x%02X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_GIR_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_GUIDINFO_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_guidinfo_rec_by_lid: ERR 007C: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_guidinfo_rec_by_lid: ERR 007D: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_guidinfo_rec_by_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get PKeyTable record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_pkeytbl_rec_by_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN ib_net64_t const sm_key,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_pkey_table_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_pkeytbl_rec_by_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_pkeytbl_rec_by_lid: "\r
+ "Getting PKeyTable record for LID 0x%02X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_PKEY_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_PKEY_TBL_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = sm_key;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_pkeytbl_rec_by_lid: ERR 007E: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_pkeytbl_rec_by_lid: ERR 007F: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_pkeytbl_rec_by_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ * Get LFT record by LID\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_get_lft_rec_by_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_lft_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_lft_rec_by_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_get_lft_rec_by_lid: "\r
+ "Getting LFT record for LID 0x%02X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ /*\r
+ * Do a blocking query for this record in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+ p_context->p_osmt = p_osmt;\r
+ user.comp_mask = IB_LFTR_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_LFT_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_lft_rec_by_lid: ERR 008A: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_lft_rec_by_lid: ERR 008B: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_lft_rec_by_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_sminfo_record_request(\r
+ IN osmtest_t * const p_osmt,\r
+ IN OUT osmtest_req_context_t * const p_context )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_sminfo_record_t record;\r
+ ib_mad_t *p_mad;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_sminfo_record_request );\r
+\r
+ /*\r
+ * Do a blocking query for these records in the subnet.\r
+ * The result is returned in the result field of the caller's\r
+ * context structure.\r
+ *\r
+ * The query structures are locals.\r
+ */\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ p_context->p_osmt = p_osmt;\r
+ user.attr_id = IB_MAD_ATTR_SMINFO_RECORD;\r
+ user.attr_offset = cl_ntoh16( ( uint16_t ) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = p_context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_sminfo_record_request: ERR 008C: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = p_context->result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_sminfo_record_request: ERR 008D: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ p_mad = osm_madw_get_mad_ptr( p_context->result.p_result_madw );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_sminfo_record_request: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( p_mad ));\r
+\r
+ status = (ib_net16_t) (p_mad->status & IB_SMP_STATUS_MASK );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+#endif\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_rec_lid_pair( IN osmtest_t * const p_osmt,\r
+ IN path_t * const p_path )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_path_rec_t *p_rec;\r
+ cl_status_t status = IB_SUCCESS;\r
+ size_t num_recs;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_lid_pair );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt,\r
+ p_path->rec.slid,\r
+ p_path->rec.dlid,\r
+ &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_lid_pair: ERR 0102: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+ if( num_recs != 1 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_lid_pair: ERR 0103: "\r
+ "Too many records. Expected 1, received %zu\n", num_recs );\r
+\r
+ status = IB_ERROR;\r
+ }\r
+ else\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, 0 );\r
+\r
+ status = osmtest_validate_path_data( p_osmt, p_path, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_lid_pair: ERR 0104: "\r
+ "osmtest_validate_path_data failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_node_rec_lid( IN osmtest_t * const p_osmt,\r
+ IN ib_net16_t const lid,\r
+ IN node_t * const p_node )\r
+{\r
+ cl_status_t status = IB_SUCCESS;\r
+ osmv_user_query_t user;\r
+ osmv_query_req_t req;\r
+ ib_node_record_t record;\r
+\r
+ osmtest_req_context_t context;\r
+ const ib_node_record_t *p_rec;\r
+ int num_recs, i;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_rec_lid );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_validate_single_node_rec_lid: "\r
+ "Getting NodeRecord for node with LID 0x%X\n",\r
+ cl_ntoh16( lid ) );\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &user, 0, sizeof( user ) );\r
+ memset( &record, 0, sizeof( record ) );\r
+\r
+ record.lid = lid;\r
+\r
+ context.p_osmt = p_osmt;\r
+ user.comp_mask = IB_NR_COMPMASK_LID;\r
+ user.attr_id = IB_MAD_ATTR_NODE_RECORD;\r
+ user.attr_offset = cl_ntoh16( (uint16_t) ( sizeof( record ) >> 3 ) );\r
+ user.p_attr = &record;\r
+\r
+ req.query_type = OSMV_QUERY_USER_DEFINED;\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = &context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+ req.p_query_input = &user;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_rec_lid: ERR 0105: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = context.result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_rec_lid: ERR 0106: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_rec_lid: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( context.result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_node_rec_lid: "\r
+ "Received %d nodes\n", num_recs);\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_node_rec( context.result.p_result_madw, i );\r
+\r
+ status = osmtest_validate_node_rec( p_osmt, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_rec_lid: ERR 0107: "\r
+ "osmtest_validate_node_data failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_port_rec_lid( IN osmtest_t * const p_osmt,\r
+ IN port_t * const p_port )\r
+{\r
+ osmtest_req_context_t context;\r
+\r
+ const ib_portinfo_record_t *p_rec;\r
+ cl_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_rec_lid );\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ context.p_osmt = p_osmt;\r
+ osmtest_get_port_rec_by_num( p_osmt,\r
+ p_port->rec.lid,\r
+ p_port->rec.port_num,\r
+ &context);\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_port_rec_lid: ERR 0108: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ goto Exit;\r
+ }\r
+\r
+ /* we should have got exactly one port */\r
+ p_rec = osmv_get_query_portinfo_rec( context.result.p_result_madw, 0);\r
+ status = osmtest_validate_port_rec( p_osmt, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_port_rec_lid: ERR 0109: "\r
+ "osmtest_validate_port_data failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_rec_guid_pair( IN osmtest_t * const p_osmt,\r
+ IN const osmv_guid_pair_t *\r
+ const p_pair )\r
+{\r
+ osmtest_req_context_t context;\r
+ const ib_path_rec_t *p_rec;\r
+ cl_status_t status = IB_SUCCESS;\r
+ size_t num_recs;\r
+ osmv_query_req_t req;\r
+ uint32_t i;\r
+ boolean_t got_error = FALSE;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_rec_guid_pair );\r
+\r
+ memset( &req, 0, sizeof( req ) );\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: "\r
+ "\n\t\t\t\tChecking src 0x%016" PRIx64\r
+ " to dest 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pair->src_guid ),\r
+ cl_ntoh64( p_pair->dest_guid ) );\r
+ }\r
+\r
+ context.p_osmt = p_osmt;\r
+\r
+ req.timeout_ms = p_osmt->opt.transaction_timeout;\r
+ req.retry_cnt = p_osmt->opt.retry_count;\r
+ req.flags = OSM_SA_FLAGS_SYNC;\r
+ req.query_context = &context;\r
+ req.pfn_query_cb = osmtest_query_res_cb;\r
+\r
+ req.query_type = OSMV_QUERY_PATH_REC_BY_PORT_GUIDS;\r
+ req.p_query_input = p_pair;\r
+ req.sm_key = 0;\r
+\r
+ status = osmv_query_sa( p_osmt->h_bind, &req );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: ERR 0110: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = context.result.status;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: ERR 0111: "\r
+ "ib_query failed (%s)\n", ib_get_err_str( status ) );\r
+\r
+ if( status == IB_REMOTE_ERROR )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: "\r
+ "Remote error = %s\n",\r
+ ib_get_mad_status_str( osm_madw_get_mad_ptr\r
+ ( context.result.p_result_madw ) ) );\r
+ }\r
+ goto Exit;\r
+ }\r
+\r
+ num_recs = context.result.result_cnt;\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_path_rec_guid_pair: %zu records\n",\r
+ num_recs);\r
+\r
+ for( i = 0; i < num_recs; i++ )\r
+ {\r
+ p_rec = osmv_get_query_path_rec( context.result.p_result_madw, i );\r
+\r
+ /*\r
+ * Make sure the GUID values are correct\r
+ */\r
+ if( p_rec->dgid.unicast.interface_id != p_pair->dest_guid )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: ERR 0112: "\r
+ "Destination GUID mismatch\n"\r
+ "\t\t\t\texpected 0x%016" PRIx64\r
+ ", received 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_pair->dest_guid ),\r
+ cl_ntoh64( p_rec->dgid.unicast.interface_id ) );\r
+ got_error = TRUE;\r
+ }\r
+\r
+ if( p_rec->sgid.unicast.interface_id != p_pair->src_guid )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: ERR 0113: "\r
+ "Source GUID mismatch\n"\r
+ "\t\t\t\texpected 0x%016" PRIx64\r
+ ", received 0x%016" PRIx64 ".\n",\r
+ cl_ntoh64( p_pair->src_guid ),\r
+ cl_ntoh64( p_rec->sgid.unicast.interface_id ) );\r
+ got_error = TRUE;\r
+ }\r
+\r
+ status = osmtest_validate_path_rec( p_osmt, p_rec );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_rec_guid_pair: ERR 0114: "\r
+ "osmtest_validate_path_rec failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ got_error = TRUE;\r
+ }\r
+ if( got_error || (status != IB_SUCCESS) )\r
+ {\r
+ osm_dump_path_record( &p_osmt->log, p_rec, OSM_LOG_VERBOSE );\r
+ if( status == IB_SUCCESS )\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ /*\r
+ * Return the IB query MAD to the pool as necessary.\r
+ */\r
+ if( context.result.p_result_madw != NULL )\r
+ {\r
+ osm_mad_pool_put( &p_osmt->mad_pool, context.result.p_result_madw );\r
+ context.result.p_result_madw = NULL;\r
+ }\r
+\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_path_recs( IN osmtest_t * const p_osmt )\r
+{\r
+ path_t *p_path;\r
+ cl_status_t status = IB_SUCCESS;\r
+ const cl_qmap_t *p_path_tbl;\r
+/* We skip node to node path record validation since it might contains \r
+ NONEXISTENT PATHS, i.e. when using UPDN */\r
+ osmv_guid_pair_t guid_pair;\r
+ uint16_t cnt;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_path_recs );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_path_recs: "\r
+ "Validating individual path record queries\n" );\r
+ }\r
+ p_path_tbl = &p_osmt->exp_subn.path_tbl;\r
+\r
+ osmtest_prepare_db( p_osmt );\r
+\r
+ /*\r
+ * Walk the list of all path records, and ask for each one\r
+ * specifically. Make sure we get it.\r
+ */\r
+ cnt = 0;\r
+ p_path = ( path_t * ) cl_qmap_head( p_path_tbl );\r
+ while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )\r
+ {\r
+ status = osmtest_validate_single_path_rec_lid_pair( p_osmt, p_path );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+ cnt++;\r
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_path_recs: "\r
+ "Total of %u path records validated using LID based query\n", cnt );\r
+ }\r
+\r
+ status = osmtest_check_missing_paths( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_recs: ERR 0115: "\r
+ "osmtest_check_missing_paths failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Do the whole thing again with port GUID pairs.\r
+ * Note that multiple path records may be returned\r
+ * for each guid pair if LMC > 0.\r
+ */\r
+ osmtest_prepare_db( p_osmt );\r
+ cnt = 0;\r
+ p_path = ( path_t * ) cl_qmap_head( p_path_tbl );\r
+ while( p_path != ( path_t * ) cl_qmap_end( p_path_tbl ) )\r
+ {\r
+ guid_pair.src_guid = p_path->rec.sgid.unicast.interface_id;\r
+ guid_pair.dest_guid = p_path->rec.dgid.unicast.interface_id;\r
+ status = osmtest_validate_single_path_rec_guid_pair( p_osmt,\r
+ &guid_pair );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+ cnt++;\r
+ p_path = ( path_t * ) cl_qmap_next( &p_path->map_item );\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_path_recs: "\r
+ "Total of %u path records validated using GUID based query\n", cnt );\r
+ }\r
+\r
+ status = osmtest_check_missing_paths( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_path_recs: ERR 0116: "\r
+ "osmtest_check_missing_paths failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_node_recs( IN osmtest_t * const p_osmt )\r
+{\r
+ node_t *p_node;\r
+ cl_status_t status = IB_SUCCESS;\r
+ const cl_qmap_t *p_node_lid_tbl;\r
+ uint16_t cnt = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_node_recs );\r
+\r
+ p_node_lid_tbl = &p_osmt->exp_subn.node_lid_tbl;\r
+\r
+ osmtest_prepare_db( p_osmt );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_node_recs: "\r
+ "Validating individual node record queries\n" );\r
+ }\r
+\r
+ /*\r
+ * Walk the list of all node records, and ask for each one\r
+ * specifically. Make sure we get it.\r
+ */\r
+ p_node = ( node_t * ) cl_qmap_head( p_node_lid_tbl );\r
+ while( p_node != ( node_t * ) cl_qmap_end( p_node_lid_tbl ) )\r
+ {\r
+ status = osmtest_validate_single_node_rec_lid( p_osmt,\r
+ (ib_net16_t) cl_qmap_key ((cl_map_item_t*)p_node),\r
+ p_node );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_recs: ERR 011A: "\r
+ "osmtest_validate_single_node_rec_lid (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ cnt++;\r
+ p_node = ( node_t * ) cl_qmap_next( &p_node->map_item );\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_node_recs: "\r
+ "Total of %u node records validated\n", cnt );\r
+ }\r
+\r
+ status = osmtest_check_missing_nodes( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_node_recs: ERR 0117: "\r
+ "osmtest_check_missing_nodes (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_single_port_recs( IN osmtest_t * const p_osmt )\r
+{\r
+ port_t *p_port;\r
+ cl_status_t status = IB_SUCCESS;\r
+ const cl_qmap_t *p_port_key_tbl;\r
+ uint16_t cnt = 0;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_single_port_recs );\r
+\r
+ p_port_key_tbl = &p_osmt->exp_subn.port_key_tbl;\r
+\r
+ osmtest_prepare_db( p_osmt );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_port_recs: "\r
+ "Validating individual port record queries\n" );\r
+ }\r
+\r
+ /*\r
+ * Walk the list of all port records, and ask for each one\r
+ * specifically. Make sure we get it.\r
+ */\r
+ p_port = ( port_t * ) cl_qmap_head( p_port_key_tbl );\r
+ while( p_port != ( port_t * ) cl_qmap_end( p_port_key_tbl ) )\r
+ {\r
+ status = osmtest_validate_single_port_rec_lid( p_osmt, p_port );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_port_recs: ERR 011B: "\r
+ "osmtest_validate_single_port_rec_lid (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ cnt++;\r
+ p_port = ( port_t * ) cl_qmap_next( &p_port->map_item );\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_VERBOSE ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_VERBOSE,\r
+ "osmtest_validate_single_port_recs: "\r
+ "Total of %u port records validated\n", cnt );\r
+ }\r
+\r
+ status = osmtest_check_missing_ports( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_validate_single_port_recs: ERR 0118: "\r
+ "osmtest_check_missing_paths failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_validate_against_db( IN osmtest_t * const p_osmt )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ ib_gid_t portgid, mgid;\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+ ib_net64_t sm_key;\r
+ ib_net16_t test_lid;\r
+ uint8_t lmc;\r
+ osmtest_req_context_t context;\r
+#ifdef DUAL_SIDED_RMPP\r
+ osmv_multipath_req_t request;\r
+#endif\r
+#endif\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_validate_against_db );\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+ status = osmtest_validate_all_node_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+#endif\r
+\r
+ status = osmtest_validate_single_node_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Exercise SA PathRecord multicast destination code */\r
+ memset( &context, 0, sizeof( context ) );\r
+ ib_gid_set_default( &portgid, portguid );\r
+ /* Set IPoIB broadcast MGID */\r
+ mgid.unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+ mgid.unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+ /* Can't check status as don't know whether port is running IPoIB */\r
+ osmtest_get_path_rec_by_gid_pair( p_osmt, portgid, mgid, &context);\r
+\r
+#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &request, 0, sizeof( request ) );\r
+ request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+ request.sgid_count = 1;\r
+ request.dgid_count = 1;\r
+ ib_gid_set_default( &request.gids[0], portguid );\r
+ ib_gid_set_default( &request.gids[1], portguid );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &request, 0, sizeof( request ) );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &request, 0, sizeof( request ) );\r
+ request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT;\r
+ request.sgid_count = 1;\r
+ ib_gid_set_default( &request.gids[0], portguid );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &request, 0, sizeof( request ) );\r
+ request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+ request.sgid_count = 1;\r
+ request.dgid_count = 1;\r
+ ib_gid_set_default( &request.gids[0], portguid );\r
+ /* Set IPoIB broadcast MGID */\r
+ request.gids[1].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+ request.gids[1].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT;\r
+ request.sgid_count = 1;\r
+ request.dgid_count = 1;\r
+ /* Set IPoIB broadcast MGID */\r
+ request.gids[0].unicast.prefix = CL_HTON64(0xff12401bffff0000ULL);\r
+ request.gids[0].unicast.interface_id = CL_HTON64(0x00000000ffffffffULL);\r
+ ib_gid_set_default( &request.gids[1], portguid );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ memset( &request, 0, sizeof( request ) );\r
+ request.comp_mask = IB_MPR_COMPMASK_SGIDCOUNT | IB_MPR_COMPMASK_DGIDCOUNT |\r
+ IB_MPR_COMPMASK_NUMBPATH;\r
+ request.sgid_count = 2;\r
+ request.dgid_count = 2;\r
+ request.num_path = 2;\r
+ ib_gid_set_default( &request.gids[0], portguid );\r
+ ib_gid_set_default( &request.gids[1], portguid );\r
+ ib_gid_set_default( &request.gids[2], portguid );\r
+ ib_gid_set_default( &request.gids[3], portguid );\r
+ status = osmtest_get_multipath_rec( p_osmt, &request, &context );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+#endif\r
+\r
+#ifdef VENDOR_RMPP_SUPPORT\r
+ /* GUIDInfoRecords */\r
+ status = osmtest_validate_all_guidinfo_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* If LMC > 0, test non base LID SA PortInfoRecord request */\r
+ status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid, &lmc );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ if (lmc != 0)\r
+ {\r
+ status = osmtest_get_local_port_lmc( p_osmt, p_osmt->local_port.lid + 1, NULL );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_get_local_port_lmc( p_osmt, 0xffff, NULL );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ test_lid = cl_ntoh16( p_osmt->local_port.lid );\r
+\r
+ /* More GUIDInfo Record tests */\r
+ memset( &context, 0, sizeof( context ) ); \r
+ status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_guidinfo_rec_by_lid( p_osmt, 0xffff, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Some PKeyTable Record tests */\r
+ sm_key = OSM_DEFAULT_SM_KEY;\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_multipath_rec: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, 0xffff, sm_key, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* LFT Record test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Some LinkRecord tests */\r
+ /* FromLID */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* ToLID */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* FromLID & ToLID */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* NodeRecord test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_node_rec_by_lid( p_osmt, 0xffff , &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* SMInfoRecord test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_sminfo_record_request( p_osmt, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ if (lmc != 0)\r
+ {\r
+ test_lid = cl_ntoh16( p_osmt->local_port.lid + 1 );\r
+\r
+ /* Another GUIDInfo Record test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_guidinfo_rec_by_lid( p_osmt, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Another PKeyTable Record test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_pkeytbl_rec_by_lid( p_osmt, test_lid, sm_key, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Another LFT Record test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_lft_rec_by_lid( p_osmt, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* More LinkRecord tests */\r
+ /* FromLID */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_link_rec_by_lid( p_osmt, test_lid, 0, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* ToLID */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_link_rec_by_lid( p_osmt, 0, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ /* Another NodeRecord test */\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_node_rec_by_lid( p_osmt, test_lid, &context );\r
+ if ( status != IB_SUCCESS )\r
+ goto Exit;\r
+ }\r
+\r
+ /* PathRecords */\r
+ if (! p_osmt->opt.ignore_path_records)\r
+ {\r
+ status = osmtest_validate_all_path_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ if (lmc != 0)\r
+ {\r
+ memset( &context, 0, sizeof( context ) );\r
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid,\r
+ test_lid, &context );\r
+ if (status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ memset( &context, 0, sizeof( context ) );\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" );\r
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt, 0xffff,\r
+ 0xffff, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_START "\n" );\r
+\r
+ status = osmtest_get_path_rec_by_lid_pair( p_osmt, test_lid,\r
+ 0xffff, &context );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: "\r
+ "Got error %s\n", ib_get_err_str(status) );\r
+ }\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_get_path_rec_by_lid_pair: " EXPECTING_ERRORS_END "\n" );\r
+\r
+ if( status == IB_SUCCESS )\r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+ status = osmtest_validate_single_port_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+\r
+ if (! p_osmt->opt.ignore_path_records)\r
+ {\r
+ status = osmtest_validate_single_path_recs( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static const osmtest_token_t *\r
+str_get_token( IN char *const p_str )\r
+{\r
+ const osmtest_token_t *p_tok;\r
+ uint32_t index = 0;\r
+\r
+ p_tok = &token_array[index];\r
+\r
+ while( p_tok->val != OSMTEST_TOKEN_UNKNOWN )\r
+ {\r
+ if( strnicmp( p_str, p_tok->str, p_tok->str_size ) == 0 )\r
+ return ( p_tok );\r
+\r
+ p_tok = &token_array[++index];\r
+ }\r
+\r
+ return ( NULL );\r
+}\r
+\r
+/**********************************************************************\r
+ Returns true if not whitespace character encountered before EOL.\r
+**********************************************************************/\r
+static boolean_t\r
+str_skip_white( IN char line[],\r
+ IN OUT uint32_t * const p_offset )\r
+{\r
+ while( ( ( line[*p_offset] == '\t' ) ||\r
+ ( line[*p_offset] == ' ' ) ) &&\r
+ ( line[*p_offset] != '\n' ) && ( line[*p_offset] != '\0' ) )\r
+ {\r
+ ++*p_offset;\r
+ }\r
+\r
+ if( ( line[*p_offset] == '\n' ) || ( line[*p_offset] == '\0' ) )\r
+ return ( FALSE );\r
+ else\r
+ return ( TRUE );\r
+}\r
+\r
+/**********************************************************************\r
+ Returns true if not whitespace character encountered before EOL.\r
+**********************************************************************/\r
+static void\r
+str_skip_token( IN char line[],\r
+ IN OUT uint32_t * const p_offset )\r
+{\r
+ while( ( line[*p_offset] != '\t' ) &&\r
+ ( line[*p_offset] != ' ' ) && ( line[*p_offset] != '\0' ) )\r
+ {\r
+ ++*p_offset;\r
+ }\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_node( IN osmtest_t * const p_osmt,\r
+ IN FILE * const fh,\r
+ IN OUT uint32_t * const p_line_num )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint32_t offset;\r
+ char line[OSMTEST_MAX_LINE_LEN];\r
+ boolean_t done = FALSE;\r
+ node_t *p_node;\r
+ node_t *p_guid_node;\r
+ const osmtest_token_t *p_tok;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_node );\r
+\r
+ p_node = node_new( );\r
+ CL_ASSERT( p_node != NULL );\r
+\r
+ /*\r
+ * Parse the inventory file and create the database.\r
+ */\r
+ while( !done )\r
+ {\r
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+ {\r
+ /*\r
+ * End of file in the middle of a definition.\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_node: ERR 0119: "\r
+ "Unexpected end of file\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++*p_line_num;\r
+\r
+ /*\r
+ * Skip whitespace\r
+ */\r
+ offset = 0;\r
+ if( !str_skip_white( line, &offset ) )\r
+ continue; /* whole line was whitespace */\r
+\r
+ p_tok = str_get_token( &line[offset] );\r
+ if( p_tok == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_node: ERR 0120: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ continue;\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+ }\r
+\r
+ str_skip_token( line, &offset );\r
+\r
+ switch ( p_tok->val )\r
+ {\r
+ case OSMTEST_TOKEN_COMMENT:\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LID:\r
+ p_node->comp.lid = 0xFFFF;\r
+ p_node->rec.lid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "lid = 0x%X\n", cl_ntoh16( p_node->rec.lid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_BASE_VERSION:\r
+ p_node->comp.node_info.base_version = 0xFF;\r
+ p_node->rec.node_info.base_version =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "base_version = 0x%X\n",\r
+ p_node->rec.node_info.base_version );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_CLASS_VERSION:\r
+ p_node->comp.node_info.class_version = 0xFF;\r
+ p_node->rec.node_info.class_version =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "class_version = 0x%X\n",\r
+ p_node->rec.node_info.class_version );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_NODE_TYPE:\r
+ p_node->comp.node_info.node_type = 0xFF;\r
+ p_node->rec.node_info.node_type =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "node_type = 0x%X\n",\r
+ p_node->rec.node_info.node_type );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_NUM_PORTS:\r
+ p_node->comp.node_info.num_ports = 0xFF;\r
+ p_node->rec.node_info.num_ports =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "num_ports = 0x%X\n",\r
+ p_node->rec.node_info.num_ports );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SYS_GUID:\r
+ p_node->comp.node_info.sys_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_node->rec.node_info.sys_guid =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "sys_guid = 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_node->rec.node_info.sys_guid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_NODE_GUID:\r
+ p_node->comp.node_info.node_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_node->rec.node_info.node_guid =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "node_guid = 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_node->rec.node_info.node_guid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PORT_GUID:\r
+ p_node->comp.node_info.port_guid = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_node->rec.node_info.port_guid =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "port_guid = 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_node->rec.node_info.port_guid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PARTITION_CAP:\r
+ p_node->comp.node_info.partition_cap = 0xFFFF;\r
+ p_node->rec.node_info.partition_cap = cl_hton16( ( uint16_t )\r
+ strtoul( &line[offset],\r
+ NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "partition_cap = 0x%X\n",\r
+ cl_ntoh16( p_node->rec.node_info.partition_cap ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DEVICE_ID:\r
+ p_node->comp.node_info.device_id = 0xFFFF;\r
+ p_node->rec.node_info.device_id = cl_hton16( ( uint16_t )\r
+ strtoul( &line[offset],\r
+ NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "device_id = 0x%X\n",\r
+ cl_ntoh16( p_node->rec.node_info.device_id ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_REVISION:\r
+ p_node->comp.node_info.revision = 0xFFFFFFFF;\r
+ p_node->rec.node_info.revision =\r
+ cl_hton32( strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "revision = 0x%X\n",\r
+ cl_ntoh32( p_node->rec.node_info.revision ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PORT_NUM:\r
+ p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_PORT_NUM_MASK;\r
+ p_node->rec.node_info.port_num_vendor_id |=\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "local_port_num = 0x%X\n",\r
+ ib_node_info_get_local_port_num( &p_node->rec.\r
+ node_info ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VENDOR_ID:\r
+ p_node->comp.node_info.port_num_vendor_id |= IB_NODE_INFO_VEND_ID_MASK;\r
+ p_node->rec.node_info.port_num_vendor_id |=\r
+ cl_hton32( strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_node: "\r
+ "vendor_id = 0x%X\n",\r
+ cl_ntoh32( ib_node_info_get_vendor_id\r
+ ( &p_node->rec.node_info ) ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_END:\r
+ done = TRUE;\r
+ break;\r
+\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_node: ERR 0121: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Make sure the user specified enough information, then\r
+ * add this object to the database.\r
+ */\r
+ if( p_node->comp.lid == 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_node: ERR 0122: "\r
+ "LID must be specified for defined nodes\n" );\r
+ node_delete( p_node );\r
+ goto Exit;\r
+ }\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.node_lid_tbl,\r
+ p_node->rec.lid, &p_node->map_item );\r
+\r
+ p_guid_node = node_new( );\r
+ CL_ASSERT( p_node != NULL );\r
+\r
+ *p_guid_node = *p_node;\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.node_guid_tbl,\r
+ p_guid_node->rec.node_info.node_guid,\r
+ &p_guid_node->map_item );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_port( IN osmtest_t * const p_osmt,\r
+ IN FILE * const fh,\r
+ IN OUT uint32_t * const p_line_num )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint32_t offset;\r
+ char line[OSMTEST_MAX_LINE_LEN];\r
+ boolean_t done = FALSE;\r
+ port_t *p_port;\r
+ const osmtest_token_t *p_tok;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_port );\r
+\r
+ p_port = port_new( );\r
+ CL_ASSERT( p_port != NULL );\r
+\r
+ /*\r
+ * Parse the inventory file and create the database.\r
+ */\r
+ while( !done )\r
+ {\r
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+ {\r
+ /*\r
+ * End of file in the middle of a definition.\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_port: ERR 0123: "\r
+ "Unexpected end of file\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++*p_line_num;\r
+\r
+ /*\r
+ * Skip whitespace\r
+ */\r
+ offset = 0;\r
+ if( !str_skip_white( line, &offset ) )\r
+ continue; /* whole line was whitespace */\r
+\r
+ p_tok = str_get_token( &line[offset] );\r
+ if( p_tok == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_port: ERR 0124: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ continue;\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+ }\r
+\r
+ str_skip_token( line, &offset );\r
+\r
+ switch ( p_tok->val )\r
+ {\r
+ case OSMTEST_TOKEN_COMMENT:\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LID:\r
+ p_port->comp.lid = 0xFFFF;\r
+ p_port->rec.lid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "lid = 0x%X\n", cl_ntoh16( p_port->rec.lid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PORT_NUM:\r
+ p_port->comp.port_num = 0xFF;\r
+ p_port->rec.port_num =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "port_num = 0x%u\n",\r
+ p_port->rec.port_num );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MKEY:\r
+ p_port->comp.port_info.m_key = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_port->rec.port_info.m_key =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "m_key = 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_port->rec.port_info.m_key ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SUBN_PREF:\r
+ p_port->comp.port_info.subnet_prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_port->rec.port_info.subnet_prefix =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "subnet_prefix = 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_port->rec.port_info.subnet_prefix ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_BASE_LID:\r
+ p_port->comp.port_info.base_lid = 0xFFFF;\r
+ p_port->rec.port_info.base_lid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "base_lid = 0x%X\n", cl_ntoh16( p_port->rec.port_info.base_lid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SM_BASE_LID:\r
+ p_port->comp.port_info.master_sm_base_lid = 0xFFFF;\r
+ p_port->rec.port_info.master_sm_base_lid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "master_sm_base_lid = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.master_sm_base_lid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_CAP_MASK:\r
+ p_port->comp.port_info.capability_mask = 0xFFFFFFFF;\r
+ p_port->rec.port_info.capability_mask =\r
+ cl_hton32( ( uint32_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "capability_mask = 0x%X\n",\r
+ cl_ntoh32( p_port->rec.port_info.capability_mask ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DIAG_CODE:\r
+ p_port->comp.port_info.diag_code = 0xFFFF;\r
+ p_port->rec.port_info.diag_code =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "diag_code = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.diag_code ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MKEY_LEASE_PER:\r
+ p_port->comp.port_info.m_key_lease_period = 0xFFFF;\r
+ p_port->rec.port_info.m_key_lease_period =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "m_key_lease_period = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.m_key_lease_period ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LOC_PORT_NUM:\r
+ p_port->comp.port_info.local_port_num = 0xFF;\r
+ p_port->rec.port_info.local_port_num =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "local_port_num = 0x%u\n",\r
+ p_port->rec.port_info.local_port_num );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LINK_WID_EN:\r
+ p_port->comp.port_info.link_width_enabled = 0xFF;\r
+ p_port->rec.port_info.link_width_enabled =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "link_width_enabled = 0x%u\n",\r
+ p_port->rec.port_info.link_width_enabled );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LINK_WID_SUP:\r
+ p_port->comp.port_info.link_width_supported = 0xFF;\r
+ p_port->rec.port_info.link_width_supported =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "link_width_supported = 0x%u\n",\r
+ p_port->rec.port_info.link_width_supported );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LINK_WID_ACT:\r
+ p_port->comp.port_info.link_width_active = 0xFF;\r
+ p_port->rec.port_info.link_width_active =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "link_width_active = 0x%u\n",\r
+ p_port->rec.port_info.link_width_active );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LINK_SPEED_SUP:\r
+ p_port->comp.port_info.state_info1 = 0xFF;\r
+ ib_port_info_set_link_speed_sup( ( uint8_t ) strtoul( &line[offset],\r
+ NULL, 0 ),\r
+ &p_port->rec.port_info);\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "link_speed_supported = 0x%u\n",\r
+ ib_port_info_get_link_speed_sup(&p_port->rec.port_info));\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PORT_STATE:\r
+ str_skip_white( line, &offset );\r
+ p_port->comp.port_info.state_info1 = 0xFF;\r
+ ib_port_info_set_port_state(&p_port->rec.port_info,\r
+ ib_get_port_state_from_str(&line[offset]));\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "port_state = 0x%u\n",\r
+ ib_port_info_get_port_state(&p_port->rec.port_info));\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_STATE_INFO2:\r
+ p_port->comp.port_info.state_info2 = 0xFF;\r
+ p_port->rec.port_info.state_info2 =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "state_info2 = 0x%u\n",\r
+ p_port->rec.port_info.state_info2 );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MKEY_PROT_BITS:\r
+ p_port->comp.port_info.mkey_lmc = 0xFF;\r
+ ib_port_info_set_mpb( &p_port->rec.port_info,\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "mpb = 0x%u\n",\r
+ ib_port_info_get_mpb(&p_port->rec.port_info) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LMC:\r
+ p_port->comp.port_info.mkey_lmc = 0xFF;\r
+ ib_port_info_set_lmc( &p_port->rec.port_info,\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 ) );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "lmc = 0x%u\n",\r
+ ib_port_info_get_lmc(&p_port->rec.port_info) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_LINK_SPEED:\r
+ p_port->comp.port_info.link_speed = 0xFF;\r
+ p_port->rec.port_info.link_speed =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "link_speed = 0x%u\n",\r
+ p_port->rec.port_info.link_speed );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MTU_SMSL:\r
+ p_port->comp.port_info.mtu_smsl = 0xFF;\r
+ p_port->rec.port_info.mtu_smsl =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "mtu_smsl = 0x%u\n",\r
+ p_port->rec.port_info.mtu_smsl );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_CAP:\r
+ p_port->comp.port_info.vl_cap = 0xFF;\r
+ p_port->rec.port_info.vl_cap =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_cap = 0x%u\n",\r
+ p_port->rec.port_info.vl_cap );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_HIGH_LIMIT:\r
+ p_port->comp.port_info.vl_high_limit = 0xFF;\r
+ p_port->rec.port_info.vl_high_limit =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_high_limit = 0x%u\n",\r
+ p_port->rec.port_info.vl_high_limit );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_ARB_HIGH_CAP:\r
+ p_port->comp.port_info.vl_arb_high_cap = 0xFF;\r
+ p_port->rec.port_info.vl_arb_high_cap =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_arb_high_cap = 0x%u\n",\r
+ p_port->rec.port_info.vl_arb_high_cap );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_ARB_LOW_CAP:\r
+ p_port->comp.port_info.vl_arb_low_cap = 0xFF;\r
+ p_port->rec.port_info.vl_arb_low_cap =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_arb_low_cap = 0x%u\n",\r
+ p_port->rec.port_info.vl_arb_low_cap );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MTU_CAP:\r
+ p_port->comp.port_info.mtu_cap = 0xFF;\r
+ p_port->rec.port_info.mtu_cap =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "mtu_cap = 0x%u\n",\r
+ p_port->rec.port_info.mtu_cap );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_STALL_LIFE:\r
+ p_port->comp.port_info.vl_stall_life = 0xFF;\r
+ p_port->rec.port_info.vl_stall_life =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_stall_life = 0x%u\n",\r
+ p_port->rec.port_info.vl_stall_life );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_VL_ENFORCE:\r
+ p_port->comp.port_info.vl_enforce = 0xFF;\r
+ p_port->rec.port_info.vl_enforce =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "vl_enforce = 0x%u\n",\r
+ p_port->rec.port_info.vl_enforce );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_MKEY_VIOL:\r
+ p_port->comp.port_info.m_key_violations = 0xFFFF;\r
+ p_port->rec.port_info.m_key_violations =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "m_key_violations = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.m_key_violations ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PKEY_VIOL:\r
+ p_port->comp.port_info.p_key_violations = 0xFFFF;\r
+ p_port->rec.port_info.p_key_violations =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "p_key_violations = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.p_key_violations ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_QKEY_VIOL:\r
+ p_port->comp.port_info.q_key_violations = 0xFFFF;\r
+ p_port->rec.port_info.q_key_violations =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "q_key_violations = 0x%X\n",\r
+ cl_ntoh16( p_port->rec.port_info.q_key_violations ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_GUID_CAP:\r
+ p_port->comp.port_info.guid_cap = 0xFF;\r
+ p_port->rec.port_info.guid_cap =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "guid_cap = 0x%u\n",\r
+ p_port->rec.port_info.guid_cap );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SUBN_TIMEOUT:\r
+ p_port->comp.port_info.subnet_timeout = 0x1F;\r
+ p_port->rec.port_info.subnet_timeout =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "subnet_timeout = 0x%u\n",\r
+ ib_port_info_get_timeout(&p_port->rec.port_info) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_RESP_TIME_VAL:\r
+ p_port->comp.port_info.resp_time_value = 0xFF;\r
+ p_port->rec.port_info.resp_time_value =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "resp_time_value = 0x%u\n",\r
+ p_port->rec.port_info.resp_time_value );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_ERR_THRESHOLD:\r
+ p_port->comp.port_info.error_threshold = 0xFF;\r
+ p_port->rec.port_info.error_threshold =\r
+ ( uint8_t ) strtoul( &line[offset], NULL, 0 );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_port: "\r
+ "error_threshold = 0x%u\n",\r
+ p_port->rec.port_info.error_threshold );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_END:\r
+ done = TRUE;\r
+ break;\r
+\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_port: ERR 0125: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ break;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Make sure the user specified enough information, then\r
+ * add this object to the database.\r
+ */\r
+ if( p_port->comp.lid == 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_port: ERR 0126: "\r
+ "LID must be specified for defined ports\n" );\r
+ port_delete( p_port );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.port_key_tbl,\r
+ port_gen_id(p_port->rec.lid, p_port->rec.port_num),\r
+ &p_port->map_item );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_path( IN osmtest_t * const p_osmt,\r
+ IN FILE * const fh,\r
+ IN OUT uint32_t * const p_line_num )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint32_t offset;\r
+ char line[OSMTEST_MAX_LINE_LEN];\r
+ boolean_t done = FALSE;\r
+ path_t *p_path;\r
+ const osmtest_token_t *p_tok;\r
+ boolean_t got_error = FALSE;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_path );\r
+\r
+ p_path = path_new( );\r
+ CL_ASSERT( p_path != NULL );\r
+\r
+ /*\r
+ * Parse the inventory file and create the database.\r
+ */\r
+ while( !done )\r
+ {\r
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+ {\r
+ /*\r
+ * End of file in the middle of a definition.\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_path: ERR 0127: "\r
+ "Unexpected end of file\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++*p_line_num;\r
+\r
+ /*\r
+ * Skip whitespace\r
+ */\r
+ offset = 0;\r
+ if( !str_skip_white( line, &offset ) )\r
+ continue; /* whole line was whitespace */\r
+\r
+ p_tok = str_get_token( &line[offset] );\r
+ if( p_tok == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_path: ERR 0128: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ continue;\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+ }\r
+\r
+ str_skip_token( line, &offset );\r
+\r
+ switch ( p_tok->val )\r
+ {\r
+ case OSMTEST_TOKEN_COMMENT:\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DGID:\r
+ p_path->comp.dgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_path->comp.dgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+ str_skip_white( line, &offset );\r
+ p_path->rec.dgid.unicast.prefix =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ str_skip_token( line, &offset );\r
+ p_path->rec.dgid.unicast.interface_id =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "dgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_path->rec.dgid.unicast.prefix ),\r
+ cl_ntoh64( p_path->rec.dgid.unicast.interface_id ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SGID:\r
+ p_path->comp.sgid.unicast.prefix = 0xFFFFFFFFFFFFFFFFULL;\r
+ p_path->comp.sgid.unicast.interface_id = 0xFFFFFFFFFFFFFFFFULL;\r
+\r
+ str_skip_white( line, &offset );\r
+ p_path->rec.sgid.unicast.prefix =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+ str_skip_token( line, &offset );\r
+ p_path->rec.sgid.unicast.interface_id =\r
+ cl_hton64( strtoull( &line[offset], NULL, 0 ) );\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "sgid = 0x%016" PRIx64 " 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( p_path->rec.sgid.unicast.prefix ),\r
+ cl_ntoh64( p_path->rec.sgid.unicast.interface_id ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DLID:\r
+ p_path->comp.dlid = 0xFFFF;\r
+ p_path->rec.dlid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "dlid = 0x%X\n", cl_ntoh16( p_path->rec.dlid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_SLID:\r
+ p_path->comp.slid = 0xFFFF;\r
+ p_path->rec.slid =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "slid = 0x%X\n", cl_ntoh16( p_path->rec.slid ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_PKEY:\r
+ p_path->comp.pkey = 0xFFFF;\r
+ p_path->rec.pkey =\r
+ cl_hton16( ( uint16_t ) strtoul( &line[offset], NULL, 0 ) );\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_path: "\r
+ "pkey = 0x%X\n", cl_ntoh16( p_path->rec.pkey ) );\r
+ }\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_END:\r
+ done = TRUE;\r
+ break;\r
+\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_path: ERR 0129: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( got_error ) \r
+ {\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+ /*\r
+ * Make sure the user specified enough information, then\r
+ * add this object to the database.\r
+ */\r
+ if( osmtest_path_rec_kay_is_valid( p_osmt, p_path ) == FALSE )\r
+ {\r
+ path_delete( p_path );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ cl_qmap_insert( &p_osmt->exp_subn.path_tbl,\r
+ osmtest_path_rec_key_get( &p_path->rec ),\r
+ &p_path->map_item );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_parse_link( IN osmtest_t * const p_osmt,\r
+ IN FILE * const fh,\r
+ IN OUT uint32_t * const p_line_num )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint32_t offset;\r
+ char line[OSMTEST_MAX_LINE_LEN];\r
+ boolean_t done = FALSE;\r
+ const osmtest_token_t *p_tok;\r
+ boolean_t got_error = FALSE;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_parse_link);\r
+\r
+ /*\r
+ * Parse the inventory file and create the database.\r
+ */\r
+ while( !done )\r
+ {\r
+ if( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) == NULL )\r
+ {\r
+ /*\r
+ * End of file in the middle of a definition.\r
+ */\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_link: ERR 012A: "\r
+ "Unexpected end of file\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ ++*p_line_num;\r
+\r
+ /*\r
+ * Skip whitespace\r
+ */\r
+ offset = 0;\r
+ if( !str_skip_white( line, &offset ) )\r
+ continue; /* whole line was whitespace */\r
+\r
+ p_tok = str_get_token( &line[offset] );\r
+ if( p_tok == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_link: ERR 012B: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ continue;\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_parse_link: "\r
+ "Found '%s' (line %u)\n", p_tok->str, *p_line_num );\r
+ }\r
+\r
+ str_skip_token( line, &offset );\r
+\r
+ switch ( p_tok->val )\r
+ {\r
+ case OSMTEST_TOKEN_FROMLID:\r
+ case OSMTEST_TOKEN_FROMPORTNUM:\r
+ case OSMTEST_TOKEN_TOPORTNUM:\r
+ case OSMTEST_TOKEN_TOLID:\r
+ /* For now */\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_END:\r
+ done = TRUE;\r
+ break;\r
+\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_parse_link: ERR 012C: "\r
+ "Ignoring line %u with unknown token: %s\n",\r
+ *p_line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if( got_error )\r
+ status = IB_ERROR;\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+static ib_api_status_t\r
+osmtest_create_db( IN osmtest_t * const p_osmt )\r
+{\r
+ FILE *fh;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ uint32_t offset;\r
+ char line[OSMTEST_MAX_LINE_LEN];\r
+ uint32_t line_num = 0;\r
+ const osmtest_token_t *p_tok;\r
+ boolean_t got_error = FALSE;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_create_db );\r
+\r
+ fh = fopen( p_osmt->opt.file_name, "r" );\r
+ if( fh == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_create_db: ERR 0130: "\r
+ "Unable to open inventory file (%s)\n", p_osmt->opt.file_name);\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ /*\r
+ * Parse the inventory file and create the database.\r
+ */\r
+ while( fgets( line, OSMTEST_MAX_LINE_LEN, fh ) != NULL )\r
+ {\r
+ line_num++;\r
+\r
+ /*\r
+ * Skip whitespace\r
+ */\r
+ offset = 0;\r
+ if( !str_skip_white( line, &offset ) )\r
+ continue; /* whole line was whitespace */\r
+\r
+ p_tok = str_get_token( &line[offset] );\r
+ if( p_tok == NULL )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_create_db: ERR 0131: "\r
+ "Ignoring line %u: %s\n", line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ continue;\r
+ }\r
+\r
+ if( osm_log_is_active( &p_osmt->log, OSM_LOG_DEBUG ) )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_create_db: "\r
+ "Found '%s' (line %u)\n", p_tok->str, line_num );\r
+ }\r
+\r
+ switch ( p_tok->val )\r
+ {\r
+ case OSMTEST_TOKEN_COMMENT:\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DEFINE_NODE:\r
+ status = osmtest_parse_node( p_osmt, fh, &line_num );\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DEFINE_PORT:\r
+ status = osmtest_parse_port( p_osmt, fh, &line_num );\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DEFINE_PATH:\r
+ status = osmtest_parse_path( p_osmt, fh, &line_num );\r
+ break;\r
+\r
+ case OSMTEST_TOKEN_DEFINE_LINK:\r
+ status = osmtest_parse_link( p_osmt, fh, &line_num );\r
+ break;\r
+\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_create_db: ERR 0132: "\r
+ "Ignoring line %u: %s\n", line_num, &line[offset] );\r
+ got_error = TRUE;\r
+ break;\r
+ }\r
+\r
+ if( got_error )\r
+ status = IB_ERROR;\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_create_db: ERR 0133: "\r
+ "Bad status received during parsing (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ fclose( fh );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ fclose( fh );\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ Returns the index in the local port attribute array for the\r
+ user's selection.\r
+**********************************************************************/\r
+static uint32_t\r
+osmtest_get_user_port( IN osmtest_t * const p_osmt,\r
+ IN const ib_port_attr_t p_attr_array[],\r
+ IN uint32_t const num_ports )\r
+{\r
+ uint32_t i;\r
+ uint32_t choice = 0;\r
+ boolean_t done_flag = FALSE;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_get_user_port );\r
+\r
+ /*\r
+ * User needs prompting for the local port GUID with which\r
+ * to bind.\r
+ */\r
+\r
+ while( done_flag == FALSE )\r
+ {\r
+ printf( "\nChoose a local port number with which to bind:\n\n" );\r
+ for( i = 0; i < num_ports; i++ )\r
+ {\r
+ /*\r
+ * Print the index + 1 since by convention, port numbers\r
+ * start with 1 on host channel adapters.\r
+ */\r
+\r
+ printf( "\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",\r
+ i + 1, cl_ntoh64( p_attr_array[i].port_guid ),\r
+ p_attr_array[i].lid,\r
+ ib_get_port_state_str( p_attr_array[i].link_state ) );\r
+ }\r
+\r
+ printf( "\nEnter choice (1-%u): ", i );\r
+ scanf( "%u", &choice );\r
+ if( choice > num_ports )\r
+ printf( "\nError: Lame choice!\n" );\r
+ else\r
+ done_flag = TRUE;\r
+\r
+ }\r
+ printf("\n");\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( choice - 1 );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_bind( IN osmtest_t * p_osmt,\r
+ IN uint16_t max_lid,\r
+ IN ib_net64_t guid OPTIONAL )\r
+{\r
+ uint32_t port_index;\r
+ ib_api_status_t status;\r
+ uint32_t num_ports = GUID_ARRAY_SIZE;\r
+ ib_port_attr_t attr_array[GUID_ARRAY_SIZE];\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_bind );\r
+\r
+ /*\r
+ * Call the transport layer for a list of local port\r
+ * GUID values.\r
+ */\r
+ status = osm_vendor_get_all_port_attr( p_osmt->p_vendor,\r
+ attr_array, &num_ports );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_bind: ERR 0134: "\r
+ "Failure getting local port attributes (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ if( guid == 0 )\r
+ {\r
+ /*\r
+ * User needs prompting for the local port GUID with which\r
+ * to bind.\r
+ */\r
+ port_index = osmtest_get_user_port( p_osmt, attr_array, num_ports );\r
+\r
+ if( num_ports == 0 )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_bind: ERR 0135: "\r
+ "No local ports. Unable to proceed\n" );\r
+ goto Exit;\r
+ }\r
+ guid = attr_array[port_index].port_guid;\r
+ }\r
+ else\r
+ {\r
+ for( port_index = 0; port_index < num_ports; port_index++ )\r
+ {\r
+ if( attr_array[port_index].port_guid == guid )\r
+ break;\r
+ }\r
+\r
+ if( port_index == num_ports )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_bind: ERR 0136: "\r
+ "No local port with guid 0x%016" PRIx64 "\n",\r
+ cl_ntoh64( guid ) );\r
+ status = IB_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * Copy the port info for the selected port.\r
+ */\r
+ memcpy( &p_osmt->local_port, &attr_array[port_index],\r
+ sizeof( p_osmt->local_port ) );\r
+\r
+ /* bind to the SA */\r
+ osm_log( &p_osmt->log, OSM_LOG_DEBUG,\r
+ "osmtest_bind: "\r
+ "Using port with SM LID:0x%04X\n",\r
+ p_osmt->local_port.sm_lid);\r
+ p_osmt->max_lid = max_lid;\r
+\r
+ p_osmt->h_bind = osmv_bind_sa(p_osmt->p_vendor, &p_osmt->mad_pool, guid);\r
+\r
+ if( p_osmt->h_bind == OSM_BIND_INVALID_HANDLE )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_bind: ERR 0137: "\r
+ "Unable to bind to SA\n" );\r
+ status = IB_ERROR;\r
+ goto Exit;\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r
+/**********************************************************************\r
+ **********************************************************************/\r
+ib_api_status_t\r
+osmtest_run( IN osmtest_t * const p_osmt )\r
+{\r
+ ib_api_status_t status = IB_SUCCESS;\r
+\r
+ OSM_LOG_ENTER( &p_osmt->log, osmtest_run );\r
+\r
+ status = osmtest_validate_sa_class_port_info(p_osmt);\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0138: "\r
+ "Could not obtain SA ClassPortInfo (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ if( p_osmt->opt.flow == 1 )\r
+ {\r
+ /*\r
+ * Creating an inventory file with all nodes, ports and paths\r
+ */\r
+ status = osmtest_create_inventory_file( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0139: "\r
+ "Inventory file create failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if( p_osmt->opt.flow == 5 )\r
+ {\r
+ /*\r
+ * Stress SA - flood the it with queries\r
+ */\r
+ switch ( p_osmt->opt.stress )\r
+ {\r
+ case 0:\r
+ case 1: /* small response SA query stress */\r
+ status = osmtest_stress_small_rmpp( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0140: "\r
+ "Small RMPP stress test failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ break;\r
+ case 2: /* large response SA query stress */\r
+ status = osmtest_stress_large_rmpp( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0141: "\r
+ "Large RMPP stress test failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ break;\r
+ case 3: /* large response Path Record SA query stress */\r
+ status = osmtest_create_db( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0142: "\r
+ "Database creation failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_stress_large_rmpp_pr( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0143: "\r
+ "Large RMPP stress test failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ break;\r
+ default:\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0144: "\r
+ "Unknown stress test value %u\n",\r
+ p_osmt->opt.stress );\r
+ break;\r
+ }\r
+ }\r
+ else\r
+ {\r
+\r
+ /*\r
+ * Run normal validition tests.\r
+ */\r
+ if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 2)\r
+ {\r
+ /*\r
+ * Only validate the given inventory file\r
+ */ \r
+ status = osmtest_create_db( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0145: "\r
+ "Database creation failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmtest_validate_against_db( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0146: "\r
+ "SA validation database failure (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 0)\r
+ {\r
+ status = osmtest_wrong_sm_key_ignored( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0147: "\r
+ "Try wrong SM_Key failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 3)\r
+ {\r
+ /*\r
+ * run service registration, deregistration, and lease test\r
+ */\r
+ status = osmt_run_service_records_flow( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0148: "\r
+ "Service Flow failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 4)\r
+ {\r
+ /* \r
+ * Run event forwarding test\r
+ */\r
+#ifdef OSM_VENDOR_INTF_MTL\r
+ status = osmt_run_inform_info_flow( p_osmt );\r
+\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0149: "\r
+ "Inform Info Flow failed: (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+#else\r
+ osm_log (&p_osmt->log, OSM_LOG_INFO,\r
+ "osmtest_run: The event forwarding flow "\r
+ "is not implemented yet!\n");\r
+ status = IB_SUCCESS;\r
+ goto Exit;\r
+#endif\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 7)\r
+ {\r
+ /* \r
+ * QoS info: dump VLArb and SLtoVL tables.\r
+ * Since it generates a huge file, we run it only\r
+ * if explicitly required to\r
+ */\r
+ status = osmtest_create_db( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 014A: "\r
+ "Database creation failed (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+\r
+ status = osmt_run_slvl_and_vlarb_records_flow(p_osmt);\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0150: "\r
+ "Failed to get SLtoVL and VL Arbitration Tables (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 8)\r
+ {\r
+ /*\r
+ * Run trap 64/65 flow (this flow requires running of external tool)\r
+ */\r
+#ifdef OSM_VENDOR_INTF_MTL\r
+ status = osmt_run_trap64_65_flow( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0151: "\r
+ "Trap 64/65 Flow failed: (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+#else\r
+ osm_log (&p_osmt->log, OSM_LOG_INFO,\r
+ "osmtest_run: The event forwarding flow "\r
+ "is not implemented yet!\n");\r
+ status = IB_SUCCESS;\r
+ goto Exit;\r
+#endif\r
+ }\r
+\r
+ if (p_osmt->opt.flow == 0 || p_osmt->opt.flow == 6)\r
+ {\r
+ /*\r
+ * Multicast flow\r
+ */ \r
+ status = osmt_run_mcast_flow( p_osmt );\r
+ if( status != IB_SUCCESS )\r
+ {\r
+ osm_log( &p_osmt->log, OSM_LOG_ERROR,\r
+ "osmtest_run: ERR 0152: "\r
+ "Multicast Flow failed: (%s)\n",\r
+ ib_get_err_str( status ) );\r
+ goto Exit;\r
+ }\r
+ }\r
+\r
+ osm_log( &p_osmt->log, OSM_LOG_INFO,\r
+ "osmtest_run: "\r
+ "\n\n***************** ALL TESTS PASS *****************\n\n" );\r
+\r
+ }\r
+ }\r
+\r
+ Exit:\r
+ OSM_LOG_EXIT( &p_osmt->log );\r
+ return ( status );\r
+}\r
+\r